|
Packit Service |
8aa27d |
/*
|
|
Packit Service |
8aa27d |
* COPYRIGHT (c) International Business Machines Corp. 2020
|
|
Packit Service |
8aa27d |
*
|
|
Packit Service |
8aa27d |
* This program is provided under the terms of the Common Public License,
|
|
Packit Service |
8aa27d |
* version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
|
|
Packit Service |
8aa27d |
* software constitutes recipient's acceptance of CPL-1.0 terms which can be
|
|
Packit Service |
8aa27d |
* found in the file LICENSE file or at
|
|
Packit Service |
8aa27d |
* https://opensource.org/licenses/cpl1.0.php
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/*
|
|
Packit Service |
8aa27d |
* Some routines that are shared between the pkcs utilities in usr/sbin.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
#define _GNU_SOURCE
|
|
Packit Service |
8aa27d |
#include <dlfcn.h>
|
|
Packit Service |
8aa27d |
#include <errno.h>
|
|
Packit Service |
8aa27d |
#include <string.h>
|
|
Packit Service |
8aa27d |
#include <stdio.h>
|
|
Packit Service |
8aa27d |
#include <stdlib.h>
|
|
Packit Service |
8aa27d |
#include <termios.h>
|
|
Packit Service |
8aa27d |
#include <unistd.h>
|
|
Packit Service |
8aa27d |
#include <sys/stat.h>
|
|
Packit Service |
8aa27d |
#include <fcntl.h>
|
|
Packit Service |
8aa27d |
#include <dirent.h>
|
|
Packit Service |
8aa27d |
#include <grp.h>
|
|
Packit Service |
8aa27d |
#include <openssl/evp.h>
|
|
Packit Service |
8aa27d |
#include <pkcs11types.h>
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
#include "defs.h"
|
|
Packit Service |
8aa27d |
#include "host_defs.h"
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
#define OCK_TOOL
|
|
Packit Service |
8aa27d |
#include "pkcs_utils.h"
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
extern pkcs_trace_level_t trace_level;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
void pkcs_trace(pkcs_trace_level_t level, const char *file, int line,
|
|
Packit Service |
8aa27d |
const char *fmt, ...)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
va_list ap;
|
|
Packit Service |
8aa27d |
const char *fmt_pre;
|
|
Packit Service |
8aa27d |
char buf[1024];
|
|
Packit Service |
8aa27d |
char *pbuf;
|
|
Packit Service |
8aa27d |
int buflen, len;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (level > trace_level)
|
|
Packit Service |
8aa27d |
return;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
pbuf = buf;
|
|
Packit Service |
8aa27d |
buflen = sizeof(buf);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* add file line */
|
|
Packit Service |
8aa27d |
switch (level) {
|
|
Packit Service |
8aa27d |
case TRACE_LEVEL_NONE:
|
|
Packit Service |
8aa27d |
fmt_pre = "";
|
|
Packit Service |
8aa27d |
break;
|
|
Packit Service |
8aa27d |
case TRACE_LEVEL_ERROR:
|
|
Packit Service |
8aa27d |
fmt_pre = "[%s:%d] ERROR: ";
|
|
Packit Service |
8aa27d |
break;
|
|
Packit Service |
8aa27d |
case TRACE_LEVEL_WARNING:
|
|
Packit Service |
8aa27d |
fmt_pre = "[%s:%d] WARN: ";
|
|
Packit Service |
8aa27d |
break;
|
|
Packit Service |
8aa27d |
case TRACE_LEVEL_INFO:
|
|
Packit Service |
8aa27d |
fmt_pre = "[%s:%d] INFO: ";
|
|
Packit Service |
8aa27d |
break;
|
|
Packit Service |
8aa27d |
case TRACE_LEVEL_DEVEL:
|
|
Packit Service |
8aa27d |
fmt_pre = "[%s:%d] DEVEL: ";
|
|
Packit Service |
8aa27d |
break;
|
|
Packit Service |
8aa27d |
case TRACE_LEVEL_DEBUG:
|
|
Packit Service |
8aa27d |
fmt_pre = "[%s:%d] DEBUG: ";
|
|
Packit Service |
8aa27d |
break;
|
|
Packit Service |
8aa27d |
default:
|
|
Packit Service |
8aa27d |
return;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
snprintf(pbuf, buflen, fmt_pre, file, line);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
len = strlen(buf);
|
|
Packit Service |
8aa27d |
pbuf = buf + len;
|
|
Packit Service |
8aa27d |
buflen = sizeof(buf) - len;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
va_start(ap, fmt);
|
|
Packit Service |
8aa27d |
vsnprintf(pbuf, buflen, fmt, ap);
|
|
Packit Service |
8aa27d |
va_end(ap);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
printf("%s", buf);
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
int compute_hash(int hash_type, int buf_size, char *buf, char *digest)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
EVP_MD_CTX *md_ctx = NULL;
|
|
Packit Service |
8aa27d |
unsigned int result_size;
|
|
Packit Service |
8aa27d |
int rc;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
md_ctx = EVP_MD_CTX_create();
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
switch (hash_type) {
|
|
Packit Service |
8aa27d |
case HASH_SHA1:
|
|
Packit Service |
8aa27d |
rc = EVP_DigestInit(md_ctx, EVP_sha1());
|
|
Packit Service |
8aa27d |
break;
|
|
Packit Service |
8aa27d |
case HASH_MD5:
|
|
Packit Service |
8aa27d |
rc = EVP_DigestInit(md_ctx, EVP_md5());
|
|
Packit Service |
8aa27d |
break;
|
|
Packit Service |
8aa27d |
default:
|
|
Packit Service |
8aa27d |
rc = -1;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (rc != 1) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("EVP_DigestInit() failed: rc = %d\n", rc);
|
|
Packit Service |
8aa27d |
rc = -1;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
rc = EVP_DigestUpdate(md_ctx, buf, buf_size);
|
|
Packit Service |
8aa27d |
if (rc != 1) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("EVP_DigestUpdate() failed: rc = %d\n", rc);
|
|
Packit Service |
8aa27d |
rc = -1;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
result_size = EVP_MD_CTX_size(md_ctx);
|
|
Packit Service |
8aa27d |
rc = EVP_DigestFinal(md_ctx, (unsigned char *) digest, &result_size);
|
|
Packit Service |
8aa27d |
if (rc != 1) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("EVP_DigestFinal() failed: rc = %d\n", rc);
|
|
Packit Service |
8aa27d |
rc = -1;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
rc = 0;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
EVP_MD_CTX_destroy(md_ctx);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return rc;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
CK_RV local_rng(CK_BYTE *output, CK_ULONG bytes)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
int ranfd;
|
|
Packit Service |
8aa27d |
int rlen;
|
|
Packit Service |
8aa27d |
unsigned int totallen = 0;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ranfd = open("/dev/prandom", 0);
|
|
Packit Service |
8aa27d |
if (ranfd < 0)
|
|
Packit Service |
8aa27d |
ranfd = open("/dev/urandom", 0);
|
|
Packit Service |
8aa27d |
if (ranfd >= 0) {
|
|
Packit Service |
8aa27d |
do {
|
|
Packit Service |
8aa27d |
rlen = read(ranfd, output + totallen, bytes - totallen);
|
|
Packit Service |
8aa27d |
totallen += rlen;
|
|
Packit Service |
8aa27d |
} while (totallen < bytes);
|
|
Packit Service |
8aa27d |
close(ranfd);
|
|
Packit Service |
8aa27d |
return CKR_OK;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
CK_RV aes_256_wrap(unsigned char out[40], const unsigned char in[32],
|
|
Packit Service |
8aa27d |
const unsigned char kek[32])
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
CK_RV rc;
|
|
Packit Service |
8aa27d |
int outlen;
|
|
Packit Service |
8aa27d |
unsigned char buffer[40 + EVP_MAX_BLOCK_LENGTH];
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
EVP_CIPHER_CTX *ctx = NULL;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ctx = EVP_CIPHER_CTX_new();
|
|
Packit Service |
8aa27d |
if (ctx == NULL) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("EVP_CIPHER_CTX_new failed.\n");
|
|
Packit Service |
8aa27d |
rc = CKR_HOST_MEMORY;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
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 Service |
8aa27d |
TRACE_ERROR("EVP_Cipher funcs failed\n");
|
|
Packit Service |
8aa27d |
rc = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
memcpy(out, buffer, 40);
|
|
Packit Service |
8aa27d |
rc = CKR_OK;
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
EVP_CIPHER_CTX_free(ctx);
|
|
Packit Service |
8aa27d |
return rc;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
CK_RV aes_256_unwrap(unsigned char key[32], const unsigned char in[40],
|
|
Packit Service |
8aa27d |
const unsigned char kek[32])
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
CK_RV rc;
|
|
Packit Service |
8aa27d |
int outlen;
|
|
Packit Service |
8aa27d |
unsigned char buffer[32 + EVP_MAX_BLOCK_LENGTH];
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
EVP_CIPHER_CTX *ctx = NULL;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ctx = EVP_CIPHER_CTX_new();
|
|
Packit Service |
8aa27d |
if (ctx == NULL) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("EVP_CIPHER_CTX_new failed\n");
|
|
Packit Service |
8aa27d |
rc = CKR_HOST_MEMORY;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
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 Service |
8aa27d |
rc = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
memcpy(key, buffer, 32);
|
|
Packit Service |
8aa27d |
rc = CKR_OK;
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
EVP_CIPHER_CTX_free(ctx);
|
|
Packit Service |
8aa27d |
return rc;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
CK_RV aes_256_gcm_seal(unsigned char *out, unsigned char tag[16],
|
|
Packit Service |
8aa27d |
const unsigned char *aad, size_t aadlen,
|
|
Packit Service |
8aa27d |
const unsigned char *in, size_t inlen,
|
|
Packit Service |
8aa27d |
const unsigned char key[32],
|
|
Packit Service |
8aa27d |
const unsigned char iv[12])
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
CK_RV rc;
|
|
Packit Service |
8aa27d |
int outlen;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
EVP_CIPHER_CTX *ctx = NULL;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ctx = EVP_CIPHER_CTX_new();
|
|
Packit Service |
8aa27d |
if (ctx == NULL) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("EVP_CIPHER_CTX_new failed\n");
|
|
Packit Service |
8aa27d |
rc = CKR_HOST_MEMORY;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (EVP_CipherInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL, -1) != 1
|
|
Packit Service |
8aa27d |
|| EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 12, NULL) != 1
|
|
Packit Service |
8aa27d |
|| EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1) != 1
|
|
Packit Service |
8aa27d |
|| EVP_CipherUpdate(ctx, NULL, &outlen, aad, aadlen) != 1
|
|
Packit Service |
8aa27d |
|| EVP_CipherUpdate(ctx, out, &outlen, in, inlen) != 1
|
|
Packit Service |
8aa27d |
|| EVP_CipherFinal_ex(ctx, out + outlen, &outlen) != 1
|
|
Packit Service |
8aa27d |
|| EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag) != 1) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("EVP_Cipher funcs failed\n");
|
|
Packit Service |
8aa27d |
rc = CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
rc = CKR_OK;
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
EVP_CIPHER_CTX_free(ctx);
|
|
Packit Service |
8aa27d |
return rc;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
int get_pin(char **pin, size_t *pinlen)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
struct termios old, new;
|
|
Packit Service |
8aa27d |
int nread;
|
|
Packit Service |
8aa27d |
char *buff = NULL;
|
|
Packit Service |
8aa27d |
size_t buflen;
|
|
Packit Service |
8aa27d |
int rc = 0;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* turn echoing off */
|
|
Packit Service |
8aa27d |
if (tcgetattr(fileno(stdin), &old) != 0)
|
|
Packit Service |
8aa27d |
return -1;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
new = old;
|
|
Packit Service |
8aa27d |
new.c_lflag &= ~ECHO;
|
|
Packit Service |
8aa27d |
if (tcsetattr(fileno(stdin), TCSAFLUSH, &new) != 0)
|
|
Packit Service |
8aa27d |
return -1;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* read the pin
|
|
Packit Service |
8aa27d |
* Note: getline will allocate memory for buff. free it when done.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
nread = getline(&buff, &buflen, stdin);
|
|
Packit Service |
8aa27d |
if (nread == -1) {
|
|
Packit Service |
8aa27d |
rc = -1;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Restore terminal */
|
|
Packit Service |
8aa27d |
(void) tcsetattr(fileno(stdin), TCSAFLUSH, &old;;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* start a newline */
|
|
Packit Service |
8aa27d |
printf("\n");
|
|
Packit Service |
8aa27d |
fflush(stdout);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* Allocate PIN.
|
|
Packit Service |
8aa27d |
* Note: nread includes carriage return.
|
|
Packit Service |
8aa27d |
* Replace with terminating NULL.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
*pin = (char *) malloc(nread);
|
|
Packit Service |
8aa27d |
if (*pin == NULL) {
|
|
Packit Service |
8aa27d |
rc = -ENOMEM;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* strip the carriage return since not part of pin. */
|
|
Packit Service |
8aa27d |
buff[nread - 1] = '\0';
|
|
Packit Service |
8aa27d |
memcpy(*pin, buff, nread);
|
|
Packit Service |
8aa27d |
/* don't include the terminating null in the pinlen */
|
|
Packit Service |
8aa27d |
*pinlen = nread - 1;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
if (buff)
|
|
Packit Service |
8aa27d |
free(buff);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return rc;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/**
|
|
Packit Service |
8aa27d |
* Verify that SO PIN and user PIN are correct by comparing their SHA-1
|
|
Packit Service |
8aa27d |
* values with the stored hashes in NVTOK.DAT.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
int verify_pins(char *data_store, char *sopin, unsigned long sopinlen,
|
|
Packit Service |
8aa27d |
char *userpin, unsigned long userpinlen)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
TOKEN_DATA td;
|
|
Packit Service |
8aa27d |
char fname[PATH_MAX];
|
|
Packit Service |
8aa27d |
char pin_sha[SHA1_HASH_SIZE];
|
|
Packit Service |
8aa27d |
FILE *fp = NULL;
|
|
Packit Service |
8aa27d |
int ret;
|
|
Packit Service |
8aa27d |
int tdnew;
|
|
Packit Service |
8aa27d |
struct stat stbuf;
|
|
Packit Service |
8aa27d |
size_t tdlen;
|
|
Packit Service |
8aa27d |
int fd;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
/* read the NVTOK.DAT */
|
|
Packit Service |
8aa27d |
snprintf(fname, PATH_MAX, "%s/NVTOK.DAT", data_store);
|
|
Packit Service |
8aa27d |
fp = fopen((char *) fname, "r");
|
|
Packit Service |
8aa27d |
if (!fp) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Cannot not open %s: %s\n", fname, strerror(errno));
|
|
Packit Service |
8aa27d |
return -1;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
fd = fileno(fp);
|
|
Packit Service |
8aa27d |
if ((fstat(fd, &stbuf) != 0) || (!S_ISREG(stbuf.st_mode))) {
|
|
Packit Service |
8aa27d |
ret = -1;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (stbuf.st_size == sizeof(TOKEN_DATA_OLD)) {
|
|
Packit Service |
8aa27d |
/* old data store/pin format */
|
|
Packit Service |
8aa27d |
tdnew = 0;
|
|
Packit Service |
8aa27d |
tdlen = sizeof(TOKEN_DATA_OLD);
|
|
Packit Service |
8aa27d |
} else if (stbuf.st_size == sizeof(TOKEN_DATA)) {
|
|
Packit Service |
8aa27d |
/* new data store/pin format */
|
|
Packit Service |
8aa27d |
tdnew = 1;
|
|
Packit Service |
8aa27d |
tdlen = sizeof(TOKEN_DATA);
|
|
Packit Service |
8aa27d |
} else {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("%s has an invalid size of %ld bytes. Neither old nor new token format.\n",
|
|
Packit Service |
8aa27d |
fname, stbuf.st_size);
|
|
Packit Service |
8aa27d |
ret = -1;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = fread(&td, tdlen, 1, fp);
|
|
Packit Service |
8aa27d |
if (ret != 1) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Could not read %s: %s\n", fname, strerror(errno));
|
|
Packit Service |
8aa27d |
ret = -1;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (tdnew == 0) {
|
|
Packit Service |
8aa27d |
/* Now compute the SHAs for the SO and USER pins entered.
|
|
Packit Service |
8aa27d |
* Compare with the SHAs for SO and USER PINs saved in
|
|
Packit Service |
8aa27d |
* NVTOK.DAT to verify.
|
|
Packit Service |
8aa27d |
*/
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (sopin != NULL) {
|
|
Packit Service |
8aa27d |
ret = compute_sha1(sopin, sopinlen, pin_sha);
|
|
Packit Service |
8aa27d |
if (ret) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Failed to compute sha for SO.\n");
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (memcmp(td.so_pin_sha, pin_sha, SHA1_HASH_SIZE) != 0) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("SO PIN is incorrect.\n");
|
|
Packit Service |
8aa27d |
ret = -1;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (userpin != NULL) {
|
|
Packit Service |
8aa27d |
ret = compute_sha1(userpin, userpinlen, pin_sha);
|
|
Packit Service |
8aa27d |
if (ret) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Failed to compute sha for USER.\n");
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (memcmp(td.user_pin_sha, pin_sha, SHA1_HASH_SIZE) != 0) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("USER PIN is incorrect.\n");
|
|
Packit Service |
8aa27d |
ret = -1;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
} else if (tdnew == 1) {
|
|
Packit Service |
8aa27d |
if (sopin != NULL) {
|
|
Packit Service |
8aa27d |
unsigned char so_login_key[32];
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = PKCS5_PBKDF2_HMAC(sopin, sopinlen,
|
|
Packit Service |
8aa27d |
td.dat.so_login_salt, 64,
|
|
Packit Service |
8aa27d |
td.dat.so_login_it, EVP_sha512(),
|
|
Packit Service |
8aa27d |
256 / 8, so_login_key);
|
|
Packit Service |
8aa27d |
if (ret != 1) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("PBKDF2 failed.\n");
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (CRYPTO_memcmp(td.dat.so_login_key, so_login_key, 32) != 0) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("USER PIN is incorrect.\n");
|
|
Packit Service |
8aa27d |
ret = -1;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
if (userpin != NULL) {
|
|
Packit Service |
8aa27d |
unsigned char user_login_key[32];
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
ret = PKCS5_PBKDF2_HMAC(userpin, userpinlen,
|
|
Packit Service |
8aa27d |
td.dat.user_login_salt, 64,
|
|
Packit Service |
8aa27d |
td.dat.user_login_it, EVP_sha512(),
|
|
Packit Service |
8aa27d |
256 / 8, user_login_key);
|
|
Packit Service |
8aa27d |
if (ret != 1) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("PBKDF2 failed.\n");
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (CRYPTO_memcmp(td.dat.user_login_key, user_login_key, 32) != 0) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("USER PIN is incorrect.\n");
|
|
Packit Service |
8aa27d |
ret = -1;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
} else {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("Unknown token format.\n");
|
|
Packit Service |
8aa27d |
ret = -1;
|
|
Packit Service |
8aa27d |
goto done;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
ret = 0;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
done:
|
|
Packit Service |
8aa27d |
/* clear out the hash */
|
|
Packit Service |
8aa27d |
memset(pin_sha, 0, SHA1_HASH_SIZE);
|
|
Packit Service |
8aa27d |
if (fp)
|
|
Packit Service |
8aa27d |
fclose(fp);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return ret;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
void set_perm(int file)
|
|
Packit Service |
8aa27d |
{
|
|
Packit Service |
8aa27d |
struct group *grp;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
// Set absolute permissions or rw-rw----
|
|
Packit Service |
8aa27d |
fchmod(file, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
grp = getgrnam("pkcs11"); // Obtain the group id
|
|
Packit Service |
8aa27d |
if (grp) {
|
|
Packit Service |
8aa27d |
// set ownership to root, and pkcs11 group
|
|
Packit Service |
8aa27d |
if (fchown(file, getuid(), grp->gr_gid) != 0) {
|
|
Packit Service |
8aa27d |
goto error;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
} else {
|
|
Packit Service |
8aa27d |
goto error;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
return;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
error:
|
|
Packit Service |
8aa27d |
TRACE_DEVEL("Unable to set permissions on file.\n");
|
|
Packit Service |
8aa27d |
}
|