Skip to content

Commit

Permalink
Add option to specify CKA_ID in generate-keypair and import-object
Browse files Browse the repository at this point in the history
Signed-off-by: Zoltan Fridrich <[email protected]>
  • Loading branch information
ZoltanFridrich committed Jan 8, 2024
1 parent 304db35 commit 5d9c43b
Show file tree
Hide file tree
Showing 9 changed files with 288 additions and 21 deletions.
4 changes: 4 additions & 0 deletions common/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ c_tests += \
test-hash \
test-dict \
test-array \
test-hex \
test-constants \
test-attrs \
test-buffer \
Expand All @@ -93,6 +94,9 @@ test_argv_LDADD = $(common_LIBS)
test_array_SOURCES = common/test-array.c
test_array_LDADD = $(common_LIBS)

test_hex_SOURCES = common/test-hex.c
test_hex_LDADD = $(common_LIBS)

test_attrs_SOURCES = common/test-attrs.c
test_attrs_LDADD = $(common_LIBS)

Expand Down
56 changes: 55 additions & 1 deletion common/hex.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,12 @@
*/

#include "config.h"

#include "debug.h"
#include "hex.h"
#include <stdint.h>

#include <stdlib.h>
#include <string.h>

static const char HEXC_LOWER[] = "0123456789abcdef";

