Skip to content

Commit

Permalink
Added cli to unlock the YubiHSM from commandline on power up.
Browse files Browse the repository at this point in the history
  • Loading branch information
Ratler committed Aug 9, 2011
1 parent 43b01fe commit 22c2d09
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 3 deletions.
5 changes: 5 additions & 0 deletions pom.xml
Expand Up @@ -75,6 +75,11 @@
<version>2.2pre2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>1.2</version>
</dependency>
</dependencies>

<build>
Expand Down
100 changes: 100 additions & 0 deletions src/main/java/org/unitedid/yhsm/YubiHSM.java
Expand Up @@ -18,11 +18,13 @@

package org.unitedid.yhsm;

import org.apache.commons.cli.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.unitedid.yhsm.internal.*;

import java.util.Map;
import java.util.Scanner;

/** <code>YubiHSM</code> */

Expand All @@ -36,6 +38,9 @@ public class YubiHSM {
/** The hash length, default is 20 */
public static int minHashLength = 20;

/** Debug output */
private static boolean debug = false;

/**
* Constructor
*
Expand Down Expand Up @@ -431,4 +436,99 @@ public int getMinHashLength() {
public void setMinHashLength(int value) {
minHashLength = value;
}

/**
* Print usage information when running from command line.
*
* @param options the option definitions
*/
public static void printUsage(Options options) {
HelpFormatter help = new HelpFormatter();
help.setWidth(80);
help.printHelp("[-D <device>] [OPTION]...", "", options, "");
}

/**
* Prompts for HSM key storage password on the command line.
*
* @param deviceName the YubiHSM device name (ex /dev/ttyACM0)
*/
public static void runUnlock(String deviceName) {
try {
YubiHSM hsm = new YubiHSM(deviceName, 1);

String password;
Scanner in = new Scanner(System.in);
System.out.print("Please enter HSM password: ");
password = in.nextLine();
in.close();

if (hsm.keyStorageUnlock(password)) {
System.out.println("YubiHSM " + deviceName + " was successfully unlocked.");
} else {
System.out.println("Unlock failed, bad password.");
}
} catch (YubiHSMCommandFailedException e) {
System.out.println("Unlock command failed with the reason: " + e.getMessage());
} catch (YubiHSMInputException e) {
System.out.println("Invalid input. Password has to be in hex format.");
if (debug) {
System.out.println(e);
}
} catch (NumberFormatException e) {
System.out.println("Invalid input. Password has to be in hex format.");
} catch (YubiHSMErrorException e) {
System.out.println("An error has occurred: " + e.getMessage());
}
}

/**
* Main method.
*
* @param args the command arguments
*/
public static void main(String[] args) {
CommandLineParser parser = new PosixParser();
Options options = new Options();
options.addOption("h", "help", false, "This usage information");
options.addOption("d", "debug", false, "Debug output");
options.addOption("D", "device", true, "YubiHSM device name, default is /dev/ttyACM0");
options.addOption("u", "unlock-hsm", false, "Unlock YubiHSM key storage");

if (args.length < 1) {
printUsage(options);
System.exit(0);
}

/* Defaults */
String deviceName = "/dev/ttyACM0";

try {
CommandLine cmdLine = parser.parse(options, args);

if (cmdLine.hasOption("h")) {
printUsage(options);
System.exit(0);
}

if (cmdLine.hasOption("d")) {
debug = true;
}

if (cmdLine.hasOption("D")) {
deviceName = cmdLine.getOptionValue("D");
}

if (cmdLine.hasOption("u")) {
runUnlock(deviceName);
} else {
printUsage(options);
}
} catch (org.apache.commons.cli.ParseException e) {
System.out.println("Bad command arguments.");
printUsage(options);
System.exit(1);
}
System.exit(0);
}
}
1 change: 1 addition & 0 deletions src/main/java/org/unitedid/yhsm/internal/Defines.java
Expand Up @@ -118,6 +118,7 @@ private Defines() {}
final static public byte YSM_STATUS_OK = (byte) 0x80;
final static public byte YSM_RESPONSE = (byte) 0x80;
final static public byte YSM_MISMATCH = (byte) 0x8b;
final static public byte YSM_KEY_STORAGE_LOCKED = (byte) 0x8a;


final public static String getCommandString(byte b) {
Expand Down
Expand Up @@ -36,7 +36,8 @@ private KeyStorageUnlockCmd() {}
* @throws YubiHSMCommandFailedException command failed exception
*/
public static boolean execute(DeviceHandler device, String password) throws YubiHSMErrorException, YubiHSMInputException, YubiHSMCommandFailedException {
byte[] passwordBA = Utils.validateByteArray("password", Utils.hexToByteArray(password), Defines.YSM_BLOCK_SIZE, 0, Defines.YSM_BLOCK_SIZE);
byte[] pw = Utils.hexToByteArray(password);
byte[] passwordBA = Utils.validateByteArray("password", pw, Defines.YSM_BLOCK_SIZE, 0, Defines.YSM_BLOCK_SIZE);
return parseResult(CommandHandler.execute(device, Defines.YSM_KEY_STORAGE_UNLOCK, passwordBA, true));
}

Expand All @@ -50,6 +51,8 @@ public static boolean execute(DeviceHandler device, String password) throws Yubi
private static boolean parseResult(byte[] result) throws YubiHSMCommandFailedException {
if (result[0] == Defines.YSM_STATUS_OK) {
return true;
} else if (result[0] == Defines.YSM_KEY_STORAGE_LOCKED) {
return false;
} else {
throw new YubiHSMCommandFailedException("Command " + Defines.getCommandString(Defines.YSM_KEY_STORAGE_UNLOCK) + " failed: " + Defines.getCommandStatus(result[0]));
}
Expand Down
Expand Up @@ -25,6 +25,7 @@
import org.junit.rules.ExpectedException;
import org.unitedid.yhsm.SetupCommon;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

public class KeyStorageUnlockTest extends SetupCommon {
Expand All @@ -44,8 +45,7 @@ public void tearDown() throws Exception {

@Test
public void failedUnlockHsm() throws YubiHSMCommandFailedException, YubiHSMErrorException, YubiHSMInputException {
thrown.expect(YubiHSMCommandFailedException.class);
hsm.keyStorageUnlock("aabb");
assertFalse(hsm.keyStorageUnlock("1111"));
}

@Test
Expand Down

0 comments on commit 22c2d09

Please sign in to comment.