sesame/tools Getopt.java, NONE, 1.1 GnomeSesameFormat.java, NONE, 1.1 LongOpt.java, NONE, 1.1 Makefile.am, 1.3, 1.4 check_common.c, NONE, 1.1 common.c, NONE, 1.1 common.h, NONE, 1.1 sesame-format.c, NONE, 1.1 sesame-is-encrypted.c, NONE, 1.1 sesame-setup.c, 1.2, 1.3 test-crypto.c, NONE, 1.1

David Zeuthen david at freedesktop.org
Mon Feb 7 13:52:18 PST 2005


Update of /cvs/hal/sesame/tools
In directory gabe:/tmp/cvs-serv27744/tools

Modified Files:
	Makefile.am sesame-setup.c 
Added Files:
	Getopt.java GnomeSesameFormat.java LongOpt.java check_common.c 
	common.c common.h sesame-format.c sesame-is-encrypted.c 
	test-crypto.c 
Log Message:
2005-01-26  W. Michael Petullo  <mike at flyn.org>

	* tools/*.c: Major overhaul to use LUKS instead of the proposed
	sesame encrypted header.

	* tools/GnomeSesameFormat.java: Implemented a GUI tool that can
	format a device as a LUKS device.

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.



--- NEW FILE: Getopt.java ---
/**************************************************************************
/* Getopt.java -- Java port of GNU getopt from glibc 2.0.6
/*
/* Copyright (c) 1987-1997 Free Software Foundation, Inc.
/* Java Port Copyright (c) 1998 by Aaron M. Renn (arenn at urbanophile.com)
/*
/* This program is free software; you can redistribute it and/or modify
/* it under the terms of the GNU Library General Public License as published 
/* by  the Free Software Foundation; either version 2 of the License or
/* (at your option) any later version.
/*
/* This program is distributed in the hope that it will be useful, but
/* WITHOUT ANY WARRANTY; without even the implied warranty of
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
/* GNU Library General Public License for more details.
/*
/* You should have received a copy of the GNU Library General Public License
/* along with this program; see the file COPYING.LIB.  If not, write to 
/* the Free Software Foundation Inc., 59 Temple Place - Suite 330, 
[...1271 lines suppressed...]
                  // Don't permute as we do on -- up above since we
                  // know we aren't in permute mode because of Posix.
                  optarg = argv[optind];
                  ++optind;
                  first_nonopt = optind;
                  last_nonopt = argv.length;
                  endparse = true;
                }
            }

          nextchar = null;
        }
    }

  return(c);
}

} // Class Getopt



--- NEW FILE: GnomeSesameFormat.java ---
//   FILE: GnomeSesameFormat.java -- A GUI for sesame-format
// AUTHOR: W. Michael Petullo <mike at flyn.org>
//   DATE: 26 January 2005

// Copyright (C) 2005 W. Michael Petullo <mike at flyn.org>
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

import java.io.IOException;
import java.io.FileNotFoundException;
import java.io.File;
import java.io.DataOutputStream;

import java.lang.Runtime;
import java.lang.Process;
import java.lang.System;
import java.lang.InterruptedException;

// import gnu.getopt.Getopt;
// import gnu.getopt.LongOpt;

import org.gnu.glade.LibGlade;
import org.gnu.gtk.Gtk;
import org.gnu.gtk.Button;
import org.gnu.gtk.CheckButton;
import org.gnu.gtk.Entry;
import org.gnu.gtk.Label;
import org.gnu.gtk.ProgressBar;
import org.gnu.gtk.Window;
import org.gnu.gtk.FileSelection;
import org.gnu.gtk.event.GtkEvent;
import org.gnu.pango.FontDescription;

interface Cipher {
	public String name();
	public int keyBitCount();
}

class AES256 implements Cipher {
	public String name() { return "aes"; }
	public int keyBitCount() { return 256; }
}

class AES128 implements Cipher {
	public String name() { return "aes"; }
	public int keyBitCount() { return 128; }
}

interface FS {
	public String name();
}

class Ext3 implements FS {
	public String name() { return "ext3"; }
}

class Ext2 implements FS {
	public String name() { return "ext2"; }
}

class ProgressBarUpdater extends Thread {
	boolean stop;
	ProgressBar progressBar;

	private ProgressBarUpdater() {};

	ProgressBarUpdater(ProgressBar p) {
		stop = false;
		progressBar = p;
	}

	public void run() {
		while (stop == false) {
			while (Gtk.eventsPending()) {
				Gtk.mainIteration();
			}
			progressBar.pulse();
			try {
				Thread.sleep(100);
			} catch (java.lang.InterruptedException e) {}
		}
	}

	void stopReq() {
		stop = true;
	}
}

public class GnomeSesameFormat {
	private LibGlade glade;

	private boolean dryRun;
	private Cipher cipher;
	private FS fs;
	private String passphrase;
	private String volName;
	private String device;

	private Window topLevel;
	private FileSelection devSelUI;
	private Window errUI;
	private Window progressUI;

	public void init() throws IOException {
	        glade = new LibGlade(System.getProperty("GLADE_FILE"), this);

		dryRun = false;
		cipher = new AES256();
		fs = new Ext3();
		passphrase = null;
		volName = null;

		topLevel = (Window) glade.getWidget("topLevel");
		devSelUI = (FileSelection) glade.getWidget("devSelUI");
		errUI = (Window) glade.getWidget("errUI");
		progressUI = (Window) glade.getWidget("progressUI");
	}

	public GnomeSesameFormat() throws IOException {
		init();
		device = null;

		Label l = (Label) glade.getWidget("displayedDevice");
		l.setText("none selected");
	}

	public GnomeSesameFormat(String d) throws IOException {
		init();
		device = d;

		Label l = (Label) glade.getWidget("labelDevice");
		l.setSensitive(false);

		Button b = (Button) glade.getWidget("buttonOpen");
		b.setSensitive(false);

		l = (Label) glade.getWidget("displayedDevice");
		l.setText(d);
		l.setSensitive(false);
	}

	public void onTopLevelDeleteEvent(GtkEvent event) {
		Gtk.mainQuit();
		System.exit(0);
	}

	public void onAES128Activate(GtkEvent event) {
		cipher = new AES128();
	}

	public void onAES256Activate(GtkEvent event) {
		cipher = new AES256();
	}

	public void onExt2Activate(GtkEvent event) {
		fs = new Ext2();
	}

	public void onExt3Activate(GtkEvent event) {
		fs = new Ext3();
	}

	public void onCloseButtonClicked(GtkEvent event) {
		Gtk.mainQuit();
		System.exit(0);
	}

	public void onHelpButtonClicked(GtkEvent event) {
		// FIXME
	}

	public void onFormatButtonClicked(GtkEvent event) {
		Entry entry;
		
		entry = (Entry) glade.getWidget("entryPassphrase");
		passphrase = entry.getText();

		entry = (Entry) glade.getWidget("entryVolumeName");
		volName = entry.getText();

		if (device == null)
			error("Device not selected");
		else if (passphrase.equals(""))
			error("Passphrase not entered");
		else if (volName.equals(""))
			error("Volume name not entered");
		else {
			ProgressBar p = (ProgressBar) 
				glade.getWidget("progressBarFormat");
			Label l = (Label) glade.getWidget("labelFormat");
			ProgressBarUpdater pU = new ProgressBarUpdater(p);

			topLevel.setSensitive(false);
			progressUI.show();

			if (! dryRun) {
				l.setText("Formatting " + device);	
				pU.start();
				execSesameFormat();
				pU.stopReq();
				try {
					pU.join();
				} catch (java.lang.InterruptedException e) {}
			} else {
				l.setText("[Simulated] Formatting " + device);	
				pU.start();
				try {
					Thread.sleep(1000);
				} catch (java.lang.InterruptedException e) {}
				pU.stopReq();
				try {
					pU.join();
				} catch (java.lang.InterruptedException e) {}
			}

			progressUI.hide();
			topLevel.setSensitive(true);
		}
	}

	public void onOpenButtonClicked(GtkEvent event) {
		topLevel.setSensitive(false);
		devSelUI.show();
	}

	public void onErrOkButtonClicked(GtkEvent event) {
		errUI.hide();
		topLevel.setSensitive(true);
	}

	public void onDevSelOkButtonClicked(GtkEvent event) {
		String tmp = devSelUI.getFilename();
		if (! new File (tmp).exists())
			error("Device " + tmp + " does not exist");
		else {
			device = tmp;

			Label l = (Label) glade.getWidget("displayedDevice");
			l.setText(device);

			devSelUI.hide();
			topLevel.setSensitive(true);
		}
	}

	public void onDevSelCancelButtonClicked(GtkEvent event) {
		devSelUI.hide();
		topLevel.setSensitive(true);
	}

	private String getSesameFormatPath() throws SecurityException, 
	                 NullPointerException, IllegalArgumentException {
		return System.getProperty("SESAME_FORMAT");
	}

	private void execSesameFormat() {
		CheckButton c = (CheckButton) glade.getWidget
		                              ("checkButtonBadBlocks");

		StringBuffer cmd = new StringBuffer();
		String progpath = "";

		if (! dryRun) try {
			progpath = getSesameFormatPath();

			cmd.append(progpath);
			cmd.append(" --fs-type=");
			cmd.append(fs.name());
			cmd.append(" --fs-cipher=");
			cmd.append(cipher.name());
			cmd.append(" --fs-keylen=");
			cmd.append(cipher.keyBitCount());
			cmd.append(" ");
			if (c.getState()) {
				cmd.append("-c");
				cmd.append(" ");
			}
			cmd.append("--volume-name=");
			cmd.append(volName);
			cmd.append(" ");
			cmd.append(device);

System.out.println(cmd);
			Process p = Runtime.getRuntime().exec(cmd.toString());

			DataOutputStream o = new DataOutputStream(p.getOutputStream());

			o.writeBytes(passphrase);
			o.close();

			if (p.waitFor() != 0)
				throw new InterruptedException ();

		} catch (SecurityException e) {
			error("Could not find sesame-format");
		} catch (NullPointerException e) {
			error("Could not find sesame-format");
		} catch (IllegalArgumentException e) {
			error("Could not find sesame-format");
		} catch (IOException e) {
			error("Error executing " + progpath);
		} catch (InterruptedException e) {
			error("Error executing " + progpath);
		} 
	}

	private void error(String msg) {
		Label l = (Label) glade.getWidget("labelErr");
		l.setText(msg);
		topLevel.setSensitive(false);
		errUI.show();
	}

	private void setDryRun(boolean setting) {
		dryRun = setting;
	}

	private static void printUsage(int status, String error, String more) {
		System.err.println("gnome-sesame-setup [options] [device]\n\n" +
		  "-h, --help\n" +
		  "      print a list of options\n\n" +
		  "-d, --dry-run\n" +
		  "      do not actually perform any operations on device\n");
		if (error != null)
			System.err.println(error + ": " + more);
		System.exit(status);
	}

	private static void main() {}

	public static void main(String args[]) {
		GnomeSesameFormat gui;

		Gtk.init(args);

		LongOpt[] longOpt = new LongOpt[2];
		longOpt[0] = new LongOpt("help", LongOpt.NO_ARGUMENT, null, 
					 'h');
		longOpt[1] = new LongOpt("dry-run", LongOpt.NO_ARGUMENT, null,
					 'd');

		Getopt g = new Getopt("gnome-sesame-format", args, "hd", 
				      longOpt);
		
		int c;
		boolean argDryRun = false;
		while ((c = g.getopt()) != -1)
			switch (c) {
			case 'h':
				printUsage(0, null, null);
			case 'd':
				argDryRun = true;
				break;
			default:
				printUsage(1, null, null);
		}

		try {
			int i = g.getOptind();
			if (i < args.length)
				gui = new GnomeSesameFormat(args[i]);
			else
				gui = new GnomeSesameFormat();
			gui.setDryRun(argDryRun);
		} catch (Exception e) {
			System.err.println(e);
			System.exit(1);
		}

		Gtk.main();
	}

}

--- NEW FILE: LongOpt.java ---
/**************************************************************************
/* LongOpt.java -- Long option object for Getopt
/*
/* Copyright (c) 1998 by Aaron M. Renn (arenn at urbanophile.com)
/*
/* This program is free software; you can redistribute it and/or modify
/* it under the terms of the GNU Library General Public License as published 
/* by  the Free Software Foundation; either version 2 of the License or
/* (at your option) any later version.
/*
/* This program is distributed in the hope that it will be useful, but
/* WITHOUT ANY WARRANTY; without even the implied warranty of
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
/* GNU Library General Public License for more details.
/*
/* You should have received a copy of the GNU Library General Public License
/* along with this program; see the file COPYING.LIB.  If not, write to 
/* the Free Software Foundation Inc., 59 Temple Place - Suite 330, 
/* Boston, MA  02111-1307 USA
/**************************************************************************/

