|
Packit |
8681c6 |
/*
|
|
Packit |
8681c6 |
* COPYRIGHT (c) International Business Machines Corp. 2013-2017
|
|
Packit |
8681c6 |
*
|
|
Packit |
8681c6 |
* This program is provided under the terms of the Common Public License,
|
|
Packit |
8681c6 |
* version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
|
|
Packit |
8681c6 |
* software constitutes recipient's acceptance of CPL-1.0 terms which can be
|
|
Packit |
8681c6 |
* found in the file LICENSE file or at
|
|
Packit |
8681c6 |
* https://opensource.org/licenses/cpl1.0.php
|
|
Packit |
8681c6 |
*/
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Reenryption of EP11 secure keys. The secure key is reencrypted at the card
|
|
Packit |
8681c6 |
* by a new wrapping (still pending) key. Needed also for SPKIs of public
|
|
Packit |
8681c6 |
* keys.
|
|
Packit |
8681c6 |
*/
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
#define _GNU_SOURCE
|
|
Packit |
8681c6 |
#include <stdint.h>
|
|
Packit |
8681c6 |
#include <stdio.h>
|
|
Packit |
8681c6 |
#include <stdlib.h>
|
|
Packit |
8681c6 |
#include <string.h>
|
|
Packit |
8681c6 |
#include <memory.h>
|
|
Packit |
8681c6 |
#include <dlfcn.h>
|
|
Packit |
8681c6 |
#include <pkcs11types.h>
|
|
Packit |
8681c6 |
#include <ep11.h>
|
|
Packit |
8681c6 |
#include <ep11adm.h>
|
|
Packit |
8681c6 |
#include <p11util.h>
|
|
Packit |
8681c6 |
#include <ctype.h>
|
|
Packit |
8681c6 |
#include <termios.h>
|
|
Packit |
8681c6 |
#include <errno.h>
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
#define EP11SHAREDLIB_NAME "OCK_EP11_LIBRARY"
|
|
Packit |
8681c6 |
#define EP11SHAREDLIB_V3 "libep11.so.3"
|
|
Packit |
8681c6 |
#define EP11SHAREDLIB_V2 "libep11.so.2"
|
|
Packit |
8681c6 |
#define EP11SHAREDLIB_V1 "libep11.so.1"
|
|
Packit |
8681c6 |
#define EP11SHAREDLIB "libep11.so"
|
|
Packit |
8681c6 |
#define PKCS11_MAX_PIN_LEN 128
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_FUNCTION_LIST *funcs;
|
|
Packit |
8681c6 |
CK_SLOT_ID SLOT_ID = -1;
|
|
Packit |
8681c6 |
CK_LONG adapter = -1;
|
|
Packit |
8681c6 |
CK_LONG domain = -1;
|
|
Packit |
8681c6 |
CK_OBJECT_HANDLE key_store[4096];
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
typedef unsigned long int (*m_admin_t) (unsigned char *, size_t *,
|
|
Packit |
8681c6 |
unsigned char *,
|
|
Packit |
8681c6 |
size_t *, const unsigned char *,
|
|
Packit |
8681c6 |
size_t, const unsigned char *,
|
|
Packit |
8681c6 |
size_t, target_t);
|
|
Packit |
8681c6 |
typedef long (*xcpa_cmdblock_t) (unsigned char *, size_t, unsigned int,
|
|
Packit |
8681c6 |
const struct XCPadmresp *,
|
|
Packit |
8681c6 |
const unsigned char *,
|
|
Packit |
8681c6 |
const unsigned char *, size_t);
|
|
Packit |
8681c6 |
typedef long (*xcpa_internal_rv_t) (const unsigned char *, size_t,
|
|
Packit |
8681c6 |
struct XCPadmresp *, CK_RV *);
|
|
Packit |
8681c6 |
typedef int (*m_add_module_t) (XCP_Module_t, target_t *);
|
|
Packit |
8681c6 |
typedef int (*m_rm_module_t) (XCP_Module_t, target_t);
|
|
Packit |
8681c6 |
typedef CK_RV (*m_get_xcp_info_t)(CK_VOID_PTR pinfo, CK_ULONG_PTR infbytes,
|
|
Packit |
8681c6 |
unsigned int query, unsigned int subquery,
|
|
Packit |
8681c6 |
target_t target);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
m_get_xcp_info_t _m_get_xcp_info;
|
|
Packit |
8681c6 |
m_admin_t _m_admin;
|
|
Packit |
8681c6 |
xcpa_cmdblock_t _xcpa_cmdblock;
|
|
Packit |
8681c6 |
xcpa_internal_rv_t _xcpa_internal_rv;
|
|
Packit |
8681c6 |
m_add_module_t _m_add_module;
|
|
Packit |
8681c6 |
m_rm_module_t _m_rm_module;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_VERSION lib_version;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
#define CK_IBM_XCPHQ_VERSION 0xff000001
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
typedef struct {
|
|
Packit |
8681c6 |
short format;
|
|
Packit |
8681c6 |
short length;
|
|
Packit |
8681c6 |
short apqns[512];
|
|
Packit |
8681c6 |
} __attribute__ ((packed)) ep11_target_t;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
#define BLOBSIZE 2048*4
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
static int reencrypt(CK_SESSION_HANDLE session, CK_ULONG obj, CK_BYTE *old,
|
|
Packit |
8681c6 |
CK_ULONG old_len)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
CK_BYTE req[BLOBSIZE];
|
|
Packit |
8681c6 |
CK_BYTE resp[BLOBSIZE];
|
|
Packit |
8681c6 |
CK_LONG req_len;
|
|
Packit |
8681c6 |
size_t resp_len;
|
|
Packit |
8681c6 |
struct XCPadmresp rb;
|
|
Packit |
8681c6 |
struct XCPadmresp lrb;
|
|
Packit |
8681c6 |
ep11_target_t target_list;
|
|
Packit |
8681c6 |
struct XCP_Module module;
|
|
Packit |
8681c6 |
target_t target = XCP_TGT_INIT;
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit |
8681c6 |
CK_BYTE name[256];
|
|
Packit |
8681c6 |
unsigned char blob[BLOBSIZE];
|
|
Packit |
8681c6 |
CK_ULONG blob_len;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_ATTRIBUTE opaque_template[] = {
|
|
Packit |
8681c6 |
{ CKA_IBM_OPAQUE, blob, BLOBSIZE }
|
|
Packit |
8681c6 |
};
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_ATTRIBUTE name_template[] = {
|
|
Packit |
8681c6 |
{CKA_LABEL, NULL_PTR, 0}
|
|
Packit |
8681c6 |
};
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
memset(name, 0, 256);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* print CKA_LABEL if it exists, only informational
|
|
Packit |
8681c6 |
exist and size query */
|
|
Packit |
8681c6 |
rc = funcs->C_GetAttributeValue(session, key_store[obj], name_template, 1);
|
|
Packit |
8681c6 |
if (rc == CKR_OK && name_template[0].ulValueLen < 256) {
|
|
Packit |
8681c6 |
name_template[0].pValue = name;
|
|
Packit |
8681c6 |
/* knowing its size, after mem allocation, get the name value */
|
|
Packit |
8681c6 |
rc = funcs->C_GetAttributeValue(session, key_store[obj], name_template,
|
|
Packit |
8681c6 |
1);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
memset(&rb, 0, sizeof(rb));
|
|
Packit |
8681c6 |
memset(&lrb, 0, sizeof(lrb));
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (_m_add_module != NULL) {
|
|
Packit |
8681c6 |
memset(&module, 0, sizeof(module));
|
|
Packit |
8681c6 |
module.version = lib_version.major >= 3 ? XCP_MOD_VERSION_2
|
|
Packit |
8681c6 |
: XCP_MOD_VERSION_1;
|
|
Packit |
8681c6 |
module.flags = XCP_MFL_MODULE;
|
|
Packit |
8681c6 |
module.module_nr = adapter;
|
|
Packit |
8681c6 |
XCPTGTMASK_SET_DOM(module.domainmask, domain);
|
|
Packit |
8681c6 |
rc = _m_add_module(&module, &target);
|
|
Packit |
8681c6 |
if (rc != 0)
|
|
Packit |
8681c6 |
return CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
} else {
|
|
Packit |
8681c6 |
/* Fall back to old target handling */
|
|
Packit |
8681c6 |
memset(&target_list, 0, sizeof(ep11_target_t));
|
|
Packit |
8681c6 |
target_list.length = 1;
|
|
Packit |
8681c6 |
target_list.apqns[0] = adapter;
|
|
Packit |
8681c6 |
target_list.apqns[1] = domain;
|
|
Packit |
8681c6 |
target = (target_t)&target_list;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rb.domain = domain;
|
|
Packit |
8681c6 |
lrb.domain = domain;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
fprintf(stderr, "going to reencrpyt key %lx with blob len %lx: '%s'\n", obj,
|
|
Packit |
8681c6 |
old_len, name);
|
|
Packit |
8681c6 |
resp_len = BLOBSIZE;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
req_len = _xcpa_cmdblock(req, BLOBSIZE, XCP_ADM_REENCRYPT, &rb,
|
|
Packit |
8681c6 |
NULL, old, old_len);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (req_len < 0) {
|
|
Packit |
8681c6 |
fprintf(stderr, "reencrypt cmd block construction failed\n");
|
|
Packit |
8681c6 |
rc = -2;
|
|
Packit |
8681c6 |
goto out;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = _m_admin(resp, &resp_len, NULL, 0, req, req_len, NULL, 0,
|
|
Packit |
8681c6 |
target);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (rc != CKR_OK || resp_len == 0) {
|
|
Packit |
8681c6 |
fprintf(stderr, "reencryption failed: %lx %ld\n", rc, req_len);
|
|
Packit |
8681c6 |
rc = -3;
|
|
Packit |
8681c6 |
goto out;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (_xcpa_internal_rv(resp, resp_len, &lrb, &rc) < 0) {
|
|
Packit |
8681c6 |
fprintf(stderr, "reencryption response malformed: %lx\n", rc);
|
|
Packit |
8681c6 |
rc = -4;
|
|
Packit |
8681c6 |
goto out;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (rc != 0) {
|
|
Packit |
8681c6 |
fprintf(stderr, "reencryption failed: %lx\n", rc);
|
|
Packit |
8681c6 |
rc = -7;
|
|
Packit |
8681c6 |
goto out;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (old_len != lrb.pllen) {
|
|
Packit |
8681c6 |
fprintf(stderr, "reencryption blob size changed: %lx %lx %lx %lx\n",
|
|
Packit |
8681c6 |
old_len, lrb.pllen, resp_len, req_len);
|
|
Packit |
8681c6 |
rc = -5;
|
|
Packit |
8681c6 |
goto out;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
memset(blob, 0, sizeof(blob));
|
|
Packit |
8681c6 |
blob_len = old_len;
|
|
Packit |
8681c6 |
memcpy(blob, lrb.payload, blob_len);
|
|
Packit |
8681c6 |
opaque_template[0].ulValueLen = blob_len;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = funcs->C_SetAttributeValue(session, key_store[obj], opaque_template,
|
|
Packit |
8681c6 |
1);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
fprintf(stderr,
|
|
Packit |
8681c6 |
"reencryption C_SetAttributeValue failed: obj %lx '%s' rc: %lx\n",
|
|
Packit |
8681c6 |
obj, name, rc);
|
|
Packit |
8681c6 |
rc = -6;
|
|
Packit |
8681c6 |
goto out;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
fprintf(stderr, "reencryption success obj: %lx '%s:\n", obj, name);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
out:
|
|
Packit |
8681c6 |
if (_m_rm_module != NULL)
|
|
Packit |
8681c6 |
_m_rm_module(&module, target);
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
static CK_RV get_ep11_library_version(CK_VERSION *lib_version)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
unsigned int host_version;
|
|
Packit |
8681c6 |
CK_ULONG version_len = sizeof(host_version);
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = _m_get_xcp_info(&host_version, &version_len,
|
|
Packit |
8681c6 |
CK_IBM_XCPHQ_VERSION, 0, 0);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
fprintf(stderr, "_m_get_xcp_info (HOST) failed: rc=0x%lx\n", rc);
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
lib_version->major = (host_version & 0x00FF0000) >> 16;
|
|
Packit |
8681c6 |
lib_version->minor = host_version & 0x000000FF0000;
|
|
Packit |
8681c6 |
/*
|
|
Packit |
8681c6 |
* EP11 host library < v2.0 returns an invalid version (i.e. 0x100). This
|
|
Packit |
8681c6 |
* can safely be treated as version 1.0
|
|
Packit |
8681c6 |
*/
|
|
Packit |
8681c6 |
if (lib_version->major == 0) {
|
|
Packit |
8681c6 |
lib_version->major = 1;
|
|
Packit |
8681c6 |
lib_version->minor = 0;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return CKR_OK;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
static int check_card_status()
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit |
8681c6 |
ep11_target_t target_list;
|
|
Packit |
8681c6 |
struct XCP_Module module;
|
|
Packit |
8681c6 |
target_t target = XCP_TGT_INIT;
|
|
Packit |
8681c6 |
CK_IBM_DOMAIN_INFO dinf;
|
|
Packit |
8681c6 |
CK_ULONG dinf_len = sizeof(dinf);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (adapter == -1 || domain == -1) {
|
|
Packit |
8681c6 |
fprintf(stderr, "adapter/domain specification missing.\n");
|
|
Packit |
8681c6 |
return -1;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (_m_add_module != NULL) {
|
|
Packit |
8681c6 |
memset(&module, 0, sizeof(module));
|
|
Packit |
8681c6 |
module.version = lib_version.major >= 3 ? XCP_MOD_VERSION_2
|
|
Packit |
8681c6 |
: XCP_MOD_VERSION_1;
|
|
Packit |
8681c6 |
module.flags = XCP_MFL_MODULE;
|
|
Packit |
8681c6 |
module.module_nr = adapter;
|
|
Packit |
8681c6 |
XCPTGTMASK_SET_DOM(module.domainmask, domain);
|
|
Packit |
8681c6 |
rc = _m_add_module(&module, &target);
|
|
Packit |
8681c6 |
if (rc != 0)
|
|
Packit |
8681c6 |
return CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
} else {
|
|
Packit |
8681c6 |
/* Fall back to old target handling */
|
|
Packit |
8681c6 |
memset(&target_list, 0, sizeof(ep11_target_t));
|
|
Packit |
8681c6 |
target_list.length = 1;
|
|
Packit |
8681c6 |
target_list.apqns[0] = adapter;
|
|
Packit |
8681c6 |
target_list.apqns[1] = domain;
|
|
Packit |
8681c6 |
target = (target_t)&target_list;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = _m_get_xcp_info((CK_VOID_PTR) &dinf, &dinf_len,
|
|
Packit |
8681c6 |
CK_IBM_XCPQ_DOMAIN, 0, target);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
fprintf(stderr, "m_get_xcp_info rc 0x%lx, valid apapter/domain "
|
|
Packit |
8681c6 |
"0x%02lx/%ld?.\n", rc, adapter, domain);
|
|
Packit |
8681c6 |
rc = -1;
|
|
Packit |
8681c6 |
goto out;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (CK_IBM_DOM_COMMITTED_NWK & dinf.flags) {
|
|
Packit |
8681c6 |
fprintf(stderr, "Card ID 0x%02lx, domain ID %ld has committed "
|
|
Packit |
8681c6 |
"pending(next) WK\n", adapter, domain);
|
|
Packit |
8681c6 |
} else {
|
|
Packit |
8681c6 |
fprintf(stderr,
|
|
Packit |
8681c6 |
"Card ID 0x%02lx, domain ID %ld has no committed pending WK\n",
|
|
Packit |
8681c6 |
adapter, domain);
|
|
Packit |
8681c6 |
rc = -1;
|
|
Packit |
8681c6 |
goto out;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
out:
|
|
Packit |
8681c6 |
if (_m_rm_module != NULL)
|
|
Packit |
8681c6 |
_m_rm_module(&module, target);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
int get_pin(char **pin, size_t *pinlen)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
struct termios old, new;
|
|
Packit |
8681c6 |
int nread;
|
|
Packit |
8681c6 |
char *buff = NULL;
|
|
Packit |
8681c6 |
size_t buflen;
|
|
Packit |
8681c6 |
int rc = 0;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* turn echoing off */
|
|
Packit |
8681c6 |
if (tcgetattr(fileno(stdin), &old) != 0)
|
|
Packit |
8681c6 |
return -1;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
new = old;
|
|
Packit |
8681c6 |
new.c_lflag &= ~ECHO;
|
|
Packit |
8681c6 |
if (tcsetattr(fileno(stdin), TCSAFLUSH, &new) != 0)
|
|
Packit |
8681c6 |
return -1;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* read the pin
|
|
Packit |
8681c6 |
* Note: getline will allocate memory for buff. free it when done.
|
|
Packit |
8681c6 |
*/
|
|
Packit |
8681c6 |
nread = getline(&buff, &buflen, stdin);
|
|
Packit |
8681c6 |
if (nread == -1) {
|
|
Packit |
8681c6 |
rc = -1;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Restore terminal */
|
|
Packit |
8681c6 |
tcsetattr(fileno(stdin), TCSAFLUSH, &old;;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* start a newline */
|
|
Packit |
8681c6 |
printf("\n");
|
|
Packit |
8681c6 |
fflush(stdout);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Allocate PIN.
|
|
Packit |
8681c6 |
* Note: nread includes carriage return.
|
|
Packit |
8681c6 |
* Replace with terminating NULL.
|
|
Packit |
8681c6 |
*/
|
|
Packit |
8681c6 |
*pin = (char *) malloc(nread);
|
|
Packit |
8681c6 |
if (*pin == NULL) {
|
|
Packit |
8681c6 |
rc = -ENOMEM;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* strip the carriage return since not part of pin. */
|
|
Packit |
8681c6 |
buff[nread - 1] = '\0';
|
|
Packit |
8681c6 |
memcpy(*pin, buff, nread);
|
|
Packit |
8681c6 |
/* don't include the terminating null in the pinlen */
|
|
Packit |
8681c6 |
*pinlen = nread - 1;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
done:
|
|
Packit |
8681c6 |
if (buff)
|
|
Packit |
8681c6 |
free(buff);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
static int get_user_pin(CK_BYTE *dest)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
int ret;
|
|
Packit |
8681c6 |
char *userpin = NULL;
|
|
Packit |
8681c6 |
size_t userpinlen;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
printf("Enter the USER PIN: ");
|
|
Packit |
8681c6 |
fflush(stdout);
|
|
Packit |
8681c6 |
ret = get_pin(&userpin, &userpinlen);
|
|
Packit |
8681c6 |
if (ret != 0) {
|
|
Packit |
8681c6 |
fprintf(stderr, "Could not get USER PIN.\n");
|
|
Packit |
8681c6 |
return -1;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (userpinlen > PKCS11_MAX_PIN_LEN) {
|
|
Packit |
8681c6 |
fprintf(stderr, "The USER PIN must be less than %d chars in length.\n",
|
|
Packit |
8681c6 |
(int) PKCS11_MAX_PIN_LEN);
|
|
Packit |
8681c6 |
free(userpin);
|
|
Packit |
8681c6 |
return -1;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
memcpy(dest, userpin, userpinlen + 1);
|
|
Packit |
8681c6 |
free(userpin);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return 0;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
static int do_GetFunctionList(void)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit |
8681c6 |
CK_RV (*func_list) () = NULL;
|
|
Packit |
8681c6 |
void *d;
|
|
Packit |
8681c6 |
char *evar;
|
|
Packit |
8681c6 |
char *evar_default = "libopencryptoki.so";
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
evar = secure_getenv("PKCSLIB");
|
|
Packit |
8681c6 |
if (evar == NULL) {
|
|
Packit |
8681c6 |
evar = evar_default;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
d = dlopen(evar, RTLD_NOW);
|
|
Packit |
8681c6 |
if (d == NULL) {
|
|
Packit |
8681c6 |
return 0;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
*(void **)(&func_list) = dlsym(d, "C_GetFunctionList");
|
|
Packit |
8681c6 |
if (func_list == NULL) {
|
|
Packit |
8681c6 |
return 0;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
rc = func_list(&funcs);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
return 0;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return 1;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
static void usage(char *fct)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
printf("usage: %s [-slot <num>] [-adapter <num>] [-domain <num>] [-h]\n\n",
|
|
Packit |
8681c6 |
fct);
|
|
Packit |
8681c6 |
return;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
static int do_ParseArgs(int argc, char **argv)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
int i;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (argc <= 1) {
|
|
Packit |
8681c6 |
printf("No Arguments given. "
|
|
Packit |
8681c6 |
"For help use the '--help' or '-h' option.\n");
|
|
Packit |
8681c6 |
return -1;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
for (i = 1; i < argc; i++) {
|
|
Packit |
8681c6 |
if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
|
|
Packit |
8681c6 |
usage(argv[0]);
|
|
Packit |
8681c6 |
return 0;
|
|
Packit |
8681c6 |
} else if (strcmp(argv[i], "-slot") == 0) {
|
|
Packit |
8681c6 |
if (!isdigit(*argv[i + 1])) {
|
|
Packit |
8681c6 |
printf("Slot parameter is not numeric!\n");
|
|
Packit |
8681c6 |
return -1;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
SLOT_ID = (int) strtol(argv[i + 1], NULL, 0);
|
|
Packit |
8681c6 |
i++;
|
|
Packit |
8681c6 |
} else if (strcmp(argv[i], "-adapter") == 0) {
|
|
Packit |
8681c6 |
if (!isdigit(*argv[i + 1])) {
|
|
Packit |
8681c6 |
printf("Adapter parameter is not numeric!\n");
|
|
Packit |
8681c6 |
return -1;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
adapter = (int) strtol(argv[i + 1], NULL, 0);
|
|
Packit |
8681c6 |
i++;
|
|
Packit |
8681c6 |
} else if (strcmp(argv[i], "-domain") == 0) {
|
|
Packit |
8681c6 |
if (!isdigit(*argv[i + 1])) {
|
|
Packit |
8681c6 |
printf("Domain parameter is not numeric!\n");
|
|
Packit |
8681c6 |
return -1;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
domain = (int) strtol(argv[i + 1], NULL, 0);
|
|
Packit |
8681c6 |
i++;
|
|
Packit |
8681c6 |
} else {
|
|
Packit |
8681c6 |
printf("Invalid argument passed as option: %s\n", argv[i]);
|
|
Packit |
8681c6 |
usage(argv[0]);
|
|
Packit |
8681c6 |
return -1;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
if (SLOT_ID == (CK_SLOT_ID)(-1)) {
|
|
Packit |
8681c6 |
printf("Slot-ID not set!\n");
|
|
Packit |
8681c6 |
return -1;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
if (adapter == -1) {
|
|
Packit |
8681c6 |
printf("Adapter-ID not set!\n");
|
|
Packit |
8681c6 |
return -1;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
if (domain == -1) {
|
|
Packit |
8681c6 |
printf("Domain-ID not set!\n");
|
|
Packit |
8681c6 |
return -1;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return 1;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
#ifdef EP11_HSMSIM
|
|
Packit |
8681c6 |
#define DLOPEN_FLAGS RTLD_GLOBAL | RTLD_NOW | RTLD_DEEPBIND
|
|
Packit |
8681c6 |
#else
|
|
Packit |
8681c6 |
#define DLOPEN_FLAGS RTLD_GLOBAL | RTLD_NOW
|
|
Packit |
8681c6 |
#endif
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
static void *ep11_load_host_lib()
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
void *lib_ep11;
|
|
Packit |
8681c6 |
char *ep11_lib_name;
|
|
Packit |
8681c6 |
char *errstr;
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
ep11_lib_name = secure_getenv(EP11SHAREDLIB_NAME);
|
|
Packit |
8681c6 |
if (ep11_lib_name != NULL) {
|
|
Packit |
8681c6 |
lib_ep11 = dlopen(ep11_lib_name, DLOPEN_FLAGS);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (lib_ep11 == NULL) {
|
|
Packit |
8681c6 |
errstr = dlerror();
|
|
Packit |
8681c6 |
fprintf(stderr, "Error loading shared library '%s' [%s]\n",
|
|
Packit |
8681c6 |
ep11_lib_name, errstr);
|
|
Packit |
8681c6 |
return NULL;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
return lib_ep11;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
ep11_lib_name = EP11SHAREDLIB_V3;
|
|
Packit |
8681c6 |
lib_ep11 = dlopen(ep11_lib_name, DLOPEN_FLAGS);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (lib_ep11 == NULL) {
|
|
Packit |
8681c6 |
/* Try version 2 instead */
|
|
Packit |
8681c6 |
ep11_lib_name = EP11SHAREDLIB_V2;
|
|
Packit |
8681c6 |
lib_ep11 = dlopen(ep11_lib_name, DLOPEN_FLAGS);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (lib_ep11 == NULL) {
|
|
Packit |
8681c6 |
/* Try version 1 instead */
|
|
Packit |
8681c6 |
ep11_lib_name = EP11SHAREDLIB_V1;
|
|
Packit |
8681c6 |
lib_ep11 = dlopen(ep11_lib_name, DLOPEN_FLAGS);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (lib_ep11 == NULL) {
|
|
Packit |
8681c6 |
/* Try unversioned library instead */
|
|
Packit |
8681c6 |
ep11_lib_name = EP11SHAREDLIB;
|
|
Packit |
8681c6 |
lib_ep11 = dlopen(ep11_lib_name, DLOPEN_FLAGS);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (lib_ep11 == NULL) {
|
|
Packit |
8681c6 |
errstr = dlerror();
|
|
Packit |
8681c6 |
fprintf(stderr, "Error loading shared library '%s[.3|.2|.1]' [%s]\n",
|
|
Packit |
8681c6 |
EP11SHAREDLIB, errstr);
|
|
Packit |
8681c6 |
return NULL;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return lib_ep11;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
int main(int argc, char **argv)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
int rc;
|
|
Packit |
8681c6 |
void *lib_ep11;
|
|
Packit |
8681c6 |
CK_C_INITIALIZE_ARGS cinit_args;
|
|
Packit |
8681c6 |
CK_BYTE user_pin[PKCS11_MAX_PIN_LEN + 1];
|
|
Packit |
8681c6 |
CK_FLAGS flags;
|
|
Packit |
8681c6 |
CK_SESSION_HANDLE session;
|
|
Packit |
8681c6 |
CK_ULONG obj;
|
|
Packit |
8681c6 |
CK_ULONG user_pin_len;
|
|
Packit |
8681c6 |
CK_ULONG keys_found = 0;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = do_ParseArgs(argc, argv);
|
|
Packit |
8681c6 |
if (rc != 1) {
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* dynamically load in the ep11 shared library */
|
|
Packit |
8681c6 |
lib_ep11 = ep11_load_host_lib();
|
|
Packit |
8681c6 |
if (!lib_ep11)
|
|
Packit |
8681c6 |
return CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
*(void **)(&_xcpa_cmdblock) = dlsym(lib_ep11, "xcpa_cmdblock");
|
|
Packit |
8681c6 |
if (_xcpa_cmdblock == NULL)
|
|
Packit |
8681c6 |
*(void **)(&_xcpa_cmdblock) = dlsym(lib_ep11, "ep11a_cmdblock");
|
|
Packit |
8681c6 |
*(void **)(&_m_admin) = dlsym(lib_ep11, "m_admin");
|
|
Packit |
8681c6 |
*(void **)(&_xcpa_internal_rv) = dlsym(lib_ep11, "xcpa_internal_rv");
|
|
Packit |
8681c6 |
if (_xcpa_internal_rv == NULL)
|
|
Packit |
8681c6 |
*(void **)(&_xcpa_internal_rv) = dlsym(lib_ep11, "ep11a_internal_rv");
|
|
Packit |
8681c6 |
*(void **)(&_m_get_xcp_info) = dlsym(lib_ep11, "m_get_xcp_info");
|
|
Packit |
8681c6 |
if (_m_get_xcp_info == NULL)
|
|
Packit |
8681c6 |
*(void **)(&_m_get_xcp_info) = dlsym(lib_ep11, "m_get_ep11_info");
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (!_m_get_xcp_info || !_xcpa_cmdblock ||
|
|
Packit |
8681c6 |
!_m_admin || !_xcpa_internal_rv) {
|
|
Packit |
8681c6 |
fprintf(stderr, "ERROR getting function pointer from shared lib '%s'",
|
|
Packit |
8681c6 |
EP11SHAREDLIB);
|
|
Packit |
8681c6 |
return CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/*
|
|
Packit |
8681c6 |
* The following are only available since EP11 host library version 2.
|
|
Packit |
8681c6 |
* Ignore if they fail to load, the code will fall back to the old target
|
|
Packit |
8681c6 |
* handling in this case.
|
|
Packit |
8681c6 |
*/
|
|
Packit |
8681c6 |
*(void **)(&_m_add_module) = dlsym(lib_ep11, "m_add_module");
|
|
Packit |
8681c6 |
*(void **)(&_m_rm_module) = dlsym(lib_ep11, "m_rm_module");
|
|
Packit |
8681c6 |
if (_m_add_module == NULL || _m_rm_module == NULL) {
|
|
Packit |
8681c6 |
_m_add_module = NULL;
|
|
Packit |
8681c6 |
_m_rm_module = NULL;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
printf("Using slot #%lu...\n\n", SLOT_ID);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = do_GetFunctionList();
|
|
Packit |
8681c6 |
if (!rc) {
|
|
Packit |
8681c6 |
fprintf(stderr, "ERROR do_GetFunctionList() Failed, rx = 0x%0x\n", rc);
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
memset(&cinit_args, 0x0, sizeof(cinit_args));
|
|
Packit |
8681c6 |
cinit_args.flags = CKF_OS_LOCKING_OK;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
funcs->C_Initialize(&cinit_args);
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
CK_SESSION_HANDLE hsess = 0;
|
|
Packit |
8681c6 |
rc = funcs->C_GetFunctionStatus(hsess);
|
|
Packit |
8681c6 |
if (rc != CKR_FUNCTION_NOT_PARALLEL) {
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = funcs->C_CancelFunction(hsess);
|
|
Packit |
8681c6 |
if (rc != CKR_FUNCTION_NOT_PARALLEL) {
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
flags = CKF_SERIAL_SESSION | CKF_RW_SESSION;
|
|
Packit |
8681c6 |
rc = funcs->C_OpenSession(SLOT_ID, flags, NULL, NULL, &session);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
fprintf(stderr, "C_OpenSession() rc = 0x%02x [%s]\n", rc,
|
|
Packit |
8681c6 |
p11_get_ckr(rc));
|
|
Packit |
8681c6 |
session = CK_INVALID_HANDLE;
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (get_user_pin(user_pin)) {
|
|
Packit |
8681c6 |
fprintf(stderr, "get_user_pin() failed\n");
|
|
Packit |
8681c6 |
rc = funcs->C_CloseAllSessions(SLOT_ID);
|
|
Packit |
8681c6 |
if (rc != CKR_OK)
|
|
Packit |
8681c6 |
fprintf(stderr, "C_CloseAllSessions() rc = 0x%02x [%s]\n", rc,
|
|
Packit |
8681c6 |
p11_get_ckr(rc));
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
user_pin_len = (CK_ULONG) strlen((char *) user_pin);
|
|
Packit |
8681c6 |
rc = funcs->C_Login(session, CKU_USER, user_pin, user_pin_len);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
fprintf(stderr, "C_Login() rc = 0x%02x [%s]\n", rc, p11_get_ckr(rc));
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = get_ep11_library_version(&lib_version);
|
|
Packit |
8681c6 |
if (rc != CKR_OK)
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (check_card_status() != 0)
|
|
Packit |
8681c6 |
return 1;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* find all objects */
|
|
Packit |
8681c6 |
rc = funcs->C_FindObjectsInit(session, NULL, 0);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
do {
|
|
Packit |
8681c6 |
rc = funcs->C_FindObjects(session, key_store, 4096, &keys_found);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
fprintf(stderr, "C_FindObjects() rc = 0x%02x [%s]\n", rc,
|
|
Packit |
8681c6 |
p11_get_ckr(rc));
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
for (obj = 0; obj < keys_found; obj++) {
|
|
Packit |
8681c6 |
CK_ATTRIBUTE opaque_template[] = {
|
|
Packit |
8681c6 |
{CKA_IBM_OPAQUE, NULL_PTR, 0}
|
|
Packit |
8681c6 |
};
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_KEY_TYPE keytype;
|
|
Packit |
8681c6 |
CK_ATTRIBUTE key_type_template[] = {
|
|
Packit |
8681c6 |
{CKA_KEY_TYPE, &keytype, sizeof(CK_KEY_TYPE)}
|
|
Packit |
8681c6 |
};
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_BYTE *old_blob;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* only for keys */
|
|
Packit |
8681c6 |
rc = funcs->C_GetAttributeValue(session, key_store[obj],
|
|
Packit |
8681c6 |
key_type_template, 1);
|
|
Packit |
8681c6 |
if (rc != CKR_OK)
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* exist and size query CKA_IBM_QPAQUE */
|
|
Packit |
8681c6 |
rc = funcs->C_GetAttributeValue(session, key_store[obj],
|
|
Packit |
8681c6 |
opaque_template, 1);
|
|
Packit |
8681c6 |
if (rc == CKR_OK) {
|
|
Packit |
8681c6 |
old_blob = malloc(opaque_template[0].ulValueLen);
|
|
Packit |
8681c6 |
opaque_template[0].pValue = old_blob;
|
|
Packit |
8681c6 |
/* get the blob after knowing its size */
|
|
Packit |
8681c6 |
rc = funcs->C_GetAttributeValue(session, key_store[obj],
|
|
Packit |
8681c6 |
opaque_template, 1);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
fprintf(stderr, "second C_GetAttributeValue failed "
|
|
Packit |
8681c6 |
"rc = 0x%02x [%s]\n", rc, p11_get_ckr(rc));
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
} else {
|
|
Packit |
8681c6 |
if (reencrypt(session, obj,
|
|
Packit |
8681c6 |
(CK_BYTE *) opaque_template[0].pValue,
|
|
Packit |
8681c6 |
opaque_template[0].ulValueLen) != 0) {
|
|
Packit |
8681c6 |
/* reencrypt failed */
|
|
Packit |
8681c6 |
return -1;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
free(old_blob);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
/* next 4096 objects */
|
|
Packit |
8681c6 |
while (keys_found != 0);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = funcs->C_FindObjectsFinal(session);
|
|
Packit |
8681c6 |
fprintf(stderr, "all keys successfully reencrypted\n");
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = funcs->C_Logout(session);
|
|
Packit |
8681c6 |
rc = funcs->C_CloseAllSessions(SLOT_ID);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|