|
Packit |
8681c6 |
/*
|
|
Packit |
8681c6 |
* COPYRIGHT (c) International Business Machines Corp. 2001-2017
|
|
Packit |
8681c6 |
*
|
|
Packit |
8681c6 |
* This program is provided under the terms of the Common Public License,
|
|
Packit |
8681c6 |
* version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
|
|
Packit |
8681c6 |
* software constitutes recipient's acceptance of CPL-1.0 terms which can be
|
|
Packit |
8681c6 |
* found in the file LICENSE file or at
|
|
Packit |
8681c6 |
* https://opensource.org/licenses/cpl1.0.php
|
|
Packit |
8681c6 |
*/
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// loadsave.c
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
// routines associated with loading/saving files
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
#define _GNU_SOURCE
|
|
Packit |
8681c6 |
#include <pthread.h>
|
|
Packit |
8681c6 |
#include <stdio.h>
|
|
Packit |
8681c6 |
#include <stdlib.h>
|
|
Packit |
8681c6 |
#include <string.h>
|
|
Packit |
8681c6 |
#include <strings.h>
|
|
Packit |
8681c6 |
#include <unistd.h>
|
|
Packit |
8681c6 |
#include <alloca.h>
|
|
Packit |
8681c6 |
#include <sys/types.h>
|
|
Packit |
8681c6 |
#include <sys/stat.h>
|
|
Packit |
8681c6 |
#include <sys/ipc.h>
|
|
Packit |
8681c6 |
#include <sys/file.h>
|
|
Packit |
8681c6 |
#include <errno.h>
|
|
Packit |
8681c6 |
#include <syslog.h>
|
|
Packit |
8681c6 |
#include <pwd.h>
|
|
Packit |
8681c6 |
#include <grp.h>
|
|
Packit |
8681c6 |
#include <openssl/evp.h>
|
|
Packit |
8681c6 |
#include <endian.h>
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
#include "pkcs11types.h"
|
|
Packit |
8681c6 |
#include "defs.h"
|
|
Packit |
8681c6 |
#include "host_defs.h"
|
|
Packit |
8681c6 |
#include "h_extern.h"
|
|
Packit |
8681c6 |
#include "tok_spec_struct.h"
|
|
Packit |
8681c6 |
#include "pkcs32.h"
|
|
Packit |
8681c6 |
#include "sw_crypt.h"
|
|
Packit |
8681c6 |
#include "trace.h"
|
|
Packit |
8681c6 |
#include "ock_syslog.h"
|
|
Packit Service |
8aa27d |
#include "slotmgr.h" // for ock_snprintf
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
extern void set_perm(int);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_RV restore_private_token_object_old(STDLL_TokData_t *tokdata, CK_BYTE *data,
|
|
Packit |
8681c6 |
CK_ULONG len, OBJECT *pObj);
|
|
Packit |
8681c6 |
CK_RV reload_token_object_old(STDLL_TokData_t *tokdata, OBJECT *obj);
|
|
Packit |
8681c6 |
CK_RV save_public_token_object_old(STDLL_TokData_t *tokdata, OBJECT *obj);
|
|
Packit |
8681c6 |
CK_RV load_public_token_objects_old(STDLL_TokData_t *tokdata);
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
static int get_token_object_path(char *buf, size_t buflen,
|
|
Packit Service |
8aa27d |
STDLL_TokData_t *tokdata, char *path)
|
|
Packit |
8681c6 |
{
|
|
Packit Service |
8aa27d |
if (ock_snprintf(buf, buflen, "%s/" PK_LITE_OBJ_DIR "/%s",
|
|
Packit Service |
8aa27d |
tokdata->data_store, path) != 0) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("buffer overflow for object path %s", path);
|
|
Packit Service |
8aa27d |
return -1;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
return 0;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
static FILE *open_token_object_path(char *buf, size_t buflen,
|
|
Packit Service |
8aa27d |
STDLL_TokData_t *tokdata, char *path,
|
|
Packit Service |
8aa27d |
char *mode)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
if (get_token_object_path(buf, buflen, tokdata, path) < 0)
|
|
Packit Service |
8aa27d |
return NULL;
|
|
Packit Service |
8aa27d |
return fopen(buf, mode);
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
static int get_token_data_store_path(char *buf, size_t buflen,
|
|
Packit Service |
8aa27d |
STDLL_TokData_t *tokdata, char *path)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
if (ock_snprintf(buf, buflen, "%s/%s", tokdata->data_store, path)) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("buffer overflow for path %s", path);
|
|
Packit Service |
8aa27d |
return -1;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
return 0;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
static FILE *open_token_data_store_path(char *buf, size_t buflen,
|
|
Packit Service |
8aa27d |
STDLL_TokData_t *tokdata, char *path,
|
|
Packit Service |
8aa27d |
char *mode)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
if (get_token_data_store_path(buf, buflen, tokdata, path) < 0)
|
|
Packit Service |
8aa27d |
return NULL;
|
|
Packit Service |
8aa27d |
return fopen(buf, mode);
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
static FILE *open_token_object_index(char *buf, size_t buflen,
|
|
Packit Service |
8aa27d |
STDLL_TokData_t *tokdata, char *mode)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
return open_token_object_path(buf, buflen, tokdata, PK_LITE_OBJ_IDX, mode);
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
static FILE *open_token_nvdat(char *buf, size_t buflen,
|
|
Packit Service |
8aa27d |
STDLL_TokData_t *tokdata, char *mode)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
if (ock_snprintf(buf, buflen, "%s/" PK_LITE_NV, tokdata->data_store)) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("NVDAT.TOK file name buffer overflow\n");
|
|
Packit Service |
8aa27d |
return NULL;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
return fopen(buf, mode);
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
char *get_pk_dir(STDLL_TokData_t *tokdata, char *fname, size_t len)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
int snres;
|
|
Packit |
8681c6 |
struct passwd *pw = NULL;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (token_specific.data_store.per_user && (pw = getpwuid(getuid())) != NULL)
|
|
Packit Service |
8aa27d |
snres = ock_snprintf(fname, len, "%s/%s", tokdata->pk_dir, pw->pw_name);
|
|
Packit |
8681c6 |
else
|
|
Packit Service |
8aa27d |
snres = ock_snprintf(fname, len, "%s", tokdata->pk_dir);
|
|
Packit Service |
8aa27d |
return snres != 0 ? NULL : fname;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
void set_perm(int file)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
struct group *grp;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (token_specific.data_store.per_user) {
|
|
Packit |
8681c6 |
/* In the TPM token, with per user data stores, we don't share
|
|
Packit |
8681c6 |
* the token object amongst a group. In fact, we want to
|
|
Packit |
8681c6 |
* restrict access to a single user */
|
|
Packit |
8681c6 |
fchmod(file, S_IRUSR | S_IWUSR);
|
|
Packit |
8681c6 |
} else {
|
|
Packit |
8681c6 |
// Set absolute permissions or rw-rw----
|
|
Packit |
8681c6 |
fchmod(file, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
grp = getgrnam("pkcs11"); // Obtain the group id
|
|
Packit |
8681c6 |
if (grp) {
|
|
Packit |
8681c6 |
// set ownership to root, and pkcs11 group
|
|
Packit |
8681c6 |
if (fchown(file, getuid(), grp->gr_gid) != 0) {
|
|
Packit |
8681c6 |
goto error;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
} else {
|
|
Packit |
8681c6 |
goto error;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
error:
|
|
Packit |
8681c6 |
TRACE_DEVEL("Unable to set permissions on file.\n");
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
// Note: The token lock (XProcLock) must be held when calling this function.
|
|
Packit |
8681c6 |
// The object must hold the READ lock when this function is called.
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
CK_RV save_token_object(STDLL_TokData_t *tokdata, OBJECT *obj)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
FILE *fp = NULL;
|
|
Packit |
8681c6 |
char line[256];
|
|
Packit |
8681c6 |
char fname[PATH_MAX];
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// write token object
|
|
Packit |
8681c6 |
if (object_is_private(obj) == TRUE)
|
|
Packit |
8681c6 |
rc = save_private_token_object(tokdata, obj);
|
|
Packit |
8681c6 |
else
|
|
Packit |
8681c6 |
rc = save_public_token_object(tokdata, obj);
|
|
Packit |
8681c6 |
if (rc != CKR_OK)
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// update the index file if it exists
|
|
Packit Service |
8aa27d |
fp = open_token_object_index(fname, sizeof(fname), tokdata, "r");
|
|
Packit |
8681c6 |
if (fp) {
|
|
Packit |
8681c6 |
set_perm(fileno(fp));
|
|
Packit |
8681c6 |
while (fgets(line, 50, fp)) {
|
|
Packit |
8681c6 |
line[strlen(line) - 1] = 0;
|
|
Packit |
8681c6 |
if (strcmp(line, (char *)obj->name) == 0) {
|
|
Packit |
8681c6 |
fclose(fp);
|
|
Packit |
8681c6 |
// object is already in the list
|
|
Packit |
8681c6 |
return CKR_OK;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
fclose(fp);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
// we didn't find it...either the index file doesn't exist or this
|
|
Packit |
8681c6 |
// is a new object...
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
fp = fopen(fname, "a");
|
|
Packit |
8681c6 |
if (!fp) {
|
|
Packit |
8681c6 |
TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
|
|
Packit |
8681c6 |
return CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
set_perm(fileno(fp));
|
|
Packit |
8681c6 |
fprintf(fp, "%s\n", obj->name);
|
|
Packit |
8681c6 |
fclose(fp);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return CKR_OK;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
// Note: The token lock (XProcLock) must be held when calling this function.
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
CK_RV delete_token_object(STDLL_TokData_t *tokdata, OBJECT *obj)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
FILE *fp1, *fp2;
|
|
Packit |
8681c6 |
char objidx[PATH_MAX], idxtmp[PATH_MAX], fname[PATH_MAX], line[256];
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// FIXME: on UNIX, we need to make sure these guys aren't symlinks
|
|
Packit |
8681c6 |
// before we blindly write to these files...
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// remove the object from the index file
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
fp1 = open_token_object_index(objidx, sizeof(objidx), tokdata, "r");
|
|
Packit Service |
8aa27d |
fp2 = open_token_object_path(idxtmp, sizeof(idxtmp),
|
|
Packit Service |
8aa27d |
tokdata, "IDX.TMP", "w");
|
|
Packit |
8681c6 |
if (!fp1 || !fp2) {
|
|
Packit |
8681c6 |
if (fp1)
|
|
Packit |
8681c6 |
fclose(fp1);
|
|
Packit |
8681c6 |
if (fp2)
|
|
Packit |
8681c6 |
fclose(fp2);
|
|
Packit |
8681c6 |
TRACE_ERROR("fopen failed\n");
|
|
Packit |
8681c6 |
return CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
set_perm(fileno(fp2));
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
while (fgets(line, 50, fp1)) {
|
|
Packit |
8681c6 |
line[strlen(line) - 1] = 0;
|
|
Packit |
8681c6 |
if (strcmp(line, (char *)obj->name) == 0)
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
else
|
|
Packit |
8681c6 |
fprintf(fp2, "%s\n", line);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
fclose(fp1);
|
|
Packit |
8681c6 |
fclose(fp2);
|
|
Packit |
8681c6 |
fp2 = fopen(objidx, "w");
|
|
Packit |
8681c6 |
fp1 = fopen(idxtmp, "r");
|
|
Packit |
8681c6 |
if (!fp1 || !fp2) {
|
|
Packit |
8681c6 |
if (fp1)
|
|
Packit |
8681c6 |
fclose(fp1);
|
|
Packit |
8681c6 |
if (fp2)
|
|
Packit |
8681c6 |
fclose(fp2);
|
|
Packit |
8681c6 |
TRACE_ERROR("fopen failed\n");
|
|
Packit |
8681c6 |
return CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
set_perm(fileno(fp2));
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
while (fgets(line, 50, fp1)) {
|
|
Packit |
8681c6 |
fprintf(fp2, "%s", line);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
fclose(fp1);
|
|
Packit |
8681c6 |
fclose(fp2);
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
if (get_token_object_path(fname, sizeof(fname), tokdata,
|
|
Packit Service |
8aa27d |
(char *) obj->name) < 0)
|
|
Packit Service |
8aa27d |
TRACE_DEVEL("file name buffer overflow in obj unlink\n");
|
|
Packit Service |
8aa27d |
else
|
|
Packit Service |
8aa27d |
unlink(fname);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return CKR_OK;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_RV delete_token_data(STDLL_TokData_t *tokdata)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
CK_RV rc = CKR_OK;
|
|
Packit |
8681c6 |
char *cmd = NULL;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// Construct a string to delete the token objects.
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
// META This should be fine since the open session checking
|
|
Packit |
8681c6 |
// should occur at the API not the STDLL
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
// TODO: Implement delete_all_files_in_dir() */
|
|
Packit |
8681c6 |
if (asprintf(&cmd, "%s %s/%s/* > /dev/null 2>&1", DEL_CMD,
|
|
Packit |
8681c6 |
tokdata->data_store, PK_LITE_OBJ_DIR) < 0) {
|
|
Packit |
8681c6 |
rc = CKR_HOST_MEMORY;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (system(cmd))
|
|
Packit |
8681c6 |
TRACE_ERROR("system() failed.\n");
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
done:
|
|
Packit |
8681c6 |
free(cmd);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
CK_RV init_data_store(STDLL_TokData_t *tokdata, char *directory,
|
|
Packit Service |
8aa27d |
char *data_store, size_t len)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
char *pkdir;
|
|
Packit Service |
8aa27d |
int pklen;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (tokdata->pk_dir != NULL) {
|
|
Packit |
8681c6 |
free(tokdata->pk_dir);
|
|
Packit |
8681c6 |
tokdata->pk_dir = NULL;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
if ((pkdir = secure_getenv("PKCS_APP_STORE")) != NULL) {
|
|
Packit Service |
8aa27d |
pklen = strlen(pkdir) + 1024;
|
|
Packit Service |
8aa27d |
tokdata->pk_dir = (char *) calloc(pklen, 1);
|
|
Packit Service |
8aa27d |
if (!(tokdata->pk_dir))
|
|
Packit Service |
8aa27d |
return CKR_HOST_MEMORY;
|
|
Packit Service |
8aa27d |
if (ock_snprintf(tokdata->pk_dir, pklen, "%s/%s", pkdir, SUB_DIR) != 0)
|
|
Packit Service |
8aa27d |
return CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
return get_pk_dir(tokdata, data_store, len) ? CKR_OK : CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (directory) {
|
|
Packit Service |
8aa27d |
pklen = strlen(directory) + 1;
|
|
Packit Service |
8aa27d |
tokdata->pk_dir = (char *) calloc(pklen, 1);
|
|
Packit Service |
8aa27d |
if (!(tokdata->pk_dir))
|
|
Packit Service |
8aa27d |
return CKR_HOST_MEMORY;
|
|
Packit Service |
8aa27d |
if (ock_snprintf(tokdata->pk_dir, pklen, "%s", directory) != 0)
|
|
Packit Service |
8aa27d |
return CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
} else {
|
|
Packit Service |
8aa27d |
pklen = strlen(PK_DIR) + 1;
|
|
Packit Service |
8aa27d |
tokdata->pk_dir = (char *) calloc(pklen, 1);
|
|
Packit Service |
8aa27d |
if (!(tokdata->pk_dir))
|
|
Packit Service |
8aa27d |
return CKR_HOST_MEMORY;
|
|
Packit Service |
8aa27d |
if (ock_snprintf(tokdata->pk_dir, pklen, "%s", PK_DIR) != 0)
|
|
Packit Service |
8aa27d |
return CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
return get_pk_dir(tokdata, data_store, len) ? CKR_OK : CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
void final_data_store(STDLL_TokData_t * tokdata)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
if (tokdata->pk_dir != NULL) {
|
|
Packit |
8681c6 |
free(tokdata->pk_dir);
|
|
Packit |
8681c6 |
tokdata->pk_dir = NULL;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/******************************************************************************
|
|
Packit |
8681c6 |
* tokversion < 3.12 object store
|
|
Packit |
8681c6 |
*/
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
static CK_RV get_encryption_info(CK_ULONG *p_key_len, CK_ULONG *p_block_size)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
CK_ULONG key_len = 0L;
|
|
Packit |
8681c6 |
CK_ULONG block_size = 0L;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
switch (token_specific.data_store.encryption_algorithm) {
|
|
Packit |
8681c6 |
case CKM_DES3_CBC:
|
|
Packit |
8681c6 |
key_len = 3 * DES_KEY_SIZE;
|
|
Packit |
8681c6 |
block_size = DES_BLOCK_SIZE;
|
|
Packit |
8681c6 |
break;
|
|
Packit |
8681c6 |
case CKM_AES_CBC:
|
|
Packit |
8681c6 |
key_len = AES_KEY_SIZE_256;
|
|
Packit |
8681c6 |
block_size = AES_BLOCK_SIZE;
|
|
Packit |
8681c6 |
break;
|
|
Packit |
8681c6 |
default:
|
|
Packit |
8681c6 |
TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID));
|
|
Packit |
8681c6 |
return ERR_MECHANISM_INVALID;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (p_key_len)
|
|
Packit |
8681c6 |
*p_key_len = key_len;
|
|
Packit |
8681c6 |
if (p_block_size)
|
|
Packit |
8681c6 |
*p_block_size = block_size;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return CKR_OK;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
static CK_BYTE *duplicate_initial_vector(const CK_BYTE *iv)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
CK_ULONG block_size = 0L;
|
|
Packit |
8681c6 |
CK_BYTE *initial_vector = NULL;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (iv == NULL)
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (get_encryption_info(NULL, &block_size) != CKR_OK)
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
initial_vector = malloc(block_size);
|
|
Packit |
8681c6 |
if (initial_vector == NULL) {
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
memcpy(initial_vector, iv, block_size);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
done:
|
|
Packit |
8681c6 |
return initial_vector;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
static CK_RV encrypt_data(STDLL_TokData_t *tokdata, CK_BYTE *key,
|
|
Packit |
8681c6 |
CK_ULONG keylen, const CK_BYTE *iv,
|
|
Packit |
8681c6 |
CK_BYTE *clear, CK_ULONG clear_len,
|
|
Packit |
8681c6 |
CK_BYTE *cipher, CK_ULONG *p_cipher_len)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
#ifndef CLEARTEXT
|
|
Packit |
8681c6 |
CK_RV rc = CKR_OK;
|
|
Packit |
8681c6 |
CK_BYTE *initial_vector = NULL;
|
|
Packit |
8681c6 |
OBJECT *keyobj = NULL;
|
|
Packit |
8681c6 |
CK_KEY_TYPE keyType;
|
|
Packit |
8681c6 |
CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
|
|
Packit |
8681c6 |
CK_ATTRIBUTE key_tmpl[] = {
|
|
Packit |
8681c6 |
{CKA_CLASS, &keyClass, sizeof(keyClass)}
|
|
Packit |
8681c6 |
,
|
|
Packit |
8681c6 |
{CKA_KEY_TYPE, &keyType, sizeof(keyType)}
|
|
Packit |
8681c6 |
,
|
|
Packit |
8681c6 |
{CKA_VALUE, key, keylen}
|
|
Packit |
8681c6 |
};
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
switch (token_specific.data_store.encryption_algorithm) {
|
|
Packit |
8681c6 |
case CKM_DES3_CBC:
|
|
Packit |
8681c6 |
keyType = CKK_DES3;
|
|
Packit |
8681c6 |
break;
|
|
Packit |
8681c6 |
case CKM_AES_CBC:
|
|
Packit |
8681c6 |
keyType = CKK_AES;
|
|
Packit |
8681c6 |
break;
|
|
Packit |
8681c6 |
default:
|
|
Packit |
8681c6 |
TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID));
|
|
Packit |
8681c6 |
return ERR_MECHANISM_INVALID;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
rc = object_create_skel(tokdata, key_tmpl, 3, MODE_CREATE,
|
|
Packit |
8681c6 |
CKO_SECRET_KEY, keyType, &keyobj);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
TRACE_DEVEL("object_create_skel failed.\n");
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
initial_vector = duplicate_initial_vector(iv);
|
|
Packit |
8681c6 |
if (initial_vector == NULL) {
|
|
Packit |
8681c6 |
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
|
|
Packit |
8681c6 |
return ERR_HOST_MEMORY;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
switch (token_specific.data_store.encryption_algorithm) {
|
|
Packit |
8681c6 |
case CKM_DES3_CBC:
|
|
Packit |
8681c6 |
rc = ckm_des3_cbc_encrypt(tokdata, clear, clear_len,
|
|
Packit |
8681c6 |
cipher, p_cipher_len, initial_vector, keyobj);
|
|
Packit |
8681c6 |
break;
|
|
Packit |
8681c6 |
case CKM_AES_CBC:
|
|
Packit |
8681c6 |
rc = ckm_aes_cbc_encrypt(tokdata, clear, clear_len,
|
|
Packit |
8681c6 |
cipher, p_cipher_len, initial_vector, keyobj);
|
|
Packit |
8681c6 |
break;
|
|
Packit |
8681c6 |
default:
|
|
Packit |
8681c6 |
TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID));
|
|
Packit |
8681c6 |
rc = ERR_MECHANISM_INVALID;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (initial_vector)
|
|
Packit |
8681c6 |
free(initial_vector);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
#else
|
|
Packit |
8681c6 |
memcpy(cipher, clear, clear_len);
|
|
Packit |
8681c6 |
return CKR_OK;
|
|
Packit |
8681c6 |
#endif
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
static CK_RV encrypt_data_with_clear_key(STDLL_TokData_t *tokdata,
|
|
Packit |
8681c6 |
CK_BYTE *key, CK_ULONG keylen,
|
|
Packit |
8681c6 |
const CK_BYTE *iv,
|
|
Packit |
8681c6 |
CK_BYTE *clear, CK_ULONG clear_len,
|
|
Packit |
8681c6 |
CK_BYTE *cipher,
|
|
Packit |
8681c6 |
CK_ULONG *p_cipher_len)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
#ifndef CLEARTEXT
|
|
Packit |
8681c6 |
CK_RV rc = CKR_OK;
|
|
Packit |
8681c6 |
CK_BYTE *initial_vector = NULL;
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
if (!token_specific.secure_key_token &&
|
|
Packit |
8681c6 |
token_specific.data_store.encryption_algorithm != CKM_DES3_CBC) {
|
|
Packit |
8681c6 |
return encrypt_data(tokdata, key, keylen, iv, clear, clear_len,
|
|
Packit |
8681c6 |
cipher, p_cipher_len);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Fall back to a software alternative if key is secure, or
|
|
Packit |
8681c6 |
* if token's data store encryption algorithm is 3DES_CBC */
|
|
Packit |
8681c6 |
initial_vector = duplicate_initial_vector(iv);
|
|
Packit |
8681c6 |
if (initial_vector == NULL) {
|
|
Packit |
8681c6 |
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
|
|
Packit |
8681c6 |
return ERR_HOST_MEMORY;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
switch (token_specific.data_store.encryption_algorithm) {
|
|
Packit |
8681c6 |
case CKM_DES3_CBC:
|
|
Packit |
8681c6 |
rc = sw_des3_cbc_encrypt(clear, clear_len,
|
|
Packit |
8681c6 |
cipher, p_cipher_len, initial_vector, key);
|
|
Packit |
8681c6 |
break;
|
|
Packit |
8681c6 |
case CKM_AES_CBC:
|
|
Packit |
8681c6 |
rc = sw_aes_cbc_encrypt(clear, clear_len, cipher, p_cipher_len,
|
|
Packit |
8681c6 |
initial_vector, key, keylen);
|
|
Packit |
8681c6 |
break;
|
|
Packit |
8681c6 |
default:
|
|
Packit |
8681c6 |
TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID));
|
|
Packit |
8681c6 |
rc = ERR_MECHANISM_INVALID;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (initial_vector)
|
|
Packit |
8681c6 |
free(initial_vector);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
#else
|
|
Packit |
8681c6 |
memcpy(cipher, clear, clear_len);
|
|
Packit |
8681c6 |
return CKR_OK;
|
|
Packit |
8681c6 |
#endif
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
static CK_RV decrypt_data(STDLL_TokData_t *tokdata,
|
|
Packit |
8681c6 |
CK_BYTE *key, CK_ULONG keylen, const CK_BYTE *iv,
|
|
Packit |
8681c6 |
CK_BYTE *cipher, CK_ULONG cipher_len,
|
|
Packit |
8681c6 |
CK_BYTE *clear, CK_ULONG *p_clear_len)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
#ifndef CLEARTEXT
|
|
Packit |
8681c6 |
CK_RV rc = CKR_OK;
|
|
Packit |
8681c6 |
CK_BYTE *initial_vector = NULL;
|
|
Packit |
8681c6 |
OBJECT *keyobj = NULL;
|
|
Packit |
8681c6 |
CK_KEY_TYPE keyType;
|
|
Packit |
8681c6 |
CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
|
|
Packit |
8681c6 |
CK_ATTRIBUTE key_tmpl[] = {
|
|
Packit |
8681c6 |
{ CKA_CLASS, &keyClass, sizeof(keyClass) },
|
|
Packit |
8681c6 |
{ CKA_KEY_TYPE, &keyType, sizeof(keyType) },
|
|
Packit |
8681c6 |
{ CKA_VALUE, key, keylen }
|
|
Packit |
8681c6 |
};
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
switch (token_specific.data_store.encryption_algorithm) {
|
|
Packit |
8681c6 |
case CKM_DES3_CBC:
|
|
Packit |
8681c6 |
keyType = CKK_DES3;
|
|
Packit |
8681c6 |
break;
|
|
Packit |
8681c6 |
case CKM_AES_CBC:
|
|
Packit |
8681c6 |
keyType = CKK_AES;
|
|
Packit |
8681c6 |
break;
|
|
Packit |
8681c6 |
default:
|
|
Packit |
8681c6 |
TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID));
|
|
Packit |
8681c6 |
return ERR_MECHANISM_INVALID;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
rc = object_create_skel(tokdata, key_tmpl, 3, MODE_CREATE,
|
|
Packit |
8681c6 |
CKO_SECRET_KEY, keyType, &keyobj);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
TRACE_DEVEL("object_create_skel failed.\n");
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
initial_vector = duplicate_initial_vector(iv);
|
|
Packit |
8681c6 |
if (initial_vector == NULL) {
|
|
Packit |
8681c6 |
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
|
|
Packit |
8681c6 |
return ERR_HOST_MEMORY;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
switch (token_specific.data_store.encryption_algorithm) {
|
|
Packit |
8681c6 |
case CKM_DES3_CBC:
|
|
Packit |
8681c6 |
rc = ckm_des3_cbc_decrypt(tokdata, cipher, cipher_len,
|
|
Packit |
8681c6 |
clear, p_clear_len, initial_vector, keyobj);
|
|
Packit |
8681c6 |
break;
|
|
Packit |
8681c6 |
case CKM_AES_CBC:
|
|
Packit |
8681c6 |
rc = ckm_aes_cbc_decrypt(tokdata, cipher, cipher_len,
|
|
Packit |
8681c6 |
clear, p_clear_len, initial_vector, keyobj);
|
|
Packit |
8681c6 |
break;
|
|
Packit |
8681c6 |
default:
|
|
Packit |
8681c6 |
TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID));
|
|
Packit |
8681c6 |
rc = ERR_MECHANISM_INVALID;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (initial_vector)
|
|
Packit |
8681c6 |
free(initial_vector);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
#else
|
|
Packit |
8681c6 |
memcpy(clear, cipher, cipher_len);
|
|
Packit |
8681c6 |
return CKR_OK;
|
|
Packit |
8681c6 |
#endif
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
static CK_RV decrypt_data_with_clear_key(STDLL_TokData_t *tokdata,
|
|
Packit |
8681c6 |
CK_BYTE *key, CK_ULONG keylen,
|
|
Packit |
8681c6 |
const CK_BYTE *iv,
|
|
Packit |
8681c6 |
CK_BYTE *cipher, CK_ULONG cipher_len,
|
|
Packit |
8681c6 |
CK_BYTE *clear,
|
|
Packit |
8681c6 |
CK_ULONG *p_clear_len)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
#ifndef CLEARTEXT
|
|
Packit |
8681c6 |
CK_RV rc = CKR_OK;
|
|
Packit |
8681c6 |
CK_BYTE *initial_vector = NULL;
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
if (!token_specific.secure_key_token &&
|
|
Packit |
8681c6 |
token_specific.data_store.encryption_algorithm != CKM_DES3_CBC) {
|
|
Packit |
8681c6 |
return decrypt_data(tokdata, key, keylen, iv, cipher,
|
|
Packit |
8681c6 |
cipher_len, clear, p_clear_len);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Fall back to a software alternative if key is secure, or
|
|
Packit |
8681c6 |
* if token's data store encryption algorithm is 3DES_CBC */
|
|
Packit |
8681c6 |
initial_vector = duplicate_initial_vector(iv);
|
|
Packit |
8681c6 |
if (initial_vector == NULL) {
|
|
Packit |
8681c6 |
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
|
|
Packit |
8681c6 |
return ERR_HOST_MEMORY;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
switch (token_specific.data_store.encryption_algorithm) {
|
|
Packit |
8681c6 |
case CKM_DES3_CBC:
|
|
Packit |
8681c6 |
rc = sw_des3_cbc_decrypt(cipher, cipher_len, clear, p_clear_len,
|
|
Packit |
8681c6 |
initial_vector, key);
|
|
Packit |
8681c6 |
break;
|
|
Packit |
8681c6 |
case CKM_AES_CBC:
|
|
Packit |
8681c6 |
rc = sw_aes_cbc_decrypt(cipher, cipher_len, clear, p_clear_len,
|
|
Packit |
8681c6 |
initial_vector, key, keylen);
|
|
Packit |
8681c6 |
break;
|
|
Packit |
8681c6 |
default:
|
|
Packit |
8681c6 |
TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID));
|
|
Packit |
8681c6 |
rc = ERR_MECHANISM_INVALID;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (initial_vector)
|
|
Packit |
8681c6 |
free(initial_vector);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
#else
|
|
Packit |
8681c6 |
memcpy(clear, cipher, cipher_len);
|
|
Packit |
8681c6 |
return CKR_OK;
|
|
Packit |
8681c6 |
#endif
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
CK_RV load_token_data_old(STDLL_TokData_t *tokdata, CK_SLOT_ID slot_id)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
FILE *fp = NULL;
|
|
Packit |
8681c6 |
char fname[PATH_MAX];
|
|
Packit |
8681c6 |
TOKEN_DATA td;
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = XProcLock(tokdata);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
TRACE_ERROR("Failed to get Process Lock.\n");
|
|
Packit |
8681c6 |
goto out_nolock;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
fp = open_token_nvdat(fname, sizeof(fname), tokdata, "r");
|
|
Packit |
8681c6 |
if (!fp) {
|
|
Packit |
8681c6 |
/* Better error checking added */
|
|
Packit |
8681c6 |
if (errno == ENOENT) {
|
|
Packit |
8681c6 |
init_token_data(tokdata, slot_id);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
fp = fopen(fname, "r");
|
|
Packit |
8681c6 |
if (!fp) {
|
|
Packit |
8681c6 |
// were really hosed here since the created
|
|
Packit |
8681c6 |
// did not occur
|
|
Packit |
8681c6 |
TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto out_unlock;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
} else {
|
|
Packit |
8681c6 |
/* Could not open file for some unknown reason */
|
|
Packit |
8681c6 |
TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto out_unlock;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
set_perm(fileno(fp));
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Load generic token data */
|
|
Packit |
8681c6 |
if (!fread(&td, sizeof(TOKEN_DATA_OLD), 1, fp)) {
|
|
Packit |
8681c6 |
TRACE_ERROR("fread(%s): %s\n", fname,
|
|
Packit |
8681c6 |
ferror(fp) ? strerror(errno) : "failed");
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto out_unlock;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
memcpy(tokdata->nv_token_data, &td, sizeof(TOKEN_DATA_OLD));
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Load token-specific data */
|
|
Packit |
8681c6 |
if (token_specific.t_load_token_data) {
|
|
Packit |
8681c6 |
rc = token_specific.t_load_token_data(tokdata, slot_id, fp);
|
|
Packit |
8681c6 |
if (rc)
|
|
Packit |
8681c6 |
goto out_unlock;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = CKR_OK;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
out_unlock:
|
|
Packit |
8681c6 |
if (fp)
|
|
Packit |
8681c6 |
fclose(fp);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (rc == CKR_OK) {
|
|
Packit |
8681c6 |
rc = XProcUnLock(tokdata);
|
|
Packit |
8681c6 |
if (rc != CKR_OK)
|
|
Packit |
8681c6 |
TRACE_ERROR("Failed to release Process Lock.\n");
|
|
Packit |
8681c6 |
} else {
|
|
Packit |
8681c6 |
/* return error that occurred first */
|
|
Packit |
8681c6 |
XProcUnLock(tokdata);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
out_nolock:
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
CK_RV save_token_data_old(STDLL_TokData_t *tokdata, CK_SLOT_ID slot_id)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
FILE *fp = NULL;
|
|
Packit |
8681c6 |
TOKEN_DATA td;
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit |
8681c6 |
char fname[PATH_MAX];
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = XProcLock(tokdata);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
TRACE_ERROR("Failed to get Process Lock.\n");
|
|
Packit |
8681c6 |
goto out_nolock;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
fp = open_token_nvdat(fname, sizeof(fname), tokdata, "w");
|
|
Packit |
8681c6 |
if (!fp) {
|
|
Packit |
8681c6 |
TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
set_perm(fileno(fp));
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Write generic token data */
|
|
Packit |
8681c6 |
memcpy(&td, tokdata->nv_token_data, sizeof(TOKEN_DATA_OLD));
|
|
Packit |
8681c6 |
if (!fwrite(&td, sizeof(TOKEN_DATA_OLD), 1, fp)) {
|
|
Packit |
8681c6 |
TRACE_ERROR("fwrite(%s): %s\n", fname,
|
|
Packit |
8681c6 |
ferror(fp) ? strerror(errno) : "failed");
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Write token-specific data */
|
|
Packit |
8681c6 |
if (token_specific.t_save_token_data) {
|
|
Packit |
8681c6 |
rc = token_specific.t_save_token_data(tokdata, slot_id, fp);
|
|
Packit |
8681c6 |
if (rc)
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = CKR_OK;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
done:
|
|
Packit |
8681c6 |
if (fp)
|
|
Packit |
8681c6 |
fclose(fp);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (rc == CKR_OK) {
|
|
Packit |
8681c6 |
rc = XProcUnLock(tokdata);
|
|
Packit |
8681c6 |
if (rc != CKR_OK)
|
|
Packit |
8681c6 |
TRACE_ERROR("Failed to release Process Lock.\n");
|
|
Packit |
8681c6 |
} else {
|
|
Packit |
8681c6 |
/* return error that occurred first */
|
|
Packit |
8681c6 |
XProcUnLock(tokdata);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
out_nolock:
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
// Note: The token lock (XProcLock) must be held when calling this function.
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
static CK_RV save_private_token_object_old(STDLL_TokData_t *tokdata, OBJECT *obj)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
FILE *fp = NULL;
|
|
Packit |
8681c6 |
CK_BYTE *obj_data = NULL;
|
|
Packit |
8681c6 |
CK_BYTE *clear = NULL;
|
|
Packit |
8681c6 |
CK_BYTE *cipher = NULL;
|
|
Packit |
8681c6 |
CK_BYTE *ptr = NULL;
|
|
Packit |
8681c6 |
char fname[PATH_MAX];
|
|
Packit |
8681c6 |
CK_BYTE hash_sha[SHA1_HASH_SIZE];
|
|
Packit |
8681c6 |
CK_BYTE *key = NULL;
|
|
Packit |
8681c6 |
CK_ULONG key_len = 0L;
|
|
Packit |
8681c6 |
CK_ULONG block_size = 0L;
|
|
Packit |
8681c6 |
CK_ULONG obj_data_len, clear_len, cipher_len;
|
|
Packit |
8681c6 |
CK_ULONG padded_len;
|
|
Packit |
8681c6 |
CK_BBOOL flag;
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit |
8681c6 |
CK_ULONG_32 obj_data_len_32;
|
|
Packit |
8681c6 |
CK_ULONG_32 total_len;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = object_flatten(obj, &obj_data, &obj_data_len);
|
|
Packit |
8681c6 |
obj_data_len_32 = obj_data_len;
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
goto error;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
// format for the object file:
|
|
Packit |
8681c6 |
// private flag
|
|
Packit |
8681c6 |
// ---- begin encrypted part <--+
|
|
Packit |
8681c6 |
// length of object data |
|
|
Packit |
8681c6 |
// object data +---- sensitive part
|
|
Packit |
8681c6 |
// SHA of (object data) |
|
|
Packit |
8681c6 |
// ---- end encrypted part <--+
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
compute_sha1(tokdata, obj_data, obj_data_len, hash_sha);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// encrypt the sensitive object data. need to be careful.
|
|
Packit |
8681c6 |
// if I use the normal high-level encryption routines I'll need to
|
|
Packit |
8681c6 |
// create a tepmorary key object containing the master key, perform the
|
|
Packit |
8681c6 |
// encryption, then destroy the key object. There is a race condition
|
|
Packit |
8681c6 |
// here if the application is multithreaded (if a thread-switch occurs,
|
|
Packit |
8681c6 |
// the other application thread could do a FindObject and be able to
|
|
Packit |
8681c6 |
// access the master key object.
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
// So I have to use the low-level encryption routines.
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if ((rc = get_encryption_info(&key_len, &block_size)) != CKR_OK)
|
|
Packit |
8681c6 |
goto error;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// Duplicate key
|
|
Packit |
8681c6 |
key = malloc(key_len);
|
|
Packit |
8681c6 |
if (!key)
|
|
Packit |
8681c6 |
goto oom_error;
|
|
Packit |
8681c6 |
memcpy(key, tokdata->master_key, key_len);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
clear_len = sizeof(CK_ULONG_32) + obj_data_len_32 + SHA1_HASH_SIZE;
|
|
Packit |
8681c6 |
cipher_len = padded_len = block_size * (clear_len / block_size + 1);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
clear = malloc(padded_len);
|
|
Packit |
8681c6 |
cipher = malloc(padded_len);
|
|
Packit |
8681c6 |
if (!clear || !cipher)
|
|
Packit |
8681c6 |
goto oom_error;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// Build data that will be encrypted
|
|
Packit |
8681c6 |
ptr = clear;
|
|
Packit |
8681c6 |
memcpy(ptr, &obj_data_len_32, sizeof(CK_ULONG_32));
|
|
Packit |
8681c6 |
ptr += sizeof(CK_ULONG_32);
|
|
Packit |
8681c6 |
memcpy(ptr, obj_data, obj_data_len_32);
|
|
Packit |
8681c6 |
ptr += obj_data_len_32;
|
|
Packit |
8681c6 |
memcpy(ptr, hash_sha, SHA1_HASH_SIZE);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
add_pkcs_padding(clear + clear_len, block_size, clear_len, padded_len);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = encrypt_data_with_clear_key(tokdata, key, key_len,
|
|
Packit |
8681c6 |
token_specific.data_store.
|
|
Packit |
8681c6 |
obj_initial_vector, clear, padded_len,
|
|
Packit |
8681c6 |
cipher, &cipher_len);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
goto error;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
if (ock_snprintf(fname, PATH_MAX, "%s/%s/%.8s", tokdata->data_store,
|
|
Packit Service |
8aa27d |
PK_LITE_OBJ_DIR, (char *)obj->name) != 0) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("private token object old name buffer overflow\n");
|
|
Packit Service |
8aa27d |
rc = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto error;
|
|
Packit Service |
8aa27d |
}
|
|
Packit |
8681c6 |
fp = fopen(fname, "w");
|
|
Packit |
8681c6 |
if (!fp) {
|
|
Packit |
8681c6 |
TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto error;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
set_perm(fileno(fp));
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
total_len = sizeof(CK_ULONG_32) + sizeof(CK_BBOOL) + cipher_len;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
flag = TRUE;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
(void) fwrite(&total_len, sizeof(CK_ULONG_32), 1, fp);
|
|
Packit |
8681c6 |
(void) fwrite(&flag, sizeof(CK_BBOOL), 1, fp);
|
|
Packit |
8681c6 |
(void) fwrite(cipher, cipher_len, 1, fp);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
fclose(fp);
|
|
Packit |
8681c6 |
free(obj_data);
|
|
Packit |
8681c6 |
free(clear);
|
|
Packit |
8681c6 |
free(cipher);
|
|
Packit |
8681c6 |
free(key);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return CKR_OK;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
oom_error:
|
|
Packit |
8681c6 |
rc = CKR_HOST_MEMORY;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
error:
|
|
Packit |
8681c6 |
if (fp)
|
|
Packit |
8681c6 |
fclose(fp);
|
|
Packit |
8681c6 |
if (obj_data)
|
|
Packit |
8681c6 |
free(obj_data);
|
|
Packit |
8681c6 |
if (clear)
|
|
Packit |
8681c6 |
free(clear);
|
|
Packit |
8681c6 |
if (cipher)
|
|
Packit |
8681c6 |
free(cipher);
|
|
Packit |
8681c6 |
if (key)
|
|
Packit |
8681c6 |
free(key);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
// Note: The token lock (XProcLock) must be held when calling this function.
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
CK_RV load_private_token_objects_old(STDLL_TokData_t *tokdata)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
FILE *fp1 = NULL, *fp2 = NULL;
|
|
Packit |
8681c6 |
CK_BYTE *buf = NULL;
|
|
Packit |
8681c6 |
char tmp[PATH_MAX];
|
|
Packit |
8681c6 |
char iname[PATH_MAX];
|
|
Packit |
8681c6 |
char fname[PATH_MAX];
|
|
Packit |
8681c6 |
CK_BBOOL priv;
|
|
Packit |
8681c6 |
CK_ULONG_32 size;
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit |
8681c6 |
size_t read_size;
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
fp1 = open_token_object_index(iname, sizeof(iname), tokdata, "r");
|
|
Packit |
8681c6 |
if (!fp1)
|
|
Packit |
8681c6 |
return CKR_OK; // no token objects
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
while (fgets(tmp, 50, fp1)) {
|
|
Packit |
8681c6 |
tmp[strlen(tmp) - 1] = 0;
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
fp2 = open_token_object_path(fname, sizeof(fname), tokdata, tmp, "r");
|
|
Packit |
8681c6 |
if (!fp2)
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (!fread(&size, sizeof(CK_ULONG_32), 1, fp2)) {
|
|
Packit |
8681c6 |
fclose(fp2);
|
|
Packit |
8681c6 |
OCK_SYSLOG(LOG_ERR, "Cannot read size\n");
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
if (!fread(&priv, sizeof(CK_BBOOL), 1, fp2)) {
|
|
Packit |
8681c6 |
fclose(fp2);
|
|
Packit |
8681c6 |
OCK_SYSLOG(LOG_ERR, "Cannot read boolean\n");
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
if (priv == FALSE) {
|
|
Packit |
8681c6 |
fclose(fp2);
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
//size--;
|
|
Packit |
8681c6 |
size = size - sizeof(CK_ULONG_32) - sizeof(CK_BBOOL);
|
|
Packit |
8681c6 |
buf = (CK_BYTE *) malloc(size);
|
|
Packit |
8681c6 |
if (!buf) {
|
|
Packit |
8681c6 |
fclose(fp2);
|
|
Packit |
8681c6 |
OCK_SYSLOG(LOG_ERR,
|
|
Packit |
8681c6 |
"Cannot malloc %u bytes to read in "
|
|
Packit |
8681c6 |
"token object %s (ignoring it)", size, fname);
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
read_size = fread(buf, 1, size, fp2);
|
|
Packit |
8681c6 |
if (read_size != size) {
|
|
Packit |
8681c6 |
free(buf);
|
|
Packit |
8681c6 |
fclose(fp2);
|
|
Packit |
8681c6 |
OCK_SYSLOG(LOG_ERR,
|
|
Packit |
8681c6 |
"Cannot read token object %s " "(ignoring it)", fname);
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = restore_private_token_object_old(tokdata, buf, size, NULL);
|
|
Packit |
8681c6 |
if (rc != CKR_OK)
|
|
Packit |
8681c6 |
goto error;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
free(buf);
|
|
Packit |
8681c6 |
fclose(fp2);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
fclose(fp1);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return CKR_OK;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
error:
|
|
Packit |
8681c6 |
if (buf)
|
|
Packit |
8681c6 |
free(buf);
|
|
Packit |
8681c6 |
if (fp1)
|
|
Packit |
8681c6 |
fclose(fp1);
|
|
Packit |
8681c6 |
if (fp2)
|
|
Packit |
8681c6 |
fclose(fp2);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
CK_RV load_masterkey_so_old(STDLL_TokData_t *tokdata)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
FILE *fp = NULL;
|
|
Packit |
8681c6 |
CK_BYTE hash_sha[SHA1_HASH_SIZE];
|
|
Packit |
8681c6 |
CK_BYTE *cipher = NULL;
|
|
Packit |
8681c6 |
CK_BYTE *clear = NULL;
|
|
Packit |
8681c6 |
CK_BYTE *key = NULL;
|
|
Packit |
8681c6 |
CK_ULONG data_len;
|
|
Packit |
8681c6 |
CK_ULONG cipher_len, clear_len;
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit |
8681c6 |
char fname[PATH_MAX];
|
|
Packit |
8681c6 |
CK_ULONG key_len = 0L;
|
|
Packit |
8681c6 |
CK_ULONG master_key_len = 0L;
|
|
Packit |
8681c6 |
CK_ULONG block_size = 0L;
|
|
Packit Service |
8aa27d |
struct stat sb;
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
if ((rc = get_encryption_info(&key_len, &block_size)) != CKR_OK)
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
master_key_len = key_len;
|
|
Packit |
8681c6 |
memset(tokdata->master_key, 0x0, master_key_len);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
data_len = master_key_len + SHA1_HASH_SIZE;
|
|
Packit |
8681c6 |
clear_len = cipher_len = (data_len + block_size - 1)
|
|
Packit |
8681c6 |
& ~(block_size - 1);
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
sprintf(fname, "%s/MK_SO", tokdata->data_store);
|
|
Packit Service |
8aa27d |
if (stat(fname, &sb) != 0) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("stat(%s): %s\n", fname, strerror(errno));
|
|
Packit Service |
8aa27d |
rc = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if ((CK_ULONG)sb.st_size > cipher_len &&
|
|
Packit Service |
8aa27d |
token_specific.secure_key_token &&
|
|
Packit Service |
8aa27d |
strcmp(token_specific.token_subdir, "ccatok") == 0) {
|
|
Packit Service |
8aa27d |
/*
|
|
Packit Service |
8aa27d |
* The CCA token used to have a secure master key length of 64, although
|
|
Packit Service |
8aa27d |
* it uses clear keys for the master key in the meantime. The master key
|
|
Packit Service |
8aa27d |
* length has an influence on the file size of the MK_SO and MK_USER
|
|
Packit Service |
8aa27d |
* files when using the old pin encryption format. Use special handling
|
|
Packit Service |
8aa27d |
* for such larger MK_SO files, and accept the larger length. Newly
|
|
Packit Service |
8aa27d |
* written MK_SO files will use the clear key master key length, but we
|
|
Packit Service |
8aa27d |
* need to be able to read larger files for backwards compatibility.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
master_key_len = 64;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
data_len = master_key_len + SHA1_HASH_SIZE;
|
|
Packit Service |
8aa27d |
clear_len = cipher_len = (data_len + block_size - 1)
|
|
Packit Service |
8aa27d |
& ~(block_size - 1);
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit |
8681c6 |
key = malloc(key_len);
|
|
Packit |
8681c6 |
cipher = malloc(cipher_len);
|
|
Packit |
8681c6 |
clear = malloc(clear_len);
|
|
Packit |
8681c6 |
if (key == NULL || cipher == NULL || clear == NULL) {
|
|
Packit |
8681c6 |
rc = ERR_HOST_MEMORY;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
// this file gets created on C_InitToken so we can assume that it always
|
|
Packit |
8681c6 |
// exists
|
|
Packit |
8681c6 |
//
|
|
Packit Service |
8aa27d |
fp = open_token_data_store_path(fname, sizeof(fname), tokdata, "MK_SO", "r");
|
|
Packit |
8681c6 |
if (!fp) {
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
set_perm(fileno(fp));
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = fread(cipher, cipher_len, 1, fp);
|
|
Packit |
8681c6 |
if (rc != 1) {
|
|
Packit |
8681c6 |
TRACE_ERROR("fread() failed.\n");
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
// decrypt the master key data using the MD5 of the SO key
|
|
Packit |
8681c6 |
// (we can't use the SHA of the SO key since the SHA of the key is
|
|
Packit |
8681c6 |
// stored in the token data file).
|
|
Packit |
8681c6 |
memcpy(key, tokdata->so_pin_md5, MD5_HASH_SIZE);
|
|
Packit |
8681c6 |
memcpy(key + MD5_HASH_SIZE, tokdata->so_pin_md5, key_len - MD5_HASH_SIZE);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = decrypt_data_with_clear_key(tokdata, key, key_len,
|
|
Packit |
8681c6 |
token_specific.data_store.
|
|
Packit |
8681c6 |
pin_initial_vector, cipher, cipher_len,
|
|
Packit |
8681c6 |
clear, &clear_len);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
TRACE_DEVEL("decrypt_data_with_clear_key failed.\n");
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
// technically should strip PKCS padding here but since I already know
|
|
Packit |
8681c6 |
// what the length should be, I don't bother.
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// compare the hashes
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
rc = compute_sha1(tokdata, clear, master_key_len, hash_sha);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (memcmp(hash_sha, clear + master_key_len, SHA1_HASH_SIZE) != 0) {
|
|
Packit |
8681c6 |
TRACE_ERROR("masterkey hashes do not match\n");
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
memcpy(tokdata->master_key, clear, master_key_len);
|
|
Packit |
8681c6 |
rc = CKR_OK;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
done:
|
|
Packit |
8681c6 |
if (fp)
|
|
Packit |
8681c6 |
fclose(fp);
|
|
Packit |
8681c6 |
if (clear)
|
|
Packit |
8681c6 |
free(clear);
|
|
Packit |
8681c6 |
if (cipher)
|
|
Packit |
8681c6 |
free(cipher);
|
|
Packit |
8681c6 |
if (key)
|
|
Packit |
8681c6 |
free(key);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
CK_RV load_masterkey_user_old(STDLL_TokData_t *tokdata)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
FILE *fp = NULL;
|
|
Packit |
8681c6 |
CK_BYTE hash_sha[SHA1_HASH_SIZE];
|
|
Packit |
8681c6 |
CK_BYTE *cipher = NULL;
|
|
Packit |
8681c6 |
CK_BYTE *clear = NULL;
|
|
Packit |
8681c6 |
CK_BYTE *key = NULL;
|
|
Packit |
8681c6 |
CK_ULONG data_len;
|
|
Packit |
8681c6 |
CK_ULONG cipher_len, clear_len;
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit |
8681c6 |
char fname[PATH_MAX];
|
|
Packit |
8681c6 |
CK_ULONG key_len = 0L;
|
|
Packit |
8681c6 |
CK_ULONG master_key_len = 0L;
|
|
Packit |
8681c6 |
CK_ULONG block_size = 0L;
|
|
Packit Service |
8aa27d |
struct stat sb;
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
if ((rc = get_encryption_info(&key_len, &block_size)) != CKR_OK)
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
master_key_len = key_len;
|
|
Packit |
8681c6 |
memset(tokdata->master_key, 0x0, master_key_len);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
data_len = master_key_len + SHA1_HASH_SIZE;
|
|
Packit |
8681c6 |
clear_len = cipher_len = (data_len + block_size - 1)
|
|
Packit |
8681c6 |
& ~(block_size - 1);
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
sprintf(fname, "%s/MK_USER", tokdata->data_store);
|
|
Packit Service |
8aa27d |
if (stat(fname, &sb) != 0) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("stat(%s): %s\n", fname, strerror(errno));
|
|
Packit Service |
8aa27d |
rc = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if ((CK_ULONG)sb.st_size > cipher_len &&
|
|
Packit Service |
8aa27d |
token_specific.secure_key_token &&
|
|
Packit Service |
8aa27d |
strcmp(token_specific.token_subdir, "ccatok") == 0) {
|
|
Packit Service |
8aa27d |
/*
|
|
Packit Service |
8aa27d |
* The CCA token used to have a secure master key length of 64, although
|
|
Packit Service |
8aa27d |
* it uses clear keys for the master key in the meantime. The master key
|
|
Packit Service |
8aa27d |
* length has an influence on the file size of the MK_SO and MK_USER
|
|
Packit Service |
8aa27d |
* files when using the old pin encryption format. Use special handling
|
|
Packit Service |
8aa27d |
* for such larger MK_USER files, and accept the larger length. Newly
|
|
Packit Service |
8aa27d |
* written MK_USER files will use the clear key master key length, but
|
|
Packit Service |
8aa27d |
* we need to be able to read larger files for backwards compatibility.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
master_key_len = 64;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
data_len = master_key_len + SHA1_HASH_SIZE;
|
|
Packit Service |
8aa27d |
clear_len = cipher_len = (data_len + block_size - 1)
|
|
Packit Service |
8aa27d |
& ~(block_size - 1);
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit |
8681c6 |
key = malloc(key_len);
|
|
Packit |
8681c6 |
cipher = malloc(cipher_len);
|
|
Packit |
8681c6 |
clear = malloc(clear_len);
|
|
Packit |
8681c6 |
if (key == NULL || cipher == NULL || clear == NULL) {
|
|
Packit |
8681c6 |
rc = ERR_HOST_MEMORY;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
// this file gets created on C_InitToken so we can assume that it always
|
|
Packit |
8681c6 |
// exists
|
|
Packit |
8681c6 |
//
|
|
Packit Service |
8aa27d |
fp = open_token_data_store_path(fname, sizeof(fname), tokdata, "MK_USER", "r");
|
|
Packit |
8681c6 |
if (!fp) {
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
set_perm(fileno(fp));
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = fread(cipher, cipher_len, 1, fp);
|
|
Packit |
8681c6 |
if (rc != 1) {
|
|
Packit |
8681c6 |
TRACE_ERROR("fread failed.\n");
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
// decrypt the master key data using the MD5 of the SO key
|
|
Packit |
8681c6 |
// (we can't use the SHA of the SO key since the SHA of the key is
|
|
Packit |
8681c6 |
// stored in the token data file).
|
|
Packit |
8681c6 |
memcpy(key, tokdata->user_pin_md5, MD5_HASH_SIZE);
|
|
Packit |
8681c6 |
memcpy(key + MD5_HASH_SIZE, tokdata->user_pin_md5, key_len - MD5_HASH_SIZE);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = decrypt_data_with_clear_key(tokdata, key, key_len,
|
|
Packit |
8681c6 |
token_specific.data_store.
|
|
Packit |
8681c6 |
pin_initial_vector, cipher, cipher_len,
|
|
Packit |
8681c6 |
clear, &clear_len);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
TRACE_DEVEL("decrypt_data_with_clear_key failed.\n");
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
// technically should strip PKCS padding here but since I already know
|
|
Packit |
8681c6 |
// what the length should be, I don't bother.
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// compare the hashes
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
rc = compute_sha1(tokdata, clear, master_key_len, hash_sha);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (memcmp(hash_sha, clear + master_key_len, SHA1_HASH_SIZE) != 0) {
|
|
Packit |
8681c6 |
TRACE_ERROR("User's masterkey hashes do not match.\n");
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
memcpy(tokdata->master_key, clear, master_key_len);
|
|
Packit |
8681c6 |
rc = CKR_OK;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
done:
|
|
Packit |
8681c6 |
if (fp)
|
|
Packit |
8681c6 |
fclose(fp);
|
|
Packit |
8681c6 |
if (key)
|
|
Packit |
8681c6 |
free(key);
|
|
Packit |
8681c6 |
if (clear)
|
|
Packit |
8681c6 |
free(clear);
|
|
Packit |
8681c6 |
if (cipher)
|
|
Packit |
8681c6 |
free(cipher);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
CK_RV save_masterkey_so_old(STDLL_TokData_t *tokdata)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
FILE *fp = NULL;
|
|
Packit |
8681c6 |
CK_BYTE *clear = NULL;
|
|
Packit |
8681c6 |
CK_ULONG clear_len = 0L;
|
|
Packit |
8681c6 |
CK_BYTE *cipher = NULL;
|
|
Packit |
8681c6 |
CK_ULONG cipher_len = 0L;
|
|
Packit |
8681c6 |
CK_BYTE *key = NULL;
|
|
Packit |
8681c6 |
CK_ULONG key_len = 0L;
|
|
Packit |
8681c6 |
CK_ULONG block_size = 0L;
|
|
Packit |
8681c6 |
CK_ULONG data_len = 0L;
|
|
Packit |
8681c6 |
char fname[PATH_MAX];
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Skip it if master key is not needed. */
|
|
Packit |
8681c6 |
if (!token_specific.data_store.use_master_key)
|
|
Packit |
8681c6 |
return CKR_OK;
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
if ((rc = get_encryption_info(&key_len, &block_size)) != CKR_OK)
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
data_len = key_len + SHA1_HASH_SIZE;
|
|
Packit |
8681c6 |
cipher_len = clear_len = block_size * (data_len / block_size + 1);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
key = malloc(key_len);
|
|
Packit |
8681c6 |
clear = malloc(clear_len);
|
|
Packit |
8681c6 |
cipher = malloc(cipher_len);
|
|
Packit |
8681c6 |
if (key == NULL || clear == NULL || cipher == NULL) {
|
|
Packit |
8681c6 |
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
|
|
Packit |
8681c6 |
rc = ERR_HOST_MEMORY;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
// Copy data to buffer (key+hash)
|
|
Packit Service |
8aa27d |
memcpy(clear, tokdata->master_key, key_len);
|
|
Packit |
8681c6 |
if ((rc = compute_sha1(tokdata, tokdata->master_key,
|
|
Packit Service |
8aa27d |
key_len, clear + key_len)) != CKR_OK)
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
add_pkcs_padding(clear + data_len, block_size, data_len, clear_len);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// encrypt the key data
|
|
Packit |
8681c6 |
memcpy(key, tokdata->so_pin_md5, MD5_HASH_SIZE);
|
|
Packit |
8681c6 |
memcpy(key + MD5_HASH_SIZE, tokdata->so_pin_md5, key_len - MD5_HASH_SIZE);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = encrypt_data_with_clear_key(tokdata, key, key_len,
|
|
Packit |
8681c6 |
token_specific.data_store.
|
|
Packit |
8681c6 |
pin_initial_vector, clear, clear_len,
|
|
Packit |
8681c6 |
cipher, &cipher_len);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
// write the file
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
// probably ought to ensure the permissions are correct
|
|
Packit |
8681c6 |
//
|
|
Packit Service |
8aa27d |
fp = open_token_data_store_path(fname, sizeof(fname), tokdata, "MK_SO", "w");
|
|
Packit |
8681c6 |
if (!fp) {
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
set_perm(fileno(fp));
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = fwrite(cipher, cipher_len, 1, fp);
|
|
Packit |
8681c6 |
if (rc != 1) {
|
|
Packit |
8681c6 |
TRACE_ERROR("fwrite failed.\n");
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = CKR_OK;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
done:
|
|
Packit |
8681c6 |
if (fp)
|
|
Packit |
8681c6 |
fclose(fp);
|
|
Packit |
8681c6 |
if (key)
|
|
Packit |
8681c6 |
free(key);
|
|
Packit |
8681c6 |
if (clear)
|
|
Packit |
8681c6 |
free(clear);
|
|
Packit |
8681c6 |
if (cipher)
|
|
Packit |
8681c6 |
free(cipher);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
CK_RV save_masterkey_user_old(STDLL_TokData_t *tokdata)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
FILE *fp = NULL;
|
|
Packit |
8681c6 |
CK_BYTE *clear = NULL;
|
|
Packit |
8681c6 |
CK_ULONG clear_len = 0L;
|
|
Packit |
8681c6 |
CK_BYTE *cipher = NULL;
|
|
Packit |
8681c6 |
CK_ULONG cipher_len = 0L;
|
|
Packit |
8681c6 |
CK_BYTE *key = NULL;
|
|
Packit |
8681c6 |
CK_ULONG key_len = 0L;
|
|
Packit |
8681c6 |
CK_ULONG block_size = 0L;
|
|
Packit |
8681c6 |
CK_ULONG data_len = 0L;
|
|
Packit |
8681c6 |
char fname[PATH_MAX];
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
if ((rc = get_encryption_info(&key_len, &block_size)) != CKR_OK)
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
data_len = key_len + SHA1_HASH_SIZE;
|
|
Packit |
8681c6 |
cipher_len = clear_len = block_size * (data_len / block_size + 1);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
key = malloc(key_len);
|
|
Packit |
8681c6 |
clear = malloc(clear_len);
|
|
Packit |
8681c6 |
cipher = malloc(cipher_len);
|
|
Packit |
8681c6 |
if (key == NULL || clear == NULL || cipher == NULL) {
|
|
Packit |
8681c6 |
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
|
|
Packit |
8681c6 |
rc = ERR_HOST_MEMORY;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
// Copy data to buffer (key+hash)
|
|
Packit Service |
8aa27d |
memcpy(clear, tokdata->master_key, key_len);
|
|
Packit |
8681c6 |
if ((rc = compute_sha1(tokdata, tokdata->master_key,
|
|
Packit Service |
8aa27d |
key_len, clear + key_len)) != CKR_OK)
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
add_pkcs_padding(clear + data_len, block_size, data_len, clear_len);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// encrypt the key data
|
|
Packit |
8681c6 |
memcpy(key, tokdata->user_pin_md5, MD5_HASH_SIZE);
|
|
Packit |
8681c6 |
memcpy(key + MD5_HASH_SIZE, tokdata->user_pin_md5, key_len - MD5_HASH_SIZE);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = encrypt_data_with_clear_key(tokdata, key, key_len,
|
|
Packit |
8681c6 |
token_specific.data_store.
|
|
Packit |
8681c6 |
pin_initial_vector, clear, clear_len,
|
|
Packit |
8681c6 |
cipher, &cipher_len);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
// write the file
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
// probably ought to ensure the permissions are correct
|
|
Packit |
8681c6 |
//
|
|
Packit Service |
8aa27d |
fp = open_token_data_store_path(fname, sizeof(fname), tokdata, "MK_USER", "w");
|
|
Packit |
8681c6 |
if (!fp) {
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
set_perm(fileno(fp));
|
|
Packit |
8681c6 |
rc = fwrite(cipher, cipher_len, 1, fp);
|
|
Packit |
8681c6 |
if (rc != 1) {
|
|
Packit |
8681c6 |
TRACE_ERROR("fwrite failed.\n");
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = CKR_OK;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
done:
|
|
Packit |
8681c6 |
if (fp)
|
|
Packit |
8681c6 |
fclose(fp);
|
|
Packit |
8681c6 |
if (key)
|
|
Packit |
8681c6 |
free(key);
|
|
Packit |
8681c6 |
if (clear)
|
|
Packit |
8681c6 |
free(clear);
|
|
Packit |
8681c6 |
if (cipher)
|
|
Packit |
8681c6 |
free(cipher);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_RV generate_master_key_old(STDLL_TokData_t *tokdata, CK_BYTE *key)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
CK_RV rc = CKR_OK;
|
|
Packit |
8681c6 |
CK_ULONG key_len = 0L;
|
|
Packit Service |
8aa27d |
CK_ULONG master_key_len;
|
|
Packit Service |
8aa27d |
CK_BYTE *master_key = NULL;
|
|
Packit Service |
8aa27d |
CK_BBOOL is_opaque = FALSE;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Skip it if master key is not needed. */
|
|
Packit |
8681c6 |
if (!token_specific.data_store.use_master_key)
|
|
Packit |
8681c6 |
return CKR_OK;
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
if ((rc = get_encryption_info(&key_len, NULL)) != CKR_OK)
|
|
Packit Service |
8aa27d |
return CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* For secure key tokens, object encrypt/decrypt uses
|
|
Packit |
8681c6 |
* software(openssl), not token. So generate masterkey via RNG.
|
|
Packit |
8681c6 |
*/
|
|
Packit Service |
8aa27d |
if (token_specific.secure_key_token)
|
|
Packit |
8681c6 |
return rng_generate(tokdata, key, key_len);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* For clear key tokens, let token generate masterkey
|
|
Packit |
8681c6 |
* since token will also encrypt/decrypt the objects.
|
|
Packit |
8681c6 |
*/
|
|
Packit |
8681c6 |
switch (token_specific.data_store.encryption_algorithm) {
|
|
Packit |
8681c6 |
case CKM_DES3_CBC:
|
|
Packit Service |
8aa27d |
rc = token_specific.t_des_key_gen(tokdata, &master_key,
|
|
Packit Service |
8aa27d |
&master_key_len, key_len,
|
|
Packit Service |
8aa27d |
&is_opaque);
|
|
Packit Service |
8aa27d |
break;
|
|
Packit |
8681c6 |
case CKM_AES_CBC:
|
|
Packit Service |
8aa27d |
rc = token_specific.t_aes_key_gen(tokdata, &master_key,
|
|
Packit Service |
8aa27d |
&master_key_len, key_len,
|
|
Packit Service |
8aa27d |
&is_opaque);
|
|
Packit Service |
8aa27d |
break;
|
|
Packit Service |
8aa27d |
default:
|
|
Packit Service |
8aa27d |
return CKR_MECHANISM_INVALID;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (rc != CKR_OK)
|
|
Packit Service |
8aa27d |
return rc;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (master_key_len != key_len) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Invalid master key size: %lu\n", master_key_len);
|
|
Packit Service |
8aa27d |
free(master_key);
|
|
Packit Service |
8aa27d |
return CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
memcpy(key, master_key, master_key_len);
|
|
Packit Service |
8aa27d |
free(master_key);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return CKR_OK;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_RV restore_private_token_object_old(STDLL_TokData_t *tokdata, CK_BYTE *data,
|
|
Packit |
8681c6 |
CK_ULONG len, OBJECT *pObj)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
CK_BYTE *clear = NULL;
|
|
Packit |
8681c6 |
CK_BYTE *obj_data = NULL;
|
|
Packit |
8681c6 |
CK_BYTE *ptr = NULL;
|
|
Packit |
8681c6 |
CK_BYTE *key = NULL;
|
|
Packit |
8681c6 |
CK_ULONG key_len;
|
|
Packit |
8681c6 |
CK_ULONG block_size;
|
|
Packit |
8681c6 |
CK_BYTE hash_sha[SHA1_HASH_SIZE];
|
|
Packit |
8681c6 |
CK_ULONG clear_len, obj_data_len;
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// format for the object data:
|
|
Packit |
8681c6 |
// (private flag has already been read at this point)
|
|
Packit |
8681c6 |
// ---- begin encrypted part
|
|
Packit |
8681c6 |
// length of object data
|
|
Packit |
8681c6 |
// object data
|
|
Packit |
8681c6 |
// SHA of object data
|
|
Packit |
8681c6 |
// ---- end encrypted part
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
clear_len = len;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
clear = (CK_BYTE *) malloc(len);
|
|
Packit |
8681c6 |
if (!clear) {
|
|
Packit |
8681c6 |
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
|
|
Packit |
8681c6 |
rc = CKR_HOST_MEMORY;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if ((rc = get_encryption_info(&key_len, &block_size)) != CKR_OK)
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// decrypt the encrypted chunk
|
|
Packit |
8681c6 |
key = malloc(key_len);
|
|
Packit |
8681c6 |
if (!key) {
|
|
Packit |
8681c6 |
rc = ERR_HOST_MEMORY;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
memcpy(key, tokdata->master_key, key_len);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = decrypt_data_with_clear_key(tokdata, key, key_len,
|
|
Packit |
8681c6 |
token_specific.data_store.
|
|
Packit |
8681c6 |
obj_initial_vector, data, len, clear,
|
|
Packit |
8681c6 |
&clear_len);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = strip_pkcs_padding(clear, len, &clear_len);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// if the padding extraction didn't work it means the object was
|
|
Packit |
8681c6 |
// tampered with or the key was incorrect
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
if (rc != CKR_OK || (clear_len > len)) {
|
|
Packit |
8681c6 |
TRACE_DEVEL("strip_pkcs_padding failed.\n");
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
ptr = clear;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
obj_data_len = *(CK_ULONG_32 *) ptr;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// prevent buffer overflow in sha_update
|
|
Packit |
8681c6 |
if (obj_data_len > clear_len) {
|
|
Packit |
8681c6 |
TRACE_ERROR("stripped length is greater than clear length\n");
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
ptr += sizeof(CK_ULONG_32);
|
|
Packit |
8681c6 |
obj_data = ptr;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// check the hash
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
rc = compute_sha1(tokdata, ptr, obj_data_len, hash_sha);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
ptr += obj_data_len;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (memcmp(ptr, hash_sha, SHA1_HASH_SIZE) != 0) {
|
|
Packit |
8681c6 |
TRACE_ERROR("stored hash does not match restored data hash.\n");
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
// okay. at this point, we're satisfied that nobody has tampered with
|
|
Packit |
8681c6 |
// the token object...
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = object_mgr_restore_obj(tokdata, obj_data, pObj);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
rc = CKR_OK;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
done:
|
|
Packit |
8681c6 |
if (clear)
|
|
Packit |
8681c6 |
free(clear);
|
|
Packit |
8681c6 |
if (key)
|
|
Packit |
8681c6 |
free(key);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
CK_RV reload_token_object_old(STDLL_TokData_t *tokdata, OBJECT *obj)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
FILE *fp = NULL;
|
|
Packit |
8681c6 |
CK_BYTE *buf = NULL;
|
|
Packit |
8681c6 |
char fname[PATH_MAX];
|
|
Packit |
8681c6 |
CK_BBOOL priv;
|
|
Packit |
8681c6 |
CK_ULONG_32 size;
|
|
Packit |
8681c6 |
CK_ULONG size_64;
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit |
8681c6 |
size_t read_size;
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
if (ock_snprintf(fname, PATH_MAX, "%s/%s/%.8s", tokdata->data_store,
|
|
Packit Service |
8aa27d |
PK_LITE_OBJ_DIR, (char *)obj->name) != 0) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("token object file name buffer overflow\n");
|
|
Packit Service |
8aa27d |
rc = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit |
8681c6 |
fp = fopen(fname, "r");
|
|
Packit |
8681c6 |
if (!fp) {
|
|
Packit |
8681c6 |
TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
set_perm(fileno(fp));
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (!fread(&size, sizeof(CK_ULONG_32), 1, fp)) {
|
|
Packit |
8681c6 |
OCK_SYSLOG(LOG_ERR, "Cannot read size\n");
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (!fread(&priv, sizeof(CK_BBOOL), 1, fp)) {
|
|
Packit |
8681c6 |
OCK_SYSLOG(LOG_ERR, "Cannot read boolean\n");
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
size = size - sizeof(CK_ULONG_32) - sizeof(CK_BBOOL); // SAB
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
buf = (CK_BYTE *) malloc(size);
|
|
Packit |
8681c6 |
if (!buf) {
|
|
Packit |
8681c6 |
rc = CKR_HOST_MEMORY;
|
|
Packit |
8681c6 |
OCK_SYSLOG(LOG_ERR,
|
|
Packit |
8681c6 |
"Cannot malloc %u bytes to read in token object %s "
|
|
Packit |
8681c6 |
"(ignoring it)", size, fname);
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
read_size = fread(buf, 1, size, fp);
|
|
Packit |
8681c6 |
if (read_size != size) {
|
|
Packit |
8681c6 |
OCK_SYSLOG(LOG_ERR,
|
|
Packit |
8681c6 |
"Token object %s appears corrupted (ignoring it)", fname);
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
size_64 = size;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (priv)
|
|
Packit |
8681c6 |
rc = restore_private_token_object_old(tokdata, buf, size_64, obj);
|
|
Packit |
8681c6 |
else
|
|
Packit |
8681c6 |
rc = object_mgr_restore_obj(tokdata, buf, obj);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
done:
|
|
Packit |
8681c6 |
if (fp)
|
|
Packit |
8681c6 |
fclose(fp);
|
|
Packit |
8681c6 |
if (buf)
|
|
Packit |
8681c6 |
free(buf);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// this is the same as the old version. public token objects are stored in the
|
|
Packit |
8681c6 |
// clear
|
|
Packit |
8681c6 |
// Note: The token lock (XProcLock) must be held when calling this function.
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
CK_RV save_public_token_object_old(STDLL_TokData_t *tokdata, OBJECT * obj)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
FILE *fp = NULL;
|
|
Packit |
8681c6 |
CK_BYTE *clear = NULL;
|
|
Packit |
8681c6 |
char fname[PATH_MAX];
|
|
Packit |
8681c6 |
CK_ULONG clear_len;
|
|
Packit |
8681c6 |
CK_BBOOL flag = FALSE;
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit |
8681c6 |
CK_ULONG_32 total_len;
|
|
Packit Service |
8aa27d |
|
|
Packit |
8681c6 |
rc = object_flatten(obj, &clear, &clear_len);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
goto error;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
if (ock_snprintf(fname, PATH_MAX, "%s/%s/%.8s", tokdata->data_store,
|
|
Packit Service |
8aa27d |
PK_LITE_OBJ_DIR, (char *)obj->name) != 0) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("public token object file name buffer overflow\n");
|
|
Packit Service |
8aa27d |
rc = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto error;
|
|
Packit Service |
8aa27d |
}
|
|
Packit |
8681c6 |
fp = fopen(fname, "w");
|
|
Packit |
8681c6 |
if (!fp) {
|
|
Packit |
8681c6 |
TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto error;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
set_perm(fileno(fp));
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
total_len = clear_len + sizeof(CK_ULONG_32) + sizeof(CK_BBOOL);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
(void) fwrite(&total_len, sizeof(CK_ULONG_32), 1, fp);
|
|
Packit |
8681c6 |
(void) fwrite(&flag, sizeof(CK_BBOOL), 1, fp);
|
|
Packit |
8681c6 |
(void) fwrite(clear, clear_len, 1, fp);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
fclose(fp);
|
|
Packit |
8681c6 |
free(clear);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return CKR_OK;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
error:
|
|
Packit |
8681c6 |
if (fp)
|
|
Packit |
8681c6 |
fclose(fp);
|
|
Packit |
8681c6 |
if (clear)
|
|
Packit |
8681c6 |
free(clear);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
// Note: The token lock (XProcLock) must be held when calling this function.
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
CK_RV load_public_token_objects_old(STDLL_TokData_t *tokdata)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
FILE *fp1 = NULL, *fp2 = NULL;
|
|
Packit |
8681c6 |
CK_BYTE *buf = NULL;
|
|
Packit |
8681c6 |
char tmp[PATH_MAX];
|
|
Packit |
8681c6 |
char iname[PATH_MAX];
|
|
Packit |
8681c6 |
char fname[PATH_MAX];
|
|
Packit |
8681c6 |
CK_BBOOL priv;
|
|
Packit |
8681c6 |
CK_ULONG_32 size;
|
|
Packit |
8681c6 |
size_t read_size;
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
fp1 = open_token_object_index(iname, sizeof(iname), tokdata, "r");
|
|
Packit |
8681c6 |
if (!fp1)
|
|
Packit |
8681c6 |
return CKR_OK; // no token objects
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
while (fgets(tmp, 50, fp1)) {
|
|
Packit |
8681c6 |
tmp[strlen(tmp) - 1] = 0;
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
fp2 = open_token_object_path(fname, sizeof(fname), tokdata, tmp, "r");
|
|
Packit |
8681c6 |
if (!fp2)
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (!fread(&size, sizeof(CK_ULONG_32), 1, fp2)) {
|
|
Packit |
8681c6 |
fclose(fp2);
|
|
Packit |
8681c6 |
OCK_SYSLOG(LOG_ERR, "Cannot read size\n");
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
if (!fread(&priv, sizeof(CK_BBOOL), 1, fp2)) {
|
|
Packit |
8681c6 |
fclose(fp2);
|
|
Packit |
8681c6 |
OCK_SYSLOG(LOG_ERR, "Cannot read boolean\n");
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
if (priv == TRUE) {
|
|
Packit |
8681c6 |
fclose(fp2);
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
// size--;
|
|
Packit |
8681c6 |
size = size - sizeof(CK_ULONG_32) - sizeof(CK_BBOOL);
|
|
Packit |
8681c6 |
buf = (CK_BYTE *) malloc(size);
|
|
Packit |
8681c6 |
if (!buf) {
|
|
Packit |
8681c6 |
fclose(fp2);
|
|
Packit |
8681c6 |
OCK_SYSLOG(LOG_ERR,
|
|
Packit |
8681c6 |
"Cannot malloc %u bytes to read in "
|
|
Packit |
8681c6 |
"token object %s (ignoring it)", size, fname);
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
read_size = fread(buf, 1, size, fp2);
|
|
Packit |
8681c6 |
if (read_size != size) {
|
|
Packit |
8681c6 |
fclose(fp2);
|
|
Packit |
8681c6 |
free(buf);
|
|
Packit |
8681c6 |
OCK_SYSLOG(LOG_ERR,
|
|
Packit |
8681c6 |
"Cannot read token object %s " "(ignoring it)", fname);
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
// ... grab object mutex here.
|
|
Packit |
8681c6 |
if (object_mgr_restore_obj_withSize(tokdata,
|
|
Packit |
8681c6 |
buf, NULL, size) != CKR_OK) {
|
|
Packit |
8681c6 |
OCK_SYSLOG(LOG_ERR,
|
|
Packit |
8681c6 |
"Cannot restore token object %s "
|
|
Packit |
8681c6 |
"(ignoring it)", fname);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
free(buf);
|
|
Packit |
8681c6 |
fclose(fp2);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
fclose(fp1);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return CKR_OK;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/******************************************************************************
|
|
Packit |
8681c6 |
* tokversion >= 3.12 object store
|
|
Packit |
8681c6 |
*/
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
static CK_RV aes_256_gcm_seal(unsigned char *out,
|
|
Packit |
8681c6 |
unsigned char tag[16],
|
|
Packit |
8681c6 |
const unsigned char *aad,
|
|
Packit |
8681c6 |
size_t aadlen,
|
|
Packit |
8681c6 |
const unsigned char *in,
|
|
Packit |
8681c6 |
size_t inlen,
|
|
Packit |
8681c6 |
const unsigned char key[32],
|
|
Packit |
8681c6 |
const unsigned char iv[12])
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit |
8681c6 |
int outlen;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
EVP_CIPHER_CTX *ctx = NULL;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
ctx = EVP_CIPHER_CTX_new();
|
|
Packit |
8681c6 |
if (ctx == NULL) {
|
|
Packit |
8681c6 |
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
|
|
Packit |
8681c6 |
rc = ERR_HOST_MEMORY;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (EVP_CipherInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL, -1) != 1
|
|
Packit |
8681c6 |
|| EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 12, NULL) != 1
|
|
Packit |
8681c6 |
|| EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1) != 1
|
|
Packit |
8681c6 |
|| EVP_CipherUpdate(ctx, NULL, &outlen, aad, aadlen) != 1
|
|
Packit |
8681c6 |
|| EVP_CipherUpdate(ctx, out, &outlen, in, inlen) != 1
|
|
Packit Service |
8aa27d |
|| EVP_CipherFinal_ex(ctx, out + outlen, &outlen) != 1
|
|
Packit |
8681c6 |
|| EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag) != 1) {
|
|
Packit |
8681c6 |
TRACE_ERROR("%s\n", ock_err(ERR_GENERAL_ERROR));
|
|
Packit |
8681c6 |
rc = ERR_GENERAL_ERROR;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = CKR_OK;
|
|
Packit |
8681c6 |
done:
|
|
Packit |
8681c6 |
EVP_CIPHER_CTX_free(ctx);
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
static CK_RV aes_256_gcm_unseal(unsigned char *out,
|
|
Packit |
8681c6 |
const unsigned char *aad,
|
|
Packit |
8681c6 |
size_t aadlen,
|
|
Packit |
8681c6 |
const unsigned char *in,
|
|
Packit |
8681c6 |
size_t inlen,
|
|
Packit |
8681c6 |
const unsigned char tag[16],
|
|
Packit |
8681c6 |
const unsigned char key[32],
|
|
Packit |
8681c6 |
const unsigned char iv[12])
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit |
8681c6 |
int outlen;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
EVP_CIPHER_CTX *ctx = NULL;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
ctx = EVP_CIPHER_CTX_new();
|
|
Packit |
8681c6 |
if (ctx == NULL) {
|
|
Packit |
8681c6 |
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
|
|
Packit |
8681c6 |
rc = ERR_HOST_MEMORY;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (EVP_CipherInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL, -1) != 1
|
|
Packit |
8681c6 |
|| EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, (unsigned char *)tag) != 1
|
|
Packit |
8681c6 |
|| EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 12, NULL) != 1
|
|
Packit |
8681c6 |
|| EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 0) != 1
|
|
Packit |
8681c6 |
|| EVP_CipherUpdate(ctx, NULL, &outlen, aad, aadlen) != 1
|
|
Packit |
8681c6 |
|| EVP_CipherUpdate(ctx, out, &outlen, in, inlen) != 1
|
|
Packit Service |
8aa27d |
|| EVP_CipherFinal_ex(ctx, out + outlen, &outlen) != 1) {
|
|
Packit |
8681c6 |
TRACE_ERROR("%s\n", ock_err(ERR_GENERAL_ERROR));
|
|
Packit |
8681c6 |
rc = ERR_GENERAL_ERROR;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = CKR_OK;
|
|
Packit |
8681c6 |
done:
|
|
Packit |
8681c6 |
EVP_CIPHER_CTX_free(ctx);
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
static CK_RV aes_256_wrap(unsigned char out[40],
|
|
Packit |
8681c6 |
const unsigned char in[32],
|
|
Packit |
8681c6 |
const unsigned char kek[32])
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit |
8681c6 |
int outlen;
|
|
Packit Service |
8aa27d |
unsigned char buffer[40 + EVP_MAX_BLOCK_LENGTH];
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
EVP_CIPHER_CTX *ctx = NULL;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
ctx = EVP_CIPHER_CTX_new();
|
|
Packit |
8681c6 |
if (ctx == NULL) {
|
|
Packit |
8681c6 |
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
|
|
Packit |
8681c6 |
rc = ERR_HOST_MEMORY;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (EVP_CipherInit_ex(ctx, EVP_aes_256_wrap(), NULL, kek, NULL, 1) != 1
|
|
Packit Service |
8aa27d |
|| EVP_CipherUpdate(ctx, buffer, &outlen, in, 32) != 1
|
|
Packit Service |
8aa27d |
|| EVP_CipherFinal_ex(ctx, buffer + outlen, &outlen) != 1) {
|
|
Packit |
8681c6 |
TRACE_ERROR("%s\n", ock_err(ERR_GENERAL_ERROR));
|
|
Packit |
8681c6 |
rc = ERR_GENERAL_ERROR;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
memcpy(out, buffer, 40);
|
|
Packit |
8681c6 |
rc = CKR_OK;
|
|
Packit |
8681c6 |
done:
|
|
Packit |
8681c6 |
EVP_CIPHER_CTX_free(ctx);
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
static CK_RV aes_256_unwrap(unsigned char key[32],
|
|
Packit |
8681c6 |
const unsigned char in[40],
|
|
Packit |
8681c6 |
const unsigned char kek[32])
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit |
8681c6 |
int outlen;
|
|
Packit Service |
8aa27d |
unsigned char buffer[32 + EVP_MAX_BLOCK_LENGTH];
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
EVP_CIPHER_CTX *ctx = NULL;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
ctx = EVP_CIPHER_CTX_new();
|
|
Packit |
8681c6 |
if (ctx == NULL) {
|
|
Packit |
8681c6 |
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
|
|
Packit |
8681c6 |
rc = ERR_HOST_MEMORY;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (EVP_CipherInit_ex(ctx, EVP_aes_256_wrap(), NULL, kek, NULL, 0) != 1
|
|
Packit Service |
8aa27d |
|| EVP_CipherUpdate(ctx, buffer, &outlen, in, 40) != 1
|
|
Packit Service |
8aa27d |
|| EVP_CipherFinal_ex(ctx, buffer + outlen, &outlen) != 1) {
|
|
Packit |
8681c6 |
TRACE_ERROR("%s\n", ock_err(ERR_GENERAL_ERROR));
|
|
Packit |
8681c6 |
rc = ERR_GENERAL_ERROR;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
memcpy(key, buffer, 32);
|
|
Packit |
8681c6 |
rc = CKR_OK;
|
|
Packit |
8681c6 |
done:
|
|
Packit |
8681c6 |
EVP_CIPHER_CTX_free(ctx);
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_RV generate_master_key(STDLL_TokData_t *tokdata, CK_BYTE *key)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
if (tokdata->version < TOK_NEW_DATA_STORE)
|
|
Packit |
8681c6 |
return generate_master_key_old(tokdata, key);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* generate a 256-bit AES key */
|
|
Packit |
8681c6 |
return rng_generate(tokdata, key, 32);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/**
|
|
Packit |
8681c6 |
* Wrap 256-bit AES master key by 256-bit AES SO wrap key
|
|
Packit |
8681c6 |
* using AES-KW (RFC 3394). The resulting 40-bytes cipher-text
|
|
Packit |
8681c6 |
* is stored in the MK_SO file in the token's data store.
|
|
Packit |
8681c6 |
*/
|
|
Packit |
8681c6 |
CK_RV save_masterkey_so(STDLL_TokData_t *tokdata)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
FILE *fp = NULL;
|
|
Packit |
8681c6 |
char fname[PATH_MAX];
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit |
8681c6 |
unsigned char outbuf[40];
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (tokdata->version < TOK_NEW_DATA_STORE)
|
|
Packit |
8681c6 |
return save_masterkey_so_old(tokdata);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Skip it if master key is not needed. */
|
|
Packit |
8681c6 |
if (!token_specific.data_store.use_master_key)
|
|
Packit |
8681c6 |
return CKR_OK;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* wrap master key with so_wrap_key */
|
|
Packit |
8681c6 |
rc = aes_256_wrap(outbuf, tokdata->master_key, tokdata->so_wrap_key);
|
|
Packit |
8681c6 |
if (rc != CKR_OK)
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// write the file
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
// probably ought to ensure the permissions are correct
|
|
Packit |
8681c6 |
//
|
|
Packit Service |
8aa27d |
fp = open_token_data_store_path(fname, sizeof(fname), tokdata, "MK_SO",
|
|
Packit Service |
8aa27d |
"w");
|
|
Packit |
8681c6 |
if (!fp) {
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
set_perm(fileno(fp));
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = fwrite(outbuf, sizeof(outbuf), 1, fp);
|
|
Packit |
8681c6 |
if (rc != 1) {
|
|
Packit |
8681c6 |
TRACE_ERROR("fwrite failed.\n");
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = CKR_OK;
|
|
Packit |
8681c6 |
done:
|
|
Packit |
8681c6 |
if (fp)
|
|
Packit |
8681c6 |
fclose(fp);
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_RV load_masterkey_so(STDLL_TokData_t *tokdata)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
FILE *fp = NULL;
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit |
8681c6 |
char fname[PATH_MAX];
|
|
Packit |
8681c6 |
unsigned char inbuf[40];
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (tokdata->version < TOK_NEW_DATA_STORE)
|
|
Packit |
8681c6 |
return load_masterkey_so_old(tokdata);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
memset(tokdata->master_key, 0, sizeof(tokdata->master_key));
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// this file gets created on C_InitToken so we can assume that it always
|
|
Packit |
8681c6 |
// exists
|
|
Packit |
8681c6 |
//
|
|
Packit Service |
8aa27d |
fp = open_token_data_store_path(fname, sizeof(fname), tokdata, "MK_SO",
|
|
Packit Service |
8aa27d |
"r");
|
|
Packit |
8681c6 |
if (!fp) {
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
set_perm(fileno(fp));
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = fread(inbuf, sizeof(inbuf), 1, fp);
|
|
Packit |
8681c6 |
if (rc != 1) {
|
|
Packit |
8681c6 |
TRACE_ERROR("fread() failed.\n");
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* unwrap master key with so_wrap_key */
|
|
Packit |
8681c6 |
rc = aes_256_unwrap(tokdata->master_key, inbuf, tokdata->so_wrap_key);
|
|
Packit |
8681c6 |
if (rc != CKR_OK)
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = CKR_OK;
|
|
Packit |
8681c6 |
done:
|
|
Packit |
8681c6 |
if (fp)
|
|
Packit |
8681c6 |
fclose(fp);
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/**
|
|
Packit |
8681c6 |
* Wrap 256-bit AES master key by 256-bit AES User wrap key
|
|
Packit |
8681c6 |
* using AES-KW (RFC 3394). The resulting 40-bytes cipher-text
|
|
Packit |
8681c6 |
* is stored in the MK_SO file in the token's data store.
|
|
Packit |
8681c6 |
*/
|
|
Packit |
8681c6 |
CK_RV save_masterkey_user(STDLL_TokData_t *tokdata)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
FILE *fp = NULL;
|
|
Packit |
8681c6 |
char fname[PATH_MAX];
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit |
8681c6 |
unsigned char outbuf[40];
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (tokdata->version < TOK_NEW_DATA_STORE)
|
|
Packit |
8681c6 |
return save_masterkey_user_old(tokdata);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* wrap master key with so_wrap_key */
|
|
Packit |
8681c6 |
rc = aes_256_wrap(outbuf, tokdata->master_key, tokdata->user_wrap_key);
|
|
Packit |
8681c6 |
if (rc != CKR_OK)
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// write the file
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
// probably ought to ensure the permissions are correct
|
|
Packit |
8681c6 |
//
|
|
Packit Service |
8aa27d |
fp = open_token_data_store_path(fname, sizeof(fname), tokdata, "MK_USER",
|
|
Packit Service |
8aa27d |
"w");
|
|
Packit |
8681c6 |
if (!fp) {
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
set_perm(fileno(fp));
|
|
Packit |
8681c6 |
rc = fwrite(outbuf, sizeof(outbuf), 1, fp);
|
|
Packit |
8681c6 |
if (rc != 1) {
|
|
Packit |
8681c6 |
TRACE_ERROR("fwrite failed.\n");
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = CKR_OK;
|
|
Packit |
8681c6 |
done:
|
|
Packit |
8681c6 |
if (fp)
|
|
Packit |
8681c6 |
fclose(fp);
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_RV load_masterkey_user(STDLL_TokData_t *tokdata)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
FILE *fp = NULL;
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit |
8681c6 |
char fname[PATH_MAX];
|
|
Packit |
8681c6 |
EVP_CIPHER_CTX *ctx = NULL;
|
|
Packit |
8681c6 |
unsigned char inbuf[40];
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (tokdata->version < TOK_NEW_DATA_STORE)
|
|
Packit |
8681c6 |
return load_masterkey_user_old(tokdata);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
memset(tokdata->master_key, 0, sizeof(tokdata->master_key));
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
// this file gets created on C_InitToken so we can assume that it always
|
|
Packit |
8681c6 |
// exists
|
|
Packit |
8681c6 |
//
|
|
Packit Service |
8aa27d |
fp = open_token_data_store_path(fname, sizeof(fname), tokdata, "MK_USER",
|
|
Packit Service |
8aa27d |
"r");
|
|
Packit |
8681c6 |
if (!fp) {
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
set_perm(fileno(fp));
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = fread(inbuf, sizeof(inbuf), 1, fp);
|
|
Packit |
8681c6 |
if (rc != 1) {
|
|
Packit |
8681c6 |
TRACE_ERROR("fread failed.\n");
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* unwrap master key with user_wrap_key */
|
|
Packit |
8681c6 |
rc = aes_256_unwrap(tokdata->master_key, inbuf, tokdata->user_wrap_key);
|
|
Packit |
8681c6 |
if (rc != CKR_OK)
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = CKR_OK;
|
|
Packit |
8681c6 |
done:
|
|
Packit |
8681c6 |
if (fp)
|
|
Packit |
8681c6 |
fclose(fp);
|
|
Packit |
8681c6 |
EVP_CIPHER_CTX_free(ctx);
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_RV save_token_data(STDLL_TokData_t *tokdata, CK_SLOT_ID slot_id)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
FILE *fp = NULL;
|
|
Packit |
8681c6 |
TOKEN_DATA td;
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit |
8681c6 |
char fname[PATH_MAX];
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (tokdata->version < TOK_NEW_DATA_STORE)
|
|
Packit |
8681c6 |
return save_token_data_old(tokdata, slot_id);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = XProcLock(tokdata);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
TRACE_ERROR("Failed to get Process Lock.\n");
|
|
Packit |
8681c6 |
goto out_nolock;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
fp = open_token_nvdat(fname, sizeof(fname), tokdata, "w");
|
|
Packit |
8681c6 |
if (!fp) {
|
|
Packit |
8681c6 |
TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
set_perm(fileno(fp));
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Write generic token data */
|
|
Packit |
8681c6 |
memcpy(&td, tokdata->nv_token_data, sizeof(TOKEN_DATA));
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
td.token_info.flags = htobe32(td.token_info.flags);
|
|
Packit |
8681c6 |
td.token_info.ulMaxSessionCount = htobe32(td.token_info.ulMaxSessionCount);
|
|
Packit |
8681c6 |
td.token_info.ulSessionCount = htobe32(td.token_info.ulSessionCount);
|
|
Packit |
8681c6 |
td.token_info.ulMaxRwSessionCount
|
|
Packit |
8681c6 |
= htobe32(td.token_info.ulMaxRwSessionCount);
|
|
Packit |
8681c6 |
td.token_info.ulRwSessionCount = htobe32(td.token_info.ulRwSessionCount);
|
|
Packit |
8681c6 |
td.token_info.ulMaxPinLen = htobe32(td.token_info.ulMaxPinLen);
|
|
Packit |
8681c6 |
td.token_info.ulMinPinLen = htobe32(td.token_info.ulMinPinLen);
|
|
Packit |
8681c6 |
td.token_info.ulTotalPublicMemory
|
|
Packit |
8681c6 |
= htobe32(td.token_info.ulTotalPublicMemory);
|
|
Packit |
8681c6 |
td.token_info.ulFreePublicMemory
|
|
Packit |
8681c6 |
= htobe32(td.token_info.ulFreePublicMemory);
|
|
Packit |
8681c6 |
td.token_info.ulTotalPrivateMemory
|
|
Packit |
8681c6 |
= htobe32(td.token_info.ulTotalPrivateMemory);
|
|
Packit |
8681c6 |
td.token_info.ulFreePrivateMemory
|
|
Packit |
8681c6 |
= htobe32(td.token_info.ulFreePrivateMemory);
|
|
Packit |
8681c6 |
td.tweak_vector.allow_weak_des = htobe32(td.tweak_vector.allow_weak_des);
|
|
Packit |
8681c6 |
td.tweak_vector.check_des_parity
|
|
Packit |
8681c6 |
= htobe32(td.tweak_vector.check_des_parity);
|
|
Packit |
8681c6 |
td.tweak_vector.allow_key_mods = htobe32(td.tweak_vector.allow_key_mods);
|
|
Packit |
8681c6 |
td.tweak_vector.netscape_mods = htobe32(td.tweak_vector.netscape_mods);
|
|
Packit |
8681c6 |
td.dat.version = htobe32(td.dat.version);
|
|
Packit |
8681c6 |
td.dat.so_login_it = htobe64(td.dat.so_login_it);
|
|
Packit |
8681c6 |
td.dat.user_login_it = htobe64(td.dat.user_login_it);
|
|
Packit |
8681c6 |
td.dat.so_wrap_it = htobe64(td.dat.so_wrap_it);
|
|
Packit |
8681c6 |
td.dat.user_wrap_it = htobe64(td.dat.user_wrap_it);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (!fwrite(&td, sizeof(TOKEN_DATA), 1, fp)) {
|
|
Packit |
8681c6 |
TRACE_ERROR("fwrite(%s): %s\n", fname,
|
|
Packit |
8681c6 |
ferror(fp) ? strerror(errno) : "failed");
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Write token-specific data */
|
|
Packit |
8681c6 |
if (token_specific.t_save_token_data) {
|
|
Packit |
8681c6 |
rc = token_specific.t_save_token_data(tokdata, slot_id, fp);
|
|
Packit |
8681c6 |
if (rc)
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = CKR_OK;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
done:
|
|
Packit |
8681c6 |
if (fp)
|
|
Packit |
8681c6 |
fclose(fp);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (rc == CKR_OK) {
|
|
Packit |
8681c6 |
rc = XProcUnLock(tokdata);
|
|
Packit |
8681c6 |
if (rc != CKR_OK)
|
|
Packit |
8681c6 |
TRACE_ERROR("Failed to release Process Lock.\n");
|
|
Packit |
8681c6 |
} else {
|
|
Packit |
8681c6 |
/* return error that occurred first */
|
|
Packit |
8681c6 |
XProcUnLock(tokdata);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
out_nolock:
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_RV load_token_data(STDLL_TokData_t *tokdata, CK_SLOT_ID slot_id)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
FILE *fp = NULL;
|
|
Packit |
8681c6 |
char fname[PATH_MAX];
|
|
Packit |
8681c6 |
TOKEN_DATA td;
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (tokdata->version < TOK_NEW_DATA_STORE)
|
|
Packit |
8681c6 |
return load_token_data_old(tokdata, slot_id);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = XProcLock(tokdata);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
TRACE_ERROR("Failed to get Process Lock.\n");
|
|
Packit |
8681c6 |
goto out_nolock;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
fp = open_token_nvdat(fname, sizeof(fname), tokdata, "r");
|
|
Packit |
8681c6 |
if (!fp) {
|
|
Packit |
8681c6 |
/* Better error checking added */
|
|
Packit |
8681c6 |
if (errno == ENOENT) {
|
|
Packit |
8681c6 |
init_token_data(tokdata, slot_id);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
fp = fopen(fname, "r");
|
|
Packit |
8681c6 |
if (!fp) {
|
|
Packit |
8681c6 |
// were really hosed here since the created
|
|
Packit |
8681c6 |
// did not occur
|
|
Packit |
8681c6 |
TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto out_unlock;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
} else {
|
|
Packit |
8681c6 |
/* Could not open file for some unknown reason */
|
|
Packit |
8681c6 |
TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto out_unlock;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
set_perm(fileno(fp));
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Load generic token data */
|
|
Packit |
8681c6 |
if (!fread(&td, sizeof(TOKEN_DATA), 1, fp)) {
|
|
Packit |
8681c6 |
TRACE_ERROR("fread(%s): %s\n", fname,
|
|
Packit |
8681c6 |
ferror(fp) ? strerror(errno) : "failed");
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto out_unlock;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
/* data marshalling */
|
|
Packit |
8681c6 |
td.token_info.flags = be32toh(td.token_info.flags);
|
|
Packit |
8681c6 |
td.token_info.ulMaxSessionCount = be32toh(td.token_info.ulMaxSessionCount);
|
|
Packit |
8681c6 |
td.token_info.ulSessionCount = be32toh(td.token_info.ulSessionCount);
|
|
Packit |
8681c6 |
td.token_info.ulMaxRwSessionCount
|
|
Packit |
8681c6 |
= be32toh(td.token_info.ulMaxRwSessionCount);
|
|
Packit |
8681c6 |
td.token_info.ulRwSessionCount = be32toh(td.token_info.ulRwSessionCount);
|
|
Packit |
8681c6 |
td.token_info.ulMaxPinLen = be32toh(td.token_info.ulMaxPinLen);
|
|
Packit |
8681c6 |
td.token_info.ulMinPinLen = be32toh(td.token_info.ulMinPinLen);
|
|
Packit |
8681c6 |
td.token_info.ulTotalPublicMemory
|
|
Packit |
8681c6 |
= be32toh(td.token_info.ulTotalPublicMemory);
|
|
Packit |
8681c6 |
td.token_info.ulFreePublicMemory
|
|
Packit |
8681c6 |
= be32toh(td.token_info.ulFreePublicMemory);
|
|
Packit |
8681c6 |
td.token_info.ulTotalPrivateMemory
|
|
Packit |
8681c6 |
= be32toh(td.token_info.ulTotalPrivateMemory);
|
|
Packit |
8681c6 |
td.token_info.ulFreePrivateMemory
|
|
Packit |
8681c6 |
= be32toh(td.token_info.ulFreePrivateMemory);
|
|
Packit |
8681c6 |
td.tweak_vector.allow_weak_des = be32toh(td.tweak_vector.allow_weak_des);
|
|
Packit |
8681c6 |
td.tweak_vector.check_des_parity
|
|
Packit |
8681c6 |
= be32toh(td.tweak_vector.check_des_parity);
|
|
Packit |
8681c6 |
td.tweak_vector.allow_key_mods = be32toh(td.tweak_vector.allow_key_mods);
|
|
Packit |
8681c6 |
td.tweak_vector.netscape_mods = be32toh(td.tweak_vector.netscape_mods);
|
|
Packit |
8681c6 |
td.dat.version = be32toh(td.dat.version);
|
|
Packit |
8681c6 |
td.dat.so_login_it = be64toh(td.dat.so_login_it);
|
|
Packit |
8681c6 |
td.dat.user_login_it = be64toh(td.dat.user_login_it);
|
|
Packit |
8681c6 |
td.dat.so_wrap_it = be64toh(td.dat.so_wrap_it);
|
|
Packit |
8681c6 |
td.dat.user_wrap_it = be64toh(td.dat.user_wrap_it);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
memcpy(tokdata->nv_token_data, &td, sizeof(TOKEN_DATA));
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* Load token-specific data */
|
|
Packit |
8681c6 |
if (token_specific.t_load_token_data) {
|
|
Packit |
8681c6 |
rc = token_specific.t_load_token_data(tokdata, slot_id, fp);
|
|
Packit |
8681c6 |
if (rc)
|
|
Packit |
8681c6 |
goto out_unlock;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = CKR_OK;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
out_unlock:
|
|
Packit |
8681c6 |
if (fp)
|
|
Packit |
8681c6 |
fclose(fp);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (rc == CKR_OK) {
|
|
Packit |
8681c6 |
rc = XProcUnLock(tokdata);
|
|
Packit |
8681c6 |
if (rc != CKR_OK)
|
|
Packit |
8681c6 |
TRACE_ERROR("Failed to release Process Lock.\n");
|
|
Packit |
8681c6 |
} else {
|
|
Packit |
8681c6 |
/* return error that occurred first */
|
|
Packit |
8681c6 |
XProcUnLock(tokdata);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
out_nolock:
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/**
|
|
Packit |
8681c6 |
* Big-endian increment. Return carry.
|
|
Packit |
8681c6 |
*/
|
|
Packit |
8681c6 |
static inline int inc32(unsigned char ctr[4])
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
unsigned int c = 1;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
c += (unsigned int)ctr[3];
|
|
Packit |
8681c6 |
ctr[3] = (unsigned char)c;
|
|
Packit |
8681c6 |
c >>= 8;
|
|
Packit |
8681c6 |
c += (unsigned int)ctr[2];
|
|
Packit |
8681c6 |
ctr[2] = (unsigned char)c;
|
|
Packit |
8681c6 |
c >>= 8;
|
|
Packit |
8681c6 |
c += (unsigned int)ctr[1];
|
|
Packit |
8681c6 |
ctr[1] = (unsigned char)c;
|
|
Packit |
8681c6 |
c >>= 8;
|
|
Packit |
8681c6 |
c += (unsigned int)ctr[0];
|
|
Packit |
8681c6 |
ctr[0] = (unsigned char)c;
|
|
Packit |
8681c6 |
c >>= 8;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return c;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/**
|
|
Packit |
8681c6 |
* private tok obj layout
|
|
Packit |
8681c6 |
*
|
|
Packit |
8681c6 |
* --- auth ------- <--+
|
|
Packit |
8681c6 |
* u32 tokversion | 64-byte header
|
|
Packit |
8681c6 |
* u8 private_flag |
|
|
Packit |
8681c6 |
* u8 reserved[3] |
|
|
Packit |
8681c6 |
* u8 key_wrapped[40] |
|
|
Packit |
8681c6 |
* u8 iv[12] |
|
|
Packit |
8681c6 |
* u32 object_len |
|
|
Packit |
8681c6 |
* --- auth+enc --- <--+
|
|
Packit |
8681c6 |
* u8 object[object_len] | body
|
|
Packit |
8681c6 |
* ---------------- <--+
|
|
Packit |
8681c6 |
* u8 tag[16] | 16-byte footer
|
|
Packit |
8681c6 |
* ---------------- <--+
|
|
Packit |
8681c6 |
*/
|
|
Packit Service |
8aa27d |
#define HEADER_LEN 64
|
|
Packit Service |
8aa27d |
#define FOOTER_LEN 16
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
// Note: The token lock (XProcLock) must be held when calling this function.
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
CK_RV save_private_token_object(STDLL_TokData_t *tokdata, OBJECT *obj)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
FILE *fp = NULL;
|
|
Packit |
8681c6 |
CK_BYTE *obj_data = NULL;
|
|
Packit |
8681c6 |
char fname[PATH_MAX];
|
|
Packit |
8681c6 |
CK_ULONG obj_data_len;
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit |
8681c6 |
CK_ULONG_32 obj_data_len_32;
|
|
Packit |
8681c6 |
CK_ULONG_32 total_len;
|
|
Packit |
8681c6 |
CK_BBOOL flag = CK_TRUE;
|
|
Packit |
8681c6 |
unsigned char obj_key[256 / 8], obj_iv[96 / 8], obj_key_wrapped[40];
|
|
Packit |
8681c6 |
unsigned char *data = NULL;
|
|
Packit |
8681c6 |
uint32_t tmp;
|
|
Packit |
8681c6 |
int new = 0;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (tokdata->version < TOK_NEW_DATA_STORE)
|
|
Packit |
8681c6 |
return save_private_token_object_old(tokdata, obj);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
sprintf(fname, "%s/%s/", tokdata->data_store, PK_LITE_OBJ_DIR);
|
|
Packit |
8681c6 |
strncat(fname, (char *)obj->name, 8);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = object_flatten(obj, &obj_data, &obj_data_len);
|
|
Packit |
8681c6 |
obj_data_len_32 = obj_data_len;
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
total_len = HEADER_LEN + obj_data_len_32 + FOOTER_LEN;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
data = malloc(total_len);
|
|
Packit |
8681c6 |
if (data == NULL) {
|
|
Packit |
8681c6 |
rc = CKR_HOST_MEMORY;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
fp = fopen(fname, "r");
|
|
Packit |
8681c6 |
if (fp == NULL) {
|
|
Packit |
8681c6 |
/* create new token object */
|
|
Packit |
8681c6 |
new = 1;
|
|
Packit |
8681c6 |
} else {
|
|
Packit |
8681c6 |
/* update existing token object */
|
|
Packit |
8681c6 |
if (fread(data, HEADER_LEN, 1, fp) != 1) {
|
|
Packit |
8681c6 |
TRACE_ERROR("fread(%s): %s\n", fname, strerror(errno));
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
fclose(fp);
|
|
Packit |
8681c6 |
fp = NULL;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* iv */
|
|
Packit |
8681c6 |
memcpy(obj_iv, data + 48, 12);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* increment iv counter field */
|
|
Packit |
8681c6 |
if (inc32(obj_iv + 8)) {
|
|
Packit |
8681c6 |
/* counter overflow: generate new key */
|
|
Packit |
8681c6 |
new = 1;
|
|
Packit |
8681c6 |
} else {
|
|
Packit |
8681c6 |
/* get wrapped key key */
|
|
Packit |
8681c6 |
memcpy(obj_key_wrapped, data + 8, 40);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* get key */
|
|
Packit |
8681c6 |
rc = aes_256_unwrap(obj_key, obj_key_wrapped, tokdata->master_key);
|
|
Packit |
8681c6 |
if (rc != CKR_OK)
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
if (new) {
|
|
Packit |
8681c6 |
/* get key */
|
|
Packit |
8681c6 |
rng_generate(tokdata, obj_key, 32);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* iv = [obj.-name|counter] */
|
|
Packit |
8681c6 |
memcpy(obj_iv, obj->name, 8);
|
|
Packit |
8681c6 |
obj_iv[8] = 0;
|
|
Packit |
8681c6 |
obj_iv[9] = 0;
|
|
Packit |
8681c6 |
obj_iv[10] = 0;
|
|
Packit |
8681c6 |
obj_iv[11] = 1;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* get wrapped key */
|
|
Packit |
8681c6 |
rc = aes_256_wrap(obj_key_wrapped, obj_key, tokdata->master_key);
|
|
Packit |
8681c6 |
if (rc != CKR_OK)
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* version */
|
|
Packit |
8681c6 |
tmp = htobe32(tokdata->version);
|
|
Packit |
8681c6 |
memcpy(data, &tmp, 4);
|
|
Packit |
8681c6 |
/* flags */
|
|
Packit |
8681c6 |
memcpy(data + 4, &flag, 1);
|
|
Packit |
8681c6 |
tmp = 0;
|
|
Packit |
8681c6 |
memcpy(data + 5, &tmp, 3);
|
|
Packit |
8681c6 |
/* wrapped key */
|
|
Packit |
8681c6 |
memcpy(data + 8, obj_key_wrapped, 40);
|
|
Packit |
8681c6 |
/* iv */
|
|
Packit |
8681c6 |
memcpy(data + 48, obj_iv, 12);
|
|
Packit |
8681c6 |
/* object len */
|
|
Packit |
8681c6 |
tmp = htobe32(obj_data_len_32);
|
|
Packit |
8681c6 |
memcpy(data + 60, &tmp, 4);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = aes_256_gcm_seal(/* ciphertext */
|
|
Packit |
8681c6 |
data + HEADER_LEN,
|
|
Packit |
8681c6 |
/* tag */
|
|
Packit |
8681c6 |
data + HEADER_LEN
|
|
Packit |
8681c6 |
+ obj_data_len_32,
|
|
Packit |
8681c6 |
/* aad */
|
|
Packit |
8681c6 |
data, HEADER_LEN,
|
|
Packit |
8681c6 |
/* plaintext */
|
|
Packit |
8681c6 |
obj_data, obj_data_len_32,
|
|
Packit |
8681c6 |
/* key */
|
|
Packit |
8681c6 |
obj_key,
|
|
Packit |
8681c6 |
/* iv */
|
|
Packit |
8681c6 |
obj_iv);
|
|
Packit |
8681c6 |
if (rc != CKR_OK)
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
fp = fopen(fname, "w");
|
|
Packit |
8681c6 |
if (!fp) {
|
|
Packit |
8681c6 |
TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
set_perm(fileno(fp));
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (fwrite(data, total_len, 1, fp) != 1) {
|
|
Packit |
8681c6 |
TRACE_ERROR("fwrite(%s): %s\n", fname, strerror(errno));
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
fclose(fp);
|
|
Packit |
8681c6 |
fp = NULL;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = CKR_OK;
|
|
Packit |
8681c6 |
done:
|
|
Packit |
8681c6 |
if (fp)
|
|
Packit |
8681c6 |
fclose(fp);
|
|
Packit |
8681c6 |
if (obj_data)
|
|
Packit |
8681c6 |
free(obj_data);
|
|
Packit |
8681c6 |
if (data)
|
|
Packit |
8681c6 |
free(data);
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
// Note: The token lock (XProcLock) must be held when calling this function.
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
CK_RV load_private_token_objects(STDLL_TokData_t *tokdata)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
FILE *fp1 = NULL, *fp2 = NULL;
|
|
Packit |
8681c6 |
CK_BYTE *buf = NULL;
|
|
Packit |
8681c6 |
char tmp[PATH_MAX];
|
|
Packit |
8681c6 |
char iname[PATH_MAX];
|
|
Packit |
8681c6 |
char fname[PATH_MAX];
|
|
Packit |
8681c6 |
CK_BBOOL priv;
|
|
Packit |
8681c6 |
CK_ULONG_32 size;
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit |
8681c6 |
unsigned char header[HEADER_LEN], footer[FOOTER_LEN];
|
|
Packit |
8681c6 |
uint32_t len;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (tokdata->version < TOK_NEW_DATA_STORE)
|
|
Packit |
8681c6 |
return load_private_token_objects_old(tokdata);
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
fp1 = open_token_object_index(iname, sizeof(iname), tokdata, "r");
|
|
Packit |
8681c6 |
if (!fp1)
|
|
Packit |
8681c6 |
return CKR_OK; // no token objects
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
while (fgets(tmp, 50, fp1)) {
|
|
Packit |
8681c6 |
tmp[strlen(tmp) - 1] = 0;
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
fp2 = open_token_object_path(fname, sizeof(fname), tokdata, tmp,"r");
|
|
Packit |
8681c6 |
if (!fp2)
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (fread(header, HEADER_LEN, 1, fp2) != 1) {
|
|
Packit |
8681c6 |
fclose(fp2);
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
memcpy(&priv, header + 4, 1);
|
|
Packit |
8681c6 |
if (priv == FALSE) {
|
|
Packit |
8681c6 |
fclose(fp2);
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
memcpy(&len, header + 60, 4);
|
|
Packit |
8681c6 |
size = be32toh(len);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
buf = (CK_BYTE *)malloc(size);
|
|
Packit |
8681c6 |
if (!buf) {
|
|
Packit |
8681c6 |
fclose(fp2);
|
|
Packit |
8681c6 |
OCK_SYSLOG(LOG_ERR,
|
|
Packit |
8681c6 |
"Cannot malloc %u bytes to read in "
|
|
Packit |
8681c6 |
"token object %s (ignoring it)", size, fname);
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (fread(buf, size, 1, fp2) != 1) {
|
|
Packit |
8681c6 |
free(buf);
|
|
Packit |
8681c6 |
fclose(fp2);
|
|
Packit |
8681c6 |
OCK_SYSLOG(LOG_ERR,
|
|
Packit |
8681c6 |
"Cannot read token object %s " "(ignoring it)", fname);
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
if (fread(footer, FOOTER_LEN, 1, fp2) != 1) {
|
|
Packit |
8681c6 |
fclose(fp2);
|
|
Packit |
8681c6 |
OCK_SYSLOG(LOG_ERR,
|
|
Packit |
8681c6 |
"Cannot read token object %s " "(ignoring it)", fname);
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = restore_private_token_object(tokdata, header,
|
|
Packit |
8681c6 |
buf, size,
|
|
Packit |
8681c6 |
footer, NULL);
|
|
Packit |
8681c6 |
if (rc != CKR_OK)
|
|
Packit |
8681c6 |
goto error;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
free(buf);
|
|
Packit |
8681c6 |
fclose(fp2);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
fclose(fp1);
|
|
Packit |
8681c6 |
return CKR_OK;
|
|
Packit |
8681c6 |
error:
|
|
Packit |
8681c6 |
if (buf)
|
|
Packit |
8681c6 |
free(buf);
|
|
Packit |
8681c6 |
if (fp1)
|
|
Packit |
8681c6 |
fclose(fp1);
|
|
Packit |
8681c6 |
if (fp2)
|
|
Packit |
8681c6 |
fclose(fp2);
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
CK_RV restore_private_token_object(STDLL_TokData_t *tokdata,
|
|
Packit |
8681c6 |
CK_BYTE *header,
|
|
Packit |
8681c6 |
CK_BYTE *data, CK_ULONG len,
|
|
Packit |
8681c6 |
CK_BYTE *footer,
|
|
Packit |
8681c6 |
OBJECT *pObj)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
unsigned char obj_iv[12], obj_key[32], obj_key_wrapped[40];
|
|
Packit |
8681c6 |
CK_BYTE *buff = NULL;
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (tokdata->version < TOK_NEW_DATA_STORE)
|
|
Packit |
8681c6 |
return restore_private_token_object_old(tokdata, data, len, pObj);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* wrapped key */
|
|
Packit |
8681c6 |
memcpy(obj_key_wrapped, header + 8, 40);
|
|
Packit |
8681c6 |
/* iv */
|
|
Packit |
8681c6 |
memcpy(obj_iv, header + 48, 12);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = aes_256_unwrap(obj_key, obj_key_wrapped, tokdata->master_key);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
buff = (CK_BYTE *)malloc(len);
|
|
Packit |
8681c6 |
if (buff == NULL) {
|
|
Packit |
8681c6 |
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
|
|
Packit |
8681c6 |
rc = CKR_HOST_MEMORY;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = aes_256_gcm_unseal(buff, /* plain-text */
|
|
Packit |
8681c6 |
header, HEADER_LEN, /* aad */
|
|
Packit |
8681c6 |
data, len, /* cipher-text*/
|
|
Packit |
8681c6 |
footer, /* tag */
|
|
Packit |
8681c6 |
obj_key, obj_iv);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = object_mgr_restore_obj(tokdata, buff, pObj);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = CKR_OK;
|
|
Packit |
8681c6 |
done:
|
|
Packit |
8681c6 |
if (buff)
|
|
Packit |
8681c6 |
free(buff);
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_RV reload_token_object(STDLL_TokData_t *tokdata, OBJECT *obj)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
unsigned char header[HEADER_LEN], footer[FOOTER_LEN];
|
|
Packit |
8681c6 |
FILE *fp = NULL;
|
|
Packit |
8681c6 |
CK_BYTE *buf = NULL;
|
|
Packit |
8681c6 |
char fname[PATH_MAX];
|
|
Packit |
8681c6 |
CK_BBOOL priv;
|
|
Packit |
8681c6 |
CK_ULONG_32 size;
|
|
Packit |
8681c6 |
CK_ULONG size_64;
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit |
8681c6 |
uint32_t len;
|
|
Packit Service |
8aa27d |
uint32_t ver;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (tokdata->version < TOK_NEW_DATA_STORE)
|
|
Packit |
8681c6 |
return reload_token_object_old(tokdata, obj);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
memset(fname, 0x0, sizeof(fname));
|
|
Packit |
8681c6 |
sprintf(fname, "%s/%s/", tokdata->data_store, PK_LITE_OBJ_DIR);
|
|
Packit |
8681c6 |
strncat(fname, (char *) obj->name, 8);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
fp = fopen(fname, "r");
|
|
Packit |
8681c6 |
if (!fp) {
|
|
Packit |
8681c6 |
TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
set_perm(fileno(fp));
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (fread(header, HEADER_LEN, 1, fp) != 1) {
|
|
Packit |
8681c6 |
OCK_SYSLOG(LOG_ERR, "Cannot read header\n");
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
memcpy(&ver, header, 4);
|
|
Packit |
8681c6 |
memcpy(&priv, header + 4, 1);
|
|
Packit |
8681c6 |
memcpy(&len, header + 60, 4);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/*
|
|
Packit Service |
8aa27d |
* In OCK 3.12 - 3.14 the version and size was not stored in BE. So if
|
|
Packit Service |
8aa27d |
* version field is in platform endianness, keep size as is also.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
if (ver == TOK_NEW_DATA_STORE)
|
|
Packit Service |
8aa27d |
size = len;
|
|
Packit Service |
8aa27d |
else
|
|
Packit Service |
8aa27d |
size = be32toh(len);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
buf = (CK_BYTE *) malloc(size);
|
|
Packit |
8681c6 |
if (buf == NULL) {
|
|
Packit |
8681c6 |
rc = CKR_HOST_MEMORY;
|
|
Packit |
8681c6 |
OCK_SYSLOG(LOG_ERR,
|
|
Packit |
8681c6 |
"Cannot malloc %u bytes to read in token object %s "
|
|
Packit |
8681c6 |
"(ignoring it)", size, fname);
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (fread(buf, size, 1, fp) != 1) {
|
|
Packit |
8681c6 |
OCK_SYSLOG(LOG_ERR,
|
|
Packit |
8681c6 |
"Token object %s appears corrupted (ignoring it)", fname);
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
if (fread(footer, FOOTER_LEN, 1, fp) != 1) {
|
|
Packit |
8681c6 |
OCK_SYSLOG(LOG_ERR,
|
|
Packit |
8681c6 |
"Token object %s appears corrupted (ignoring it)", fname);
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
size_64 = size;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (priv) {
|
|
Packit |
8681c6 |
rc = restore_private_token_object(tokdata, header, buf, size_64,
|
|
Packit |
8681c6 |
footer, obj);
|
|
Packit |
8681c6 |
} else {
|
|
Packit |
8681c6 |
rc = object_mgr_restore_obj(tokdata, buf, obj);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
done:
|
|
Packit |
8681c6 |
if (fp)
|
|
Packit |
8681c6 |
fclose(fp);
|
|
Packit |
8681c6 |
if (buf)
|
|
Packit |
8681c6 |
free(buf);
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/**
|
|
Packit |
8681c6 |
* public tok obj layout
|
|
Packit |
8681c6 |
*
|
|
Packit |
8681c6 |
* ---------------- <--+
|
|
Packit |
8681c6 |
* u32 tokversion | 16-byte header
|
|
Packit |
8681c6 |
* u8 private_flag |
|
|
Packit |
8681c6 |
* u8 reserved[7] |
|
|
Packit |
8681c6 |
* u32 object_len |
|
|
Packit |
8681c6 |
* ---------------- <--+
|
|
Packit |
8681c6 |
* u8 object[object_len] | body
|
|
Packit |
8681c6 |
* ---------------- <--+
|
|
Packit |
8681c6 |
*/
|
|
Packit Service |
8aa27d |
#define PUB_HEADER_LEN 16
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
// Note: The token lock (XProcLock) must be held when calling this function.
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
CK_RV save_public_token_object(STDLL_TokData_t *tokdata, OBJECT *obj)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
FILE *fp = NULL;
|
|
Packit |
8681c6 |
CK_BYTE *clear = NULL;
|
|
Packit |
8681c6 |
char fname[PATH_MAX];
|
|
Packit |
8681c6 |
CK_ULONG clear_len;
|
|
Packit |
8681c6 |
CK_BBOOL flag = FALSE;
|
|
Packit |
8681c6 |
CK_RV rc;
|
|
Packit Service |
8aa27d |
CK_ULONG_32 len, be_len;
|
|
Packit |
8681c6 |
unsigned char reserved[7] = {0};
|
|
Packit Service |
8aa27d |
uint32_t tmp;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (tokdata->version < TOK_NEW_DATA_STORE)
|
|
Packit |
8681c6 |
return save_public_token_object_old(tokdata, obj);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = object_flatten(obj, &clear, &clear_len);
|
|
Packit |
8681c6 |
if (rc != CKR_OK) {
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
len = (CK_ULONG_32)clear_len;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
sprintf(fname, "%s/%s/", tokdata->data_store, PK_LITE_OBJ_DIR);
|
|
Packit |
8681c6 |
strncat(fname, (char *) obj->name, 8);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
fp = fopen(fname, "w");
|
|
Packit |
8681c6 |
if (!fp) {
|
|
Packit |
8681c6 |
TRACE_ERROR("fopen(%s): %s\n", fname, strerror(errno));
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
tmp = htobe32(tokdata->version);
|
|
Packit Service |
8aa27d |
be_len = htobe32(len);
|
|
Packit Service |
8aa27d |
|
|
Packit |
8681c6 |
set_perm(fileno(fp));
|
|
Packit Service |
8aa27d |
if (fwrite(&tmp, 4, 1, fp) != 1
|
|
Packit |
8681c6 |
|| fwrite(&flag, 1, 1, fp) != 1
|
|
Packit |
8681c6 |
|| fwrite(reserved, 7, 1, fp) != 1
|
|
Packit Service |
8aa27d |
|| fwrite(&be_len, 4, 1, fp) != 1
|
|
Packit |
8681c6 |
|| fwrite(clear, len, 1, fp) != 1) {
|
|
Packit |
8681c6 |
rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
goto done;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
fclose(fp);
|
|
Packit |
8681c6 |
fp = NULL;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
rc = CKR_OK;
|
|
Packit |
8681c6 |
done:
|
|
Packit |
8681c6 |
if (fp)
|
|
Packit |
8681c6 |
fclose(fp);
|
|
Packit |
8681c6 |
if (clear)
|
|
Packit |
8681c6 |
free(clear);
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
// Note: The token lock (XProcLock) must be held when calling this function.
|
|
Packit |
8681c6 |
//
|
|
Packit |
8681c6 |
CK_RV load_public_token_objects(STDLL_TokData_t *tokdata)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
FILE *fp1 = NULL, *fp2 = NULL;
|
|
Packit |
8681c6 |
CK_BYTE *buf = NULL;
|
|
Packit |
8681c6 |
char tmp[PATH_MAX];
|
|
Packit |
8681c6 |
char iname[PATH_MAX];
|
|
Packit |
8681c6 |
char fname[PATH_MAX];
|
|
Packit |
8681c6 |
CK_BBOOL priv;
|
|
Packit |
8681c6 |
CK_ULONG_32 size;
|
|
Packit |
8681c6 |
unsigned char header[PUB_HEADER_LEN];
|
|
Packit Service |
8aa27d |
uint32_t ver;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (tokdata->version < TOK_NEW_DATA_STORE)
|
|
Packit |
8681c6 |
return load_public_token_objects_old(tokdata);
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
fp1 = open_token_object_index(iname, sizeof(iname), tokdata, "r");
|
|
Packit |
8681c6 |
if (!fp1)
|
|
Packit |
8681c6 |
return CKR_OK; // no token objects
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
while (fgets(tmp, 50, fp1)) {
|
|
Packit |
8681c6 |
tmp[strlen(tmp) - 1] = 0;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
sprintf(fname, "%s/%s/", tokdata->data_store, PK_LITE_OBJ_DIR);
|
|
Packit |
8681c6 |
strcat(fname, tmp);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
fp2 = fopen(fname, "r");
|
|
Packit |
8681c6 |
if (!fp2)
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (fread(header, PUB_HEADER_LEN, 1, fp2) != 1) {
|
|
Packit |
8681c6 |
fclose(fp2);
|
|
Packit |
8681c6 |
OCK_SYSLOG(LOG_ERR, "Cannot read header\n");
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
memcpy(&ver, header, 4);
|
|
Packit |
8681c6 |
memcpy(&priv, header + 4, 1);
|
|
Packit |
8681c6 |
memcpy(&size, header + 12, 4);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/*
|
|
Packit Service |
8aa27d |
* In OCK 3.12 - 3.14 the version and size was not stored in BE. So if
|
|
Packit Service |
8aa27d |
* version field is in platform endianness, keep size as is also
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
if (ver != TOK_NEW_DATA_STORE)
|
|
Packit Service |
8aa27d |
size = be32toh(size);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (priv == TRUE) {
|
|
Packit |
8681c6 |
fclose(fp2);
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
buf = (CK_BYTE *) malloc(size);
|
|
Packit |
8681c6 |
if (!buf) {
|
|
Packit |
8681c6 |
fclose(fp2);
|
|
Packit |
8681c6 |
OCK_SYSLOG(LOG_ERR,
|
|
Packit |
8681c6 |
"Cannot malloc %u bytes to read in "
|
|
Packit |
8681c6 |
"token object %s (ignoring it)", size, fname);
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (fread(buf, size, 1, fp2) != 1) {
|
|
Packit |
8681c6 |
fclose(fp2);
|
|
Packit |
8681c6 |
free(buf);
|
|
Packit |
8681c6 |
OCK_SYSLOG(LOG_ERR,
|
|
Packit |
8681c6 |
"Cannot read token object %s " "(ignoring it)", fname);
|
|
Packit |
8681c6 |
continue;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
// ... grab object mutex here.
|
|
Packit |
8681c6 |
if (object_mgr_restore_obj_withSize(tokdata,
|
|
Packit |
8681c6 |
buf, NULL, size) != CKR_OK) {
|
|
Packit |
8681c6 |
OCK_SYSLOG(LOG_ERR,
|
|
Packit |
8681c6 |
"Cannot restore token object %s "
|
|
Packit |
8681c6 |
"(ignoring it)", fname);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
free(buf);
|
|
Packit |
8681c6 |
fclose(fp2);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
fclose(fp1);
|
|
Packit |
8681c6 |
return CKR_OK;
|
|
Packit |
8681c6 |
}
|