import java.util.Locale;
import java.util.ResourceBundle;
import java.util.PropertyResourceBundle;
import java.text.MessageFormat;

/**************************************************************************/

/**
  * This object represents the definition of a long option in the Java port
  * of GNU getopt.  An array of LongOpt objects is passed to the Getopt
  * object to define the list of valid long options for a given parsing
  * session.  Refer to the getopt documentation for details on the
  * format of long options.
  * 
  * @version 1.0.5
  * @author Aaron M. Renn (arenn at urbanophile.com)
  *
  * @see Getopt
  */
public class LongOpt extends Object
{

/**************************************************************************/

/*
 * Class Variables
 */

/**
  * Constant value used for the "has_arg" constructor argument.  This
  * value indicates that the option takes no argument.
  */
public static final int NO_ARGUMENT = 0;

/** 
  * Constant value used for the "has_arg" constructor argument.  This
  * value indicates that the option takes an argument that is required.
  */
public static final int REQUIRED_ARGUMENT = 1;

/**
  * Constant value used for the "has_arg" constructor argument.  This
  * value indicates that the option takes an argument that is optional.
  */
public static final int OPTIONAL_ARGUMENT = 2;

/**************************************************************************/

/*
 * Instance Variables
 */

/**
  * The name of the long option
  */
protected String name;

/**
  * Indicates whether the option has no argument, a required argument, or
  * an optional argument.
  */
protected int has_arg;

/**
  * If this variable is not null, then the value stored in "val" is stored
  * here when this long option is encountered.  If this is null, the value
  * stored in "val" is treated as the name of an equivalent short option.
  */
protected StringBuffer flag;

/**
  * The value to store in "flag" if flag is not null, otherwise the
  * equivalent short option character for this long option.
  */
protected int val;

/**
  * Localized strings for error messages
  */
/*private ResourceBundle _messages = PropertyResourceBundle.getBundle(
                            "gnu/getopt/MessagesBundle", Locale.getDefault());
			    */

/**************************************************************************/

/*
 * Constructors
 */

/**
  * Create a new LongOpt object with the given parameter values.  If the
  * value passed as has_arg is not valid, then an exception is thrown.
  *
  * @param name The long option String.
  * @param has_arg Indicates whether the option has no argument (NO_ARGUMENT), a required argument (REQUIRED_ARGUMENT) or an optional argument (OPTIONAL_ARGUMENT).
  * @param flag If non-null, this is a location to store the value of "val" when this option is encountered, otherwise "val" is treated as the equivalent short option character.
  * @param val The value to return for this long option, or the equivalent single letter option to emulate if flag is null.
  * 
  * @exception IllegalArgumentException If the has_arg param is not one of NO_ARGUMENT, REQUIRED_ARGUMENT or OPTIONAL_ARGUMENT.
  */
public
LongOpt(String name, int has_arg, 
        StringBuffer flag, int val) throws IllegalArgumentException
{
  // Validate has_arg
  if ((has_arg != NO_ARGUMENT) && (has_arg != REQUIRED_ARGUMENT) 
     && (has_arg != OPTIONAL_ARGUMENT))
    {
      Object[] msgArgs = { new Integer(has_arg).toString() };
      throw new IllegalArgumentException();
    }

  // Store off values
  this.name = name;
  this.has_arg = has_arg;
  this.flag = flag;
  this.val = val;
}

/**************************************************************************/

/**
  * Returns the name of this LongOpt as a String
  *
  * @return Then name of the long option
  */
public String
getName()
{
  return(name);
}

/**************************************************************************/

/**
  * Returns the value set for the 'has_arg' field for this long option
  *
  * @return The value of 'has_arg'
  */
public int
getHasArg()
{
  return(has_arg);
}

/**************************************************************************/

/**
  * Returns the value of the 'flag' field for this long option
  *
  * @return The value of 'flag'
  */
public StringBuffer
getFlag()
{
  return(flag);
}

/**
  * Returns the value of the 'val' field for this long option
  *
  * @return The value of 'val'
  */
public int
getVal()
{
  return(val);
}

/**************************************************************************/

} // Class LongOpt


