Another sesame patch
W. Michael Petullo
mike at flyn.org
Wed Jan 19 12:32:24 PST 2005
Attached you should find another patch vs. sesame CVS.
This patch contains the following changes from the previous one:
* tools/check-common.c: Added some unit tests using the check
framework -- preparation for refactoring
* tools/common.c: Refactoring of some code
* tools/sesame-format.c: Check if a device is mounted before
formatting it
* tools/sesame-format.c: Use a temporary DM device to format --
hide device from hal until ready
* tools/sesame-is-encrypted.c: Begin a program that checks if a
device is encrypted using sesame
Using the programs is very similar to the previous patch. I am
doing everything by hand right now -- eventually hald will handle the
sesame-setup automatically. Here are the steps:
==== FORMAT ====
1. Execute sesame-format. This will block, waiting for a password on stdin:
./sesame-format -v /dev/sdb4
2. Place the information printed by sesame-format into a sesame header:
uuid is <UUID>
encrypted key is <EKEY>
The header should look like this:
# SESAME_MAGIC
version = '0'
uuid = '<UUID>'
block_key_cipher = 'aes'
block_key_sha1 = 'FIXME'
enc_key_cipher = 'aes'
enc_key = '<EKEY>'
3. Remove the dm-crypt device created in step 1:
cryptsetup remove DMDEVICE
4. Install the sesame header (this should be done by sesame-format, but
libsetup does not yet support writing):
dd if=/dev/zero bs=1c count=512 of=/dev/sdb4
dd if=../../cryptheader bs=1c count=512 of=/dev/sdb4
==== SETUP (eventually will be performed by hald) ====
1. Execute sesame-setup, entering the password from step 1.
./sesame-setup -v /dev/sdb4
2. Mount the dm-crypt device.
mount /dev/mapper/sesame_crypto_<UUID> ...
--
Mike
:wq
-------------- next part --------------
diff -u --recursive --new-file sesame-cvs-vanilla/ChangeLog sesame-cvs/ChangeLog
--- sesame-cvs-vanilla/ChangeLog 2004-12-31 07:35:47.000000000 -0600
+++ sesame-cvs/ChangeLog 2005-01-19 14:17:04.119372424 -0600
@@ -1,3 +1,33 @@
+2005-01-19 W. Michael Petullo <mike at flyn.org>
+
+ * tools/check-common.c: Added some unit tests using the check
+ framework -- preparation for refactoring
+
+ * tools/common.c: Refactoring of some code
+
+ * tools/sesame-format.c: Check if a device is mounted before
+ formatting it
+
+ * tools/sesame-format.c: Use a temporary DM device to format --
+ hide device from hal until ready
+
+ * tools/sesame-is-encrypted.c: Begin a program that checks if a
+ device is encrypted using sesame
+
+2004-01-19 W. Michael Petullo <mike at flyn.org>
+
+ * tools/common.c: Moved some code to common.c
+
+ * tools/common.c: Fixed encode/decode leak
+
+ * tools/sesame-setup.c: Minor code changes
+
+ * tools/sesame-format.c: Began work on a new utility to format
+ a sesame-compliant disk
+
+ * tools/sesame-setup.c: Now takes aes as name of cipher and
+ resolved this to aes-128-ecb for OpenSSL calls.
+
2004-12-31 David Zeuthen <davidz at redhat.com>
Patch from W. Michael Petullo <mike at flyn.org>. I wrote a patch for
diff -u --recursive --new-file sesame-cvs-vanilla/configure.in sesame-cvs/configure.in
--- sesame-cvs-vanilla/configure.in 2004-12-31 07:35:47.000000000 -0600
+++ sesame-cvs/configure.in 2005-01-19 13:11:15.000000000 -0600
@@ -6,6 +6,11 @@
AM_CONFIG_HEADER(config.h)
AM_MAINTAINER_MODE
+AM_PATH_CHECK(,[have_check="yes"],
+ AC_MSG_WARN([Check not found; cannot run unit tests!])
+ [have_check="no"])
+ AM_CONDITIONAL(HAVE_CHECK, test x"$have_check" = "xyes")
+
AC_ISC_POSIX
AC_PROG_CC
AM_PROG_CC_STDC
@@ -14,6 +19,7 @@
AC_PROG_MAKE_SET
AC_PROG_LN_S
AC_SYS_LARGEFILE
+AM_PATH_GLIB_2_0(,,AC_MSG_ERROR(You are missing glib))
AC_ARG_ENABLE(ansi, [ --enable-ansi enable -ansi -pedantic gcc flags],enable_ansi=$enableval,enable_ansi=no)
@@ -105,6 +111,7 @@
#PKG_CHECK_MODULES(PACKAGE, [$pkg_modules])
AC_CHECK_LIB(crypto, EVP_DecryptInit_ex)
AC_CHECK_LIB(ssl, SSL_load_error_strings)
+AC_CHECK_LIB(uuid, uuid_generate)
AC_PATH_PROG(CRYPTSETUP, cryptsetup, no)
if test x"$CRYPTSETUP" = xno; then
@@ -112,6 +119,18 @@
fi
AC_SUBST(CRYPTSETUP)
+AC_PATH_PROG(DD, dd, no)
+if test x"$DD" = xno; then
+ AC_MSG_ERROR([dd executable not found in your path])
+fi
+AC_SUBST(DD)
+
+AC_PATH_PROG(MKFS, mkfs, no)
+if test x"$MKFS" = xno; then
+ AC_MSG_ERROR([mkfs executable not found in your path])
+fi
+AC_SUBST(MKFS)
+
AS_AC_EXPAND(LOCALSTATEDIR, $localstatedir)
AS_AC_EXPAND(SYSCONFDIR, $sysconfdir)
AS_AC_EXPAND(DATADIR, $datadir)
Binary files sesame-cvs-vanilla/libsesame/libsesame.o and sesame-cvs/libsesame/libsesame.o differ
Binary files sesame-cvs-vanilla/tools/check_common and sesame-cvs/tools/check_common differ
diff -u --recursive --new-file sesame-cvs-vanilla/tools/check_common.c sesame-cvs/tools/check_common.c
--- sesame-cvs-vanilla/tools/check_common.c 1969-12-31 18:00:00.000000000 -0600
+++ sesame-cvs/tools/check_common.c 2005-01-19 13:21:37.120153184 -0600
@@ -0,0 +1,156 @@
+#include <stdlib.h>
+#include <check.h>
+#include <string.h>
+#include <common.h>
+#include <openssl/evp.h>
+#include <openssl/ssl.h>
+
+#ifndef EVP_MAX_BLOCK_LENGTH
+#define EVP_MAX_BLOCK_LENGTH 32 /* some older openssl versions need this */
+#endif
+
+START_TEST(test_strip_cr)
+{
+ char str[5];
+ strcpy(str, "foo\n");
+ fail_unless(strcmp(strip_cr(str), "foo") == 0,
+ "strip_cr test failed");
+}
+END_TEST
+
+START_TEST(test_encode)
+{
+ char data[] = { 0x00, 0x01, 0x02, 0x0a, 0x0b, 0x0c, 0xfd, 0xfe,
+ 0xff };
+ char edata[sizeof data * 2 + 1];
+ fail_unless(strcmp
+ (encode(edata, data, sizeof data),
+ "0001020a0b0cfdfeff") == 0, "encode test failed");
+}
+END_TEST
+
+START_TEST(test_decode)
+{
+ char *data = "0001020a0b0cfdfeff";
+ char ddata[sizeof data / 2 - 1];
+ char answer[] = { 0x00, 0x01, 0x02, 0x0a, 0x0b, 0x0c, 0xfd, 0xfe,
+ 0xff };
+ fail_unless(memcmp(decode(ddata, data), answer, sizeof answer) == 0,
+ "decode test failed");
+}
+END_TEST
+
+START_TEST(test_encode_decode)
+{
+ char data[] = { 0x00, 0x01, 0x02, 0x0a, 0x0b, 0x0c, 0xfd, 0xfe,
+ 0xff };
+ char edata[sizeof data * 2 + 1];
+ char ddata[sizeof data / 2 - 1];
+ fail_unless(memcmp
+ (decode(ddata, encode(edata, data, sizeof data)), data,
+ sizeof data) == 0, "encode_decode test failed");
+}
+END_TEST
+
+START_TEST(test_encrypt_it)
+{
+ char data[] = { 0x00, 0x01, 0x02, 0x0a, 0x0b, 0x0c, 0xfd, 0xfe,
+ 0xff };
+ /* Salted__ + salt + padded ciphertext: */
+ char answer[] = { 0x53, 0x61, 0x6c, 0x74, 0x65, 0x64, 0x5f, 0x5f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0xf0, 0xa5, 0x83, 0x6f, 0x7c, 0xfd, 0x31,
+ 0xad, 0x0a, 0x53, 0x29, 0xc6, 0x18, 0xfb, 0x8c };
+ char edata[BUFSIZ + EVP_MAX_BLOCK_LENGTH];
+ int edata_len;
+ char salt[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
+
+ fail_unless(crypt_it(edata, &edata_len, data, sizeof data,
+ "aes-128-ecb", "passphrase", salt,
+ salt_write, EVP_EncryptInit_ex,
+ EVP_EncryptUpdate, EVP_EncryptFinal_ex) == 1);
+ fail_unless(memcmp(edata, answer, sizeof answer) == 0,
+ "encrypt_it test failed");
+}
+END_TEST
+
+START_TEST(test_decrypt_it)
+{
+ /* Salted__ + salt + padded ciphertext: */
+ char data[] = { 0x53, 0x61, 0x6c, 0x74, 0x65, 0x64, 0x5f, 0x5f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0xf0, 0xa5, 0x83, 0x6f, 0x7c, 0xfd, 0x31,
+ 0xad, 0x0a, 0x53, 0x29, 0xc6, 0x18, 0xfb, 0x8c };
+ char answer[] = { 0x00, 0x01, 0x02, 0x0a, 0x0b, 0x0c, 0xfd, 0xfe,
+ 0xff };
+ char ddata[BUFSIZ + EVP_MAX_BLOCK_LENGTH];
+ int ddata_len;
+ char salt[PKCS5_SALT_LEN];
+
+ fail_unless(crypt_it(ddata, &ddata_len, data, sizeof data,
+ "aes-128-ecb", "passphrase", salt,
+ salt_read, EVP_DecryptInit_ex, EVP_DecryptUpdate,
+ EVP_DecryptFinal_ex) == 1);
+ fail_unless(memcmp(ddata, answer, sizeof answer) == 0,
+ "decrypt_it test failed");
+}
+END_TEST
+
+START_TEST(test_encrypt_decrypt_it)
+{
+ char data[] = { 0x00, 0x01, 0x02, 0x0a, 0x0b, 0x0c, 0xfd, 0xfe,
+ 0xff };
+ char edata[BUFSIZ + EVP_MAX_BLOCK_LENGTH];
+ char ddata[BUFSIZ + EVP_MAX_BLOCK_LENGTH];
+ int edata_len;
+ int ddata_len;
+ char salt[PKCS5_SALT_LEN];
+
+ fail_unless(crypt_it(edata, &edata_len, data, sizeof data,
+ "aes-128-ecb", "passphrase", salt, salt_write,
+ EVP_EncryptInit_ex, EVP_EncryptUpdate,
+ EVP_EncryptFinal_ex) == 1);
+ fail_unless(crypt_it(ddata, &ddata_len, edata, edata_len,
+ "aes-128-ecb", "passphrase", salt,
+ salt_read, EVP_DecryptInit_ex,
+ EVP_DecryptUpdate, EVP_DecryptFinal_ex) == 1);
+ fail_unless(memcmp(ddata, data, sizeof data) == 0,
+ "encrypt_decrypt_it test failed");
+}
+END_TEST
+
+static Suite *common_suite(void)
+{
+ Suite *s = suite_create("common");
+
+ TCase *tc_strip_cr = tcase_create("test_strip_cr");
+ TCase *tc_encode = tcase_create("test_encode");
+ TCase *tc_encrypt_it = tcase_create("test_encrypt_it");
+
+ tcase_add_test(tc_strip_cr, test_strip_cr);
+
+ tcase_add_test(tc_encode, test_encode);
+ tcase_add_test(tc_encode, test_decode);
+ tcase_add_test(tc_encode, test_encode_decode);
+
+ tcase_add_test(tc_encrypt_it, test_encrypt_it);
+ tcase_add_test(tc_encrypt_it, test_decrypt_it);
+ tcase_add_test(tc_encrypt_it, test_encrypt_decrypt_it);
+
+ suite_add_tcase(s, tc_strip_cr);
+ suite_add_tcase(s, tc_encode);
+ suite_add_tcase(s, tc_encrypt_it);
+
+ return s;
+}
+
+int main(void)
+{
+ int nf;
+ Suite *s = common_suite();
+ SRunner *sr = srunner_create(s);
+ srunner_run_all(sr, CK_NORMAL);
+ nf = srunner_ntests_failed(sr);
+ srunner_free(sr);
+ return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
Binary files sesame-cvs-vanilla/tools/check_common.o and sesame-cvs/tools/check_common.o differ
diff -u --recursive --new-file sesame-cvs-vanilla/tools/common.c sesame-cvs/tools/common.c
--- sesame-cvs-vanilla/tools/common.c 1969-12-31 18:00:00.000000000 -0600
+++ sesame-cvs/tools/common.c 2005-01-19 12:42:47.000000000 -0600
@@ -0,0 +1,375 @@
+#define _GNU_SOURCE
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <limits.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <stdio.h>
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+#include <openssl/evp.h>
+
+#include "common.h"
+
+#define SALTHEAD "Salted__"
+
+void sslerror(const char *msg)
+{
+ assert(msg);
+
+ unsigned long err = ERR_get_error();
+ if (err != 0)
+ fprintf(stderr, "%s: %s", msg,
+ ERR_error_string(err, NULL));
+}
+
+char *strip_cr(char *s)
+{
+ int len;
+
+ assert(s);
+
+ len = strlen(s);
+ s[len - 1] = s[len - 1] == '\n' ? 0x00 : s[len - 1];
+
+ return s;
+}
+
+int read_key(char *buf, int size)
+{
+ int fnval = 1;
+
+ assert(buf);
+ assert(size > 0);
+
+ if (fgets(buf, size, stdin) == NULL) {
+ fnval = 0;
+ goto _return;
+ }
+
+ strip_cr(buf);
+
+ _return:
+ return fnval;
+}
+
+void msg(int verbose, const char *format, ...)
+{
+ assert(format != NULL);
+
+ if (verbose) {
+ va_list args;
+
+ va_start(args, format);
+ vfprintf(stdout, format, args);
+ va_end(args);
+ }
+}
+
+int run_cryptsetup(const char *block_key_cipher, const char *prefix,
+ const char *device, const char *uuid, const char *key,
+ const int key_len)
+{
+ pid_t child;
+ int fnval = 1, pipefd[2], child_exit;
+ char dmname[PATH_MAX + 1], *key_len_str;
+
+ assert(block_key_cipher != NULL);
+ assert(prefix != NULL);
+ assert(device != NULL);
+ assert(uuid != NULL);
+ assert(key != NULL);
+ assert(key_len > 0);
+
+ if (asprintf(&key_len_str, "%d", key_len * 8) == -1) {
+ fprintf(stderr, "Failed to allocate memory, err=%s\n",
+ strerror(errno));
+ fnval = 0;
+ goto _return_no_free;
+ }
+
+ strcpy(dmname, prefix);
+ if (strlen(dmname) + strlen(uuid) > PATH_MAX) {
+ fprintf(stderr, "Uuid %s is too long\n", uuid);
+ fnval = 0;
+ goto _return;
+ }
+ strncat(dmname, uuid, sizeof dmname - strlen(dmname));
+
+ if (pipe(pipefd) == -1) {
+ fprintf(stderr, "Failed to create pipe, err=%s\n",
+ strerror(errno));
+ fnval = 0;
+ goto _return;
+ }
+
+ child = fork();
+
+ if (child < 0) {
+ fprintf(stderr, "Failed to fork, err=%s\n",
+ strerror(errno));
+ fnval = 0;
+ goto _return;
+ } else if (child == 0) {
+ close(0);
+ dup(pipefd[0]);
+ close(pipefd[0]);
+ close(pipefd[1]);
+ execl(CRYPTSETUP, "cryptsetup", "-s", key_len_str, "-c",
+ block_key_cipher, "create", dmname, device, NULL);
+ fprintf(stderr, "Failed to execute %s, err=%s\n",
+ CRYPTSETUP, strerror(errno));
+ exit(EXIT_FAILURE);
+ } else {
+ close(pipefd[0]);
+ write(pipefd[1], key, key_len);
+ close(pipefd[1]);
+ waitpid(child, &child_exit, 0);
+ fnval = !WEXITSTATUS(child_exit);
+ goto _return;
+ }
+
+ _return:
+ free(key_len_str);
+ _return_no_free:
+ return fnval;
+}
+
+int run_cryptunsetup(const char *prefix, const char *device, const char *uuid)
+{
+ pid_t child;
+ int fnval = 1, child_exit;
+ char dmname[PATH_MAX + 1];
+
+ assert(prefix != NULL);
+ assert(device != NULL);
+ assert(uuid != NULL);
+
+ strcpy(dmname, prefix);
+ if (strlen(dmname) + strlen(uuid) > PATH_MAX) {
+ fprintf(stderr, "Uuid %s is too long\n", uuid);
+ fnval = 0;
+ goto _return;
+ }
+ strncat(dmname, uuid, sizeof dmname - strlen(dmname));
+
+ child = fork();
+
+ if (child < 0) {
+ fprintf(stderr, "Failed to fork, err=%s\n",
+ strerror(errno));
+ fnval = 0;
+ goto _return;
+ } else if (child == 0) {
+ execl(CRYPTSETUP, "cryptsetup", "remove", dmname, device, NULL);
+ fprintf(stderr, "Failed to execute %s, err=%s\n",
+ CRYPTSETUP, strerror(errno));
+ exit(EXIT_FAILURE);
+ } else {
+ waitpid(child, &child_exit, 0);
+ fnval = !WEXITSTATUS(child_exit);
+ goto _return;
+ }
+
+ _return:
+ return fnval;
+}
+
+char *encode(char *dest, const char *src, const size_t src_len)
+{
+ size_t i, j;
+
+ assert(dest);
+ assert(src);
+ assert(src_len > 0);
+
+ memset(dest, 0x00, (src_len * 2) + 1);
+
+ for (i = 0, j = 0; i < src_len; i++, j += 2) {
+ dest[j] =
+ (src[i] >> 4) >
+ 9 ? (src[i] >> 4) + 87 : (src[i] >> 4) + 48;
+ dest[j + 1] =
+ (src[i] & 0x0f) >
+ 9 ? (src[i] & 0x0f) + 87 : (src[i] & 0x0f) + 48;
+ }
+
+ return dest;
+}
+
+char *decode(char *dest, const char *src)
+{
+ size_t i;
+
+ assert(dest);
+ assert(src);
+
+ for (i = 0; i < strlen(src); i += 2) {
+ dest[i / 2] =
+ isdigit(src[i]) ? (src[i] - 48) << 4 : (src[i] -
+ 87) << 4;
+ dest[i / 2] +=
+ isdigit(src[i + 1]) ? src[i + 1] - 48 : src[i + 1] -
+ 87;
+ }
+ return dest;
+}
+
+char *cipher_lookup(char *real_cipher, const char *cipher)
+{
+ assert(real_cipher);
+ assert(cipher);
+
+ if (strcmp("aes", cipher) == 0)
+ return strcpy(real_cipher, "aes-128-ecb");
+ else
+ return NULL;
+}
+
+int hash_authtok(const EVP_CIPHER * const cipher,
+ const char *const authtok,
+ unsigned char *const hash, const unsigned char *salt,
+ unsigned char *const iv)
+{
+ const EVP_MD *md;
+
+ assert(cipher != NULL); /* FIXME: is cipher is valid OpenSSL cipher? */
+ assert(authtok != NULL);
+ assert(hash != NULL);
+ assert(salt != NULL);
+ assert(iv != NULL);
+
+ md = EVP_md5();
+ if (EVP_BytesToKey
+ (cipher, md, salt, authtok, strlen(authtok), 1,
+ hash, iv) <= 0) {
+ fprintf(stderr, "failed to hash passphrase");
+ return 0;
+ }
+
+ return 1;
+}
+
+int salt_read(unsigned char *salt, char **out, int *outl, char **in, int *inl)
+{
+ assert(salt != NULL);
+ assert(out != NULL);
+ assert(*out != NULL);
+ assert(in != NULL);
+ assert(*in != NULL);
+
+ if (memcmp(*in, "Salted__", sizeof "Salted__" - 1) != 0) {
+ fprintf(stderr, "magic string Salted__ not in stream\n");
+ return 0;
+ }
+ memcpy(salt, *in + sizeof "Salted__" - 1, PKCS5_SALT_LEN);
+ *in += (strlen("Salted__") + PKCS5_SALT_LEN);
+ *inl -= (strlen("Salted__") + PKCS5_SALT_LEN);
+
+ return 1;
+}
+
+int salt_write(unsigned char *salt, char **out, int *outl, char **in, int *inl)
+{
+ assert(salt != NULL);
+ assert(out != NULL);
+ assert(*out != NULL);
+ assert(in != NULL);
+ assert(*in != NULL);
+
+ memcpy(*out, SALTHEAD, strlen(SALTHEAD));
+ *out += strlen(SALTHEAD);
+ memcpy(*out, salt, PKCS5_SALT_LEN);
+ *out += PKCS5_SALT_LEN;
+ *outl = strlen(SALTHEAD) + PKCS5_SALT_LEN;
+
+ return 1;
+}
+
+int crypt_it(char *out, size_t * const out_len, char *in,
+ size_t in_len, const char *cipher_name,
+ const char *const authtok, unsigned char *salt,
+ int (*salt_op) (unsigned char *salt, char **out,
+ int *outl, char **in, int *inl),
+ int (*crypt_init) (EVP_CIPHER_CTX * ctx,
+ const EVP_CIPHER * type, ENGINE * impl,
+ const unsigned char *key,
+ const unsigned char *iv),
+ int (*crypt_update) (EVP_CIPHER_CTX * ctx, unsigned char *out,
+ int *outl, const unsigned char *in, int inl),
+ int (*crypt_final) (EVP_CIPHER_CTX * ctx, unsigned char *out,
+ int *outl))
+{
+ int ret = 1;
+ int segment_len;
+ unsigned char hashed_authtok[EVP_MAX_KEY_LENGTH];
+ unsigned char iv[EVP_MAX_IV_LENGTH];
+ const EVP_CIPHER *cipher;
+ EVP_CIPHER_CTX ctx;
+
+ assert(out != NULL);
+ assert(out_len != NULL);
+ assert(in != NULL);
+ assert(cipher_name != NULL);
+ assert(authtok != NULL);
+
+ *out_len = 0;
+
+ memset(out, 0x00, BUFSIZ + EVP_MAX_BLOCK_LENGTH);
+ OpenSSL_add_all_ciphers();
+ EVP_CIPHER_CTX_init(&ctx);
+ SSL_load_error_strings();
+ if (!(cipher = EVP_get_cipherbyname(cipher_name))) {
+ fprintf(stderr, "error getting cipher \"%s\"\n",
+ (const char *) cipher_name);
+ ret = 0;
+ goto _return;
+ }
+ if (salt_op(salt, &out, out_len, &in, &in_len) == 0) {
+ ret = 0;
+ goto _return;
+ }
+ if (hash_authtok(cipher, authtok, hashed_authtok, salt, iv) == 0) {
+ ret = 0;
+ goto _return;
+ }
+
+ if (crypt_init(&ctx, cipher, NULL, hashed_authtok, iv) ==
+ 0) {
+ sslerror("failed to initialize encryption code");
+ ret = 0;
+ goto _return;
+ }
+
+ /* assumes plaintexts is always <= ciphertext + EVP_MAX_BLOCK_LEN in length
+ * OpenSSL's documentation seems to promise this */
+ if (crypt_update
+ (&ctx, out, &segment_len, in, in_len) == 0) {
+ sslerror("failed to encrypt key");
+ ret = 0;
+ goto _return;
+ }
+ *out_len += segment_len;
+ out += segment_len;
+ if (crypt_final(&ctx, out, &segment_len) == 0) {
+ sslerror
+ ("error completing encryption");
+ ret = 0;
+ goto _return;
+ }
+ *out_len += segment_len;
+ _return:
+ if (EVP_CIPHER_CTX_cleanup(&ctx) == 0) {
+ sslerror("error cleaning up cipher context");
+ ret = 0;
+ }
+
+ ERR_free_strings();
+ /* out_len is unsigned */
+ assert(ret == 0 || *out_len <= BUFSIZ + EVP_MAX_BLOCK_LENGTH);
+
+ return ret;
+}
diff -u --recursive --new-file sesame-cvs-vanilla/tools/common.h sesame-cvs/tools/common.h
--- sesame-cvs-vanilla/tools/common.h 1969-12-31 18:00:00.000000000 -0600
+++ sesame-cvs/tools/common.h 2005-01-19 12:45:12.000000000 -0600
@@ -0,0 +1,38 @@
+#define MAGICTAIL "SESAME0"
+#define DMCRYPT_PREFIX "sesame_crypto_"
+#define DMCRYPT_TMP_PREFIX "sesame_crypto_tmp_"
+#define DMDIR "/dev/mapper/"
+
+#include <openssl/evp.h>
+
+void sslerror(const char *msg);
+char *strip_cr(char *s);
+int read_key(char *buf, int size);
+void msg(int verbose, const char *format, ...);
+int run_cryptsetup(const char *block_key_cipher, const char *prefix,
+ const char *device, const char *uuid, const char *key,
+ const int key_len);
+int run_cryptunsetup(const char *prefix, const char *device, const char *uuid);
+char *encode(char *dest, const char *src, const size_t src_len);
+char *decode(char *dest, const char *src);
+char *cipher_lookup(char *real_cipher, const char *cipher);
+int hash_authtok(const EVP_CIPHER * cipher, const char *authtok,
+ unsigned char *hash, const unsigned char *salt,
+ unsigned char *iv);
+int salt_read(unsigned char *salt, char **out, int *outl,
+ char **in, int *inl);
+int salt_write(unsigned char *salt, char **out, int *outl,
+ char **in, int *inl);
+int crypt_it(char *out, size_t * const out_len, char *const in,
+ size_t in_len, const char *cipher_name,
+ const char *const authtok, unsigned char *salt,
+ int (*salt_op) (unsigned char *salt, char **out,
+ int *outl, char **in, int *inl),
+ int (*crypt_init) (EVP_CIPHER_CTX * ctx,
+ const EVP_CIPHER * type, ENGINE * impl,
+ const unsigned char *key,
+ const unsigned char *iv),
+ int (*crypt_update) (EVP_CIPHER_CTX * ctx, unsigned char *out,
+ int *outl, const unsigned char *in, int inl),
+ int (*crypt_final) (EVP_CIPHER_CTX * ctx, unsigned char *out,
+ int *outl));
Binary files sesame-cvs-vanilla/tools/common.o and sesame-cvs/tools/common.o differ
diff -u --recursive --new-file sesame-cvs-vanilla/tools/Makefile.am sesame-cvs/tools/Makefile.am
--- sesame-cvs-vanilla/tools/Makefile.am 2004-12-31 07:35:47.000000000 -0600
+++ sesame-cvs/tools/Makefile.am 2005-01-19 13:37:07.176763088 -0600
@@ -1,16 +1,37 @@
INCLUDES = \
-DCRYPTSETUP=\""$(CRYPTSETUP)\"" \
+ -DDD=\""$(DD)\"" \
+ -DMKFS=\""$(MKFS)\"" \
-DPACKAGE_DATA_DIR=\""$(datadir)"\" \
-DPACKAGE_BIN_DIR=\""$(bindir)"\" \
-DPACKAGE_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\"
-sbin_PROGRAMS = sesame-setup
+if HAVE_CHECK
+noinst_PROGRAMS = check_common
-sesame_setup_SOURCES = sesame-setup.c
+check_common_SOURCES = check_common.c common.c
+
+check_common_INCLUDES = @CHECK_CFLAGS@
+check_common_LDADD = @CHECK_LIBS@
+endif
+
+sbin_PROGRAMS = sesame-format sesame-setup sesame-is-encrypted
+
+sesame_format_SOURCES = sesame-format.c common.c
+
+sesame_setup_SOURCES = sesame-setup.c common.c
+
+sesame_is_encrypted_SOURCES = sesame-is-encrypted.c common.c
+
+test_crypto_SOURCES = test-crypto.c common.c
# Add @PACKAGE_LIBS@ if using pkg-config packages; see configure.in
-sesame_setup_LDADD = $(top_builddir)/libsesame/libsesame.la
+sesame_format_LDADD = $(top_builddir)/libsesame/libsesame.la $(GLIB_LIBS)
+sesame_setup_LDADD = $(top_builddir)/libsesame/libsesame.la
+sesame_is_encrypted_LDADD = $(top_builddir)/libsesame/libsesame.la
+
+AM_CFLAGS = $(GLIB_CFLAGS) -Werror
clean-local :
rm -f *~
diff -u --recursive --new-file sesame-cvs-vanilla/tools/sesame-format.c sesame-cvs/tools/sesame-format.c
--- sesame-cvs-vanilla/tools/sesame-format.c 1969-12-31 18:00:00.000000000 -0600
+++ sesame-cvs/tools/sesame-format.c 2005-01-19 13:02:08.000000000 -0600
@@ -0,0 +1,355 @@
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <ctype.h>
+#include <assert.h>
+#include <limits.h>
+#include <getopt.h>
+#include <glib.h>
+#include <mntent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <openssl/rand.h>
+#include <openssl/evp.h>
+#include <uuid/uuid.h>
+
+#ifndef EVP_MAX_BLOCK_LENGTH
+#define EVP_MAX_BLOCK_LENGTH 32 /* some older openssl versions need this */
+#endif
+
+#include "common.h"
+/* FIXME: what about LUKS? */
+#include "../libsesame/libsesame.h"
+
+static int verbose = 0;
+static int dry_run = 0;
+static char *fs_type = "ext2";
+static char *fs_cipher = "aes";
+static size_t fs_keylen = 16;
+static char *key_cipher = "aes";
+static char *device = NULL;
+
+static void print_usage(const int exitcode, const char *error,
+ const char *more)
+{
+ if (error)
+ assert(more);
+
+ fprintf(stderr, "sesame-setup [options] device\n\n"
+ "-h, --help\n"
+ " print a list of options\n\n"
+ "-v, --verbose\n"
+ " verbose display of messages\n\n"
+ "-d, --dry-run\n"
+ " do not actually perform any operations on device\n\n"
+ "-t, --fs-type type\n"
+ " set the filesystem type to use [%s]\n\n"
+ "-c, --fs-cipher cipher\n"
+ " cipher used to encrypt the filesystem [%s]\n\n"
+ "-c, --fs-keylen length\n"
+ " length in bits of encryption key [%d]\n\n"
+ "-k, --key-cipher cipher\n"
+ " cipher used to encrypt the key [%s]\n\n",
+ fs_type, fs_cipher, fs_keylen * 8, key_cipher);
+
+ if (error)
+ fprintf(stderr, "%s: %s\n", error, more);
+
+ exit(exitcode);
+}
+
+/* FIXME: do all Unices have an /etc/mtab? */
+static int mounted(const char* match)
+{
+ int mounted = 0;
+ FILE *mtab;
+ struct mntent *mtab_record;
+
+ assert(match != NULL);
+
+ if (!(mtab = fopen("/etc/mtab", "r"))) {
+ fprintf(stderr, "Could not open /etc/mtab, assuming mounted\n");
+ mounted = 1;
+ goto _return;
+ }
+ while ((mtab_record = getmntent(mtab)) != NULL) {
+ char const *mnt_fsname = mtab_record->mnt_fsname;
+ if (!strcasecmp(mnt_fsname, match)) {
+ mounted = 1;
+ fprintf(stderr, "Volume %s currently mounted at %s\n",
+ device, mtab_record->mnt_dir);
+ }
+ }
+_return:
+ fclose(mtab);
+ return mounted;
+}
+
+static void print_output(FILE * out, int in)
+{
+ char c[1];
+
+ assert(out);
+ assert(in >= 0);
+
+ /* unbuffered I/O so we can catch progress indicators */
+ while (read(in, c, 1) != 0)
+ fprintf(out, "%c", *c);
+}
+
+static int run_mkfs(const char *uuid, const char *fs_type)
+{
+ pid_t pid;
+ GError *err = NULL;
+ char dmname[PATH_MAX + 1];
+ int fnval = 1, child_exit, pstderr = -1;
+ const char *argv[] = { MKFS, "-t", fs_type, "", NULL };
+
+ assert(uuid);
+ assert(fs_type);
+
+ strcpy(dmname, DMDIR);
+ strncat(dmname, DMCRYPT_TMP_PREFIX, sizeof dmname - strlen(dmname));
+ if (strlen(device) + strlen(uuid) > PATH_MAX) {
+ fprintf(stderr, "Uuid %s is too long\n", uuid);
+ fnval = 0;
+ goto _return;
+ }
+ strncat(dmname, uuid, sizeof dmname - strlen(dmname));
+ argv[3] = dmname;
+
+ if (g_spawn_async_with_pipes
+ (NULL, (char **) argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, NULL,
+ NULL, &pid, NULL, NULL, &pstderr, &err) == FALSE) {
+ fprintf(stderr, "%s\n", err->message);
+ g_error_free(err);
+ fnval = 0;
+ goto _return;
+ }
+
+ print_output(stderr, pstderr);
+
+ if (waitpid(pid, &child_exit, 0) == -1) {
+ fprintf(stderr, "Error waiting for child\n");
+ fnval = 0;
+ goto _return;
+ }
+
+ fnval = !WEXITSTATUS(child_exit);
+
+ _return:
+ return fnval;
+}
+
+static int run_randomize(const char *device)
+{
+ pid_t pid;
+ GError *err = NULL;
+ char of[BUFSIZ + 1];
+ int fnval = 1, child_exit, pstderr = -1;
+ const char *argv[] = { DD, "if=/dev/urandom", "", NULL };
+
+ assert(device);
+
+ strcpy(of, "of=");
+ if (strlen(device) + strlen(of) > BUFSIZ) {
+ fprintf(stderr, "Device name %s is too long\n", device);
+ fnval = 0;
+ goto _return;
+ }
+ strcat(of, device);
+ argv[2] = of;
+
+ if (g_spawn_async_with_pipes
+ (NULL, (char **) argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, NULL,
+ NULL, &pid, NULL, NULL, &pstderr, &err) == FALSE) {
+ fprintf(stderr, "%s\n", err->message);
+ g_error_free(err);
+ fnval = 0;
+ goto _return;
+ }
+
+ print_output(stderr, pstderr);
+
+ if (waitpid(pid, &child_exit, 0) == -1) {
+ fprintf(stderr, "Error waiting for child\n");
+ fnval = 0;
+ goto _return;
+ }
+
+ fnval = !WEXITSTATUS(child_exit);
+
+ _return:
+ return fnval;
+}
+
+int main(int argc, char *argv[])
+{
+ uuid_t uuid;
+ size_t efs_keylen;
+ char buf[BUFSIZ + 1];
+ char passphrase[BUFSIZ + 1];
+ int c, opt_index = 0, status = EXIT_SUCCESS;
+ char real_key_cipher[BUFSIZ + 1];
+ unsigned char uuid_str[36 + 1], salt[PKCS5_SALT_LEN];
+ char fs_key[EVP_MAX_KEY_LENGTH + sizeof(MAGICTAIL) - 1],
+ efs_key[BUFSIZ + EVP_MAX_BLOCK_LENGTH];
+ struct option opts[] = {
+ {"help", 0, 0, 'h'},
+ {"dry-run", 0, 0, 'd'},
+ {"verbose", 0, 0, 'v'},
+ {"fs-type", 1, 0, 't'},
+ {"fs-cipher", 1, 0, 'c'},
+ {"fs-keylen", 1, 0, 'l'},
+ {"key-cipher", 1, 0, 'k'},
+ {0, 0, 0, 0}
+ };
+
+ while ((c =
+ getopt_long(argc, argv, "hvdt:c:l:k:", opts, &opt_index))
+ >= 0) {
+ switch (c) {
+ case 'h':
+ print_usage(EXIT_SUCCESS, NULL, NULL);
+ case 'v':
+ verbose = 1;
+ break;
+ case 'd':
+ dry_run = 1;
+ break;
+ case 't':
+ fs_type = optarg;
+ break;
+ case 'c':
+ fs_cipher = optarg;
+ break;
+ case 'l':
+ fs_keylen = atoi(optarg) / 8;
+ break;
+ case 'k':
+ key_cipher = optarg;
+ break;
+ default:
+ print_usage(EXIT_FAILURE, NULL, NULL);
+ }
+ }
+
+ if (argv[optind] == NULL)
+ print_usage(EXIT_FAILURE, NULL, NULL);
+ device = argv[optind];
+
+ if (mounted(device)) {
+ status = EXIT_FAILURE;
+ goto _exit;
+ }
+
+ if (read_key(passphrase, BUFSIZ) == 0) {
+ fprintf(stderr, "Could not read key\n");
+ status = EXIT_FAILURE;
+ goto _exit;
+ }
+
+ msg(verbose, "generating UUID\n");
+ uuid_generate(uuid);
+ uuid_unparse(uuid, uuid_str);
+
+ msg(verbose, "randomizing %s\n", device);
+ // FIXME
+ if (0 && run_randomize(device) == 0) {
+ status = EXIT_FAILURE;
+ goto _exit;
+ }
+
+ msg(verbose, "creating random key for %s\n", device);
+ /* FIXME: is this used right? The documentation seems to state
+ * that this is seeded using /dev/urandom if it exists. What if
+ * it does not exist? */
+ if (RAND_bytes(fs_key, fs_keylen) == 0) {
+ fprintf(stderr, "Error generating random key\n");
+ status = EXIT_FAILURE;
+ goto _exit;
+ }
+ if (RAND_bytes(salt, PKCS5_SALT_LEN) == 0) {
+ fprintf(stderr, "Error generating salt key\n");
+ status = EXIT_FAILURE;
+ goto _exit;
+ }
+
+ msg(verbose,
+ "creating dm-crypt device for %s using %s (%d bit key)\n",
+ device, fs_cipher, fs_keylen * 8);
+ if (!dry_run)
+ if (run_cryptsetup
+ (fs_cipher, DMCRYPT_TMP_PREFIX, device, uuid_str, fs_key,
+ fs_keylen) == 0) {
+ status = EXIT_FAILURE;
+ goto _exit;
+ }
+
+ msg(verbose, "creating %s filesystem\n", fs_type);
+ if (!dry_run)
+ if (run_mkfs(uuid_str, fs_type) == 0) {
+ status = EXIT_FAILURE;
+ goto _exit;
+ }
+
+ msg(verbose, "appending %s onto random key\n", MAGICTAIL);
+ memcpy(fs_key + fs_keylen, MAGICTAIL, strlen(MAGICTAIL));
+
+ msg(verbose, "looking up real key cipher for %s\n", key_cipher);
+ if (cipher_lookup(real_key_cipher, key_cipher) == NULL) {
+ fprintf(stderr, "Do not recognize %s\n", key_cipher);
+ status = EXIT_FAILURE;
+ goto _exit;
+ }
+
+ msg(verbose, "encrypting key using %s and passphrase\n",
+ real_key_cipher);
+ if (crypt_it
+ (efs_key, &efs_keylen, fs_key, fs_keylen + strlen(MAGICTAIL),
+ real_key_cipher, passphrase, salt, salt_write,
+ EVP_EncryptInit_ex, EVP_EncryptUpdate,
+ EVP_EncryptFinal_ex) == 0) {
+ fprintf(stderr, "Cannot encrypt key\n");
+ status = EXIT_FAILURE;
+ goto _exit;
+ }
+
+ /* FIXME: what about LUKS? */
+ msg(verbose, "storing sesame data on %s\n", device);
+ if (!dry_run) {
+ /* FIXME */
+ }
+
+ msg(verbose, "uuid is %s\n", uuid_str);
+ msg(verbose, "encrypted key is %s\n",
+ encode(buf, efs_key, efs_keylen));
+
+ msg(verbose, "removing temporary dm-crypt device\n");
+ if (!dry_run)
+ if (run_cryptunsetup (DMCRYPT_TMP_PREFIX, device,
+ uuid_str) == 0) {
+ status = EXIT_FAILURE;
+ goto _exit;
+ }
+
+ msg(verbose, "re-initializing dm-crypt device for hald\n");
+ if (!dry_run) {
+ if (run_cryptsetup
+ (fs_cipher, DMCRYPT_PREFIX, device, uuid_str, fs_key,
+ fs_keylen) == 0) {
+ status = EXIT_FAILURE;
+ goto _exit;
+ }
+ }
+
+ _exit:
+ exit(status);
+}
Binary files sesame-cvs-vanilla/tools/sesame-format.o and sesame-cvs/tools/sesame-format.o differ
diff -u --recursive --new-file sesame-cvs-vanilla/tools/sesame-is-encrypted.c sesame-cvs/tools/sesame-is-encrypted.c
--- sesame-cvs-vanilla/tools/sesame-is-encrypted.c 1969-12-31 18:00:00.000000000 -0600
+++ sesame-cvs/tools/sesame-is-encrypted.c 2005-01-19 13:45:43.409283816 -0600
@@ -0,0 +1,157 @@
+
+#define _GNU_SOURCE
+
+#include <assert.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include "common.h"
+/* FIXME: what about LUKS? */
+#include "../libsesame/libsesame.h"
+
+static int verbose = 0;
+static char *device = NULL;
+
+static void print_usage(const int exitcode, const char *error,
+ const char *more)
+{
+ if (error)
+ assert(more);
+
+ fprintf(stderr, "sesame-is-encrypted [options] device\n\n"
+ "-h, --help\n"
+ " print a list of options\n\n"
+ "-v, --verbose\n" " verbose display of messages\n\n");
+
+ if (error)
+ fprintf(stderr, "%s: %s\n", error, more);
+
+ exit(exitcode);
+}
+
+int main(int argc, char *argv[])
+{
+ int c, opt_index = 0, status = EXIT_SUCCESS;
+ char buf[1024];
+ int fd_metadata;
+ struct option opts[] = {
+ {"help", 0, 0, 'h'},
+ {"verbose", 0, 0, 'v'},
+ {0, 0, 0, 0}
+ };
+ SesameMetaData *md;
+ const char *uuid, *enc_key, *enc_key_cipher, *block_key_cipher,
+ *block_key_sha1;
+
+ while ((c = getopt_long(argc, argv, "hv", opts, &opt_index)) >= 0) {
+ switch (c) {
+ case 'h':
+ print_usage(EXIT_SUCCESS, NULL, NULL);
+ case 'v':
+ verbose = 1;
+ break;
+ default:
+ print_usage(EXIT_FAILURE, NULL, NULL);
+ }
+ }
+
+ if (argv[optind] == NULL)
+ print_usage(EXIT_FAILURE, NULL, NULL);
+ device = argv[optind];
+
+ msg(verbose, "opening %s\n", device);
+ fd_metadata = open(device, O_RDONLY);
+ if (fd_metadata == -1) {
+ fprintf(stderr, "Cannot open %s, err=%s\n", device,
+ strerror(errno));
+ goto _exit;
+ }
+
+ msg(verbose, "reading from %s\n", device);
+ if (read(fd_metadata, buf, sizeof(buf)) == -1) {
+ fprintf(stderr, "Cannot read from %s, err=%s\n",
+ device, strerror(errno));
+ status = EXIT_FAILURE;
+ goto _exit_close;
+ }
+
+ /* FIXME: what about LUKS? */
+ msg(verbose, "parsing metadata\n");
+ md = sesame_get_metadata_from_buf(buf);
+ if (md == NULL) {
+ fprintf(stderr, "Cannot not parse metadata\n");
+ status = EXIT_FAILURE;
+ goto _exit_close;
+ }
+
+ /* FIXME: what about LUKS? */
+ msg(verbose, "getting uuid\n");
+ uuid = sesame_get(md, "uuid");
+ if (uuid == NULL) {
+ fprintf(stderr, "Cannot read uuid from %s\n", device);
+ status = EXIT_FAILURE;
+ goto _exit_free;
+ }
+
+ /* FIXME: what about LUKS? */
+ msg(verbose, "getting enc_key\n");
+ enc_key = sesame_get(md, "enc_key");
+ if (enc_key == NULL) {
+ fprintf(stderr, "Cannot read enc_key from %s\n", device);
+ status = EXIT_FAILURE;
+ goto _exit_free;
+ }
+
+ /* FIXME: what about LUKS? */
+ msg(verbose, "getting enc_key_cipher\n");
+ enc_key_cipher = sesame_get(md, "enc_key_cipher");
+ if (enc_key == NULL) {
+ fprintf(stderr, "Cannot read enc_key_cipher from %s\n",
+ device);
+ status = EXIT_FAILURE;
+ goto _exit_free;
+ }
+
+ /* FIXME: what about LUKS? */
+ msg(verbose, "getting block_key_cipher\n");
+ block_key_cipher = sesame_get(md, "block_key_cipher");
+ if (block_key_cipher == NULL) {
+ fprintf(stderr, "Cannot read block_key_cipher from %s\n",
+ device);
+ status = EXIT_FAILURE;
+ goto _exit_free;
+ }
+
+ /* FIXME: what about LUKS? */
+ msg(verbose, "getting block_key_sha1\n");
+ block_key_sha1 = sesame_get(md, "block_key_sha1");
+ if (block_key_sha1 == NULL) {
+ fprintf(stderr, "Cannot read block_key_sha1 from %s\n",
+ device);
+ status = EXIT_FAILURE;
+ goto _exit_free;
+ }
+
+ _exit_free:
+ msg(verbose, "freeing memory\n");
+ /* FIXME: what about LUKS? */
+ sesame_free(md);
+
+ _exit_close:
+ close(fd_metadata);
+
+ _exit:
+ if (status == EXIT_SUCCESS)
+ fprintf(stdout, "Device %s seems to be encrypted\n",
+ device);
+ else
+ fprintf(stdout, "Device %s does not seem to be encrypted\n",
+ device);
+ exit(status);
+}
Binary files sesame-cvs-vanilla/tools/sesame-is-encrypted.o and sesame-cvs/tools/sesame-is-encrypted.o differ
diff -u --recursive --new-file sesame-cvs-vanilla/tools/sesame-setup.c sesame-cvs/tools/sesame-setup.c
--- sesame-cvs-vanilla/tools/sesame-setup.c 2004-12-31 07:35:47.000000000 -0600
+++ sesame-cvs/tools/sesame-setup.c 2005-01-19 13:00:18.000000000 -0600
@@ -2,6 +2,7 @@
#define _GNU_SOURCE
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
@@ -13,20 +14,17 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
-#include <openssl/ssl.h>
-#include <openssl/evp.h>
-#include <openssl/err.h>
#ifndef EVP_MAX_BLOCK_LENGTH
#define EVP_MAX_BLOCK_LENGTH 32 /* some older openssl versions need this */
#endif
+#include "common.h"
+/* FIXME: what about LUKS? */
#include "../libsesame/libsesame.h"
-#define MAGICTAIL "SESAME0"
-
-int verbose = 0;
-char *device = NULL;
+static int verbose = 0;
+static char *device = NULL;
static void print_usage(const int exitcode, const char *error,
const char *more)
@@ -44,250 +42,19 @@
exit(exitcode);
}
-static void sslerror(const char *msg)
-{
- assert(msg);
-
- unsigned long err = ERR_get_error();
- if (err != 0)
- fprintf(stderr, "%s: %s", msg,
- ERR_error_string(err, NULL));
-}
-
-static int hash_authtok(const char *data, const EVP_CIPHER * const cipher,
- const char *const authtok,
- unsigned char *const hash, unsigned char *const iv)
-{
- const EVP_MD *md;
- unsigned char salt[PKCS5_SALT_LEN];
-
- assert(data != NULL);
- assert(cipher != NULL); /* FIXME: is cipher is valid OpenSSL cipher? */
- assert(authtok != NULL);
- assert(hash != NULL); /* FIXME: check hash is big enough? */
- assert(iv != NULL); /* FIXME: check iv is big enough? */
-
- if (memcmp(data, "Salted__", sizeof "Salted__" - 1) != 0) {
- fprintf(stderr, "magic string Salted__ not in stream\n");
- return 0;
- }
- memcpy(salt, data + sizeof "Salted__" - 1, PKCS5_SALT_LEN);
- md = EVP_md5();
- if (EVP_BytesToKey
- (cipher, md, salt, authtok, strlen(authtok), 1,
- hash, iv) <= 0) {
- fprintf(stderr, "failed to hash passphrase");
- return 0;
- }
-
- return 1;
-}
-
-static int
-decrypt(char *const out, size_t * const out_len,
- const char *const in, const size_t in_len,
- const char *const cipher_name, const char *const authtok)
-{
- int ret = 1;
- int segment_len;
- size_t data_len;
- const char *data;
- unsigned char hashed_authtok[EVP_MAX_KEY_LENGTH];
- unsigned char iv[EVP_MAX_IV_LENGTH];
- const EVP_CIPHER *cipher;
- EVP_CIPHER_CTX ctx;
-
- assert(out != NULL);
- assert(out_len != NULL);
- assert(cipher_name != NULL);
- assert(in != NULL);
- assert(authtok != NULL);
-
- memset(out, 0x00, BUFSIZ + EVP_MAX_BLOCK_LENGTH);
- OpenSSL_add_all_ciphers();
- EVP_CIPHER_CTX_init(&ctx);
- SSL_load_error_strings();
- if (!(cipher = EVP_get_cipherbyname(cipher_name))) {
- fprintf(stderr, "error getting cipher \"%s\"\n", (const char *)cipher);
- ret = 0;
- goto _return;
- }
- if (hash_authtok(in, cipher, authtok, hashed_authtok, iv) == 0) {
- ret = 0;
- goto _return;
- }
- if (EVP_DecryptInit_ex(&ctx, cipher, NULL, hashed_authtok, iv) ==
- 0) {
- sslerror("failed to initialize decryption code");
- ret = 0;
- goto _return;
- }
- data = in + (sizeof "Salted__" - 1) + PKCS5_SALT_LEN;
- data_len = in_len - (sizeof "Salted__" - 1) - PKCS5_SALT_LEN;
- /* assumes plaintexts is always <= ciphertext + EVP_MAX_BLOCK_LEN in length
- * OpenSSL's documentation seems to promise this */
- if (EVP_DecryptUpdate
- (&ctx, out, &segment_len, data, data_len) == 0) {
- sslerror("failed to decrypt key");
- ret = 0;
- goto _return;
- }
- *out_len = segment_len;
- if (EVP_DecryptFinal_ex(&ctx, &out[*out_len], &segment_len) == 0) {
- sslerror
- ("bad pad on end of encrypted file (wrong algorithm or key size?)");
- ret = 0;
- goto _return;
- }
- *out_len += segment_len;
- _return:
- if (EVP_CIPHER_CTX_cleanup(&ctx) == 0) {
- sslerror("error cleaning up cipher context");
- ret = 0;
- }
-
- ERR_free_strings();
- /* out_len is unsigned */
- assert(ret == 0 || *out_len <= BUFSIZ + EVP_MAX_BLOCK_LENGTH);
-
- return ret;
-}
-
-static unsigned char *decode(char *data)
-{
- size_t i;
- unsigned char *decoded =
- (char *) malloc((strlen(data) / 2) * sizeof(char));
- if (decoded == NULL)
- return NULL;
- for (i = 0; i < strlen(data); i += 2) {
- decoded[i / 2] =
- isdigit(data[i]) ? (data[i] - 48) << 4 : (data[i] -
- 87) << 4;
- decoded[i / 2] +=
- isdigit(data[i + 1]) ? data[i + 1] - 48 : data[i + 1] -
- 87;
- }
- return decoded;
-}
-
-static char *strip_cr(char *s)
-{
- int len;
-
- assert(s);
-
- len = strlen(s);
- s[len - 1] = s[len - 1] == '\n' ? 0x00 : s[len - 1];
-
- return s;
-}
-
-static int read_key(char *buf, int size)
-{
- int fnval = 1;
-
- assert(buf);
- assert(size > 0);
-
- if (fgets(buf, size, stdin) == NULL) {
- fnval = 0;
- goto _return;
- }
-
- strip_cr(buf);
-
- _return:
- return fnval;
-}
-
-static void msg(const char *format, ...)
-{
- assert(format != NULL);
-
- if (verbose) {
- /* Used to log issues that cause pam_mount to fail. */
- va_list args;
-
- va_start(args, format);
- vfprintf(stdout, format, args);
- va_end(args);
- }
-}
-
-static int run_cryptsetup(const char *block_key_cipher, const char *device,
- const char *uuid, const char *key,
- const int key_len)
-{
- pid_t child;
- int fnval = 1, pipefd[2], child_exit;
- char dmname[PATH_MAX + 1], *key_len_str;
-
- assert(block_key_cipher != NULL);
- assert(device != NULL);
- assert(uuid != NULL);
- assert(key != NULL);
- assert(key_len > 0);
-
- if (asprintf(&key_len_str, "%d", key_len) == -1) {
- fprintf(stderr, "Failed to allocate memory, err=%s\n",
- strerror(errno));
- fnval = 0;
- goto _return_no_free;
- }
-
- strcpy(dmname, "sesame_crypto_");
- strncat(dmname, uuid, sizeof dmname - strlen(dmname));
-
- if (pipe(pipefd) == -1) {
- fprintf(stderr, "Failed to create pipe, err=%s\n",
- strerror(errno));
- fnval = 0;
- goto _return;
- }
-
- child = fork();
-
- if (child < 0) {
- fprintf(stderr, "Failed to fork, err=%s\n",
- strerror(errno));
- fnval = 0;
- goto _return;
- } else if (child == 0) {
- close(0);
- dup(pipefd[0]);
- close(pipefd[0]);
- close(pipefd[1]);
- execl(CRYPTSETUP, "cryptsetup", "-s", key_len_str, "-c",
- block_key_cipher, "create", dmname, device, NULL);
- fprintf(stderr, "Failed to execute %s, err=%s\n",
- CRYPTSETUP, strerror(errno));
- exit(EXIT_FAILURE);
- } else {
- close(pipefd[0]);
- write(pipefd[1], key, key_len);
- close(pipefd[1]);
- waitpid(child, &child_exit, 0);
- fnval = !WEXITSTATUS(child_exit);
- goto _return;
- }
-
- _return:
- free(key_len_str);
- _return_no_free:
- return fnval;
-}
-
int main(int argc, char *argv[])
{
- int c, opt_index = 0;
+ int c, opt_index = 0, status = EXIT_SUCCESS;
char passphrase[BUFSIZ + 1];
- char dec_key[BUFSIZ + EVP_MAX_KEY_LENGTH];
+ char salt[PKCS5_SALT_LEN];
+ char dec_key[BUFSIZ + EVP_MAX_BLOCK_LENGTH];
+ char codebuf[BUFSIZ + 1];
int dec_key_len, real_dec_key_len;
char buf[1024];
int fd_metadata;
const char *uuid, *enc_key, *enc_key_cipher, *block_key_cipher,
*block_key_sha1;
+ char real_key_cipher[BUFSIZ + 1];
struct option opts[] = {
{"help", 0, 0, 'h'},
{"verbose", 0, 0, 'v'},
@@ -311,99 +78,129 @@
print_usage(EXIT_FAILURE, NULL, NULL);
device = argv[optind];
- msg("opening %s\n", device);
+ msg(verbose, "opening %s\n", device);
fd_metadata = open(device, O_RDONLY);
if (fd_metadata == -1) {
fprintf(stderr, "Cannot open %s, err=%s\n", device,
strerror(errno));
- goto error;
+ goto _exit;
}
- msg("reading from %s\n", device);
+ msg(verbose, "reading from %s\n", device);
if (read(fd_metadata, buf, sizeof(buf)) == -1) {
fprintf(stderr, "Cannot read from %s, err=%s\n",
device, strerror(errno));
- goto error1;
+ status = EXIT_FAILURE;
+ goto _exit_close;
}
- msg("parsing metadata\n");
+ /* FIXME: what about LUKS? */
+ msg(verbose, "parsing metadata\n");
md = sesame_get_metadata_from_buf(buf);
if (md == NULL) {
fprintf(stderr, "Cannot not parse metadata\n");
- goto error1;
+ status = EXIT_FAILURE;
+ goto _exit_close;
}
- msg("getting uuid\n");
+ /* FIXME: what about LUKS? */
+ msg(verbose, "getting uuid\n");
uuid = sesame_get(md, "uuid");
if (uuid == NULL) {
fprintf(stderr, "Cannot read uuid from %s\n", device);
- goto error2;
+ status = EXIT_FAILURE;
+ goto _exit_free;
}
- msg("getting enc_key\n");
+ /* FIXME: what about LUKS? */
+ msg(verbose, "getting enc_key\n");
enc_key = sesame_get(md, "enc_key");
if (enc_key == NULL) {
fprintf(stderr, "Cannot read enc_key from %s\n", device);
- goto error2;
+ status = EXIT_FAILURE;
+ goto _exit_free;
}
- msg("getting enc_key_cipher\n");
+ /* FIXME: what about LUKS? */
+ msg(verbose, "getting enc_key_cipher\n");
enc_key_cipher = sesame_get(md, "enc_key_cipher");
if (enc_key == NULL) {
fprintf(stderr, "Cannot read enc_key_cipher from %s\n",
device);
- goto error2;
+ status = EXIT_FAILURE;
+ goto _exit_free;
}
- msg("getting block_key_cipher\n");
+ /* FIXME: what about LUKS? */
+ msg(verbose, "getting block_key_cipher\n");
block_key_cipher = sesame_get(md, "block_key_cipher");
if (block_key_cipher == NULL) {
fprintf(stderr, "Cannot read block_key_cipher from %s\n",
device);
- goto error2;
+ status = EXIT_FAILURE;
+ goto _exit_free;
}
- msg("getting block_key_sha1\n");
+ /* FIXME: what about LUKS? */
+ msg(verbose, "getting block_key_sha1\n");
block_key_sha1 = sesame_get(md, "block_key_sha1");
if (block_key_sha1 == NULL) {
fprintf(stderr, "Cannot read block_key_sha1 from %s\n",
device);
- goto error2;
+ status = EXIT_FAILURE;
+ goto _exit_free;
}
if (read_key(passphrase, BUFSIZ) == 0) {
fprintf(stderr, "Could not read key\n");
- goto error2;
+ status = EXIT_FAILURE;
+ goto _exit_free;
}
- msg("decrypting key using passphrase\n");
- if (decrypt
- (dec_key, &dec_key_len, decode(enc_key), strlen(enc_key) / 2,
- enc_key_cipher, passphrase) == 0) {
+ msg(verbose, "looking up real key cipher for %s\n", enc_key_cipher);
+ if (cipher_lookup(real_key_cipher, enc_key_cipher) == NULL) {
+ fprintf(stderr, "Do not recognize %s\n", enc_key_cipher);
+ status = EXIT_FAILURE;
+ goto _exit_free;
+ }
+
+ msg(verbose, "decrypting key using %s and passphrase\n",
+ enc_key_cipher);
+ if (crypt_it
+ (dec_key, &dec_key_len, decode(codebuf, enc_key), strlen(enc_key) / 2,
+ real_key_cipher, passphrase, salt, salt_read, EVP_DecryptInit_ex,
+ EVP_DecryptUpdate, EVP_DecryptFinal_ex) == 0) {
fprintf(stderr, "Cannot decrypt key\n");
- goto error2;
+ status = EXIT_FAILURE;
+ goto _exit_free;
}
- msg("checking for MAGICTAIL tail in key\n");
+ msg(verbose, "checking for %s tail in key\n", MAGICTAIL);
real_dec_key_len = dec_key_len - strlen(MAGICTAIL);
if (memcmp
(dec_key + real_dec_key_len, MAGICTAIL, strlen(MAGICTAIL))) {
fprintf(stderr, "Key does not end in %s\n", MAGICTAIL);
- goto error2;
- }
-
- msg("executing cryptsetup\n");
- if (run_cryptsetup(block_key_cipher, device, uuid, dec_key,
- real_dec_key_len) == 0) {
- goto error2;
- }
-
-error2:
- msg("freeing memory\n");
+ fprintf(stderr, "Last bytes are %s\n", encode(codebuf, dec_key + real_dec_key_len, strlen(MAGICTAIL)));
+ fprintf(stderr, "Should be %s\n", encode(codebuf, MAGICTAIL, strlen(MAGICTAIL)));
+ status = EXIT_FAILURE;
+ goto _exit_free;
+ }
+
+ msg(verbose, "executing cryptsetup\n");
+ if (run_cryptsetup(block_key_cipher, DMCRYPT_PREFIX, device, uuid,
+ dec_key, real_dec_key_len) == 0) {
+ status = EXIT_FAILURE;
+ goto _exit_free;
+ }
+
+_exit_free:
+ msg(verbose, "freeing memory\n");
+ /* FIXME: what about LUKS? */
sesame_free(md);
-error1:
+_exit_close:
close(fd_metadata);
-error:
- return 0;
+
+_exit:
+ exit(status);
}
Binary files sesame-cvs-vanilla/tools/sesame-setup.o and sesame-cvs/tools/sesame-setup.o differ
Binary files sesame-cvs-vanilla/tools/test-crypto and sesame-cvs/tools/test-crypto differ
diff -u --recursive --new-file sesame-cvs-vanilla/tools/test-crypto.c sesame-cvs/tools/test-crypto.c
--- sesame-cvs-vanilla/tools/test-crypto.c 1969-12-31 18:00:00.000000000 -0600
+++ sesame-cvs/tools/test-crypto.c 2005-01-01 14:29:54.000000000 -0600
@@ -0,0 +1,126 @@
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <string.h>
+#include <getopt.h>
+#include <assert.h>
+
+#ifndef EVP_MAX_BLOCK_LENGTH
+#define EVP_MAX_BLOCK_LENGTH 32 /* some older openssl versions need this */
+#endif
+
+#include "common.h"
+
+char *plaintext = "abcdefghijklmnopqrstuvwxyz";
+char *passphrase = "passphrase";
+char *cipher = "aes";
+int keylen = 128;
+char *salt = "aaaaaaaa";
+
+static void print_usage(const int exitcode, const char *error,
+ const char *more)
+{
+ if (error)
+ assert(more);
+
+ fprintf(stderr, "sesame-setup [options] device\n\n"
+ "-h, --help\n"
+ " print a list of options\n\n"
+ "-p, --plaintext text\n"
+ " plaintext to use for test [%s]\n\n"
+ "-w, --passphrase pass\n"
+ " passphrase to use for test [%s]\n\n"
+ "-c, --cipher cipher\n"
+ " cipher used for test [%s]\n\n"
+ "-k, --keylen length\n"
+ " length in bits of encryption key [%d]\n\n"
+ "-s, --salt str\n"
+ " salt to use for test [%d]\n\n",
+ plaintext, passphrase, cipher, keylen, salt);
+
+ if (error)
+ fprintf(stderr, "%s: %s\n", error, more);
+
+ exit(exitcode);
+}
+
+int main(int argc, char *argv[])
+{
+ int c, opt_index = 0, status = EXIT_SUCCESS;
+ char pt[BUFSIZ + EVP_MAX_BLOCK_LENGTH];
+ char ct[BUFSIZ + EVP_MAX_BLOCK_LENGTH];
+ char real_cipher[BUFSIZ + 1];
+ int pt_len, ct_len;
+ struct option opts[] = {
+ {"help", 0, 0, 'h'},
+ {"plaintext", 1, 0, 'v'},
+ {"passphrase", 1, 0, 'w'},
+ {"cipher", 1, 0, 'c'},
+ {"keylen", 1, 0, 'k'},
+ {"salt", 1, 0, 's'},
+ {0, 0, 0, 0}
+ };
+
+ while ((c =
+ getopt_long(argc, argv, "hp:w:c:k:", opts, &opt_index))
+ >= 0) {
+ switch (c) {
+ case 'h':
+ print_usage(EXIT_SUCCESS, NULL, NULL);
+ case 'p':
+ plaintext = optarg;
+ break;
+ case 'w':
+ passphrase = optarg;
+ break;
+ case 'c':
+ cipher = optarg;
+ break;
+ case 'k':
+ keylen = optarg;
+ break;
+ case 's':
+ salt = optarg;
+ break;
+ default:
+ print_usage(EXIT_FAILURE, NULL, NULL);
+ }
+ }
+
+ if (strlen(plaintext) >= BUFSIZ + EVP_MAX_BLOCK_LENGTH) {
+ fprintf(stderr, "%s is too long\n", plaintext);
+ status = EXIT_FAILURE;
+ goto _exit;
+ }
+
+ if (strlen(salt) != PKCS5_SALT_LEN) {
+ fprintf(stderr, "salt must be %d bytes\n", PKCS5_SALT_LEN);
+ status = EXIT_FAILURE;
+ goto _exit;
+ }
+
+ if (cipher_lookup(real_cipher, cipher) == NULL) {
+ fprintf(stderr, "Do not recognize %s\n", cipher);
+ status = EXIT_FAILURE;
+ goto _exit;
+ }
+
+ fprintf(stdout, "original plaintext is: %s\n", plaintext);
+ if (encrypt_it(ct, &ct_len, plaintext, strlen(plaintext),
+ salt, real_cipher, passphrase) == 0) {
+ fprintf(stderr, "failed to encrypt %s\n", plaintext);
+ status = EXIT_FAILURE;
+ goto _exit;
+ }
+ fprintf(stdout, "ciphertext is %s\n", encode(ct, ct_len));
+ if (decrypt_it(pt, &pt_len, ct, ct_len, real_cipher,
+ passphrase) == 0) {
+ fprintf(stderr, "failed to decrypt %s\n", encode(ct, ct_len));
+ status = EXIT_FAILURE;
+ goto _exit;
+ }
+ fprintf(stdout, "decrypted plaintext is: %s\n", pt);
+
+_exit:
+ exit(status);
+}
-------------- next part --------------
_______________________________________________
hal mailing list
hal at lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/hal
More information about the Hal
mailing list