Skip to content

Commit

Permalink
tpm2_password_util: add from optarg handler
Browse files Browse the repository at this point in the history
Add a routine for replacing the remaining tpm2_password_util
routines. The new routine will be used to handle optarg
directly, and avoid the need of the -X argument.

Also add tests.

Signed-off-by: William Roberts <william.c.roberts@intel.com>
  • Loading branch information
William Roberts committed Aug 16, 2017
1 parent c15d5f6 commit a6e3a5e
Show file tree
Hide file tree
Showing 4 changed files with 203 additions and 1 deletion.
7 changes: 6 additions & 1 deletion Makefile.am
Expand Up @@ -176,7 +176,8 @@ check_PROGRAMS = \
test/unit/test_tpm2_header \
test/unit/test_tpm2_nv_util \
test/unit/test_tpm2_alg_util \
test/unit/test_pcr
test/unit/test_pcr \
test/unit/test_tpm2_password_util

test_unit_tpm2_rc_decode_unit_CFLAGS = $(AM_CFLAGS) $(CMOCKA_CFLAGS)
test_unit_tpm2_rc_decode_unit_LDADD = $(CMOCKA_LIBS) $(LIB_COMMON)
Expand Down Expand Up @@ -211,6 +212,10 @@ test_unit_test_pcr_CFLAGS = $(AM_CFLAGS) $(CMOCKA_CFLAGS)
test_unit_test_pcr_LDADD = $(CMOCKA_LIBS) $(LIB_COMMON)
test_unit_test_pcr_SOURCES = test/unit/test_pcr.c

test_unit_test_tpm2_password_util_CFLAGS = $(AM_CFLAGS) $(CMOCKA_CFLAGS)
test_unit_test_tpm2_password_util_LDADD = $(CMOCKA_LIBS) $(LIB_COMMON)
test_unit_test_tpm2_password_util_SOURCES = test/unit/test_tpm2_password_util.c

endif

EXTRA_DIST = $(top_srcdir)/man
Expand Down
45 changes: 45 additions & 0 deletions lib/tpm2_password_util.c
Expand Up @@ -6,8 +6,53 @@
#include "tpm2_password_util.h"
#include "tpm2_util.h"

#define HEX_PREFIX "hex:"
#define HEX_PREFIX_LEN sizeof(HEX_PREFIX) - 1

#define STR_PREFIX "str:"
#define STR_PREFIX_LEN sizeof(STR_PREFIX) - 1

#define PASSWORD_MAX (sizeof(((TPM2B_DIGEST *)NULL)->t.buffer))

bool tpm2_password_util_from_optarg(const char *password, TPM2B_AUTH *dest) {

bool is_hex = !strncmp(password, HEX_PREFIX, HEX_PREFIX_LEN);
if (!is_hex) {

/* str may or may not have the str: prefix */
bool is_str_prefix = !strncmp(password, STR_PREFIX, STR_PREFIX_LEN);
if (is_str_prefix) {
password += STR_PREFIX_LEN;
}

/*
* Per the man page:
* "a return value of size or more means that the output was truncated."
*/
size_t wrote = snprintf((char *)&dest->t.buffer, BUFFER_SIZE(typeof(*dest), buffer), "%s", password);
if (wrote >= BUFFER_SIZE(typeof(*dest), buffer)) {
dest->t.size = 0;
return false;
}

dest->t.size = wrote;

return true;
}

/* if it is hex, then skip the prefix */
password += HEX_PREFIX_LEN;

dest->t.size = BUFFER_SIZE(typeof(*dest), buffer);
int rc = tpm2_util_hex_to_byte_structure(password, &dest->t.size, dest->t.buffer);
if (rc) {
dest->t.size = 0;
return false;
}

return true;
}