Index: Makefile.am
===================================================================
RCS file: /cvs/hal/sesame/tools/Makefile.am,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- Makefile.am	31 Dec 2004 13:35:47 -0000	1.3
+++ Makefile.am	7 Feb 2005 21:52:16 -0000	1.4
@@ -1,16 +1,52 @@
 
 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
+
+bin_PROGRAMS = gnome-sesame-format
+
+# Remove Getopt.java and LongOpt.java from here and delete files once
+# Build vs. /usr/share/java/gnu.getopt.jar
+# Link vs. ???
+# uncomment imports in GnomeSesameFormat.java
+# Fedora RPM ships without -lgnu.getopt.
+gnome_sesame_format_SOURCES = GnomeSesameFormat.java Getopt.java LongOpt.java
 
 # Add @PACKAGE_LIBS@ if using pkg-config packages; see configure.in
-sesame_setup_LDADD = $(top_builddir)/libsesame/libsesame.la
+sesame_format_LDADD = $(GLIB_LIBS)
+
+# FIXME: need to implement proper Java autoconf/automake
+gnome_sesame_format_LDFLAGS = --main=GnomeSesameFormat -DSESAME_FORMAT="$(SBINDIR)/sesame-format" -DGLADE_FILE="$(DATADIR)/sesame/GnomeSesameFormat.glade"
+gnome_sesame_format_LDADD = -lgtkjar2.4 -lgnomejar2.8 -lgladejar2.8
+AM_GCJFLAGS = --CLASSPATH=.:/usr/share/java/gtk2.4.jar:/usr/share/java/gnome2.8.jar:/usr/share/java/glade2.8.jar
+
+sesamedir = $(pkgdatadir)
+sesame_DATA = GnomeSesameFormat.glade
+
+EXTRA_DIST = GnomeSesameFormat.glade
+
+AM_CFLAGS = $(GLIB_CFLAGS) -Werror
 
 clean-local :
 	rm -f *~

