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