|
Packit |
8681c6 |
/*
|
|
Packit |
8681c6 |
* COPYRIGHT (c) International Business Machines Corp. 2005-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 |
#include <sys/types.h>
|
|
Packit |
8681c6 |
#include <sys/stat.h>
|
|
Packit |
8681c6 |
#include <unistd.h>
|
|
Packit |
8681c6 |
#include <errno.h>
|
|
Packit |
8681c6 |
#include <string.h>
|
|
Packit |
8681c6 |
#include <pwd.h>
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
#include <openssl/pem.h>
|
|
Packit |
8681c6 |
#include <openssl/rsa.h>
|
|
Packit |
8681c6 |
#include <openssl/err.h>
|
|
Packit |
8681c6 |
#include <openssl/rand.h>
|
|
Packit |
8681c6 |
#include <openssl/evp.h>
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
#include <tss/platform.h>
|
|
Packit |
8681c6 |
#include <tss/tss_defines.h>
|
|
Packit |
8681c6 |
#include <tss/tss_typedef.h>
|
|
Packit |
8681c6 |
#include <tss/tss_structs.h>
|
|
Packit |
8681c6 |
#include <tss/tss_error.h>
|
|
Packit |
8681c6 |
#include <tss/tspi.h>
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
#include "pkcs11types.h"
|
|
Packit |
8681c6 |
#include "stdll.h"
|
|
Packit |
8681c6 |
#include "defs.h"
|
|
Packit |
8681c6 |
#include "host_defs.h"
|
|
Packit |
8681c6 |
#include "h_extern.h"
|
|
Packit |
8681c6 |
#include "tok_specific.h"
|
|
Packit |
8681c6 |
#include "tok_spec_struct.h"
|
|
Packit |
8681c6 |
#include "trace.h"
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
#include "tpm_specific.h"
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/*
|
|
Packit |
8681c6 |
* In order to make opencryptoki compatible with
|
|
Packit |
8681c6 |
* OpenSSL 1.1 API Changes and backward compatible
|
|
Packit |
8681c6 |
* we need to check for its version
|
|
Packit |
8681c6 |
*/
|
|
Packit |
8681c6 |
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
|
Packit |
8681c6 |
#define OLDER_OPENSSL
|
|
Packit |
8681c6 |
#endif
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
#ifdef DEBUG
|
|
Packit |
8681c6 |
void openssl_print_errors()
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
ERR_load_ERR_strings();
|
|
Packit |
8681c6 |
ERR_load_crypto_strings();
|
|
Packit |
8681c6 |
ERR_print_errors_fp(stderr);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
#endif
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
RSA *openssl_gen_key(STDLL_TokData_t *tokdata)
|
|
Packit |
8681c6 |
{
|
|
Packit Service |
8aa27d |
RSA *rsa = NULL;
|
|
Packit Service |
8aa27d |
int rc = 0, counter = 0;
|
|
Packit |
8681c6 |
char buf[32];
|
|
Packit |
8681c6 |
#ifndef OLDER_OPENSSL
|
|
Packit Service |
8aa27d |
EVP_PKEY *pkey = NULL;
|
|
Packit Service |
8aa27d |
EVP_PKEY_CTX *ctx = NULL;
|
|
Packit Service |
8aa27d |
BIGNUM *bne = NULL;
|
|
Packit |
8681c6 |
#endif
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
token_specific_rng(tokdata, (CK_BYTE *) buf, 32);
|
|
Packit |
8681c6 |
RAND_seed(buf, 32);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
regen_rsa_key:
|
|
Packit |
8681c6 |
#ifdef OLDER_OPENSSL
|
|
Packit |
8681c6 |
rsa = RSA_generate_key(2048, 65537, NULL, NULL);
|
|
Packit |
8681c6 |
if (rsa == NULL) {
|
|
Packit Service |
8aa27d |
fprintf(stderr, "Error generating user's RSA key\n");
|
|
Packit Service |
8aa27d |
ERR_load_crypto_strings();
|
|
Packit Service |
8aa27d |
ERR_print_errors_fp(stderr);
|
|
Packit Service |
8aa27d |
goto err;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
rc = RSA_check_key(rsa);
|
|
Packit |
8681c6 |
#else
|
|
Packit |
8681c6 |
bne = BN_new();
|
|
Packit |
8681c6 |
rc = BN_set_word(bne, 65537);
|
|
Packit |
8681c6 |
if (!rc) {
|
|
Packit |
8681c6 |
fprintf(stderr, "Error generating bne\n");
|
|
Packit |
8681c6 |
ERR_load_crypto_strings();
|
|
Packit |
8681c6 |
ERR_print_errors_fp(stderr);
|
|
Packit Service |
8aa27d |
goto err;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
|
|
Packit Service |
8aa27d |
if (ctx == NULL)
|
|
Packit Service |
8aa27d |
goto err;
|
|
Packit Service |
8aa27d |
|
|
Packit Service |
8aa27d |
if (EVP_PKEY_keygen_init(ctx) <= 0
|
|
Packit Service |
8aa27d |
|| EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 2048) <= 0
|
|
Packit Service |
8aa27d |
|| EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, bne) <= 0) {
|
|
Packit |
8681c6 |
fprintf(stderr, "Error generating user's RSA key\n");
|
|
Packit |
8681c6 |
ERR_load_crypto_strings();
|
|
Packit |
8681c6 |
ERR_print_errors_fp(stderr);
|
|
Packit Service |
8aa27d |
goto err;
|
|
Packit |
8681c6 |
}
|
|
Packit Service |
8aa27d |
bne = NULL; // will be freed as part of the context
|
|
Packit Service |
8aa27d |
if (EVP_PKEY_keygen(ctx, &pkey) <= 0
|
|
Packit Service |
8aa27d |
|| (rsa = EVP_PKEY_get1_RSA(pkey)) == NULL) {
|
|
Packit Service |
8aa27d |
fprintf(stderr, "Error generating user's RSA key\n");
|
|
Packit Service |
8aa27d |
ERR_load_crypto_strings();
|
|
Packit Service |
8aa27d |
ERR_print_errors_fp(stderr);
|
|
Packit Service |
8aa27d |
goto err;
|
|
Packit Service |
8aa27d |
}
|
|
Packit Service |
8aa27d |
#if OPENSSL_VERSION_NUMBER < 0x10101000L
|
|
Packit |
8681c6 |
rc = RSA_check_key(rsa);
|
|
Packit Service |
8aa27d |
#else
|
|
Packit Service |
8aa27d |
rc = (EVP_PKEY_check(ctx) == 1 ? 1 : 0);
|
|
Packit Service |
8aa27d |
#endif
|
|
Packit Service |
8aa27d |
#endif
|
|
Packit |
8681c6 |
switch (rc) {
|
|
Packit |
8681c6 |
case 0:
|
|
Packit |
8681c6 |
/* rsa is not a valid RSA key */
|
|
Packit |
8681c6 |
RSA_free(rsa);
|
|
Packit Service |
8aa27d |
rsa = NULL;
|
|
Packit |
8681c6 |
counter++;
|
|
Packit |
8681c6 |
if (counter == KEYGEN_RETRY) {
|
|
Packit |
8681c6 |
TRACE_DEVEL("Tried %d times to generate a "
|
|
Packit |
8681c6 |
"valid RSA key, failed.\n", KEYGEN_RETRY);
|
|
Packit Service |
8aa27d |
goto err;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
goto regen_rsa_key;
|
|
Packit |
8681c6 |
break;
|
|
Packit |
8681c6 |
case 1:
|
|
Packit |
8681c6 |
/* success case, rsa is a valid key */
|
|
Packit |
8681c6 |
break;
|
|
Packit |
8681c6 |
case -1:
|
|
Packit |
8681c6 |
/* fall through */
|
|
Packit |
8681c6 |
default:
|
|
Packit |
8681c6 |
DEBUG_openssl_print_errors();
|
|
Packit |
8681c6 |
break;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
#ifndef OLDER_OPENSSL
|
|
Packit Service |
8aa27d |
if (pkey != NULL)
|
|
Packit Service |
8aa27d |
EVP_PKEY_free(pkey);
|
|
Packit Service |
8aa27d |
if (ctx != NULL)
|
|
Packit Service |
8aa27d |
EVP_PKEY_CTX_free(ctx);
|
|
Packit Service |
8aa27d |
if (bne != NULL)
|
|
Packit Service |
8aa27d |
BN_free(bne);
|
|
Packit Service |
8aa27d |
#endif
|
|
Packit |
8681c6 |
return rsa;
|
|
Packit Service |
8aa27d |
err:
|
|
Packit Service |
8aa27d |
if (rsa != NULL)
|
|
Packit Service |
8aa27d |
RSA_free(rsa);
|
|
Packit Service |
8aa27d |
#ifndef OLDER_OPENSSL
|
|
Packit Service |
8aa27d |
if (pkey != NULL)
|
|
Packit Service |
8aa27d |
EVP_PKEY_free(pkey);
|
|
Packit Service |
8aa27d |
if (ctx != NULL)
|
|
Packit Service |
8aa27d |
EVP_PKEY_CTX_free(ctx);
|
|
Packit Service |
8aa27d |
if (bne != NULL)
|
|
Packit Service |
8aa27d |
BN_free(bne);
|
|
Packit Service |
8aa27d |
#endif
|
|
Packit Service |
8aa27d |
return NULL;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
int openssl_write_key(STDLL_TokData_t * tokdata, RSA * rsa, char *filename,
|
|
Packit |
8681c6 |
CK_BYTE * pPin)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
BIO *b = NULL;
|
|
Packit |
8681c6 |
char loc[PATH_MAX];
|
|
Packit |
8681c6 |
struct passwd *pw = NULL;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
errno = 0;
|
|
Packit |
8681c6 |
if ((pw = getpwuid(getuid())) == NULL) {
|
|
Packit |
8681c6 |
TRACE_ERROR("Error getting username: %s\n", strerror(errno));
|
|
Packit |
8681c6 |
return -1;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
if (ock_snprintf(loc, PATH_MAX, "%s/%s/%s",
|
|
Packit Service |
8aa27d |
tokdata->pk_dir, pw->pw_name, filename) != 0) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("key path too long\n");
|
|
Packit Service |
8aa27d |
return -1;
|
|
Packit Service |
8aa27d |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
b = BIO_new_file(loc, "w");
|
|
Packit |
8681c6 |
if (!b) {
|
|
Packit |
8681c6 |
TRACE_ERROR("Error opening file for write: %s\n", loc);
|
|
Packit |
8681c6 |
return -1;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (!PEM_write_bio_RSAPrivateKey(b, rsa,
|
|
Packit |
8681c6 |
EVP_aes_256_cbc(), NULL, 0, 0, pPin)) {
|
|
Packit |
8681c6 |
BIO_free(b);
|
|
Packit |
8681c6 |
TRACE_ERROR("Writing key %s to disk failed.\n", loc);
|
|
Packit |
8681c6 |
DEBUG_openssl_print_errors();
|
|
Packit |
8681c6 |
return -1;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
BIO_free(b);
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if (util_set_file_mode(loc, (S_IRUSR | S_IWUSR))) {
|
|
Packit |
8681c6 |
TRACE_ERROR("Setting file mode of %s failed\n", loc);
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return 0;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
CK_RV openssl_read_key(STDLL_TokData_t * tokdata, char *filename,
|
|
Packit |
8681c6 |
CK_BYTE * pPin, RSA ** ret)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
BIO *b = NULL;
|
|
Packit |
8681c6 |
RSA *rsa = NULL;
|
|
Packit |
8681c6 |
char loc[PATH_MAX];
|
|
Packit |
8681c6 |
struct passwd *pw = NULL;
|
|
Packit |
8681c6 |
CK_RV rc = CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
errno = 0;
|
|
Packit |
8681c6 |
if ((pw = getpwuid(getuid())) == NULL) {
|
|
Packit |
8681c6 |
TRACE_ERROR("Error getting username: %s\n", strerror(errno));
|
|
Packit |
8681c6 |
return CKR_FUNCTION_FAILED;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit Service |
8aa27d |
if (ock_snprintf(loc, PATH_MAX, "%s/%s/%s",
|
|
Packit Service |
8aa27d |
tokdata->pk_dir, pw->pw_name, filename) != 0) {
|
|
Packit Service |
8aa27d |
TRACE_ERROR("key file name too long\n");
|
|
Packit Service |
8aa27d |
return CKR_FUNCTION_FAILED;
|
|
Packit Service |
8aa27d |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* we can't allow a pin of NULL here, since openssl will try to prompt
|
|
Packit |
8681c6 |
* for a password in PEM_read_bio_RSAPrivateKey */
|
|
Packit |
8681c6 |
if (pPin == NULL)
|
|
Packit |
8681c6 |
return CKR_PIN_INCORRECT;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
b = BIO_new_file(loc, "r+");
|
|
Packit |
8681c6 |
if (b == NULL) {
|
|
Packit |
8681c6 |
TRACE_ERROR("Error opening file for read: %s\n", loc);
|
|
Packit |
8681c6 |
return CKR_FILE_NOT_FOUND;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
if ((rsa = PEM_read_bio_RSAPrivateKey(b, NULL, 0, pPin)) == NULL) {
|
|
Packit |
8681c6 |
TRACE_ERROR("Reading key %s from disk failed.\n", loc);
|
|
Packit |
8681c6 |
DEBUG_openssl_print_errors();
|
|
Packit |
8681c6 |
if (ERR_GET_REASON(ERR_get_error()) == PEM_R_BAD_DECRYPT) {
|
|
Packit |
8681c6 |
rc = CKR_PIN_INCORRECT;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
BIO_free(b);
|
|
Packit |
8681c6 |
return rc;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
BIO_free(b);
|
|
Packit |
8681c6 |
*ret = rsa;
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return CKR_OK;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
int openssl_get_modulus_and_prime(RSA * rsa, unsigned int *size_n,
|
|
Packit |
8681c6 |
unsigned char *n, unsigned int *size_p,
|
|
Packit |
8681c6 |
unsigned char *p)
|
|
Packit |
8681c6 |
{
|
|
Packit |
8681c6 |
#ifndef OLDER_OPENSSL
|
|
Packit |
8681c6 |
const BIGNUM *n_tmp, *p_tmp;
|
|
Packit |
8681c6 |
#endif
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* get the modulus from the RSA object */
|
|
Packit |
8681c6 |
#ifdef OLDER_OPENSSL
|
|
Packit |
8681c6 |
if ((*size_n = BN_bn2bin(rsa->n, n)) <= 0) {
|
|
Packit |
8681c6 |
#else
|
|
Packit |
8681c6 |
RSA_get0_key(rsa, &n_tmp, NULL, NULL);
|
|
Packit |
8681c6 |
if ((*size_n = BN_bn2bin(n_tmp, n)) <= 0) {
|
|
Packit |
8681c6 |
#endif
|
|
Packit |
8681c6 |
DEBUG_openssl_print_errors();
|
|
Packit |
8681c6 |
return -1;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
/* get one of the primes from the RSA object */
|
|
Packit |
8681c6 |
#ifdef OLDER_OPENSSL
|
|
Packit |
8681c6 |
if ((*size_p = BN_bn2bin(rsa->p, p)) <= 0) {
|
|
Packit |
8681c6 |
#else
|
|
Packit |
8681c6 |
RSA_get0_factors(rsa, &p_tmp, NULL);
|
|
Packit |
8681c6 |
if ((*size_p = BN_bn2bin(p_tmp, p)) <= 0) {
|
|
Packit |
8681c6 |
#endif
|
|
Packit |
8681c6 |
DEBUG_openssl_print_errors();
|
|
Packit |
8681c6 |
return -1;
|
|
Packit |
8681c6 |
}
|
|
Packit |
8681c6 |
|
|
Packit |
8681c6 |
return 0;
|
|
Packit |
8681c6 |
}
|