--- NEW FILE: check_common.c ---
#include <stdlib.h>
#include <check.h>
#include <string.h>
#include <common.h>

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

static Suite *common_suite(void)
{
	Suite *s = suite_create("common");

	TCase *tc_strip_cr = tcase_create("test_strip_cr");

	tcase_add_test(tc_strip_cr, test_strip_cr);

	suite_add_tcase(s, tc_strip_cr);

	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;
}

--- NEW FILE: common.c ---
#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 <errno.h>
#include <stdarg.h>

#include "common.h"

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_luksInit(const char *block_key_cipher,
			    const char *device,
			    const char *passphrase, const int key_len)
{
	pid_t child;
	int fnval = 1, pipefd[2], child_exit;
	char *key_len_str;

	assert(block_key_cipher != NULL);
	assert(device != NULL);
	assert(passphrase != 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;
	}

	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, "luksInit", device, NULL);
		fprintf(stderr, "Failed to execute %s, err=%s\n",
			CRYPTSETUP, strerror(errno));
		exit(EXIT_FAILURE);
	} else {
		close(pipefd[0]);
		write(pipefd[1], passphrase, strlen(passphrase));
		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_cryptsetup_luksOpen(const char *prefix, const char *device,
			    const char *passphrase)
{
	pid_t child;
	int fnval = 1, pipefd[2], child_exit;
	char uuid[UUIDLEN + 1], dmname[PATH_MAX + 1];

	assert(prefix != NULL);
	assert(device != NULL);
	assert(passphrase != NULL);

	/* FIXME: read UUID from LUKS header */
	strcpy(uuid, "FIXME");

	strncpy(dmname, 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));

	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", "luksOpen", device, dmname, 
		      NULL);
		fprintf(stderr, "Failed to execute %s, err=%s\n",
			CRYPTSETUP, strerror(errno));
		exit(EXIT_FAILURE);
	} else {
		close(pipefd[0]);
		write(pipefd[1], passphrase, strlen(passphrase));
		close(pipefd[1]);
		waitpid(child, &child_exit, 0);
		fnval = !WEXITSTATUS(child_exit);
		goto _return;
	}

      _return:
	return fnval;
}