Expand All @@ -48,6 +51,8 @@ hex_encode (const unsigned char *data,
size_t i;
size_t o;

return_val_if_fail (data != NULL, NULL);

if ((SIZE_MAX - 1) / 3 < n_data)
return NULL;
result = malloc (n_data * 3 + 1);
Expand All @@ -64,3 +69,52 @@ hex_encode (const unsigned char *data,
result[o] = 0;
return result;
}

unsigned char *
hex_decode (const char *hex,
size_t *bin_len)
{
int i, j;
size_t len, hex_len;
unsigned char n, c;
unsigned char *bin;

return_val_if_fail (hex != NULL, NULL);
return_val_if_fail (bin_len != NULL, NULL);

hex_len = strlen (hex);
return_val_if_fail (SIZE_MAX - 1 >= hex_len, NULL);
return_val_if_fail ((hex_len + 1) % 3 == 0, NULL);

len = (hex_len + 1) / 3;
bin = malloc (len);
if (bin == NULL)
return NULL;

for (i = 0; i < len; ++i) {
for (j = 0, n = 0; j < 2; ++j) {
c = hex[i * 3 + j];
if ('0' <= c && c <= '9')
n |= c - '0';
else if ('a' <= c && c <= 'f')
n |= c - 'a' + 10;
else if ('A' <= c && c <= 'F')
n |= c - 'A' + 10;
else {
free (bin);
return NULL;
}
if (j == 0)
n <<= 4;
}
c = hex[2 + i * 3];
if (c != ':' && c != '\0') {
free (bin);
return NULL;
}
bin[i] = n;
}

*bin_len = len;
return bin;
}
9 changes: 7 additions & 2 deletions common/hex.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,12 @@

#include <stddef.h>

char *hex_encode (const unsigned char *data,
size_t n_data);
char *
hex_encode (const unsigned char *data,
size_t n_data);

unsigned char *
hex_decode (const char *hex,
size_t *bin_len);

#endif /* P11_HEX_H */
1 change: 1 addition & 0 deletions common/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ if get_option('test')
'test-hash',
'test-dict',
'test-array',
'test-hex',
'test-constants',
'test-attrs',
'test-buffer',
Expand Down
96 changes: 96 additions & 0 deletions common/test-hex.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* Copyright (c) 2024, Red Hat Inc.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
* * 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.
* * The names of contributors to this software may not be
* used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 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 OWNER 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.
*
* Author: Zoltan Fridrich <[email protected]>
*/

#include "config.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "hex.h"
#include "test.h"

#define assert_mem_eq(a1, a2, n) \
do { const char *__s1 = (a1); \
const char *__s2 = (a2); \
if (__s1 && __s2 && memcmp (__s1, __s2, n) == 0) ; else \
p11_test_fail (__FILE__, __LINE__, __FUNCTION__, "assertion failed"); \
} while (0)

static void
assert_encode_eq (const char *out,
const char *in,
size_t in_len)
{
char *hex = hex_encode ((const unsigned char *)in, in_len);
assert_str_eq (out, hex);
free (hex);
}

static void
assert_decode_eq (const char *out,
size_t out_len,
const char *in)
{
size_t bin_len = 0;
char *bin = (char *)hex_decode (in, &bin_len);
assert_num_eq (out_len, bin_len);
assert_mem_eq (out, bin, bin_len);
free (bin);
}

static void
test_encode (void)
{
assert_encode_eq ("3a:bc:f6:9a", "\x3a\xbc\xf6\x9a", 4);
}

static void
test_decode (void)
{
assert_decode_eq ("\x3a\xbc\xf6\x9a", 4, "3a:bc:f6:9a");
assert_decode_eq ("\x3a\xbc\xf6\x9a", 4, "3a:Bc:F6:9A");
assert_decode_eq ("\x3a\xbc\xf6\x9a", 4, "3A:BC:F6:9A");
}

int
main (int argc,
char *argv[])
{
p11_test (test_encode, "/hex/encode");
p11_test (test_decode, "/hex/decode");
return p11_test_run (argc, argv);
}
12 changes: 10 additions & 2 deletions doc/manual/p11-kit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ $ <command>pkg-config p11-kit-1 --variable p11_module_path</command>
<para>Import object into PKCS#11 token.</para>

<programlisting>
$ p11-kit import-object --file=file.pem &lsqb;--label=label&rsqb; pkcs11:token
$ p11-kit import-object --file=file.pem &lsqb;--label=label&rsqb; &lsqb;--id=object_id&rsqb; pkcs11:token
</programlisting>

<para>Takes either an X.509 certificate or a public key in the form of a PEM file
Expand All @@ -199,6 +199,10 @@ $ p11-kit import-object --file=file.pem &lsqb;--label=label&rsqb; pkcs11:token
<term><option>--label=&lt;label&gt;</option></term>
<listitem><para>Assigns label to the imported object.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--id=&lt;object_id&gt;</option></term>
<listitem><para>Assigns ID to the imported object. The ID should be specified in hexadecimal format without '0x' prefix.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--login</option></term>
<listitem><para>Authenticate to the token before enumerating objects. The PIN value is read from either the <literal>pin-value</literal> attribute in the URI or from the terminal.</para></listitem>
Expand Down Expand Up @@ -276,7 +280,7 @@ $ <command>pkg-config p11-kit-1 --variable p11_module_path</command>
<para>Generate key-pair on a PKCS#11 token.</para>

<programlisting>
$ p11-kit generate-keypair --type=algorithm &lcub;--bits=n|--curve=name&rcub; &lsqb;--label=label&rsqb; pkcs11:token
$ p11-kit generate-keypair --type=algorithm &lcub;--bits=n|--curve=name&rcub; &lsqb;--label=label&rsqb; &lsqb;--id=object_id&rsqb; pkcs11:token
</programlisting>

<para>Generate private-public key-pair of given type on the first
Expand Down Expand Up @@ -311,6 +315,10 @@ $ p11-kit generate-keypair --type=algorithm &lcub;--bits=n|--curve=name&rcub; &l
<term><option>--label=&lt;label&gt;</option></term>
<listitem><para>Assigns label to the generated key-pair objects.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--id=&lt;object_id&gt;</option></term>
<listitem><para>Assigns ID to the generated key-pair objects. The ID should be specified in hexadecimal format without '0x' prefix.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--login</option></term>
<listitem><para>Authenticate to the token before enumerating objects. The PIN value is read from either the <literal>pin-value</literal> attribute in the URI or from the terminal.</para></listitem>
Expand Down
46 changes: 43 additions & 3 deletions p11-kit/generate-keypair.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "attrs.h"
#include "compat.h"
#include "debug.h"
#include "hex.h"
#include "iter.h"
#include "message.h"
#include "options.h"
Expand Down Expand Up @@ -160,6 +161,7 @@ check_args (CK_MECHANISM_TYPE type,

static bool
get_templates (const char *label,
const char *id,
CK_MECHANISM_TYPE type,
CK_ULONG bits,
const uint8_t *ec_params,
Expand Down Expand Up @@ -207,6 +209,36 @@ get_templates (const char *label,
priv = tmp;
}

if (id != NULL) {
size_t bin_len = 0;
unsigned char *bin = NULL;
CK_ATTRIBUTE attr_id = { CKA_ID, NULL, 0 };

bin = hex_decode (id, &bin_len);
if (bin == NULL) {
p11_message (_("failed to decode hex value: %s"), id);
goto error;
}

attr_id.pValue = (void *)bin;
attr_id.ulValueLen = bin_len;

tmp = p11_attrs_build (pub, &attr_id, NULL);
if (tmp == NULL) {
free (bin);
p11_message (_("failed to allocate memory"));
goto error;
}
pub = tmp;
tmp = p11_attrs_build (priv, &attr_id, NULL);
free (bin);
if (tmp == NULL) {
p11_message (_("failed to allocate memory"));
goto error;
}
priv = tmp;
}

switch (type) {
#ifdef P11_KIT_TESTABLE
case CKM_MOCK_GENERATE:
Expand Down Expand Up @@ -254,6 +286,7 @@ get_templates (const char *label,
static int
generate_keypair (p11_tool *tool,
const char *label,
const char *id,
CK_MECHANISM mechanism,
CK_ULONG bits,
const uint8_t *ec_params,
Expand All @@ -267,7 +300,7 @@ generate_keypair (p11_tool *tool,
CK_ATTRIBUTE *pubkey = NULL, *privkey = NULL;
CK_OBJECT_HANDLE pubkey_obj, privkey_obj;

if (!get_templates (label, mechanism.mechanism, bits,
if (!get_templates (label, id, mechanism.mechanism, bits,
ec_params, ec_params_len, &pubkey, &privkey)) {
p11_message (_("failed to create key templates"));
return 1;
Expand Down Expand Up @@ -318,7 +351,8 @@ p11_kit_generate_keypair (int argc,
char *argv[])
{
int opt, ret = 2;
char *label = NULL;
const char *label = NULL;
const char *id = NULL;
CK_ULONG bits = 0;
const uint8_t *ec_params = NULL;
size_t ec_params_len = 0;
Expand All @@ -332,6 +366,7 @@ p11_kit_generate_keypair (int argc,
opt_quiet = 'q',
opt_help = 'h',
opt_label = 'L',
opt_id = CHAR_MAX + 3,
opt_type = 't',
opt_bits = 'b',
opt_curve = 'c',
Expand All @@ -344,6 +379,7 @@ p11_kit_generate_keypair (int argc,
{ "quiet", no_argument, NULL, opt_quiet },
{ "help", no_argument, NULL, opt_help },
{ "label", required_argument, NULL, opt_label },
{ "id", required_argument, NULL, opt_id },
{ "type", required_argument, NULL, opt_type },
{ "bits", required_argument, NULL, opt_bits },
{ "curve", required_argument, NULL, opt_curve },
Expand All @@ -356,6 +392,7 @@ p11_kit_generate_keypair (int argc,
{ 0, "usage: p11-kit generate-keypair [--label=<label>]"
" --type=<algorithm> {--bits=<n>|--curve=<name>} pkcs11:token" },
{ opt_label, "label to be associated with generated key objects" },
{ opt_id, "id to be associated with generated key objects" },
{ opt_type, "type of keys to generate" },
{ opt_bits, "number of bits for key generation" },
{ opt_curve, "name of the curve for key generation" },
Expand All @@ -369,6 +406,9 @@ p11_kit_generate_keypair (int argc,
case opt_label:
label = optarg;
break;
case opt_id:
id = optarg;
break;
case opt_type:
mechanism = get_mechanism (optarg);
if (mechanism.mechanism == CKA_INVALID) {
Expand Down Expand Up @@ -442,7 +482,7 @@ p11_kit_generate_keypair (int argc,

p11_tool_set_login (tool, login);

ret = generate_keypair (tool, label, mechanism, bits, ec_params, ec_params_len);
ret = generate_keypair (tool, label, id, mechanism, bits, ec_params, ec_params_len);

cleanup:
p11_tool_free (tool);
Expand Down
Loading

0 comments on commit 5d9c43b

Please sign in to comment.