bool tpm2_password_util_fromhex(TPM2B_AUTH *password, bool is_hex, const char *description,
TPM2B_AUTH *auth) {

Expand Down
30 changes: 30 additions & 0 deletions lib/tpm2_password_util.h
Expand Up @@ -37,4 +37,34 @@ bool tpm2_password_util_fromhex(TPM2B_AUTH *password, bool is_hex, const char *d
*/
bool tpm2_password_util_copy_password(const char *password, const char *description, TPM2B_AUTH *dest);

/**
* Convert a password argument to a valid TPM2B_AUTH structure. Passwords can
* be specified in two forms: string and hex-string and are identified by a
* prefix of str: and hex: respectively. No prefix assumes the str form.
*
* For example, a string can be specified as:
* "1234"
* "str:1234"
*
* And a hexstring via:
* "hex:1234abcd"
*
* Strings are copied verbatim to the TPM2B_AUTH buffer without the terminating NULL byte,
* Hex strings differ only from strings in that they are converted to a byte array when
* storing. At the end of storing, the size field is set to the size of bytes of the
* password.
*
* If your password starts with a hex: prefix and you need to escape it, just use the string
* prefix to escape it, like so:
* "str:hex:password"
*
* @param password
* The optarg containing the password string.
* @param dest
* The TPM2B_AUTH structure to copy the string into.
* @return
* true on success, false on failure.
*/
bool tpm2_password_util_from_optarg(const char *password, TPM2B_AUTH *dest);

#endif /* SRC_PASSWORD_UTIL_H_ */
122 changes: 122 additions & 0 deletions test/unit/test_tpm2_password_util.c
@@ -0,0 +1,122 @@
//**********************************************************************;
// Copyright (c) 2017, Intel Corporation
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
// THE POSSIBILITY OF SUCH DAMAGE.
//**********************************************************************;
#include <errno.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <setjmp.h>

#include <cmocka.h>
#include <sapi/tpm20.h>

#include "tpm2_util.h"
#include "tpm2_password_util.h"

static void test_tpm2_password_util_from_optarg_raw_noprefix(void **state) {
(void)state;

TPM2B_AUTH dest;
bool res = tpm2_password_util_from_optarg("abcd", &dest);
assert_true(res);
assert_int_equal(dest.t.size, 4);
assert_memory_equal(dest.t.buffer, "abcd", 4);
}

static void test_tpm2_password_util_from_optarg_str_prefix(void **state) {
(void)state;

TPM2B_AUTH dest;
bool res = tpm2_password_util_from_optarg("str:abcd", &dest);
assert_true(res);
assert_int_equal(dest.t.size, 4);
assert_memory_equal(dest.t.buffer, "abcd", 4);
}

static void test_tpm2_password_util_from_optarg_hex_prefix(void **state) {
(void)state;

TPM2B_AUTH dest;
BYTE expected[] = {
0x12, 0x34, 0xab, 0xcd
};

bool res = tpm2_password_util_from_optarg("hex:1234abcd", &dest);
assert_true(res);
assert_int_equal(dest.t.size, sizeof(expected));
assert_memory_equal(dest.t.buffer, expected, sizeof(expected));
}

static void test_tpm2_password_util_from_optarg_str_escaped_hex_prefix(void **state) {
(void)state;

TPM2B_AUTH dest;

bool res = tpm2_password_util_from_optarg("str:hex:1234abcd", &dest);
assert_true(res);
assert_int_equal(dest.t.size, 12);
assert_memory_equal(dest.t.buffer, "hex:1234abcd", 12);
}

static void test_tpm2_password_util_from_optarg_raw_overlength(void **state) {
(void)state;

TPM2B_AUTH dest;
char *overlength = "this_password_is_over_64_characters_in_length_and_should_fail_XXX";
bool res = tpm2_password_util_from_optarg(overlength, &dest);
assert_false(res);
}

static void test_tpm2_password_util_from_optarg_hex_overlength(void **state) {
(void)state;

TPM2B_AUTH dest;
/* 65 hex chars generated via: echo \"`xxd -p -c256 -l65 /dev/urandom`\"\; */
char *overlength =
"ae6f6fa01589aa7b227bb6a34c7a8e0c273adbcf14195ce12391a5cc12a5c271f62088"
"dbfcf1914fdf120da183ec3ad6cc78a2ffd91db40a560169961e3a6d26bf";
bool res = tpm2_password_util_from_optarg(overlength, &dest);
assert_false(res);
}

int main(int argc, char* argv[]) {
(void)argc;
(void)argv;

const struct CMUnitTest tests[] = {
cmocka_unit_test(test_tpm2_password_util_from_optarg_raw_noprefix),
cmocka_unit_test(test_tpm2_password_util_from_optarg_str_prefix),
cmocka_unit_test(test_tpm2_password_util_from_optarg_hex_prefix),
cmocka_unit_test(test_tpm2_password_util_from_optarg_str_escaped_hex_prefix),

/* negative testing */
cmocka_unit_test(test_tpm2_password_util_from_optarg_raw_overlength),
cmocka_unit_test(test_tpm2_password_util_from_optarg_hex_overlength),
};

return cmocka_run_group_tests(tests, NULL, NULL);
}

0 comments on commit a6e3a5e

Please sign in to comment.