int run_cryptunsetup(const char *prefix, const char *device)
{
	pid_t child;
	int fnval = 1, child_exit;
	char dmname[PATH_MAX + 1], uuid[UUIDLEN + 1];

	assert(prefix != NULL);
	assert(device != NULL);
	assert(uuid != NULL);

	/* FIXME: read UUID from LUKS header */
	strcpy(uuid, "FIXME");

	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;
}

--- NEW FILE: common.h ---
#define DMCRYPT_PREFIX "sesame_crypto_"
#define DMCRYPT_TMP_PREFIX "sesame_crypto_tmp_"
#define DMDIR "/dev/mapper/"
#define UUIDLEN 36

char *strip_cr(char *s);
int read_key(char *buf, int size);
void msg(int verbose, const char *format, ...);
int run_cryptsetup_luksInit(const char *block_key_cipher, const char *device,
			    const char *passphrase, const int key_len);
int run_cryptsetup_luksOpen(const char *prefix, const char *device,
                            const char *passphrase);
int run_cryptunsetup(const char *prefix, const char *device);

--- NEW FILE: sesame-format.c ---

#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 <uuid/uuid.h>

#include "common.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 int do_check = 0;
static char *device = NULL;
static char *volume_name = "Untitled";

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"
		"-l, --fs-keylen length\n"
		"	length in bits of encryption key	[%d]\n\n"
		"-n, --volume-name name\n"
		"	set the name of the filesystem		[%s]\n\n"
		"-k, --check\n"
		"	check device for bad blocks		[%s]\n\n",
		fs_type, fs_cipher, fs_keylen * 8, volume_name,
		do_check ? "on" : "off");

	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 *fs_type, int check)
{
	pid_t pid;
	GError *err = NULL;
	char dmname[PATH_MAX + 1];
	int fnval = 1, child_exit, pstderr = -1, nargv = 5;
	const char *argv[] = { MKFS, "-t", fs_type, "-L", volume_name, 
	                       NULL, NULL, NULL };
	char uuid[UUIDLEN + 1];

	assert(fs_type);

	if (check)
		argv[nargv++] = "-c";
		

	/* FIXME: read UUID from LUKS header */
	strcpy(uuid, "FIXME");
	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[nargv++] = 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[])
{
	char passphrase[BUFSIZ + 1];
	int c, opt_index = 0, status = EXIT_SUCCESS;
	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'},
		{"volume-name", 1, 0, 'n'},
		{"check", 1, 0, 'k'},
		{0, 0, 0, 0}
	};

	while ((c =
		getopt_long(argc, argv, "hvdt:c:l:n: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 'n':
			volume_name = optarg;
			break;
		case 'k':
			do_check = 1;
			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, "randomizing %s\n", device);
	if (run_randomize(device) == 0) {
		status = EXIT_FAILURE;
		goto _exit;
	}

	msg(verbose, "initializing LUKS on %s using %s (%d bit key)\n",
	    device, fs_cipher, fs_keylen * 8);
	if (!dry_run)
		if (run_cryptsetup_luksInit
		    (fs_cipher, device, passphrase, fs_keylen) == 0) {
			status = EXIT_FAILURE;
			goto _exit;
		}

	msg(verbose, "setting up dmcrypt device\n");
	if (!dry_run)
		if (run_cryptsetup_luksOpen
		    (DMCRYPT_TMP_PREFIX, device, passphrase) == 0) {
			status = EXIT_FAILURE;
			goto _exit;
		}

	msg(verbose, "creating %s filesystem\n", fs_type);
	if (!dry_run)
		if (run_mkfs(fs_type, do_check) == 0) {
			status = EXIT_FAILURE;
			goto _exit;
		}

	msg(verbose, "removing temporary dm-crypt device\n");
	if (!dry_run)
		if (run_cryptunsetup(DMCRYPT_TMP_PREFIX, device) == 0) {
			status = EXIT_FAILURE;
			goto _exit;
		}

	msg(verbose, "re-initializing dm-crypt device for hald\n");
	if (!dry_run) {
		if (run_cryptsetup_luksOpen
		    (DMCRYPT_PREFIX, device, passphrase) == 0) {
			status = EXIT_FAILURE;
			goto _exit;
		}
	}

      _exit:
	exit(status);
}

--- NEW FILE: sesame-is-encrypted.c ---

#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 <stdlib.h>

#include "common.h"

int main () { return 0; }
/*
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];
	struct option opts[] = {
		{"help", 0, 0, 'h'},
		{"verbose", 0, 0, 'v'},
		{0, 0, 0, 0}
	};
	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;
	}

	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;
	}

	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;
	}

	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;
	}

	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;
	}

	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;
	}

	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");
	sesame_free(md);

      _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);
}
*/

Index: sesame-setup.c
===================================================================
RCS file: /cvs/hal/sesame/tools/sesame-setup.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- sesame-setup.c	31 Dec 2004 13:35:47 -0000	1.2
+++ sesame-setup.c	7 Feb 2005 21:52:16 -0000	1.3
@@ -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,11 @@
 #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 "../libsesame/libsesame.h"
 
-#define MAGICTAIL "SESAME0"
+#include "common.h"
 
-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,256 +36,15 @@
 	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];
