|
Packit Service |
8aa27d |
/*
|
|
Packit Service |
8aa27d |
* COPYRIGHT (c) International Business Machines Corp. 2020
|
|
Packit Service |
8aa27d |
*
|
|
Packit Service |
8aa27d |
* This program is provided under the terms of the Common Public License,
|
|
Packit Service |
8aa27d |
* version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
|
|
Packit Service |
8aa27d |
* software constitutes recipient's acceptance of CPL-1.0 terms which can be
|
|
Packit Service |
8aa27d |
* found in the file LICENSE file or at
|
|
Packit Service |
8aa27d |
* https://opensource.org/licenses/cpl1.0.php
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/*
|
|
Packit Service |
8aa27d |
* pkcstok_migrate - A tool for migrating ICA, CCA, Soft, and EP11 token
|
|
Packit Service |
8aa27d |
* repositories to 3.12 format.
|
|
Packit Service |
8aa27d |
*
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
#define _GNU_SOURCE
|
|
Packit Service |
8aa27d |
#include <dlfcn.h>
|
|
Packit Service |
8aa27d |
#include <err.h>
|
|
Packit Service |
8aa27d |
#include <errno.h>
|
|
Packit Service |
8aa27d |
#include <getopt.h>
|
|
Packit Service |
8aa27d |
#include <memory.h>
|
|
Packit Service |
8aa27d |
#include <linux/limits.h>
|
|
Packit Service |
8aa27d |
#include <openssl/evp.h>
|
|
Packit Service |
8aa27d |
#include <string.h>
|
|
Packit Service |
8aa27d |
#include <stdio.h>
|
|
Packit Service |
8aa27d |
#include <stdlib.h>
|
|
Packit Service |
8aa27d |
#include <sys/stat.h>
|
|
Packit Service |
8aa27d |
#include <sys/types.h>
|
|
Packit Service |
8aa27d |
#include <grp.h>
|
|
Packit Service |
8aa27d |
#include <termios.h>
|
|
Packit Service |
8aa27d |
#include <unistd.h>
|
|
Packit Service |
8aa27d |
#include <dirent.h>
|
|
Packit Service |
8aa27d |
#include <sys/mman.h>
|
|
Packit Service |
8aa27d |
#include <pkcs11types.h>
|
|
Packit Service |
8aa27d |
#include <configparser.h>
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
#include "sw_crypt.h"
|
|
Packit Service |
8aa27d |
#include "defs.h"
|
|
Packit Service |
8aa27d |
#include "host_defs.h"
|
|
Packit Service |
8aa27d |
#include "local_types.h"
|
|
Packit Service |
8aa27d |
#include "h_extern.h"
|
|
Packit Service |
8aa27d |
#include "slotmgr.h" // for ock_snprintf
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
#define OCK_TOOL
|
|
Packit Service |
8aa27d |
#include "pkcs_utils.h"
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
#define TOKVERSION_00 0x00000000
|
|
Packit Service |
8aa27d |
#define TOKVERSION_312 0x0003000C
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
#define INVALID_TOKEN "unknown/unsupported"
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
#define HEADER_LEN 64
|
|
Packit Service |
8aa27d |
#define FOOTER_LEN 16
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
#define PKCSTOK_MIGRATE_MAX_PATH_LEN (PATH_MAX - 200)
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
pkcs_trace_level_t trace_level = TRACE_LEVEL_NONE;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
static FILE *open_datastore_file(char *buf, size_t buflen,
|
|
Packit Service |
8aa27d |
const char *datastore, const char *file,
|
|
Packit Service |
8aa27d |
const char *mode)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
FILE *res;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (ock_snprintf(buf, buflen, "%s/%s", datastore, file) != 0) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Path overflow for datastore file %s\n", file);
|
|
Packit Service |
8aa27d |
return NULL;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
res = fopen(buf, mode);
|
|
Packit Service |
8aa27d |
if (!res)
|
|
Packit Service |
8aa27d |
TRACE_ERROR("fopen(%s) failed, errno=%s\n", buf, strerror(errno));
|
|
Packit Service |
8aa27d |
return res;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
static FILE *open_tokenobject(char *buf, size_t buflen,
|
|
Packit Service |
8aa27d |
const char *datastore, const char *tokenobj,
|
|
Packit Service |
8aa27d |
const char *file, const char *mode)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
FILE *res;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (ock_snprintf(buf, buflen, "%s/%s/%s", datastore, tokenobj, file) != 0) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Path overflow for token object file %s for token %s\n",
|
|
Packit Service |
8aa27d |
file, tokenobj);
|
|
Packit Service |
8aa27d |
return NULL;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
res = fopen(buf, mode);
|
|
Packit Service |
8aa27d |
if (!res)
|
|
Packit Service |
8aa27d |
TRACE_ERROR("fopen(%s) failed, errno=%s\n", buf, strerror(errno));
|
|
Packit Service |
8aa27d |
return res;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
struct findstdll {
|
|
Packit Service |
8aa27d |
char *stdll;
|
|
Packit Service |
8aa27d |
size_t len;
|
|
Packit Service |
8aa27d |
int slotnum;
|
|
Packit Service |
8aa27d |
int activeslot;
|
|
Packit Service |
8aa27d |
int error;
|
|
Packit Service |
8aa27d |
};
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
struct parseupdate {
|
|
Packit Service |
8aa27d |
FILE *f;
|
|
Packit Service |
8aa27d |
int slotnum;
|
|
Packit Service |
8aa27d |
int activeslot;
|
|
Packit Service |
8aa27d |
};
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* Make a 3.12 format OBJECT_PUB:
|
|
Packit Service |
8aa27d |
*
|
|
Packit Service |
8aa27d |
* struct OBJECT_PUB {
|
|
Packit Service |
8aa27d |
* //-------------- <--+
|
|
Packit Service |
8aa27d |
* u32 tokversion; | 16-byte header
|
|
Packit Service |
8aa27d |
* u8 private_flag; |
|
|
Packit Service |
8aa27d |
* u8 reserved[7]; |
|
|
Packit Service |
8aa27d |
* u32 object_len; |
|
|
Packit Service |
8aa27d |
* //-------------- <--+
|
|
Packit Service |
8aa27d |
* u8 object[object_len]; | body
|
|
Packit Service |
8aa27d |
* //-------------- <--+
|
|
Packit Service |
8aa27d |
* };
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV make_OBJECT_PUB_312(char **obj_new, unsigned int *obj_new_len,
|
|
Packit Service |
8aa27d |
unsigned char *clear, unsigned int clear_len)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
struct {
|
|
Packit Service |
8aa27d |
uint32_t tokversion;
|
|
Packit Service |
8aa27d |
uint8_t private_flag;
|
|
Packit Service |
8aa27d |
uint8_t reserved[7];
|
|
Packit Service |
8aa27d |
uint32_t object_len;
|
|
Packit Service |
8aa27d |
} header;
|
|
Packit Service |
8aa27d |
uint32_t total_len;
|
|
Packit Service |
8aa27d |
char *object;
|
|
Packit Service |
8aa27d |
CK_RV ret;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
*obj_new = NULL;
|
|
Packit Service |
8aa27d |
*obj_new_len = 0;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Check parms */
|
|
Packit Service |
8aa27d |
if (!clear || clear_len == 0) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Error in parms.\n");
|
|
Packit Service |
8aa27d |
ret = CKR_ARGUMENTS_BAD;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Allocate memory for new OBJECT_PUB */
|
|
Packit Service |
8aa27d |
total_len = sizeof(header) + clear_len;
|
|
Packit Service |
8aa27d |
object = malloc(total_len);
|
|
Packit Service |
8aa27d |
if (object == NULL) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("cannot malloc %d bytes.\n", total_len);
|
|
Packit Service |
8aa27d |
ret = CKR_HOST_MEMORY;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Setup object */
|
|
Packit Service |
8aa27d |
memset(&header, 0, sizeof(header));
|
|
Packit Service |
8aa27d |
header.tokversion = htobe32(0x0003000C);
|
|
Packit Service |
8aa27d |
header.private_flag = 0x00;
|
|
Packit Service |
8aa27d |
header.object_len = htobe32(clear_len);
|
|
Packit Service |
8aa27d |
memcpy(object, &header, sizeof(header));
|
|
Packit Service |
8aa27d |
memcpy(object + sizeof(header), clear, clear_len);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
*obj_new = object;
|
|
Packit Service |
8aa27d |
*obj_new_len = total_len;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = CKR_OK;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* This function migrates the public obj to the current format.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV migrate_public_token_object(const char *data_store, const char *name,
|
|
Packit Service |
8aa27d |
unsigned char *data, unsigned long len)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
const char *tokobj = "TOK_OBJ";
|
|
Packit Service |
8aa27d |
char fname[PATH_MAX];
|
|
Packit Service |
8aa27d |
char *obj_new = NULL;
|
|
Packit Service |
8aa27d |
unsigned int obj_new_len;
|
|
Packit Service |
8aa27d |
FILE *fp = NULL;
|
|
Packit Service |
8aa27d |
CK_RV ret = 0;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Create new public object */
|
|
Packit Service |
8aa27d |
ret = make_OBJECT_PUB_312(&obj_new, &obj_new_len, data, len);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot create an OBJECT_PUB_312, ret=%08lX.\n", ret);
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Setup file name for new object */
|
|
Packit Service |
8aa27d |
fp = open_tokenobject(fname, sizeof(fname), data_store, tokobj, name, "w");
|
|
Packit Service |
8aa27d |
if (!fp) {
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
set_perm(fileno(fp));
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Save new object */
|
|
Packit Service |
8aa27d |
if (fwrite(obj_new, obj_new_len, 1, fp) != 1) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("fwrite(%s) failed, errno=%s\n", fname, strerror(errno));
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = CKR_OK;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
free(obj_new);
|
|
Packit Service |
8aa27d |
if (fp)
|
|
Packit Service |
8aa27d |
fclose(fp);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* Make a 3.12 format OBJECT_PRIV:
|
|
Packit Service |
8aa27d |
*
|
|
Packit Service |
8aa27d |
* struct OBJECT_PRIV {
|
|
Packit Service |
8aa27d |
* u32 total_len;
|
|
Packit Service |
8aa27d |
* --- auth ------- <--+
|
|
Packit Service |
8aa27d |
* u32 tokversion | 64-byte header
|
|
Packit Service |
8aa27d |
* u8 private_flag |
|
|
Packit Service |
8aa27d |
* u8 reserved[3] |
|
|
Packit Service |
8aa27d |
* u8 key_wrapped[40] |
|
|
Packit Service |
8aa27d |
* u8 iv[12] |
|
|
Packit Service |
8aa27d |
* u32 object_len |
|
|
Packit Service |
8aa27d |
* --- auth+enc --- <--+
|
|
Packit Service |
8aa27d |
* u8 object[object_len] | body
|
|
Packit Service |
8aa27d |
* ---------------- <--+
|
|
Packit Service |
8aa27d |
* u8 tag[16] | 16-byte footer
|
|
Packit Service |
8aa27d |
* ---------------- <--+
|
|
Packit Service |
8aa27d |
* }
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV make_OBJECT_PRIV_312(unsigned char **obj_new, unsigned int *obj_new_len,
|
|
Packit Service |
8aa27d |
const char *name, unsigned char *clear,
|
|
Packit Service |
8aa27d |
unsigned int clear_len, const CK_BYTE *masterkey)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
struct {
|
|
Packit Service |
8aa27d |
uint32_t tokversion;
|
|
Packit Service |
8aa27d |
uint8_t private_flag;
|
|
Packit Service |
8aa27d |
uint8_t reserved[3];
|
|
Packit Service |
8aa27d |
uint8_t key_wrapped[40];
|
|
Packit Service |
8aa27d |
uint8_t iv[12];
|
|
Packit Service |
8aa27d |
uint32_t object_len;
|
|
Packit Service |
8aa27d |
} header;
|
|
Packit Service |
8aa27d |
unsigned char *object;
|
|
Packit Service |
8aa27d |
CK_BYTE obj_key[32];
|
|
Packit Service |
8aa27d |
uint32_t total_len;
|
|
Packit Service |
8aa27d |
CK_RV ret;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
*obj_new = NULL;
|
|
Packit Service |
8aa27d |
*obj_new_len = 0;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Check parms */
|
|
Packit Service |
8aa27d |
if (!name || !clear || clear_len == 0 || !masterkey) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Error in parms.\n");
|
|
Packit Service |
8aa27d |
ret = CKR_ARGUMENTS_BAD;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* An obj name has by definition 8 chars */
|
|
Packit Service |
8aa27d |
if (strlen(name) != 8) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("obj name %s does not have 8 chars, OBJ.IDX probably corrupted.\n",
|
|
Packit Service |
8aa27d |
name);
|
|
Packit Service |
8aa27d |
ret = CKR_ARGUMENTS_BAD;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Allocate memory for new OBJECT_PRIV */
|
|
Packit Service |
8aa27d |
total_len = sizeof(header) + clear_len + FOOTER_LEN;
|
|
Packit Service |
8aa27d |
object = malloc(total_len);
|
|
Packit Service |
8aa27d |
if (object == NULL) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("cannot malloc %d bytes.\n", total_len);
|
|
Packit Service |
8aa27d |
ret = CKR_HOST_MEMORY;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Create new object key */
|
|
Packit Service |
8aa27d |
ret = local_rng(obj_key, 32);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("local_rng failed with ret=%08lX.\n", ret);
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Setup header */
|
|
Packit Service |
8aa27d |
memset(&header, 0, sizeof(header));
|
|
Packit Service |
8aa27d |
header.tokversion = htobe32(0x0003000C);
|
|
Packit Service |
8aa27d |
header.private_flag = 0x01;
|
|
Packit Service |
8aa27d |
ret = aes_256_wrap(header.key_wrapped, obj_key, masterkey);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("aes_256_wrap failed with ret=%08lX.\n", ret);
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
memcpy(header.iv, name, 8);
|
|
Packit Service |
8aa27d |
header.iv[8] = 0;
|
|
Packit Service |
8aa27d |
header.iv[9] = 0;
|
|
Packit Service |
8aa27d |
header.iv[10] = 0;
|
|
Packit Service |
8aa27d |
header.iv[11] = 1;
|
|
Packit Service |
8aa27d |
header.object_len = htobe32(clear_len);
|
|
Packit Service |
8aa27d |
memcpy(object, &header, HEADER_LEN);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Encrypt body */
|
|
Packit Service |
8aa27d |
ret = aes_256_gcm_seal(object + HEADER_LEN, /* ciphertext */
|
|
Packit Service |
8aa27d |
object + HEADER_LEN + clear_len, /* tag */
|
|
Packit Service |
8aa27d |
object, HEADER_LEN, /* aad */
|
|
Packit Service |
8aa27d |
clear, clear_len, /* plaintext */
|
|
Packit Service |
8aa27d |
obj_key, /* key */
|
|
Packit Service |
8aa27d |
header.iv /* iv */);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("aes_256_gcm_seal failed with rc=%08lX.\n", ret);
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
*obj_new = object;
|
|
Packit Service |
8aa27d |
*obj_new_len = total_len;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = CKR_OK;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* Decrypts the given version 0.0 private object with given old masterkey.
|
|
Packit Service |
8aa27d |
*
|
|
Packit Service |
8aa27d |
* struct OBJECT_PRIV {
|
|
Packit Service |
8aa27d |
* u32 total_len;
|
|
Packit Service |
8aa27d |
* u8 private_flag;
|
|
Packit Service |
8aa27d |
* //--- enc --- <- enc_old starts here
|
|
Packit Service |
8aa27d |
* u32 object_len;
|
|
Packit Service |
8aa27d |
* u8 object[object_len];
|
|
Packit Service |
8aa27d |
* u8 sha1[20];
|
|
Packit Service |
8aa27d |
* u8 padding[padding_len];
|
|
Packit Service |
8aa27d |
* };
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV decrypt_OBJECT_PRIV_00(unsigned char **clear, unsigned int *clear_len,
|
|
Packit Service |
8aa27d |
unsigned char *enc_old, unsigned int enc_len,
|
|
Packit Service |
8aa27d |
const CK_BYTE *masterkey_old)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
CK_ULONG_32 obj_data_len_32;
|
|
Packit Service |
8aa27d |
CK_BYTE hash_sha[SHA1_HASH_SIZE];
|
|
Packit Service |
8aa27d |
CK_BYTE des3_key[MAX_MASTER_KEY_SIZE];
|
|
Packit Service |
8aa27d |
unsigned char *tmp_clear, *raw_clear;
|
|
Packit Service |
8aa27d |
CK_ULONG tmp_clear_len;
|
|
Packit Service |
8aa27d |
CK_RV ret;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
*clear = NULL;
|
|
Packit Service |
8aa27d |
*clear_len = 0;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Allocate storage for clear output */
|
|
Packit Service |
8aa27d |
tmp_clear = malloc(enc_len);
|
|
Packit Service |
8aa27d |
if (!tmp_clear) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot malloc %d bytes, errno=%s.\n",
|
|
Packit Service |
8aa27d |
enc_len, strerror(errno));
|
|
Packit Service |
8aa27d |
ret = CKR_HOST_MEMORY;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Decrypt old object */
|
|
Packit Service |
8aa27d |
memcpy(des3_key, masterkey_old, MAX_MASTER_KEY_SIZE);
|
|
Packit Service |
8aa27d |
ret = sw_des3_cbc_decrypt(enc_old, enc_len, tmp_clear, &tmp_clear_len,
|
|
Packit Service |
8aa27d |
(CK_BYTE *)"10293847", des3_key);
|
|
Packit Service |
8aa27d |
if (ret) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("sw_des3_cbc_decrypt failed with ret=%08lX\n", ret);
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Validate the length */
|
|
Packit Service |
8aa27d |
memcpy(&obj_data_len_32, tmp_clear, sizeof(CK_ULONG_32));
|
|
Packit Service |
8aa27d |
if (obj_data_len_32 >= enc_len) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Decrypted object data length %d inconsistent\n",
|
|
Packit Service |
8aa27d |
obj_data_len_32);
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Validate the hash */
|
|
Packit Service |
8aa27d |
ret = compute_sha1((char *)(tmp_clear + sizeof(CK_ULONG_32)),
|
|
Packit Service |
8aa27d |
obj_data_len_32, (char *)hash_sha);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("compute_sha1 failed with ret=%08lX\n", ret);
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (memcmp(tmp_clear + sizeof(CK_ULONG_32) + obj_data_len_32, hash_sha,
|
|
Packit Service |
8aa27d |
SHA1_HASH_SIZE) != 0) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Stored hash does not match with newly calculated hash.\n");
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* At this point, tmp_clear points to the full decrypted obj data:
|
|
Packit Service |
8aa27d |
* | 4 bytes len | clear obj[obj_data_len_32] | 20 bytes sha | padding |
|
|
Packit Service |
8aa27d |
* But the caller only wants clear obj[obj_data_len_32].
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
raw_clear = malloc(obj_data_len_32);
|
|
Packit Service |
8aa27d |
if (!raw_clear) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot malloc %d bytes, errno=%s.\n", enc_len, strerror(errno));
|
|
Packit Service |
8aa27d |
ret = CKR_HOST_MEMORY;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
memcpy(raw_clear, tmp_clear + sizeof(CK_ULONG_32), obj_data_len_32);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
*clear = raw_clear;
|
|
Packit Service |
8aa27d |
*clear_len = (unsigned int)obj_data_len_32;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = CKR_OK;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
free(tmp_clear);
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* This function migrates the private obj to the current format.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV migrate_private_token_object(const char *data_store, const char *name,
|
|
Packit Service |
8aa27d |
unsigned char *data, unsigned long len,
|
|
Packit Service |
8aa27d |
const CK_BYTE *masterkey_old,
|
|
Packit Service |
8aa27d |
const CK_BYTE *masterkey_new)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
const char *tokobj = "TOK_OBJ";
|
|
Packit Service |
8aa27d |
char fname[PATH_MAX];
|
|
Packit Service |
8aa27d |
unsigned char *clear = NULL;
|
|
Packit Service |
8aa27d |
unsigned int clear_len;
|
|
Packit Service |
8aa27d |
unsigned char *obj_new = NULL;
|
|
Packit Service |
8aa27d |
unsigned int obj_new_len;
|
|
Packit Service |
8aa27d |
FILE *fp = NULL;
|
|
Packit Service |
8aa27d |
CK_RV ret;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Decrypt old object */
|
|
Packit Service |
8aa27d |
ret = decrypt_OBJECT_PRIV_00(&clear, &clear_len, data, len, masterkey_old);
|
|
Packit Service |
8aa27d |
if (ret != 0) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot decrypt old object with old masterkey, ret=%08lX.\n", ret);
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Create new object */
|
|
Packit Service |
8aa27d |
ret = make_OBJECT_PRIV_312(&obj_new, &obj_new_len, name, clear, clear_len,
|
|
Packit Service |
8aa27d |
masterkey_new);
|
|
Packit Service |
8aa27d |
if (ret != 0) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("make_OBJECT_PRIV_312 failed with ret=%08lX.\n", ret);
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Create file name for new object */
|
|
Packit Service |
8aa27d |
fp = open_tokenobject(fname, sizeof(fname), data_store, tokobj, name, "w");
|
|
Packit Service |
8aa27d |
if (!fp) {
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
set_perm(fileno(fp));
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Save new object */
|
|
Packit Service |
8aa27d |
if (fwrite(obj_new, obj_new_len, 1, fp) != 1) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("fwrite(%s) failed, errno=%s\n", fname, strerror(errno));
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = CKR_OK;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (fp) {
|
|
Packit Service |
8aa27d |
fclose(fp);
|
|
Packit Service |
8aa27d |
fp = NULL;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
free(clear);
|
|
Packit Service |
8aa27d |
free(obj_new);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* Reads a format 0.0 object:
|
|
Packit Service |
8aa27d |
*
|
|
Packit Service |
8aa27d |
* struct OBJECT {
|
|
Packit Service |
8aa27d |
* u32 total_len; <- indicates old or new format
|
|
Packit Service |
8aa27d |
* u8 private_flag;
|
|
Packit Service |
8aa27d |
* u8 object; <- can be public or private
|
|
Packit Service |
8aa27d |
* };
|
|
Packit Service |
8aa27d |
*
|
|
Packit Service |
8aa27d |
* The total_len field has been already read to decide whether this
|
|
Packit Service |
8aa27d |
* object is old or new. Its value is passed via the size parm.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV read_object_00(FILE *fp, const char *name, unsigned int size,
|
|
Packit Service |
8aa27d |
unsigned char **obj, unsigned int *obj_len,
|
|
Packit Service |
8aa27d |
CK_BBOOL *obj_priv)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
CK_BBOOL priv;
|
|
Packit Service |
8aa27d |
size_t read_size;
|
|
Packit Service |
8aa27d |
unsigned char *buf = NULL;
|
|
Packit Service |
8aa27d |
CK_RV ret;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
*obj = NULL;
|
|
Packit Service |
8aa27d |
*obj_len = 0;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Check parms */
|
|
Packit Service |
8aa27d |
if (!fp || !name) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Arguments bad.\n");
|
|
Packit Service |
8aa27d |
ret = CKR_ARGUMENTS_BAD;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Read 1-char private flag */
|
|
Packit Service |
8aa27d |
read_size = fread(&priv, sizeof(CK_BBOOL), 1, fp);
|
|
Packit Service |
8aa27d |
if (read_size != 1) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot read private flag from old object %s.\n", name);
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Allocate buffer for obj */
|
|
Packit Service |
8aa27d |
size = size - sizeof(CK_ULONG_32) - sizeof(CK_BBOOL);
|
|
Packit Service |
8aa27d |
buf = malloc(size);
|
|
Packit Service |
8aa27d |
if (!buf) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot malloc %d bytes for object %s.\n", size, name);
|
|
Packit Service |
8aa27d |
ret = CKR_HOST_MEMORY;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Read obj into buf */
|
|
Packit Service |
8aa27d |
read_size = fread((char *)buf, 1, size, fp);
|
|
Packit Service |
8aa27d |
if (read_size != size) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot read old object %s.\n", name);
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
*obj = buf;
|
|
Packit Service |
8aa27d |
*obj_len = size;
|
|
Packit Service |
8aa27d |
*obj_priv = priv;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = CKR_OK;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* Reads the token object given by name from given data_store and returns
|
|
Packit Service |
8aa27d |
* pointers to the object, its length, and indications whether the object
|
|
Packit Service |
8aa27d |
* is in 0.0 or 3.12 format and whether it's private.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV read_object(const char *data_store, const char *name,
|
|
Packit Service |
8aa27d |
unsigned char **obj, unsigned int *obj_len,
|
|
Packit Service |
8aa27d |
CK_ULONG *version, CK_BBOOL *obj_priv)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
char fname[PATH_MAX];
|
|
Packit Service |
8aa27d |
unsigned int size = 0;
|
|
Packit Service |
8aa27d |
size_t read_size;
|
|
Packit Service |
8aa27d |
FILE *fp;
|
|
Packit Service |
8aa27d |
CK_RV ret;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
*obj = NULL;
|
|
Packit Service |
8aa27d |
*obj_len = 0;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Open token object file */
|
|
Packit Service |
8aa27d |
fp = open_tokenobject(fname, sizeof(fname), data_store, "TOK_OBJ", name, "r");
|
|
Packit Service |
8aa27d |
if (!fp) {
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Read 32-bit size field */
|
|
Packit Service |
8aa27d |
read_size = fread(&size, sizeof(CK_ULONG_32), 1, fp);
|
|
Packit Service |
8aa27d |
if (read_size != 1) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot read %ld bytes from %s, read_size = %ld. "
|
|
Packit Service |
8aa27d |
"Object probably empty or corrupted.\n",
|
|
Packit Service |
8aa27d |
sizeof(CK_ULONG_32), name, read_size);
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Check if this object is old or current */
|
|
Packit Service |
8aa27d |
if (size == TOKVERSION_312) {
|
|
Packit Service |
8aa27d |
TRACE_INFO("%s is already in current format, nothing to do.\n", name);
|
|
Packit Service |
8aa27d |
ret = CKR_OK;
|
|
Packit Service |
8aa27d |
*version = TOKVERSION_312;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Read old object */
|
|
Packit Service |
8aa27d |
*version = TOKVERSION_00;
|
|
Packit Service |
8aa27d |
ret = read_object_00(fp, name, size, obj, obj_len, obj_priv);
|
|
Packit Service |
8aa27d |
if (ret != 0) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot read old object %s.\n", name);
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = CKR_OK;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (fp)
|
|
Packit Service |
8aa27d |
fclose(fp);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* Migrate the token objects from old to new format. Some of the token objects
|
|
Packit Service |
8aa27d |
* may be in old and some may be in new format if a previous migration run
|
|
Packit Service |
8aa27d |
* was interrupted.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV migrate_token_objects(const char *data_store, const CK_BYTE *masterkey_old,
|
|
Packit Service |
8aa27d |
const CK_BYTE *masterkey_new,
|
|
Packit Service |
8aa27d |
const CK_BYTE *so_wrap_key,
|
|
Packit Service |
8aa27d |
const CK_BYTE *user_wrap_key)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
const char *tokobj = "TOK_OBJ";
|
|
Packit Service |
8aa27d |
const char *objidx = "OBJ.IDX";
|
|
Packit Service |
8aa27d |
FILE *fp = NULL;
|
|
Packit Service |
8aa27d |
unsigned char *obj = NULL;
|
|
Packit Service |
8aa27d |
unsigned int obj_len;
|
|
Packit Service |
8aa27d |
char tmp[PATH_MAX];
|
|
Packit Service |
8aa27d |
char iname[PATH_MAX + 1 + strlen(tokobj) + 1 + strlen(objidx) + 1];
|
|
Packit Service |
8aa27d |
CK_BBOOL priv;
|
|
Packit Service |
8aa27d |
CK_ULONG version;
|
|
Packit Service |
8aa27d |
int count = 0, scount = 0;
|
|
Packit Service |
8aa27d |
CK_RV ret;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Check parms */
|
|
Packit Service |
8aa27d |
if (!data_store || !masterkey_old || !masterkey_new || !so_wrap_key
|
|
Packit Service |
8aa27d |
|| !user_wrap_key) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Invalid parms.\n");
|
|
Packit Service |
8aa27d |
ret = CKR_ARGUMENTS_BAD;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Open index file OBJ.IDX */
|
|
Packit Service |
8aa27d |
fp = open_tokenobject(iname, sizeof(iname),
|
|
Packit Service |
8aa27d |
data_store, tokobj, objidx, "r");
|
|
Packit Service |
8aa27d |
if (!fp) {
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Migrate items from OBJ.IDX */
|
|
Packit Service |
8aa27d |
while (fgets(tmp, PATH_MAX, fp)) {
|
|
Packit Service |
8aa27d |
tmp[strlen(tmp) - 1] = 0;
|
|
Packit Service |
8aa27d |
ret = read_object(data_store, tmp, &obj, &obj_len, &version, &priv;;
|
|
Packit Service |
8aa27d |
if (ret == 0 && version == TOKVERSION_00) {
|
|
Packit Service |
8aa27d |
if (priv) {
|
|
Packit Service |
8aa27d |
ret = migrate_private_token_object(data_store, tmp,
|
|
Packit Service |
8aa27d |
obj, obj_len, masterkey_old, masterkey_new);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot migrate private object %s, continuing ... \n", tmp);
|
|
Packit Service |
8aa27d |
} else
|
|
Packit Service |
8aa27d |
scount++;
|
|
Packit Service |
8aa27d |
} else {
|
|
Packit Service |
8aa27d |
ret = migrate_public_token_object(data_store, tmp,
|
|
Packit Service |
8aa27d |
obj, obj_len);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot migrate public object %s, continuing ... \n", tmp);
|
|
Packit Service |
8aa27d |
} else
|
|
Packit Service |
8aa27d |
scount++;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (obj) {
|
|
Packit Service |
8aa27d |
free(obj);
|
|
Packit Service |
8aa27d |
obj = NULL;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
count++;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* OBJ.IDX must be at eof here */
|
|
Packit Service |
8aa27d |
if (!feof(fp)) {
|
|
Packit Service |
8aa27d |
TRACE_WARN("OBJ.IDX is not at eof after object %s, should not happen.\n",
|
|
Packit Service |
8aa27d |
tmp);
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Close OBJ.IDX */
|
|
Packit Service |
8aa27d |
fclose(fp);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = CKR_OK;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
TRACE_NONE("Migrated %d object(s) out of %d object(s).\n", scount, count);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* loads the new aes256 masterkey.
|
|
Packit Service |
8aa27d |
* The new format defines the MK to be an AES-256 key. Its unencrypted format
|
|
Packit Service |
8aa27d |
* are just the 32 key bytes. Its encrypted format is a 40 byte key blob
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV load_masterkey_312(const char *data_store, const char *mkfile,
|
|
Packit Service |
8aa27d |
const char *pin, TOKEN_DATA *tokdata,
|
|
Packit Service |
8aa27d |
CK_BYTE *masterkey)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
FILE *fp = NULL;
|
|
Packit Service |
8aa27d |
CK_RV ret;
|
|
Packit Service |
8aa27d |
int rc;
|
|
Packit Service |
8aa27d |
char fname[PATH_MAX];
|
|
Packit Service |
8aa27d |
unsigned char inbuf[40];
|
|
Packit Service |
8aa27d |
unsigned char wrap_key[32];
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Open file */
|
|
Packit Service |
8aa27d |
memset(fname, 0, PATH_MAX);
|
|
Packit Service |
8aa27d |
snprintf(fname, PATH_MAX, "%s/%s", data_store, mkfile);
|
|
Packit Service |
8aa27d |
fp = fopen(fname, "r");
|
|
Packit Service |
8aa27d |
if (!fp) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("fopen(%s) failed, errno=%s\n", fname, strerror(errno));
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Read wrapped key from file */
|
|
Packit Service |
8aa27d |
rc = fread(inbuf, sizeof(inbuf), 1, fp);
|
|
Packit Service |
8aa27d |
if (rc != 1) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot read %ld bytes from %s.\n", sizeof(inbuf), fname);
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Derive wrapping key from pin and public info in TOKEN_DATA */
|
|
Packit Service |
8aa27d |
if (strstr(mkfile,"MK_SO")) {
|
|
Packit Service |
8aa27d |
rc = PKCS5_PBKDF2_HMAC(pin, strlen(pin),
|
|
Packit Service |
8aa27d |
tokdata->dat.so_wrap_salt, 64,
|
|
Packit Service |
8aa27d |
tokdata->dat.so_wrap_it, EVP_sha512(),
|
|
Packit Service |
8aa27d |
256 / 8, wrap_key);
|
|
Packit Service |
8aa27d |
} else {
|
|
Packit Service |
8aa27d |
rc = PKCS5_PBKDF2_HMAC(pin, strlen(pin),
|
|
Packit Service |
8aa27d |
tokdata->dat.user_wrap_salt, 64,
|
|
Packit Service |
8aa27d |
tokdata->dat.user_wrap_it, EVP_sha512(),
|
|
Packit Service |
8aa27d |
256 / 8, wrap_key);
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
if (rc != 1) {
|
|
Packit Service |
8aa27d |
TRACE_INFO("PKCS5_PBKDF2_HMAC returned rc=%08X.\n", rc);
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Decrypt buffer with pin-related wrapping key */
|
|
Packit Service |
8aa27d |
rc = aes_256_unwrap(masterkey, inbuf, wrap_key);
|
|
Packit Service |
8aa27d |
if (rc != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("aes_256_unwrap failed with rc=%08X.\n", rc);
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = CKR_OK;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (fp)
|
|
Packit Service |
8aa27d |
fclose(fp);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* loads the old des3 masterkey from given file with given PIN.
|
|
Packit Service |
8aa27d |
* The format is:
|
|
Packit Service |
8aa27d |
*
|
|
Packit Service |
8aa27d |
* struct MK {
|
|
Packit Service |
8aa27d |
* u8 MK [24 or 64 (cca)];
|
|
Packit Service |
8aa27d |
* u8 sha1 [20];
|
|
Packit Service |
8aa27d |
* u8 padding[4];
|
|
Packit Service |
8aa27d |
* };
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV load_masterkey_00(const char *mkfile, const char *pin,
|
|
Packit Service |
8aa27d |
CK_BYTE *masterkey)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
CK_BYTE des3_key[3 * DES_KEY_SIZE];
|
|
Packit Service |
8aa27d |
char hash_sha[SHA1_HASH_SIZE];
|
|
Packit Service |
8aa27d |
char pin_md5_hash[MD5_HASH_SIZE];
|
|
Packit Service |
8aa27d |
unsigned char *cipher = NULL;
|
|
Packit Service |
8aa27d |
unsigned char *clear = NULL;
|
|
Packit Service |
8aa27d |
unsigned long cipher_len, clear_len;
|
|
Packit Service |
8aa27d |
CK_ULONG master_key_len = 0L;
|
|
Packit Service |
8aa27d |
int file_size = 0;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
CK_RV ret;
|
|
Packit Service |
8aa27d |
int rc;
|
|
Packit Service |
8aa27d |
FILE *fp = NULL;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
fp = fopen(mkfile, "r");
|
|
Packit Service |
8aa27d |
if (!fp) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("fopen(%s) failed, errno=%s\n", mkfile, strerror(errno));
|
|
Packit Service |
8aa27d |
return CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Determine the master key length */
|
|
Packit Service |
8aa27d |
fseek(fp, 0L, SEEK_END);
|
|
Packit Service |
8aa27d |
file_size = ftell(fp);
|
|
Packit Service |
8aa27d |
switch (file_size) {
|
|
Packit Service |
8aa27d |
case MK_FILE_SIZE_00_CCA: /* CCA token */
|
|
Packit Service |
8aa27d |
master_key_len = MASTER_KEY_SIZE_CCA;
|
|
Packit Service |
8aa27d |
break;
|
|
Packit Service |
8aa27d |
case MK_FILE_SIZE_00: /* All other tokens */
|
|
Packit Service |
8aa27d |
master_key_len = MASTER_KEY_SIZE;
|
|
Packit Service |
8aa27d |
break;
|
|
Packit Service |
8aa27d |
default:
|
|
Packit Service |
8aa27d |
/* Unknown MK format, should not occur. */
|
|
Packit Service |
8aa27d |
TRACE_ERROR("%s has an unknown file size of %d bytes. Should be either 48 or 88 bytes.\n",
|
|
Packit Service |
8aa27d |
mkfile, file_size);
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
rewind(fp);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Read file contents */
|
|
Packit Service |
8aa27d |
clear_len = cipher_len =
|
|
Packit Service |
8aa27d |
(master_key_len + SHA1_HASH_SIZE +
|
|
Packit Service |
8aa27d |
(DES_BLOCK_SIZE - 1)) & ~(DES_BLOCK_SIZE - 1);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
cipher = malloc(cipher_len);
|
|
Packit Service |
8aa27d |
clear = malloc(clear_len);
|
|
Packit Service |
8aa27d |
if (cipher == NULL || clear == NULL) {
|
|
Packit Service |
8aa27d |
ret = CKR_HOST_MEMORY;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
rc = fread(cipher, cipher_len, 1, fp);
|
|
Packit Service |
8aa27d |
if (rc != 1) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot read %ld bytes from %s\n", cipher_len, mkfile);
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Decrypt the masterkey */
|
|
Packit Service |
8aa27d |
ret = compute_md5((char *)pin, strlen(pin), pin_md5_hash);
|
|
Packit Service |
8aa27d |
if (ret) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Error calculating MD5 of PIN, ret=%08lX\n", ret);
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
memcpy(des3_key, pin_md5_hash, MD5_HASH_SIZE);
|
|
Packit Service |
8aa27d |
memcpy(des3_key + MD5_HASH_SIZE, pin_md5_hash, DES_KEY_SIZE);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = sw_des3_cbc_decrypt(cipher, cipher_len, clear,
|
|
Packit Service |
8aa27d |
&clear_len, (unsigned char *) "12345678",
|
|
Packit Service |
8aa27d |
des3_key);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("failed to decrypt master key file after read, ret=%08lX\n", ret);
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* compare the hashes to verify integrity */
|
|
Packit Service |
8aa27d |
ret = compute_sha1((char *)clear, master_key_len, hash_sha);
|
|
Packit Service |
8aa27d |
if (ret) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Failed to compute sha1 for masterkey, ret=%08lX\n", ret);
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (memcmp(hash_sha, clear + master_key_len, SHA1_HASH_SIZE) != 0) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("%s appears to be tampered! Cannot migrate.\n", mkfile);
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
memcpy(masterkey, clear, master_key_len);
|
|
Packit Service |
8aa27d |
ret = 0;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
if (fp)
|
|
Packit Service |
8aa27d |
fclose(fp);
|
|
Packit Service |
8aa27d |
free(clear);
|
|
Packit Service |
8aa27d |
free(cipher);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* Check if the given conf_dir exists and contains the opencryptoki.conf.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_BBOOL conffile_exists(const char *conf_dir)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
char fname[PATH_MAX];
|
|
Packit Service |
8aa27d |
struct stat statbuf;
|
|
Packit Service |
8aa27d |
DIR *dir;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
TRACE_INFO("Checking if config file exists in %s ...\n", conf_dir);
|
|
Packit Service |
8aa27d |
dir = opendir(conf_dir);
|
|
Packit Service |
8aa27d |
if (dir == NULL) {
|
|
Packit Service |
8aa27d |
TRACE_INFO("Cannot open %s.\n", conf_dir);
|
|
Packit Service |
8aa27d |
return CK_FALSE;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Check if opencryptoki.conf exists */
|
|
Packit Service |
8aa27d |
memset(fname, 0, PATH_MAX);
|
|
Packit Service |
8aa27d |
snprintf(fname, PATH_MAX, "%s/opencryptoki.conf", conf_dir);
|
|
Packit Service |
8aa27d |
if (stat(fname, &statbuf) != 0) {
|
|
Packit Service |
8aa27d |
TRACE_INFO("Cannot find %s.\n", fname);
|
|
Packit Service |
8aa27d |
closedir(dir);
|
|
Packit Service |
8aa27d |
return CK_FALSE;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
closedir(dir);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return CK_TRUE;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* Check if the given data_store directory exists.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_BBOOL datastore_exists(const char *data_store)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
DIR *dir;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
TRACE_INFO("Checking if datastore %s exists ...\n", data_store);
|
|
Packit Service |
8aa27d |
dir = opendir(data_store);
|
|
Packit Service |
8aa27d |
if (dir == NULL) {
|
|
Packit Service |
8aa27d |
TRACE_INFO("Cannot open %s.\n", data_store);
|
|
Packit Service |
8aa27d |
return CK_FALSE;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
closedir(dir);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return CK_TRUE;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* Check if the data store is empty, which is the case when
|
|
Packit Service |
8aa27d |
* there are no entries in OBJ.IDX.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_BBOOL datastore_empty(const char *data_store)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
char fname[PATH_MAX];
|
|
Packit Service |
8aa27d |
struct stat statbuf;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
TRACE_INFO("Checking if data store is empty ...\n");
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Check if OBJ.IDX exists */
|
|
Packit Service |
8aa27d |
memset(fname, 0, PATH_MAX);
|
|
Packit Service |
8aa27d |
snprintf(fname, PATH_MAX, "%s/TOK_OBJ/OBJ.IDX", data_store);
|
|
Packit Service |
8aa27d |
if (stat(fname, &statbuf) != 0) {
|
|
Packit Service |
8aa27d |
TRACE_INFO("Cannot find %s, data store probably empty.\n", fname);
|
|
Packit Service |
8aa27d |
return CK_TRUE;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Check if OBJ.IDX is empty */
|
|
Packit Service |
8aa27d |
if (statbuf.st_size == 0) {
|
|
Packit Service |
8aa27d |
TRACE_INFO("OBJ.IDX file is empty. Thus no objects to migrate.\n");
|
|
Packit Service |
8aa27d |
return CK_TRUE;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return CK_FALSE;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
*
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV load_MK_SO_00(const char *data_store, const char *sopin,
|
|
Packit Service |
8aa27d |
CK_BYTE *masterkey)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
const char *mkso = "MK_SO";
|
|
Packit Service |
8aa27d |
char fname[PATH_MAX];
|
|
Packit Service |
8aa27d |
CK_RV ret;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Get masterkey from MK_SO. This also verifies SO PIN is correct */
|
|
Packit Service |
8aa27d |
memset(masterkey, 0, MAX_MASTER_KEY_SIZE);
|
|
Packit Service |
8aa27d |
if (ock_snprintf(fname, sizeof(fname), "%s/%s", data_store, mkso) != 0) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("path name for old MK_SO too long\n");
|
|
Packit Service |
8aa27d |
return CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
ret = load_masterkey_00(fname, sopin, masterkey);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot load old masterkey from MK_SO, ret=%08lX.\n", ret);
|
|
Packit Service |
8aa27d |
// We cannot do anything more here, even when some objs are still old.
|
|
Packit Service |
8aa27d |
// We would need the old key in order to open an old obj.
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
*
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV load_MK_USER_00(const char *data_store, const char *userpin,
|
|
Packit Service |
8aa27d |
CK_BYTE *masterkey)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
const char *mkuser = "MK_USER";
|
|
Packit Service |
8aa27d |
char fname[PATH_MAX];
|
|
Packit Service |
8aa27d |
CK_RV ret;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Get masterkey from MK_USER. This also verifies user PIN is correct */
|
|
Packit Service |
8aa27d |
memset(masterkey, 0, MAX_MASTER_KEY_SIZE);
|
|
Packit Service |
8aa27d |
if (ock_snprintf(fname, sizeof(fname), "%s/%s", data_store, mkuser) != 0) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("path name for old MK_USER too long\n");
|
|
Packit Service |
8aa27d |
return CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
ret = load_masterkey_00(fname, userpin, masterkey);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot load old masterkey from MK_USER, ret=%08lX.\n", ret);
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
*
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV load_MK_SO_312(const char *data_store, const char *sopin,
|
|
Packit Service |
8aa27d |
TOKEN_DATA *tokdata, CK_BYTE *masterkey)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
CK_RV ret;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Get masterkey from MK_SO_312. This also verifies SO PIN is correct */
|
|
Packit Service |
8aa27d |
memset(masterkey, 0, MAX_MASTER_KEY_SIZE);
|
|
Packit Service |
8aa27d |
ret = load_masterkey_312(data_store, "MK_SO_312", sopin, tokdata, masterkey);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot load masterkey from MK_SO_312, ret=%08lX.\n", ret);
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
*
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV load_MK_USER_312(const char *data_store, const char *userpin,
|
|
Packit Service |
8aa27d |
TOKEN_DATA *tokdata, CK_BYTE *masterkey)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
CK_RV ret;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Get masterkey from MK_USER_312. This also verifies user PIN is correct */
|
|
Packit Service |
8aa27d |
memset(masterkey, 0, MAX_MASTER_KEY_SIZE);
|
|
Packit Service |
8aa27d |
ret = load_masterkey_312(data_store, "MK_USER_312", userpin, tokdata, masterkey);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot load masterkey from MK_USER_312, ret=%08lX.\n", ret);
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* Loads the NVTOK.DAT and returns the TOKEN_DATA struct.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV load_NVTOK_DAT(const char *data_store, const char *nvtok_name,
|
|
Packit Service |
8aa27d |
TOKEN_DATA *td)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
char fname[PATH_MAX];
|
|
Packit Service |
8aa27d |
struct stat stbuf;
|
|
Packit Service |
8aa27d |
int fd;
|
|
Packit Service |
8aa27d |
size_t tdlen;
|
|
Packit Service |
8aa27d |
FILE *fp = NULL;
|
|
Packit Service |
8aa27d |
CK_RV ret;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Check parms */
|
|
Packit Service |
8aa27d |
if (!data_store || !nvtok_name || !td) {
|
|
Packit Service |
8aa27d |
ret = CKR_ARGUMENTS_BAD;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Read the NVTOK.DAT */
|
|
Packit Service |
8aa27d |
fp = open_datastore_file(fname, sizeof(fname), data_store, nvtok_name, "r");
|
|
Packit Service |
8aa27d |
if (!fp)
|
|
Packit Service |
8aa27d |
return CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
fd = fileno(fp);
|
|
Packit Service |
8aa27d |
if ((fstat(fd, &stbuf) != 0) || (!S_ISREG(stbuf.st_mode))) {
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Check if this NVTOK.DAT is old or new */
|
|
Packit Service |
8aa27d |
if (stbuf.st_size == sizeof(TOKEN_DATA_OLD)) {
|
|
Packit Service |
8aa27d |
/* old data store/pin format */
|
|
Packit Service |
8aa27d |
tdlen = sizeof(TOKEN_DATA_OLD);
|
|
Packit Service |
8aa27d |
} else if (stbuf.st_size == sizeof(TOKEN_DATA)) {
|
|
Packit Service |
8aa27d |
/* new data store/pin format */
|
|
Packit Service |
8aa27d |
tdlen = sizeof(TOKEN_DATA);
|
|
Packit Service |
8aa27d |
} else {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("%s has an invalid size of %ld bytes. Neither old nor new token format.\n",
|
|
Packit Service |
8aa27d |
fname, stbuf.st_size);
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Read TOKEN_DATA */
|
|
Packit Service |
8aa27d |
ret = fread(td, tdlen, 1, fp);
|
|
Packit Service |
8aa27d |
if (ret != 1) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot read %s, errno=%s\n", fname, strerror(errno));
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (stbuf.st_size == sizeof(TOKEN_DATA)) {
|
|
Packit Service |
8aa27d |
/* The 312 version always uses big endian */
|
|
Packit Service |
8aa27d |
td->token_info.flags = be32toh(td->token_info.flags);
|
|
Packit Service |
8aa27d |
td->token_info.ulMaxSessionCount
|
|
Packit Service |
8aa27d |
= be32toh(td->token_info.ulMaxSessionCount);
|
|
Packit Service |
8aa27d |
td->token_info.ulSessionCount
|
|
Packit Service |
8aa27d |
= be32toh(td->token_info.ulSessionCount);
|
|
Packit Service |
8aa27d |
td->token_info.ulMaxRwSessionCount
|
|
Packit Service |
8aa27d |
= be32toh(td->token_info.ulMaxRwSessionCount);
|
|
Packit Service |
8aa27d |
td->token_info.ulRwSessionCount
|
|
Packit Service |
8aa27d |
= be32toh(td->token_info.ulRwSessionCount);
|
|
Packit Service |
8aa27d |
td->token_info.ulMaxPinLen = be32toh(td->token_info.ulMaxPinLen);
|
|
Packit Service |
8aa27d |
td->token_info.ulMinPinLen = be32toh(td->token_info.ulMinPinLen);
|
|
Packit Service |
8aa27d |
td->token_info.ulTotalPublicMemory
|
|
Packit Service |
8aa27d |
= be32toh(td->token_info.ulTotalPublicMemory);
|
|
Packit Service |
8aa27d |
td->token_info.ulFreePublicMemory
|
|
Packit Service |
8aa27d |
= be32toh(td->token_info.ulFreePublicMemory);
|
|
Packit Service |
8aa27d |
td->token_info.ulTotalPrivateMemory
|
|
Packit Service |
8aa27d |
= be32toh(td->token_info.ulTotalPrivateMemory);
|
|
Packit Service |
8aa27d |
td->token_info.ulFreePrivateMemory
|
|
Packit Service |
8aa27d |
= be32toh(td->token_info.ulFreePrivateMemory);
|
|
Packit Service |
8aa27d |
td->tweak_vector.allow_weak_des
|
|
Packit Service |
8aa27d |
= be32toh(td->tweak_vector.allow_weak_des);
|
|
Packit Service |
8aa27d |
td->tweak_vector.check_des_parity
|
|
Packit Service |
8aa27d |
= be32toh(td->tweak_vector.check_des_parity);
|
|
Packit Service |
8aa27d |
td->tweak_vector.allow_key_mods
|
|
Packit Service |
8aa27d |
= be32toh(td->tweak_vector.allow_key_mods);
|
|
Packit Service |
8aa27d |
td->tweak_vector.netscape_mods
|
|
Packit Service |
8aa27d |
= be32toh(td->tweak_vector.netscape_mods);
|
|
Packit Service |
8aa27d |
td->dat.version = be32toh(td->dat.version);
|
|
Packit Service |
8aa27d |
td->dat.so_login_it = be64toh(td->dat.so_login_it);
|
|
Packit Service |
8aa27d |
td->dat.user_login_it = be64toh(td->dat.user_login_it);
|
|
Packit Service |
8aa27d |
td->dat.so_wrap_it = be64toh(td->dat.so_wrap_it);
|
|
Packit Service |
8aa27d |
td->dat.user_wrap_it = be64toh(td->dat.user_wrap_it);
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = CKR_OK;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (fp)
|
|
Packit Service |
8aa27d |
fclose(fp);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* Strip trailing chars from given string.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static char *strip_trailing_chars(char *s, int slen, char c)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
int i;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (!s || slen == 0)
|
|
Packit Service |
8aa27d |
return s;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
for (i = slen - 1; i >= 0; i--) {
|
|
Packit Service |
8aa27d |
if (s[i] == c)
|
|
Packit Service |
8aa27d |
s[i] = '\0';
|
|
Packit Service |
8aa27d |
else
|
|
Packit Service |
8aa27d |
break;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return s;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* Read the token info from NVTOK.DAT.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV get_token_info(const char *data_store, CK_TOKEN_INFO_32 *tokinfo)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
TOKEN_DATA tokdata;
|
|
Packit Service |
8aa27d |
CK_RV ret;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
TRACE_INFO("Reading token info from NVTOK.DAT ...\n");
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = load_NVTOK_DAT(data_store, "NVTOK.DAT", &tokdata);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot load NVTOK.DAT, datastore inconsistent.\n");
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
memcpy(tokinfo, &(tokdata.token_info), sizeof(CK_TOKEN_INFO_32));
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return CKR_OK;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* Support for finding the right stdll via the parser interface. The begin
|
|
Packit Service |
8aa27d |
* slot callback checks and sets activeslot if the current slot is the target
|
|
Packit Service |
8aa27d |
* slot.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static int parsefind_begin_slot(void *private, int slot, int nl_before_begin)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
struct findstdll *d = (struct findstdll *)private;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
UNUSED(nl_before_begin);
|
|
Packit Service |
8aa27d |
if (d->slotnum == slot)
|
|
Packit Service |
8aa27d |
d->activeslot = 1;
|
|
Packit Service |
8aa27d |
return 0;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* Support for finding the right stdll via the parser interface. The end
|
|
Packit Service |
8aa27d |
* slot callback resets activeslot since we are no longer in a slot definition.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static int parsefind_end_slot(void *private)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
struct findstdll *d = (struct findstdll *)private;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
d->activeslot = 0;
|
|
Packit Service |
8aa27d |
return 0;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* Support for finding the right stdll via the parser interface. The key-str
|
|
Packit Service |
8aa27d |
* callback detects and copies the stdll path for the target slot.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static int parsefind_key_str(void *private, int tok, const char *val)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
struct findstdll *d = (struct findstdll *)private;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (d->activeslot && tok == KW_STDLL) {
|
|
Packit Service |
8aa27d |
strncpy(d->stdll, val, d->len);
|
|
Packit Service |
8aa27d |
// Make sure it is 0-terminated
|
|
Packit Service |
8aa27d |
d->stdll[d->len] = 0;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
return 0;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
static struct parsefuncs parsefindfuncs = {
|
|
Packit Service |
8aa27d |
.begin_slot = parsefind_begin_slot,
|
|
Packit Service |
8aa27d |
.end_slot = parsefind_end_slot,
|
|
Packit Service |
8aa27d |
.key_str = parsefind_key_str
|
|
Packit Service |
8aa27d |
};
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* Identify the token that belongs to the given slot ID.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV identify_token(CK_SLOT_ID slot_id, char *conf_dir,
|
|
Packit Service |
8aa27d |
char *dll_name, size_t dll_name_len)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
char conf_file[PATH_MAX];
|
|
Packit Service |
8aa27d |
CK_RV ret;
|
|
Packit Service |
8aa27d |
struct findstdll finddll;
|
|
Packit Service |
8aa27d |
size_t max_cpy_size;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
max_cpy_size = dll_name_len > sizeof(((Slot_Info_t_64 *)NULL)->dll_location)
|
|
Packit Service |
8aa27d |
? sizeof(((Slot_Info_t_64 *)NULL)->dll_location) : dll_name_len;
|
|
Packit Service |
8aa27d |
finddll.stdll = dll_name;
|
|
Packit Service |
8aa27d |
finddll.len = max_cpy_size - 1;
|
|
Packit Service |
8aa27d |
finddll.slotnum = slot_id;
|
|
Packit Service |
8aa27d |
finddll.activeslot = 0;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
TRACE_INFO("Identifying the token that belongs to slot %ld ...\n", slot_id);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (slot_id >= NUMBER_SLOTS_MANAGED) {
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Open conf file */
|
|
Packit Service |
8aa27d |
if (ock_snprintf(conf_file, PATH_MAX, "%s/%s",
|
|
Packit Service |
8aa27d |
conf_dir, "opencryptoki.conf") != 0) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Path name overflow for config file opencryptoki.conf\n");
|
|
Packit Service |
8aa27d |
return CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = CKR_OK;
|
|
Packit Service |
8aa27d |
if (load_and_parse(conf_file, &parsefindfuncs, &finddll)) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("failed to parse config file %s\n", conf_file);
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* derives the SO wrap key from the given SO pin and given public
|
|
Packit Service |
8aa27d |
* info in NVTOK.DAT.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV derive_so_wrap_key_312(const char *sopin, TOKEN_DATA *tokdata,
|
|
Packit Service |
8aa27d |
CK_BYTE *so_wrap_key)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
CK_RV ret;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = PKCS5_PBKDF2_HMAC(sopin, strlen(sopin),
|
|
Packit Service |
8aa27d |
tokdata->dat.so_wrap_salt, 64,
|
|
Packit Service |
8aa27d |
tokdata->dat.so_wrap_it, EVP_sha512(),
|
|
Packit Service |
8aa27d |
256 / 8, so_wrap_key);
|
|
Packit Service |
8aa27d |
if (ret != 1) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("PBKDF2 failed.\n");
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = CKR_OK;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* derives the user wrap key from the given user pin and given public
|
|
Packit Service |
8aa27d |
* info in NVTOK.DAT.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV derive_user_wrap_key_312(const char *userpin, TOKEN_DATA *tokdata,
|
|
Packit Service |
8aa27d |
CK_BYTE *user_wrap_key)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
CK_RV ret;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = PKCS5_PBKDF2_HMAC(userpin, strlen(userpin),
|
|
Packit Service |
8aa27d |
tokdata->dat.user_wrap_salt, 64,
|
|
Packit Service |
8aa27d |
tokdata->dat.user_wrap_it, EVP_sha512(),
|
|
Packit Service |
8aa27d |
256 / 8, user_wrap_key);
|
|
Packit Service |
8aa27d |
if (ret != 1) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("PBKDF2 failed.\n");
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = CKR_OK;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* Activates the new repository by deleting the old MK_USER, MK_SO, and
|
|
Packit Service |
8aa27d |
* NVTOK.DAT, and renaming the new MK_SO_312, MK_USER_312, NVTOK.DAT_312 to
|
|
Packit Service |
8aa27d |
* their normal names.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV cleanup_repository_backup(const char *data_store)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
static char *names[] = { "MK_SO", "MK_USER", "NVTOK.DAT" };
|
|
Packit Service |
8aa27d |
int num_names = sizeof(names) / sizeof(char *);
|
|
Packit Service |
8aa27d |
char fname1[PATH_MAX + 9 + 1]; // satisfy compiler warning
|
|
Packit Service |
8aa27d |
char fname2[PATH_MAX + 1 + 1]; // satisfy compiler warning
|
|
Packit Service |
8aa27d |
int i, rc;
|
|
Packit Service |
8aa27d |
CK_RV ret;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Delete old files */
|
|
Packit Service |
8aa27d |
for (i = 0; i < num_names; i++) {
|
|
Packit Service |
8aa27d |
snprintf(fname1, sizeof(fname1), "%s/%s", data_store, names[i]);
|
|
Packit Service |
8aa27d |
rc = remove(fname1);
|
|
Packit Service |
8aa27d |
if (rc) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot delete old file %s.\n", fname1);
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Rename new files */
|
|
Packit Service |
8aa27d |
for (i = 0; i < num_names; i++) {
|
|
Packit Service |
8aa27d |
snprintf(fname1, sizeof(fname1), "%s/%s_312", data_store, names[i]);
|
|
Packit Service |
8aa27d |
snprintf(fname2, sizeof(fname2), "%s/%s", data_store, names[i]);
|
|
Packit Service |
8aa27d |
rc = rename(fname1, fname2);
|
|
Packit Service |
8aa27d |
if (rc) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot rename new file %s.\n", fname1);
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = CKR_OK;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* Migrates the repository. This process may be interrupted at any time and
|
|
Packit Service |
8aa27d |
* must be able to resume until the complete repository is successfully
|
|
Packit Service |
8aa27d |
* migrated. This especially requires to keep the old keys until
|
|
Packit Service |
8aa27d |
* everything is done.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV migrate_repository(const char *data_store, const char *sopin,
|
|
Packit Service |
8aa27d |
const char *userpin)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
CK_BYTE so_masterkey_old[MAX_MASTER_KEY_SIZE];
|
|
Packit Service |
8aa27d |
CK_BYTE so_masterkey_new[MAX_MASTER_KEY_SIZE];
|
|
Packit Service |
8aa27d |
CK_BYTE user_masterkey_old[MAX_MASTER_KEY_SIZE];
|
|
Packit Service |
8aa27d |
CK_BYTE user_masterkey_new[MAX_MASTER_KEY_SIZE];
|
|
Packit Service |
8aa27d |
CK_BYTE so_wrap_key[32];
|
|
Packit Service |
8aa27d |
CK_BYTE user_wrap_key[32];
|
|
Packit Service |
8aa27d |
CK_RV ret;
|
|
Packit Service |
8aa27d |
TOKEN_DATA tokdata;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
TRACE_INFO("Migrating the repository ...\n");
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Load NVTOK.DAT_312, which was either created before or exists from a
|
|
Packit Service |
8aa27d |
* previous interrupted run. So tokdata definitely contains the 3.12
|
|
Packit Service |
8aa27d |
* extension.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
ret = load_NVTOK_DAT(data_store, "NVTOK.DAT_312", &tokdata);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot load NVTOK.DAT_312, ret=%08lX.\n", ret);
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = load_MK_SO_00(data_store, sopin, so_masterkey_old);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot load old masterkey, ret=%08lX.\n", ret);
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = load_MK_USER_00(data_store, userpin, user_masterkey_old);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot load old masterkey, ret=%08lX.\n", ret);
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (memcmp(so_masterkey_old, user_masterkey_old, MAX_MASTER_KEY_SIZE) != 0) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("MK_SO and MK_USER are inconsistent, got different MKs.\n");
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = load_MK_SO_312(data_store, sopin, &tokdata, so_masterkey_new);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot load new masterkey from MK_SO_312, ret=%08lX.\n", ret);
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = load_MK_USER_312(data_store, userpin, &tokdata, user_masterkey_new);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot load new masterkey from MK_USER_312, ret=%08lX.\n", ret);
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (memcmp(so_masterkey_new, user_masterkey_new, MAX_MASTER_KEY_SIZE) != 0) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("MK_SO_312 and MK_USER_312 are inconsistent, got different MKs.\n");
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* This function needs a new NVTOK.DAT with the public salt and icount */
|
|
Packit Service |
8aa27d |
ret = derive_so_wrap_key_312(sopin, &tokdata, so_wrap_key);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot create new so_wrap_key, ret=%08lX.\n", ret);
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* This function needs a new NVTOK.DAT with the public salt and icount */
|
|
Packit Service |
8aa27d |
ret = derive_user_wrap_key_312(userpin, &tokdata, user_wrap_key);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot create new user_wrap_key, ret=%08lX.\n", ret);
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Now do the migration */
|
|
Packit Service |
8aa27d |
ret = migrate_token_objects(data_store, so_masterkey_old, so_masterkey_new,
|
|
Packit Service |
8aa27d |
so_wrap_key, user_wrap_key);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Migrating token objects failed with ret=%08lX.\n", ret);
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Remove temp files in backup */
|
|
Packit Service |
8aa27d |
ret = cleanup_repository_backup(data_store);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cleanup repository backup failed with ret=%08lX.\n", ret);
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* creates a MK_USER_312 file containing the new user MK.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV create_MK_USER_312(const char *data_store, const char *userpin,
|
|
Packit Service |
8aa27d |
const CK_BYTE *masterkey,
|
|
Packit Service |
8aa27d |
TOKEN_DATA *tokdata)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
const char *mkuser = "MK_USER_312";
|
|
Packit Service |
8aa27d |
char fname[PATH_MAX];
|
|
Packit Service |
8aa27d |
CK_BYTE user_wrap_key[32];
|
|
Packit Service |
8aa27d |
CK_BYTE outbuf[40];
|
|
Packit Service |
8aa27d |
FILE *fp = NULL;
|
|
Packit Service |
8aa27d |
size_t rv;
|
|
Packit Service |
8aa27d |
CK_RV ret;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Create user wrap key */
|
|
Packit Service |
8aa27d |
ret = derive_user_wrap_key_312(userpin, tokdata, (unsigned char *)&user_wrap_key);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot derive user wrap key, ret=%08lX.\n", ret);
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Wrap user MK with user_wrap_key */
|
|
Packit Service |
8aa27d |
ret = aes_256_wrap(outbuf, masterkey, user_wrap_key);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK)
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Create file MK_USER_312 */
|
|
Packit Service |
8aa27d |
fp = open_datastore_file(fname, sizeof(fname), data_store, mkuser, "w");
|
|
Packit Service |
8aa27d |
if (!fp) {
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
set_perm(fileno(fp));
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
rv = fwrite(outbuf, sizeof(outbuf), 1, fp);
|
|
Packit Service |
8aa27d |
if (rv != 1) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("fwrite(%s) failed, errno=%s.\n", fname, strerror(errno));
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = CKR_OK;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (fp)
|
|
Packit Service |
8aa27d |
fclose(fp);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* creates a MK_SO_312 file containing the new SO MK.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV create_MK_SO_312(const char *data_store, const char *sopin,
|
|
Packit Service |
8aa27d |
const CK_BYTE *masterkey,
|
|
Packit Service |
8aa27d |
TOKEN_DATA *tokdata)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
const char *mkso = "MK_SO_312";
|
|
Packit Service |
8aa27d |
char fname[PATH_MAX];
|
|
Packit Service |
8aa27d |
CK_BYTE outbuf[40];
|
|
Packit Service |
8aa27d |
CK_BYTE so_wrap_key[32];
|
|
Packit Service |
8aa27d |
FILE *fp = NULL;
|
|
Packit Service |
8aa27d |
size_t rv;
|
|
Packit Service |
8aa27d |
CK_RV ret;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Derive so wrap key from sopin and tokdata */
|
|
Packit Service |
8aa27d |
ret = derive_so_wrap_key_312(sopin, tokdata, so_wrap_key);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot derive new so wrap key, ret=%08lX.\n", ret);
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Wrap masterkey with SO_wrap_key */
|
|
Packit Service |
8aa27d |
ret = aes_256_wrap(outbuf, masterkey, so_wrap_key);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot wrap masterkey with so wrap key, ret=%08lX.\n", ret);
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Create file MK_SO_312 */
|
|
Packit Service |
8aa27d |
fp = open_datastore_file(fname, sizeof(fname), data_store, mkso, "w");
|
|
Packit Service |
8aa27d |
if (!fp) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("fopen(%s) failed, errno=%s\n", fname, strerror(errno));
|
|
Packit Service |
8aa27d |
rv = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
set_perm(fileno(fp));
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
rv = fwrite(outbuf, sizeof(outbuf), 1, fp);
|
|
Packit Service |
8aa27d |
if (rv != 1) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("fwrite(%s) failed, errno=%s.\n", fname, strerror(errno));
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = CKR_OK;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (fp)
|
|
Packit Service |
8aa27d |
fclose(fp);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* reads the old NVTOK.DAT and returns its contents:
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV read_NVTOK_DAT_00(const char *data_store, TOKEN_DATA *tokdata)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
FILE *fp;
|
|
Packit Service |
8aa27d |
const char *nvtok = "NVTOK.DAT";
|
|
Packit Service |
8aa27d |
char fname[PATH_MAX];
|
|
Packit Service |
8aa27d |
struct stat stbuf;
|
|
Packit Service |
8aa27d |
int fd;
|
|
Packit Service |
8aa27d |
CK_RV ret;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Check parms */
|
|
Packit Service |
8aa27d |
if (!data_store || !tokdata) {
|
|
Packit Service |
8aa27d |
return CKR_ARGUMENTS_BAD;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Read the old NVTOK.DAT */
|
|
Packit Service |
8aa27d |
fp = open_datastore_file(fname, sizeof(fname), data_store, nvtok, "r");
|
|
Packit Service |
8aa27d |
if (!fp)
|
|
Packit Service |
8aa27d |
return CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
fd = fileno(fp);
|
|
Packit Service |
8aa27d |
if ((fstat(fd, &stbuf) != 0) || (!S_ISREG(stbuf.st_mode))) {
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Ensure that this NVTOK.DAT is in fact old */
|
|
Packit Service |
8aa27d |
if (stbuf.st_size != sizeof(TOKEN_DATA_OLD)) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("%s has an invalid size of %ld bytes.\n", fname, stbuf.st_size);
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Read TOKEN_DATA_OLD */
|
|
Packit Service |
8aa27d |
ret = fread(tokdata, sizeof(TOKEN_DATA_OLD), 1, fp);
|
|
Packit Service |
8aa27d |
if (ret != 1) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot read %s, errno=%s\n", fname, strerror(errno));
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = CKR_OK;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (fp)
|
|
Packit Service |
8aa27d |
fclose(fp);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* creates the additions for new format.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV create_TOKEN_DATA_VERSION(const char *sopin, const char *userpin,
|
|
Packit Service |
8aa27d |
TOKEN_DATA *tokdata)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
CK_RV ret;
|
|
Packit Service |
8aa27d |
int rc;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
tokdata->dat.version = TOKVERSION_312;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
tokdata->dat.so_login_it = SO_KDF_LOGIN_IT;
|
|
Packit Service |
8aa27d |
memcpy(tokdata->dat.so_login_salt, SO_KDF_LOGIN_PURPOSE, 32);
|
|
Packit Service |
8aa27d |
ret = local_rng(tokdata->dat.so_login_salt + 32, 32);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("local_rng returned %lX\n", ret);
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
rc = PKCS5_PBKDF2_HMAC(sopin, strlen(sopin),
|
|
Packit Service |
8aa27d |
tokdata->dat.so_login_salt, 64,
|
|
Packit Service |
8aa27d |
tokdata->dat.so_login_it, EVP_sha512(),
|
|
Packit Service |
8aa27d |
256 / 8, tokdata->dat.so_login_key);
|
|
Packit Service |
8aa27d |
if (rc != 1) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Error: PKCS5_PBKDF2_HMAC\n");
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
tokdata->dat.so_wrap_it = SO_KDF_WRAP_IT;
|
|
Packit Service |
8aa27d |
memcpy(tokdata->dat.so_wrap_salt, SO_KDF_WRAP_PURPOSE, 32);
|
|
Packit Service |
8aa27d |
ret = local_rng(tokdata->dat.so_wrap_salt + 32, 32);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("local_rng returned %lX\n", ret);
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
tokdata->dat.user_login_it = USER_KDF_LOGIN_IT;
|
|
Packit Service |
8aa27d |
memcpy(tokdata->dat.user_login_salt, USER_KDF_LOGIN_PURPOSE, 32);
|
|
Packit Service |
8aa27d |
ret = local_rng(tokdata->dat.user_login_salt + 32, 32);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("local_rng returned %lX\n", ret);
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
rc = PKCS5_PBKDF2_HMAC(userpin, strlen(userpin),
|
|
Packit Service |
8aa27d |
tokdata->dat.user_login_salt, 64,
|
|
Packit Service |
8aa27d |
tokdata->dat.user_login_it, EVP_sha512(),
|
|
Packit Service |
8aa27d |
256 / 8, tokdata->dat.user_login_key);
|
|
Packit Service |
8aa27d |
if (rc != 1) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Error: PKCS5_PBKDF2_HMAC\n");
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
tokdata->dat.user_wrap_it = USER_KDF_WRAP_IT;
|
|
Packit Service |
8aa27d |
memcpy(tokdata->dat.user_wrap_salt, USER_KDF_WRAP_PURPOSE, 32);
|
|
Packit Service |
8aa27d |
ret = local_rng(tokdata->dat.user_wrap_salt + 32, 32);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("local_rng returned %lX\n", ret);
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = CKR_OK;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* Creates the new NVTOK.DAT which now contains the public salt and iteration
|
|
Packit Service |
8aa27d |
* count values that are necessary for re-deriving the pin-related
|
|
Packit Service |
8aa27d |
* wrapping keys.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV create_NVTOK_DAT_312(const char *data_store, const char *sopin,
|
|
Packit Service |
8aa27d |
const char *userpin, TOKEN_DATA *tokdata)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
const char *nvtok = "NVTOK.DAT_312";
|
|
Packit Service |
8aa27d |
char fname[PATH_MAX];
|
|
Packit Service |
8aa27d |
TOKEN_DATA be_tokdata;
|
|
Packit Service |
8aa27d |
FILE *fp = NULL;
|
|
Packit Service |
8aa27d |
CK_RV ret;
|
|
Packit Service |
8aa27d |
size_t rc;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Check parms */
|
|
Packit Service |
8aa27d |
if (!data_store || !sopin || !userpin || !tokdata) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("invalid parms.\n");
|
|
Packit Service |
8aa27d |
ret = CKR_ARGUMENTS_BAD;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Create new file NVTOK.DAT_312 */
|
|
Packit Service |
8aa27d |
fp = open_datastore_file(fname, sizeof(fname), data_store, nvtok, "w");
|
|
Packit Service |
8aa27d |
if (!fp) {
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
set_perm(fileno(fp));
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Get contents from old NVTOK.DAT */
|
|
Packit Service |
8aa27d |
ret = read_NVTOK_DAT_00(data_store, tokdata);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot read old NVTOK.DAT, ret=%08lX\n", ret);
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Create additions for new format */
|
|
Packit Service |
8aa27d |
ret = create_TOKEN_DATA_VERSION(sopin, userpin, tokdata);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot create TOKEN_DATA_VERSION struct, ret=%08lX\n", ret);
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* The 312 version always uses big endian */
|
|
Packit Service |
8aa27d |
memcpy(&be_tokdata, tokdata, sizeof(TOKEN_DATA));
|
|
Packit Service |
8aa27d |
be_tokdata.token_info.flags = htobe32(tokdata->token_info.flags);
|
|
Packit Service |
8aa27d |
be_tokdata.token_info.ulMaxSessionCount
|
|
Packit Service |
8aa27d |
= htobe32(tokdata->token_info.ulMaxSessionCount);
|
|
Packit Service |
8aa27d |
be_tokdata.token_info.ulSessionCount
|
|
Packit Service |
8aa27d |
= htobe32(tokdata->token_info.ulSessionCount);
|
|
Packit Service |
8aa27d |
be_tokdata.token_info.ulMaxRwSessionCount
|
|
Packit Service |
8aa27d |
= htobe32(tokdata->token_info.ulMaxRwSessionCount);
|
|
Packit Service |
8aa27d |
be_tokdata.token_info.ulRwSessionCount
|
|
Packit Service |
8aa27d |
= htobe32(tokdata->token_info.ulRwSessionCount);
|
|
Packit Service |
8aa27d |
be_tokdata.token_info.ulMaxPinLen = htobe32(tokdata->token_info.ulMaxPinLen);
|
|
Packit Service |
8aa27d |
be_tokdata.token_info.ulMinPinLen = htobe32(tokdata->token_info.ulMinPinLen);
|
|
Packit Service |
8aa27d |
be_tokdata.token_info.ulTotalPublicMemory
|
|
Packit Service |
8aa27d |
= htobe32(tokdata->token_info.ulTotalPublicMemory);
|
|
Packit Service |
8aa27d |
be_tokdata.token_info.ulFreePublicMemory
|
|
Packit Service |
8aa27d |
= htobe32(tokdata->token_info.ulFreePublicMemory);
|
|
Packit Service |
8aa27d |
be_tokdata.token_info.ulTotalPrivateMemory
|
|
Packit Service |
8aa27d |
= htobe32(tokdata->token_info.ulTotalPrivateMemory);
|
|
Packit Service |
8aa27d |
be_tokdata.token_info.ulFreePrivateMemory
|
|
Packit Service |
8aa27d |
= htobe32(tokdata->token_info.ulFreePrivateMemory);
|
|
Packit Service |
8aa27d |
be_tokdata.tweak_vector.allow_weak_des
|
|
Packit Service |
8aa27d |
= htobe32(tokdata->tweak_vector.allow_weak_des);
|
|
Packit Service |
8aa27d |
be_tokdata.tweak_vector.check_des_parity
|
|
Packit Service |
8aa27d |
= htobe32(tokdata->tweak_vector.check_des_parity);
|
|
Packit Service |
8aa27d |
be_tokdata.tweak_vector.allow_key_mods
|
|
Packit Service |
8aa27d |
= htobe32(tokdata->tweak_vector.allow_key_mods);
|
|
Packit Service |
8aa27d |
be_tokdata.tweak_vector.netscape_mods
|
|
Packit Service |
8aa27d |
= htobe32(tokdata->tweak_vector.netscape_mods);
|
|
Packit Service |
8aa27d |
be_tokdata.dat.version = htobe32(tokdata->dat.version);
|
|
Packit Service |
8aa27d |
be_tokdata.dat.so_login_it = htobe64(tokdata->dat.so_login_it);
|
|
Packit Service |
8aa27d |
be_tokdata.dat.user_login_it = htobe64(tokdata->dat.user_login_it);
|
|
Packit Service |
8aa27d |
be_tokdata.dat.so_wrap_it = htobe64(tokdata->dat.so_wrap_it);
|
|
Packit Service |
8aa27d |
be_tokdata.dat.user_wrap_it = htobe64(tokdata->dat.user_wrap_it);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Write converted token data into NVTOK.DAT_312 */
|
|
Packit Service |
8aa27d |
rc = fwrite(&be_tokdata, sizeof(TOKEN_DATA), 1, fp);
|
|
Packit Service |
8aa27d |
if (rc != 1) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("fwrite(%s) failed, errno=%s.\n", fname, strerror(errno));
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = CKR_OK;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (fp)
|
|
Packit Service |
8aa27d |
fclose(fp);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* Creates new token keys MK_USER_312 and MK_SO_312. The old keys in
|
|
Packit Service |
8aa27d |
* MK_USER and MK_SO are kept until the migration is fully completed.
|
|
Packit Service |
8aa27d |
* Then the old keys are deleted and the new keys are renamed.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV create_token_keys_312(const char *data_store, const char *sopin,
|
|
Packit Service |
8aa27d |
const char *userpin)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
unsigned char masterkey[32];
|
|
Packit Service |
8aa27d |
TOKEN_DATA tokdata;
|
|
Packit Service |
8aa27d |
CK_RV ret = CKR_OK;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
TRACE_INFO("Creating new v3.12 MK_SO, MK_USER, and NVTOK.DAT ...\n");
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Create master key */
|
|
Packit Service |
8aa27d |
ret = local_rng(masterkey, 32);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot create master key, ret=%08lX\n", ret);
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = create_NVTOK_DAT_312(data_store, sopin, userpin, &tokdata);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot create NVTOK.DAT_312, ret=%08lX\n", ret);
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = create_MK_SO_312(data_store, sopin, masterkey, &tokdata);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot create MK_SO_312, ret=%08lX\n", ret);
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = create_MK_USER_312(data_store, userpin, masterkey, &tokdata);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot create MK_USER_312, ret=%08lX\n", ret);
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = CKR_OK;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* Count the objs in the data_store and return the number of total objs
|
|
Packit Service |
8aa27d |
* and number of old objs.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV count_objects(const char *data_store, unsigned int *num_objs,
|
|
Packit Service |
8aa27d |
unsigned int *num_old_objs)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
char tmp[PATH_MAX], iname[PATH_MAX];
|
|
Packit Service |
8aa27d |
unsigned char *obj = NULL;
|
|
Packit Service |
8aa27d |
unsigned int obj_len;
|
|
Packit Service |
8aa27d |
CK_ULONG version;
|
|
Packit Service |
8aa27d |
CK_BBOOL priv;
|
|
Packit Service |
8aa27d |
FILE *fp;
|
|
Packit Service |
8aa27d |
CK_RV ret;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
*num_objs = 0;
|
|
Packit Service |
8aa27d |
*num_old_objs = 0;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Open index file OBJ.IDX */
|
|
Packit Service |
8aa27d |
snprintf(iname, sizeof(iname), "%s/TOK_OBJ/OBJ.IDX", data_store);
|
|
Packit Service |
8aa27d |
fp = fopen((char *) iname, "r");
|
|
Packit Service |
8aa27d |
if (!fp) {
|
|
Packit Service |
8aa27d |
TRACE_INFO("Cannot open %s, datastore probably empty.\n", iname);
|
|
Packit Service |
8aa27d |
ret = CKR_OK;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Count objects and old objects */
|
|
Packit Service |
8aa27d |
while (fgets(tmp, PATH_MAX, fp)) {
|
|
Packit Service |
8aa27d |
tmp[strlen(tmp) - 1] = 0;
|
|
Packit Service |
8aa27d |
(*num_objs)++;
|
|
Packit Service |
8aa27d |
ret = read_object(data_store, tmp, &obj, &obj_len, &version, &priv;;
|
|
Packit Service |
8aa27d |
if (ret == 0 && version == TOKVERSION_00)
|
|
Packit Service |
8aa27d |
(*num_old_objs)++;
|
|
Packit Service |
8aa27d |
if (obj) {
|
|
Packit Service |
8aa27d |
free(obj);
|
|
Packit Service |
8aa27d |
obj = NULL;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* OBJ.IDX must be at eof here */
|
|
Packit Service |
8aa27d |
if (!feof(fp)) {
|
|
Packit Service |
8aa27d |
TRACE_WARN("OBJ.IDX is not at eof after object %s, should not happen.\n",
|
|
Packit Service |
8aa27d |
tmp);
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
fclose(fp);
|
|
Packit Service |
8aa27d |
ret = CKR_OK;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* Set parameter "*new" to true if the NVTOK.DAT in the given data store
|
|
Packit Service |
8aa27d |
* is on 3.12 level, or false otherwise.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV NVTOK_DAT_is_312(const char *data_store, CK_BBOOL *new)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
CK_RV ret;
|
|
Packit Service |
8aa27d |
char fname[PATH_MAX];
|
|
Packit Service |
8aa27d |
struct stat stbuf;
|
|
Packit Service |
8aa27d |
int fd;
|
|
Packit Service |
8aa27d |
FILE *fp = NULL;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
*new = CK_FALSE;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Read the NVTOK.DAT */
|
|
Packit Service |
8aa27d |
snprintf(fname, PATH_MAX, "%s/NVTOK.DAT", data_store);
|
|
Packit Service |
8aa27d |
fp = fopen((char *)fname, "r");
|
|
Packit Service |
8aa27d |
if (!fp) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot open %s, errno=%s\n", fname, strerror(errno));
|
|
Packit Service |
8aa27d |
return CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
fd = fileno(fp);
|
|
Packit Service |
8aa27d |
if ((fstat(fd, &stbuf) != 0) || (!S_ISREG(stbuf.st_mode))) {
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Check if this NVTOK.DAT is old or new */
|
|
Packit Service |
8aa27d |
if (stbuf.st_size == sizeof(TOKEN_DATA_OLD)) {
|
|
Packit Service |
8aa27d |
*new = CK_FALSE;
|
|
Packit Service |
8aa27d |
} else if (stbuf.st_size == sizeof(TOKEN_DATA)) {
|
|
Packit Service |
8aa27d |
*new = CK_TRUE;
|
|
Packit Service |
8aa27d |
} else {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("%s has an invalid size of %ld bytes. Neither old nor new token format.\n",
|
|
Packit Service |
8aa27d |
fname, stbuf.st_size);
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = CKR_OK;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* Check if the data store is in 3.12 format.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV datastore_is_312(const char *data_store, const char *sopin,
|
|
Packit Service |
8aa27d |
const char *userpin, CK_BBOOL *new)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
CK_RV ret;
|
|
Packit Service |
8aa27d |
CK_BYTE masterkey_so[32];
|
|
Packit Service |
8aa27d |
CK_BYTE masterkey_user[32];
|
|
Packit Service |
8aa27d |
unsigned int num_objs = 0, num_old_objs = 0;
|
|
Packit Service |
8aa27d |
TOKEN_DATA tokdata;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
*new = CK_FALSE;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
TRACE_INFO("Checking if data store is already in 3.12 format ...\n");
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Check if NVTOK.DAT is new */
|
|
Packit Service |
8aa27d |
ret = NVTOK_DAT_is_312(data_store, new);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
warnx("Cannot determine if NVTOK.DAT has an old or new format.");
|
|
Packit Service |
8aa27d |
warnx("Note that generic token formats cannot be migrated.");
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (*new == CK_FALSE) {
|
|
Packit Service |
8aa27d |
ret = CKR_OK;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* NVTOK.DAT is already new, now check if we can read the keys */
|
|
Packit Service |
8aa27d |
ret = load_NVTOK_DAT(data_store, "NVTOK.DAT", &tokdata);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot load NVTOK.DAT, datastore inconsistent, ret=%08lX\n", ret);
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = load_masterkey_312(data_store, "MK_SO", sopin, &tokdata, masterkey_so);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_INFO("Cannot load new MK from MK_SO, datastore probably old.\n");
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = load_masterkey_312(data_store, "MK_USER", userpin, &tokdata, masterkey_user);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_INFO("Cannot load new MK from MK_USER, datastore probably old.\n");
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (memcmp(masterkey_so, masterkey_user, 32) != 0) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("MKs from MK_SO and MK_USER don't match, datastore inconsistent.\n");
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = count_objects(data_store, &num_objs, &num_old_objs);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("cannot count objects in %s.\n", data_store);
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
TRACE_INFO("Found %d objects total, %d old objects.\n", num_objs, num_old_objs);
|
|
Packit Service |
8aa27d |
if (num_old_objs > 0)
|
|
Packit Service |
8aa27d |
TRACE_WARN("Note that the old objects are not usable anymore, because "
|
|
Packit Service |
8aa27d |
"we don't have the corresponding old masterkey!\n");
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (num_objs > 0 && num_old_objs == 0)
|
|
Packit Service |
8aa27d |
*new = CK_TRUE;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = CKR_OK;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* Switch to new repository by deleting the old repository and renaming
|
|
Packit Service |
8aa27d |
* the backup folder to the original data store name.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV switch_to_new_repository(const char *data_store_old,
|
|
Packit Service |
8aa27d |
const char *data_store_new)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
char fname1[PATH_MAX];
|
|
Packit Service |
8aa27d |
CK_RV ret;
|
|
Packit Service |
8aa27d |
int rc = -1;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
TRACE_INFO("Switching to new repository ...\n");
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Rename original repository folder */
|
|
Packit Service |
8aa27d |
snprintf(fname1, sizeof(fname1), "%s_BAK", data_store_old);
|
|
Packit Service |
8aa27d |
rc = rename(data_store_old, fname1);
|
|
Packit Service |
8aa27d |
if (rc) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot rename %s, errno=%s.\n", data_store_old, strerror(rc));
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Rename backup folder */
|
|
Packit Service |
8aa27d |
rc = rename(data_store_new, data_store_old);
|
|
Packit Service |
8aa27d |
if (rc) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot rename %s, errno=%s.\n", data_store_new, strerror(rc));
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = CKR_OK;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* Use a parser to create a new config file. The parser callouts
|
|
Packit Service |
8aa27d |
* basically copy the original input and add the new tokversion line
|
|
Packit Service |
8aa27d |
* for the token we just migrated.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static int parseupdate_ockversion(void *private, const char *version)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
struct parseupdate *u = (struct parseupdate *)private;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
fprintf(u->f, "version %s", version);
|
|
Packit Service |
8aa27d |
return 0;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
static void parseupdate_eol(void *private)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
struct parseupdate *u = (struct parseupdate *)private;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
fputc('\n', u->f);
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
static int parseupdate_begin_slot(void *private, int slot, int nl_before_begin)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
struct parseupdate *u = (struct parseupdate *)private;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
u->activeslot = (slot == u->slotnum);
|
|
Packit Service |
8aa27d |
if (nl_before_begin)
|
|
Packit Service |
8aa27d |
fprintf(u->f, "slot %d\n{", slot);
|
|
Packit Service |
8aa27d |
else
|
|
Packit Service |
8aa27d |
fprintf(u->f, "slot %d {", slot);
|
|
Packit Service |
8aa27d |
return 0;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
static int parseupdate_end_slot(void *private)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
struct parseupdate *u = (struct parseupdate *)private;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (u->activeslot)
|
|
Packit Service |
8aa27d |
fprintf(u->f, " tokversion = 3.12\n");
|
|
Packit Service |
8aa27d |
fputc('}', u->f);
|
|
Packit Service |
8aa27d |
u->activeslot = 0;
|
|
Packit Service |
8aa27d |
return 0;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
static int parseupdate_key_str(void *private, int tok, const char *val)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
struct parseupdate *u = (struct parseupdate *)private;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (tok != KW_TOKVERSION)
|
|
Packit Service |
8aa27d |
fprintf(u->f, " %s = %s", keyword_token_to_str(tok), val);
|
|
Packit Service |
8aa27d |
return 0;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
static int parseupdate_key_vers(void *private, int tok, unsigned int vers)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
struct parseupdate *u = (struct parseupdate *)private;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (tok != KW_TOKVERSION)
|
|
Packit Service |
8aa27d |
fprintf(u->f, " %s = %d.%d", keyword_token_to_str(tok),
|
|
Packit Service |
8aa27d |
vers >> 16, vers & 0xffu);
|
|
Packit Service |
8aa27d |
return 0;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
static void parseupdate_eolcomment(void *private, const char *comment)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
struct parseupdate *u = (struct parseupdate *)private;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
fprintf(u->f, "#%s", comment);
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
static struct parsefuncs parseupdatefuncs = {
|
|
Packit Service |
8aa27d |
.version = parseupdate_ockversion,
|
|
Packit Service |
8aa27d |
.eol = parseupdate_eol,
|
|
Packit Service |
8aa27d |
.begin_slot = parseupdate_begin_slot,
|
|
Packit Service |
8aa27d |
.end_slot = parseupdate_end_slot,
|
|
Packit Service |
8aa27d |
.key_str = parseupdate_key_str,
|
|
Packit Service |
8aa27d |
.key_vers = parseupdate_key_vers,
|
|
Packit Service |
8aa27d |
.eolcomment = parseupdate_eolcomment
|
|
Packit Service |
8aa27d |
};
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* Inserts the new tokversion parm in the token's slot configuration, e.g.
|
|
Packit Service |
8aa27d |
*
|
|
Packit Service |
8aa27d |
* slot 2
|
|
Packit Service |
8aa27d |
* {
|
|
Packit Service |
8aa27d |
* stdll = libpkcs11_cca.so
|
|
Packit Service |
8aa27d |
* tokversion = 3.12
|
|
Packit Service |
8aa27d |
* }
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV update_opencryptoki_conf(CK_SLOT_ID slot_id, char *location)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
char dst_file[PATH_MAX], src_file[PATH_MAX], fname[PATH_MAX+20];
|
|
Packit Service |
8aa27d |
FILE *fp_w = NULL;
|
|
Packit Service |
8aa27d |
CK_RV ret;
|
|
Packit Service |
8aa27d |
int rc;
|
|
Packit Service |
8aa27d |
struct parseupdate parseupdate;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
TRACE_INFO("Updating config file ...\n");
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Open current conf file for read */
|
|
Packit Service |
8aa27d |
snprintf(src_file, PATH_MAX, "%s/%s", location, "opencryptoki.conf");
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Open new conf file for write */
|
|
Packit Service |
8aa27d |
snprintf(dst_file, PATH_MAX, "%s/%s", location, "opencryptoki.conf_new");
|
|
Packit Service |
8aa27d |
fp_w = fopen(dst_file, "w");
|
|
Packit Service |
8aa27d |
if (!fp_w) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("fopen(%s) failed, errno=%s\n", dst_file, strerror(errno));
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
set_perm(fileno(fp_w));
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
parseupdate.f = fp_w;
|
|
Packit Service |
8aa27d |
parseupdate.slotnum = slot_id;
|
|
Packit Service |
8aa27d |
parseupdate.activeslot = 0;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (load_and_parse(src_file, &parseupdatefuncs, &parseupdate)) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("could not update config file\n");
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
fclose(fp_w);
|
|
Packit Service |
8aa27d |
fp_w = NULL;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Rename old conf file */
|
|
Packit Service |
8aa27d |
snprintf(fname, sizeof(fname), "%s_BAK", src_file);
|
|
Packit Service |
8aa27d |
rc = rename(src_file, fname);
|
|
Packit Service |
8aa27d |
if (rc) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot rename %s\n", src_file);
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Rename new file */
|
|
Packit Service |
8aa27d |
rc = rename(dst_file, src_file);
|
|
Packit Service |
8aa27d |
if (rc) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot rename %s.\n", dst_file);
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = CKR_OK;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
if (fp_w)
|
|
Packit Service |
8aa27d |
fclose(fp_w);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* Removes the token_s shared memory from /dev/shm
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV remove_shared_memory(char *location)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
char shm_name[PATH_MAX];
|
|
Packit Service |
8aa27d |
int i, k, rc;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
i = k = 0;
|
|
Packit Service |
8aa27d |
shm_name[k++] = '/';
|
|
Packit Service |
8aa27d |
if (location[i] == '/')
|
|
Packit Service |
8aa27d |
i++;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
for (; location[i]; i++, k++) {
|
|
Packit Service |
8aa27d |
if (location[i] == '/')
|
|
Packit Service |
8aa27d |
shm_name[k] = '.';
|
|
Packit Service |
8aa27d |
else
|
|
Packit Service |
8aa27d |
shm_name[k] = location[i];
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
shm_name[k] = '\0';
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
rc = shm_unlink(shm_name);
|
|
Packit Service |
8aa27d |
if (rc != 0) {
|
|
Packit Service |
8aa27d |
warnx("shm_unlink(%s) failed, errno=%s", shm_name, strerror(errno));
|
|
Packit Service |
8aa27d |
return CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return CKR_OK;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* Copy a file given by name from a src folder to a dst folder.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV file_copy(char *dst, const char *src, const char *name)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
char dst_file[PATH_MAX], src_file[PATH_MAX], buf[4096];
|
|
Packit Service |
8aa27d |
FILE *fp_r = NULL, *fp_w = NULL;
|
|
Packit Service |
8aa27d |
size_t written;
|
|
Packit Service |
8aa27d |
CK_RV ret;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
snprintf(dst_file, PATH_MAX, "%s/%s", dst, name);
|
|
Packit Service |
8aa27d |
snprintf(src_file, PATH_MAX, "%s/%s", src, name);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
fp_r = fopen(src_file, "r");
|
|
Packit Service |
8aa27d |
if (!fp_r) {
|
|
Packit Service |
8aa27d |
warnx("fopen(%s) failed, errno=%s", src_file, strerror(errno));
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
fp_w = fopen(dst_file, "w");
|
|
Packit Service |
8aa27d |
if (!fp_w) {
|
|
Packit Service |
8aa27d |
warnx("fopen(%s) failed, errno=%s", dst_file, strerror(errno));
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
set_perm(fileno(fp_w));
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
while (!feof(fp_r)) {
|
|
Packit Service |
8aa27d |
size_t bytes = fread(buf, 1, sizeof(buf), fp_r);
|
|
Packit Service |
8aa27d |
if (bytes) { // can be zero, if file empty
|
|
Packit Service |
8aa27d |
written = fwrite(buf, 1, bytes, fp_w);
|
|
Packit Service |
8aa27d |
if (written != bytes) {
|
|
Packit Service |
8aa27d |
warnx("fwrite(%s) failed, errno=%s", dst_file,
|
|
Packit Service |
8aa27d |
strerror(errno));
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = CKR_OK;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (fp_r)
|
|
Packit Service |
8aa27d |
fclose(fp_r);
|
|
Packit Service |
8aa27d |
if (fp_w)
|
|
Packit Service |
8aa27d |
fclose(fp_w);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* Change the group owner of the given directory to 'pkcs11'.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV change_owner(char *dir)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
struct group* grp;
|
|
Packit Service |
8aa27d |
CK_RV ret;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Set group owner */
|
|
Packit Service |
8aa27d |
grp = getgrnam("pkcs11");
|
|
Packit Service |
8aa27d |
if (grp) {
|
|
Packit Service |
8aa27d |
if (chown(dir, -1, grp->gr_gid)) {
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
} else {
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Fix group permissions (see man 2 mkdir for details) */
|
|
Packit Service |
8aa27d |
if (chmod(dir, 0770)) {
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = CKR_OK;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* Copy the given src folder to the given dst folder including all
|
|
Packit Service |
8aa27d |
* subdirectories and files.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV folder_copy(char *dst, const char *src)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
char d[PATH_MAX], s[PATH_MAX];
|
|
Packit Service |
8aa27d |
struct dirent *entry;
|
|
Packit Service |
8aa27d |
CK_RV ret;
|
|
Packit Service |
8aa27d |
DIR *dir;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Open src */
|
|
Packit Service |
8aa27d |
dir = opendir(src);
|
|
Packit Service |
8aa27d |
if (dir == NULL) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot open %s\n", src);
|
|
Packit Service |
8aa27d |
return CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Create dst */
|
|
Packit Service |
8aa27d |
if (mkdir(dst, 0) != 0) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot create %s\n", dst);
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Change group owner and set permissions */
|
|
Packit Service |
8aa27d |
ret = change_owner(dst);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot change owner and permissions for %s\n", dst);
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Copy folder recursively, skip the "." and ".." entries */
|
|
Packit Service |
8aa27d |
while ((entry = readdir(dir)) != NULL) {
|
|
Packit Service |
8aa27d |
if (entry->d_type == DT_DIR) {
|
|
Packit Service |
8aa27d |
if (strncmp(entry->d_name, ".", 1) != 0) {
|
|
Packit Service |
8aa27d |
snprintf(d, PATH_MAX, "%s/%s", dst, entry->d_name);
|
|
Packit Service |
8aa27d |
snprintf(s, PATH_MAX, "%s/%s", src, entry->d_name);
|
|
Packit Service |
8aa27d |
ret = folder_copy(d, s);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK)
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
} else {
|
|
Packit Service |
8aa27d |
ret = file_copy(dst, src, entry->d_name);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK)
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = CKR_OK;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
closedir(dir);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* Remove the given folder and all of its contents.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV folder_delete(const char *folder)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
DIR *dir;
|
|
Packit Service |
8aa27d |
char fname[PATH_MAX];
|
|
Packit Service |
8aa27d |
size_t len, path_len;
|
|
Packit Service |
8aa27d |
struct stat statbuf;
|
|
Packit Service |
8aa27d |
struct dirent *ent;
|
|
Packit Service |
8aa27d |
CK_RV ret = CKR_OK;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
dir = opendir(folder);
|
|
Packit Service |
8aa27d |
if (!dir) {
|
|
Packit Service |
8aa27d |
TRACE_INFO("Folder %s doesn't exist.\n", folder);
|
|
Packit Service |
8aa27d |
return CKR_OK;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
path_len = strlen(folder);
|
|
Packit Service |
8aa27d |
while (!ret && (ent = readdir(dir))) {
|
|
Packit Service |
8aa27d |
if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
|
|
Packit Service |
8aa27d |
continue;
|
|
Packit Service |
8aa27d |
len = path_len + strlen(ent->d_name) + 2;
|
|
Packit Service |
8aa27d |
snprintf(fname, len, "%s/%s", folder, ent->d_name);
|
|
Packit Service |
8aa27d |
if (!stat(fname, &statbuf)) {
|
|
Packit Service |
8aa27d |
if (S_ISDIR(statbuf.st_mode)) {
|
|
Packit Service |
8aa27d |
ret = folder_delete(fname);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK)
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
} else {
|
|
Packit Service |
8aa27d |
ret = remove(fname);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK)
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
} else {
|
|
Packit Service |
8aa27d |
/* stat failed */
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot stat %s, errno=%s.\n", fname, strerror(errno));
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = CKR_OK;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
closedir(dir);
|
|
Packit Service |
8aa27d |
if (ret == CKR_OK)
|
|
Packit Service |
8aa27d |
rmdir(folder);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* Backs up the given data_store to data_store_PKCSTOK_MIGRATE_TMP.
|
|
Packit Service |
8aa27d |
* All folders and files are recursively created and copied.
|
|
Packit Service |
8aa27d |
* Remove the backup if it already exists so that we always have
|
|
Packit Service |
8aa27d |
* a clean backup.
|
|
Packit Service |
8aa27d |
* The calling routine ensures that data_store does not end with a '/' !
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_RV backup_repository(const char *data_store)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
char dst[PATH_MAX];
|
|
Packit Service |
8aa27d |
CK_RV ret = CKR_OK;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
TRACE_INFO("Creating data store backup ...\n");
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
memset(dst, 0, PATH_MAX);
|
|
Packit Service |
8aa27d |
snprintf(dst, PATH_MAX, "%s_PKCSTOK_MIGRATE_TMP", data_store);
|
|
Packit Service |
8aa27d |
ret = folder_delete(dst);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
warnx("Fatal error: cannot delete old backup: %s", dst);
|
|
Packit Service |
8aa27d |
return CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return folder_copy(dst, data_store);
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* Checks if the pkcsslotd is running.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_BBOOL pkcsslotd_running(void)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
DIR *dir;
|
|
Packit Service |
8aa27d |
FILE *fp;
|
|
Packit Service |
8aa27d |
struct dirent* ent;
|
|
Packit Service |
8aa27d |
char* endptr;
|
|
Packit Service |
8aa27d |
char buf[PATH_MAX];
|
|
Packit Service |
8aa27d |
char fname[PATH_MAX];
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
TRACE_INFO("Checking if pkcsslotd is running ...\n");
|
|
Packit Service |
8aa27d |
if (!(dir = opendir("/proc"))) {
|
|
Packit Service |
8aa27d |
TRACE_WARN("Cannot open /proc, i.e. cannot check if pkcsslotd is running.\n");
|
|
Packit Service |
8aa27d |
return CK_TRUE;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
while ((ent = readdir(dir)) != NULL) {
|
|
Packit Service |
8aa27d |
/* if endptr is not a null character, the directory is not
|
|
Packit Service |
8aa27d |
* entirely numeric, so ignore it */
|
|
Packit Service |
8aa27d |
long lpid = strtol(ent->d_name, &endptr, 10);
|
|
Packit Service |
8aa27d |
if (*endptr != '\0') {
|
|
Packit Service |
8aa27d |
continue;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* try to open the cmdline file */
|
|
Packit Service |
8aa27d |
snprintf(fname, sizeof(fname), "/proc/%ld/cmdline", lpid);
|
|
Packit Service |
8aa27d |
fp = fopen(fname, "r");
|
|
Packit Service |
8aa27d |
if (!fp) {
|
|
Packit Service |
8aa27d |
warnx("fopen(%s) failed, errno=%s", fname, strerror(errno));
|
|
Packit Service |
8aa27d |
return CK_TRUE;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* check the first token in the file: the program pathname */
|
|
Packit Service |
8aa27d |
if (fgets(buf, sizeof(buf), fp) != NULL) {
|
|
Packit Service |
8aa27d |
char* first = strtok(buf, " ");
|
|
Packit Service |
8aa27d |
if (!first) {
|
|
Packit Service |
8aa27d |
TRACE_WARN("Cannot read program name from %s, i.e. cannot check if pkcsslotd is running.\n",
|
|
Packit Service |
8aa27d |
fname);
|
|
Packit Service |
8aa27d |
return CK_TRUE;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
if (strstr(first, "pkcsslotd") != NULL) {
|
|
Packit Service |
8aa27d |
fclose(fp);
|
|
Packit Service |
8aa27d |
closedir(dir);
|
|
Packit Service |
8aa27d |
return CK_TRUE;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
fclose(fp);
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
closedir(dir);
|
|
Packit Service |
8aa27d |
return CK_FALSE;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
*
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static CK_BBOOL token_invalid(const char *dll)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
if (strcmp(dll, INVALID_TOKEN) == 0)
|
|
Packit Service |
8aa27d |
return CK_TRUE;
|
|
Packit Service |
8aa27d |
else
|
|
Packit Service |
8aa27d |
return CK_FALSE;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* returns the token name related to the given stdll name for the
|
|
Packit Service |
8aa27d |
* 4 supported tokens.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static const char *dll2name(const char *dll)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
static char *dlls[] = {
|
|
Packit Service |
8aa27d |
"libpkcs11_ica.so", "libpkcs11_cca.so",
|
|
Packit Service |
8aa27d |
"libpkcs11_sw.so", "libpkcs11_ep11.so"
|
|
Packit Service |
8aa27d |
};
|
|
Packit Service |
8aa27d |
static char *names[] = {
|
|
Packit Service |
8aa27d |
"ICA", "CCA", "Soft", "EP11"
|
|
Packit Service |
8aa27d |
};
|
|
Packit Service |
8aa27d |
int i, num_tokens = sizeof(names) / sizeof(char *);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
for (i = 0; i < num_tokens; i++) {
|
|
Packit Service |
8aa27d |
if (strcmp(dll, dlls[i]) == 0)
|
|
Packit Service |
8aa27d |
return names[i];
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return INVALID_TOKEN;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* translates the given verbose level string into a numeric verbose level.
|
|
Packit Service |
8aa27d |
* Returns -1 if the string is invalid.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
static int verbose_str2level(char *str)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
const char *tlevel[] = {"none", "error", "warn", "info", "devel", "debug"};
|
|
Packit Service |
8aa27d |
const int num = sizeof(tlevel) / sizeof(char *);
|
|
Packit Service |
8aa27d |
int i;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
for (i = 0; i < num; i++) {
|
|
Packit Service |
8aa27d |
if (strcmp(str, tlevel[i]) == 0) {
|
|
Packit Service |
8aa27d |
return i;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return -1;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
static void usage(char *progname)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
printf(" Help:\t\t\t\t%s -h\n", progname);
|
|
Packit Service |
8aa27d |
printf(" -h, --help \t\t\tShow this help\n\n");
|
|
Packit Service |
8aa27d |
printf(" Options:\n");
|
|
Packit Service |
8aa27d |
printf(" -s, --slotid SLOTID\t\tPKCS slot number (required)\n");
|
|
Packit Service |
8aa27d |
printf(" -d, --datastore DATASTORE\ttoken datastore location (required)\n");
|
|
Packit Service |
8aa27d |
printf(" -c, --confdir CONFDIR\t\tlocation of opencryptoki.conf (required)\n");
|
|
Packit Service |
8aa27d |
printf(" -u, --userpin USERPIN\t\ttoken user pin (prompted if not specified)\n");
|
|
Packit Service |
8aa27d |
printf(" -p, --sopin SOPIN\t\ttoken SO pin (prompted if not specified)\n");
|
|
Packit Service |
8aa27d |
printf(" -v, --verbose LEVEL\t\tset verbose level (optional):\n");
|
|
Packit Service |
8aa27d |
printf("\t\t\t\tnone (default), error, warn, info, devel, debug\n");
|
|
Packit Service |
8aa27d |
return;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
int main(int argc, char **argv)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
CK_RV ret = 0;
|
|
Packit Service |
8aa27d |
int opt = 0, vlevel = -1;
|
|
Packit Service |
8aa27d |
CK_SLOT_ID slot_id = 0;
|
|
Packit Service |
8aa27d |
CK_BBOOL slot_id_specified = CK_FALSE;
|
|
Packit Service |
8aa27d |
size_t sopinlen, userpinlen, buflen = 0;
|
|
Packit Service |
8aa27d |
ssize_t num_chars;
|
|
Packit Service |
8aa27d |
char *data_store = NULL, *data_store_old = NULL, *conf_dir = NULL;
|
|
Packit Service |
8aa27d |
char *sopin = NULL, *userpin = NULL, *verbose = NULL;
|
|
Packit Service |
8aa27d |
char *buff = NULL;
|
|
Packit Service |
8aa27d |
char dll_name[PATH_MAX];
|
|
Packit Service |
8aa27d |
CK_TOKEN_INFO_32 tokinfo;
|
|
Packit Service |
8aa27d |
CK_BBOOL new;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
static const struct option long_opts[] = {
|
|
Packit Service |
8aa27d |
{"datastore", required_argument, NULL, 'd'},
|
|
Packit Service |
8aa27d |
{"confdir", required_argument, NULL, 'c'},
|
|
Packit Service |
8aa27d |
{"slotid", required_argument, NULL, 's'},
|
|
Packit Service |
8aa27d |
{"userpin", required_argument, NULL, 'u'},
|
|
Packit Service |
8aa27d |
{"sopin", required_argument, NULL, 'p'},
|
|
Packit Service |
8aa27d |
{"verbose", required_argument, NULL, 'v'},
|
|
Packit Service |
8aa27d |
{"help", no_argument, NULL, 'h'},
|
|
Packit Service |
8aa27d |
{0, 0, 0, 0}
|
|
Packit Service |
8aa27d |
};
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
while ((opt = getopt_long(argc, argv, "d:c:s:u:p:v:h", long_opts, NULL)) != -1) {
|
|
Packit Service |
8aa27d |
switch (opt) {
|
|
Packit Service |
8aa27d |
case 'd':
|
|
Packit Service |
8aa27d |
data_store = strdup(optarg);
|
|
Packit Service |
8aa27d |
break;
|
|
Packit Service |
8aa27d |
case 'c':
|
|
Packit Service |
8aa27d |
conf_dir = strdup(optarg);
|
|
Packit Service |
8aa27d |
break;
|
|
Packit Service |
8aa27d |
case 's':
|
|
Packit Service |
8aa27d |
slot_id = atoi(optarg);
|
|
Packit Service |
8aa27d |
slot_id_specified = CK_TRUE;
|
|
Packit Service |
8aa27d |
break;
|
|
Packit Service |
8aa27d |
case 'u':
|
|
Packit Service |
8aa27d |
userpin = strdup(optarg);
|
|
Packit Service |
8aa27d |
userpinlen = strlen(userpin);
|
|
Packit Service |
8aa27d |
break;
|
|
Packit Service |
8aa27d |
case 'p':
|
|
Packit Service |
8aa27d |
sopin = strdup(optarg);
|
|
Packit Service |
8aa27d |
sopinlen = strlen(sopin);
|
|
Packit Service |
8aa27d |
break;
|
|
Packit Service |
8aa27d |
case 'v':
|
|
Packit Service |
8aa27d |
verbose = strdup(optarg);
|
|
Packit Service |
8aa27d |
vlevel = verbose_str2level(verbose);
|
|
Packit Service |
8aa27d |
if (vlevel < 0) {
|
|
Packit Service |
8aa27d |
warnx("Invalid verbose level '%s' specified.", verbose);
|
|
Packit Service |
8aa27d |
usage(argv[0]);
|
|
Packit Service |
8aa27d |
exit(1);
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
break;
|
|
Packit Service |
8aa27d |
case 'h':
|
|
Packit Service |
8aa27d |
usage(argv[0]);
|
|
Packit Service |
8aa27d |
exit(0);
|
|
Packit Service |
8aa27d |
default:
|
|
Packit Service |
8aa27d |
warnx("pkcstok_migrate: Parameters are required.");
|
|
Packit Service |
8aa27d |
usage(argv[0]);
|
|
Packit Service |
8aa27d |
exit(1);
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (argc == 1) {
|
|
Packit Service |
8aa27d |
usage(argv[0]);
|
|
Packit Service |
8aa27d |
exit(1);
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
printf("\npkcstok_migrate:\n");
|
|
Packit Service |
8aa27d |
printf("Summary of input parameters:\n");
|
|
Packit Service |
8aa27d |
if (data_store) {
|
|
Packit Service |
8aa27d |
strip_trailing_chars(data_store, strlen(data_store), '/');
|
|
Packit Service |
8aa27d |
printf(" datastore = %s \n", data_store);
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
if (conf_dir) {
|
|
Packit Service |
8aa27d |
strip_trailing_chars(conf_dir, strlen(conf_dir), '/');
|
|
Packit Service |
8aa27d |
printf(" confdir = %s \n", conf_dir);
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
if (slot_id_specified)
|
|
Packit Service |
8aa27d |
printf(" slot ID = %ld\n", slot_id);
|
|
Packit Service |
8aa27d |
if (userpin)
|
|
Packit Service |
8aa27d |
printf(" user PIN specified\n");
|
|
Packit Service |
8aa27d |
if (sopin)
|
|
Packit Service |
8aa27d |
printf(" SO PIN specified\n");
|
|
Packit Service |
8aa27d |
if (vlevel >= 0) {
|
|
Packit Service |
8aa27d |
trace_level = vlevel;
|
|
Packit Service |
8aa27d |
printf(" verbose level = %s\n", verbose);
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
printf("\n");
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Slot ID must be given */
|
|
Packit Service |
8aa27d |
if (!slot_id_specified) {
|
|
Packit Service |
8aa27d |
warnx("Slot ID must be specified.");
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Datastore must be given */
|
|
Packit Service |
8aa27d |
if (data_store == NULL) {
|
|
Packit Service |
8aa27d |
warnx("Data store path must be specified.");
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Limit datastore path length because of appended suffixes */
|
|
Packit Service |
8aa27d |
if (strlen(data_store) > PKCSTOK_MIGRATE_MAX_PATH_LEN) {
|
|
Packit Service |
8aa27d |
warnx("Datastore path (%ld characters) is too long (max = %d).\n",
|
|
Packit Service |
8aa27d |
strlen(data_store), PKCSTOK_MIGRATE_MAX_PATH_LEN);
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Location of opencryptoki.conf must be specified. */
|
|
Packit Service |
8aa27d |
if (conf_dir == NULL) {
|
|
Packit Service |
8aa27d |
warnx("Location of opencryptoki.conf must be specified.");
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Limit path to config file because of appended suffixes */
|
|
Packit Service |
8aa27d |
if (strlen(conf_dir) > PKCSTOK_MIGRATE_MAX_PATH_LEN) {
|
|
Packit Service |
8aa27d |
warnx("Path to config file (%ld characters) is too long (max = %d).\n",
|
|
Packit Service |
8aa27d |
strlen(conf_dir), PKCSTOK_MIGRATE_MAX_PATH_LEN);
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Check if given data_store exists */
|
|
Packit Service |
8aa27d |
if (!datastore_exists(data_store)) {
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
warnx("Datastore %s does not exist.", data_store);
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Check if given conf_dir exists and contains opencryptoki.conf */
|
|
Packit Service |
8aa27d |
if (!conffile_exists(conf_dir)) {
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
warnx("%s does not exist or does not contain opencryptoki.conf", conf_dir);
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Check if pkcsslotd is running */
|
|
Packit Service |
8aa27d |
if (pkcsslotd_running()) {
|
|
Packit Service |
8aa27d |
warnx("Please stop pkcsslotd before running this utility.");
|
|
Packit Service |
8aa27d |
ret = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Identify token related to given slot ID */
|
|
Packit Service |
8aa27d |
ret = identify_token(slot_id, conf_dir, dll_name, sizeof(dll_name));
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
warnx("Cannot identify a token related to given slot ID %ld", slot_id);
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Check if DLL name from conf file is a known and migratable token */
|
|
Packit Service |
8aa27d |
printf("Slot ID %ld points to DLL name %s, which is a %s token.\n",
|
|
Packit Service |
8aa27d |
slot_id, dll_name, dll2name(dll_name));
|
|
Packit Service |
8aa27d |
if (token_invalid(dll2name(dll_name))) {
|
|
Packit Service |
8aa27d |
warnx("Please check your input.");
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Check if there are token objects to migrate */
|
|
Packit Service |
8aa27d |
if (datastore_empty(data_store)) {
|
|
Packit Service |
8aa27d |
ret = CKR_OK;
|
|
Packit Service |
8aa27d |
warnx("Datastore %s is empty, no objects to migrate.", data_store);
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Get token info from NVTOK.DAT */
|
|
Packit Service |
8aa27d |
ret = get_token_info(data_store, &tokinfo);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
warnx("Cannot get the token label from NVTOK.DAT");
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Check with user if ok to migrate this token, or quit if token not migratable */
|
|
Packit Service |
8aa27d |
printf("Data store %s points to this token info:\n", data_store);
|
|
Packit Service |
8aa27d |
printf(" label : %.*s\n", 32, tokinfo.label);
|
|
Packit Service |
8aa27d |
printf(" manufacturerID : %.*s\n", 32, tokinfo.manufacturerID);
|
|
Packit Service |
8aa27d |
printf(" model : %.*s\n", 16, tokinfo.model);
|
|
Packit Service |
8aa27d |
printf(" serialNumber : %.*s\n", 16, tokinfo.serialNumber);
|
|
Packit Service |
8aa27d |
printf(" hardwareVersion : %i.%i\n", tokinfo.hardwareVersion.major, tokinfo.hardwareVersion.minor);
|
|
Packit Service |
8aa27d |
printf(" firmwareVersion : %i.%i\n", tokinfo.firmwareVersion.major, tokinfo.firmwareVersion.minor);
|
|
Packit Service |
8aa27d |
printf("Migrate this token with given slot ID? y/n\n");
|
|
Packit Service |
8aa27d |
num_chars = getline(&buff, &buflen, stdin);
|
|
Packit Service |
8aa27d |
if (num_chars < 0 || strncmp(buff, "y", 1) != 0) {
|
|
Packit Service |
8aa27d |
printf("ok, let's quit.\n");
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Get the SO pin to authorize migration */
|
|
Packit Service |
8aa27d |
if (!sopin) {
|
|
Packit Service |
8aa27d |
printf("Enter the SO PIN: ");
|
|
Packit Service |
8aa27d |
fflush(stdout);
|
|
Packit Service |
8aa27d |
ret = get_pin(&sopin, &sopinlen);
|
|
Packit Service |
8aa27d |
if (ret != 0) {
|
|
Packit Service |
8aa27d |
warnx("Could not get SO PIN.");
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Get the USER pin to authorize migration */
|
|
Packit Service |
8aa27d |
if (!userpin) {
|
|
Packit Service |
8aa27d |
printf("Enter the USER PIN: ");
|
|
Packit Service |
8aa27d |
fflush(stdout);
|
|
Packit Service |
8aa27d |
ret = get_pin(&userpin, &userpinlen);
|
|
Packit Service |
8aa27d |
if (ret != 0) {
|
|
Packit Service |
8aa27d |
warnx("Could not get USER PIN.");
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Verify the SO and USER PINs entered against NVTOK.DAT. */
|
|
Packit Service |
8aa27d |
ret = verify_pins(data_store, sopin, sopinlen, userpin, userpinlen);
|
|
Packit Service |
8aa27d |
if (ret) {
|
|
Packit Service |
8aa27d |
warnx("Could not verify pins.");
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Check if data store is already new */
|
|
Packit Service |
8aa27d |
ret = datastore_is_312(data_store, sopin, userpin, &new;;
|
|
Packit Service |
8aa27d |
if (ret == 0 && new) {
|
|
Packit Service |
8aa27d |
printf("Data store %s is already in new format.\n", data_store);
|
|
Packit Service |
8aa27d |
ret = update_opencryptoki_conf(slot_id, conf_dir);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK)
|
|
Packit Service |
8aa27d |
warnx("Failed to update opencryptoki.conf, you must do this manually.");
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Backup repository if not already done */
|
|
Packit Service |
8aa27d |
ret = backup_repository(data_store);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
warnx("Failed to create backup.");
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Perform all actions on the backup */
|
|
Packit Service |
8aa27d |
char data_store_new[PATH_MAX];
|
|
Packit Service |
8aa27d |
data_store_old = data_store;
|
|
Packit Service |
8aa27d |
snprintf(data_store_new, PATH_MAX, "%s_PKCSTOK_MIGRATE_TMP", data_store_old);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Create new temp token keys, which exist in parallel to the old ones
|
|
Packit Service |
8aa27d |
* until the migration is fully completed. */
|
|
Packit Service |
8aa27d |
ret = create_token_keys_312(data_store_new, sopin, userpin);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
warnx("Failed to create new token keys.");
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Migrate repository */
|
|
Packit Service |
8aa27d |
ret = migrate_repository(data_store_new, sopin, userpin);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
warnx("Failed to migrate repository.");
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Switch to new repository */
|
|
Packit Service |
8aa27d |
ret = switch_to_new_repository(data_store_old, data_store_new);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
warnx("Switch to new repository failed.");
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Remove the token's shared memory */
|
|
Packit Service |
8aa27d |
ret = remove_shared_memory(data_store);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
warnx("Failed to remove token's shared memory.");
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Now insert new 'tokversion=3.12' parm in opencryptoki.conf */
|
|
Packit Service |
8aa27d |
ret = update_opencryptoki_conf(slot_id, conf_dir);
|
|
Packit Service |
8aa27d |
if (ret != CKR_OK) {
|
|
Packit Service |
8aa27d |
warnx("Failed to update opencryptoki.conf, you must do this manually.");
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
printf("Pre-migration data backed up at '%s_BAK'\n", data_store_old);
|
|
Packit Service |
8aa27d |
printf("Config file backed up at '%s/opencryptoki.conf_BAK'\n", conf_dir);
|
|
Packit Service |
8aa27d |
printf("Remove these backups manually after testing the new repository.\n");
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = CKR_OK;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
free(buff);
|
|
Packit Service |
8aa27d |
free(sopin);
|
|
Packit Service |
8aa27d |
free(userpin);
|
|
Packit Service |
8aa27d |
free(data_store);
|
|
Packit Service |
8aa27d |
free(conf_dir);
|
|
Packit Service |
8aa27d |
free(verbose);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (ret == CKR_OK) {
|
|
Packit Service |
8aa27d |
printf("pkcstok_migrate finished successfully.\n");
|
|
Packit Service |
8aa27d |
return EXIT_SUCCESS;
|
|
Packit Service |
8aa27d |
} else {
|
|
Packit Service |
8aa27d |
printf("pkcstok_migrate finished with warnings/errors.\n");
|
|
Packit Service |
8aa27d |
return EXIT_FAILURE;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
}
|