-	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;
 	struct option opts[] = {
 		{"help", 0, 0, 'h'},
 		{"verbose", 0, 0, 'v'},
 		{0, 0, 0, 0}
 	};
-	SesameMetaData *md;
 
 	while ((c = getopt_long(argc, argv, "hv", opts, &opt_index)) >= 0) {
 		switch (c) {
@@ -311,99 +62,19 @@
 		print_usage(EXIT_FAILURE, NULL, NULL);
 	device = argv[optind];
 
-	msg("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;
-	}
-
-	msg("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;
-	}
-
-	msg("parsing metadata\n");
-	md = sesame_get_metadata_from_buf(buf);
-	if (md == NULL) {
-		fprintf(stderr, "Cannot not parse metadata\n");
-		goto error1;
-	}
-
-	msg("getting uuid\n");
-	uuid = sesame_get(md, "uuid");
-	if (uuid == NULL) {
-		fprintf(stderr, "Cannot read uuid from %s\n", device);
-		goto error2;
-	}
-
-	msg("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;
-	}
-
-	msg("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;
-	}
-
-	msg("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;
-	}
-
-	msg("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;
-	}
-
 	if (read_key(passphrase, BUFSIZ) == 0) {
 		fprintf(stderr, "Could not read key\n");
-		goto error2;
-	}
-
-	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) {
-		fprintf(stderr, "Cannot decrypt key\n");
-		goto error2;
-	}
-
-	msg("checking for MAGICTAIL tail in key\n");
-	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;
+		status = EXIT_FAILURE;
+		goto _exit;
 	}
 
-	msg("executing cryptsetup\n");
-	if (run_cryptsetup(block_key_cipher, device, uuid, dec_key,
-			   real_dec_key_len) == 0) {
-		goto error2;
+	msg(verbose, "executing cryptsetup\n");
+	if (run_cryptsetup_luksOpen(DMCRYPT_PREFIX, device, passphrase) ==
+	    0) {
+		status = EXIT_FAILURE;
+		goto _exit;
 	}
 
-error2:
-	msg("freeing memory\n");
-	sesame_free(md);
-
-error1:
-	close(fd_metadata);
-error:
-	return 0;
+      _exit:
+	exit(status);
 }

--- NEW FILE: test-crypto.c ---
#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);
}




More information about the hal-commit mailing list