2001-11-20 22:21:58 +00:00
|
|
|
/*
|
2002-01-10 12:33:56 +00:00
|
|
|
* pkcs15-sec.c: PKCS#15 cryptography functions
|
2001-11-20 22:21:58 +00:00
|
|
|
*
|
2006-12-19 21:31:17 +00:00
|
|
|
* Copyright (C) 2001, 2002 Juha Yrjölä <juha.yrjola@iki.fi>
|
2018-04-14 17:38:34 +00:00
|
|
|
* Copyright (C) 2007 Nils Larsch <nils@larsch.net>
|
2001-11-20 22:21:58 +00:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*/
|
|
|
|
|
2015-04-22 21:55:33 +00:00
|
|
|
#if HAVE_CONFIG_H
|
2010-03-04 08:14:36 +00:00
|
|
|
#include "config.h"
|
2015-04-22 21:55:33 +00:00
|
|
|
#endif
|
2010-03-04 08:14:36 +00:00
|
|
|
|
2001-11-20 22:21:58 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
2002-10-19 14:04:52 +00:00
|
|
|
#ifdef HAVE_UNISTD_H
|
2001-12-15 01:29:51 +00:00
|
|
|
#include <unistd.h>
|
2002-06-14 12:52:56 +00:00
|
|
|
#endif
|
2001-11-20 22:21:58 +00:00
|
|
|
|
2010-03-04 08:14:36 +00:00
|
|
|
#include "internal.h"
|
|
|
|
#include "pkcs15.h"
|
2018-06-12 06:13:23 +00:00
|
|
|
#include "pkcs11/pkcs11.h"
|
|
|
|
|
2018-04-06 11:15:10 +00:00
|
|
|
static int sec_env_add_param(sc_security_env_t* se, const sc_sec_env_param_t* p)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (!se || !p)
|
|
|
|
return SC_ERROR_INCORRECT_PARAMETERS;
|
|
|
|
|
|
|
|
for (i = 0; i < SC_SEC_ENV_MAX_PARAMS; i++) {
|
|
|
|
if (se->params[i].value == NULL) {
|
|
|
|
se->params[i] = *p;
|
|
|
|
|
|
|
|
return SC_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return SC_ERROR_TOO_MANY_OBJECTS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-10-01 12:27:09 +00:00
|
|
|
static int get_file_path(const struct sc_pkcs15_object* obj, sc_path_t* path)
|
2018-06-12 06:13:23 +00:00
|
|
|
{
|
2018-10-01 12:27:09 +00:00
|
|
|
if (!path)
|
|
|
|
return SC_ERROR_INCORRECT_PARAMETERS;
|
|
|
|
|
2018-06-12 06:13:23 +00:00
|
|
|
const struct sc_pkcs15_prkey_info *prkey = (const struct sc_pkcs15_prkey_info *) obj->data;
|
|
|
|
const struct sc_pkcs15_skey_info *skey = (const struct sc_pkcs15_skey_info *) obj->data;
|
|
|
|
|
|
|
|
if ((obj->type & SC_PKCS15_TYPE_CLASS_MASK) == SC_PKCS15_TYPE_PRKEY) {
|
2018-10-01 12:27:09 +00:00
|
|
|
*path = prkey->path;
|
2018-06-12 06:13:23 +00:00
|
|
|
}
|
|
|
|
else if ((obj->type & SC_PKCS15_TYPE_CLASS_MASK) == SC_PKCS15_TYPE_SKEY) {
|
2018-10-01 12:27:09 +00:00
|
|
|
*path = skey->path;
|
2018-06-12 06:13:23 +00:00
|
|
|
}
|
2018-10-01 12:27:09 +00:00
|
|
|
else
|
|
|
|
return SC_ERROR_INCORRECT_PARAMETERS;
|
2018-06-12 06:13:23 +00:00
|
|
|
|
2018-10-01 12:27:09 +00:00
|
|
|
return SC_SUCCESS;
|
2018-06-12 06:13:23 +00:00
|
|
|
}
|
|
|
|
|
2010-03-04 08:14:36 +00:00
|
|
|
|
2002-06-16 21:18:05 +00:00
|
|
|
static int select_key_file(struct sc_pkcs15_card *p15card,
|
2018-06-12 06:13:23 +00:00
|
|
|
const struct sc_pkcs15_object *key,
|
2015-12-04 08:22:15 +00:00
|
|
|
sc_security_env_t *senv)
|
2002-06-16 21:18:05 +00:00
|
|
|
{
|
2011-03-13 18:11:07 +00:00
|
|
|
sc_context_t *ctx = p15card->card->ctx;
|
2018-06-12 06:13:23 +00:00
|
|
|
sc_path_t orig_path;
|
2005-03-08 20:59:35 +00:00
|
|
|
sc_path_t path, file_id;
|
2002-06-16 21:18:05 +00:00
|
|
|
int r;
|
|
|
|
|
2011-03-13 18:11:07 +00:00
|
|
|
LOG_FUNC_CALLED(ctx);
|
|
|
|
|
2018-10-01 12:27:09 +00:00
|
|
|
LOG_TEST_RET(ctx, get_file_path(key, &orig_path), "Could not get key file path.");
|
2011-01-18 09:48:26 +00:00
|
|
|
memset(&path, 0, sizeof(sc_path_t));
|
|
|
|
memset(&file_id, 0, sizeof(sc_path_t));
|
|
|
|
|
2012-05-28 21:15:37 +00:00
|
|
|
/* TODO: Why file_app may be NULL -- at least 3F00 has to be present?
|
|
|
|
* Check validity of the following assumption. */
|
2005-02-01 19:09:35 +00:00
|
|
|
/* For pkcs15-emulated cards, the file_app may be NULL,
|
2018-04-14 17:38:34 +00:00
|
|
|
* in that case we always assume an absolute path */
|
2018-06-12 06:13:23 +00:00
|
|
|
if (!orig_path.len && orig_path.aid.len) {
|
2012-05-28 21:15:37 +00:00
|
|
|
/* Private key is a SDO allocated in application DF */
|
2018-06-12 06:13:23 +00:00
|
|
|
path = orig_path;
|
2012-05-28 21:15:37 +00:00
|
|
|
}
|
2018-06-12 06:13:23 +00:00
|
|
|
else if (orig_path.len == 2 && p15card->file_app != NULL) {
|
2002-06-16 21:18:05 +00:00
|
|
|
/* Path is relative to app. DF */
|
|
|
|
path = p15card->file_app->path;
|
2018-06-12 06:13:23 +00:00
|
|
|
file_id = orig_path;
|
2002-06-16 21:18:05 +00:00
|
|
|
sc_append_path(&path, &file_id);
|
2012-05-28 21:15:37 +00:00
|
|
|
senv->file_ref = file_id;
|
|
|
|
senv->flags |= SC_SEC_ENV_FILE_REF_PRESENT;
|
|
|
|
}
|
2018-06-12 06:13:23 +00:00
|
|
|
else if (orig_path.len > 2) {
|
|
|
|
path = orig_path;
|
|
|
|
memcpy(file_id.value, orig_path.value + orig_path.len - 2, 2);
|
2002-06-16 21:18:05 +00:00
|
|
|
file_id.len = 2;
|
2006-11-02 13:58:58 +00:00
|
|
|
file_id.type = SC_PATH_TYPE_FILE_ID;
|
2012-05-28 21:15:37 +00:00
|
|
|
senv->file_ref = file_id;
|
|
|
|
senv->flags |= SC_SEC_ENV_FILE_REF_PRESENT;
|
|
|
|
}
|
2015-12-04 08:22:15 +00:00
|
|
|
else {
|
2012-05-28 21:15:37 +00:00
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "invalid private key path");
|
2002-06-16 21:18:05 +00:00
|
|
|
}
|
2012-05-28 21:15:37 +00:00
|
|
|
|
2002-06-16 21:18:05 +00:00
|
|
|
r = sc_select_file(p15card->card, &path, NULL);
|
2011-03-13 18:11:07 +00:00
|
|
|
LOG_TEST_RET(ctx, r, "sc_select_file() failed");
|
2002-06-16 21:18:05 +00:00
|
|
|
|
2011-03-13 18:11:07 +00:00
|
|
|
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
2002-06-16 21:18:05 +00:00
|
|
|
}
|
2015-12-03 16:51:10 +00:00
|
|
|
|
|
|
|
static int use_key(struct sc_pkcs15_card *p15card,
|
|
|
|
const struct sc_pkcs15_object *obj,
|
|
|
|
sc_security_env_t *senv,
|
|
|
|
int (*card_command)(sc_card_t *card,
|
|
|
|
const u8 * in, size_t inlen,
|
|
|
|
u8 * out, size_t outlen),
|
|
|
|
const u8 * in, size_t inlen, u8 * out, size_t outlen)
|
|
|
|
{
|
|
|
|
int r = SC_SUCCESS;
|
|
|
|
int revalidated_cached_pin = 0;
|
2018-10-01 12:27:09 +00:00
|
|
|
sc_path_t path;
|
|
|
|
LOG_TEST_RET(p15card->card->ctx, get_file_path(obj, &path), "Failed to get key file path.");
|
2015-12-03 16:51:10 +00:00
|
|
|
|
|
|
|
r = sc_lock(p15card->card);
|
|
|
|
LOG_TEST_RET(p15card->card->ctx, r, "sc_lock() failed");
|
|
|
|
|
|
|
|
do {
|
2018-06-12 06:13:23 +00:00
|
|
|
if (path.len != 0 || path.aid.len != 0) {
|
|
|
|
r = select_key_file(p15card, obj, senv);
|
2015-12-03 16:51:10 +00:00
|
|
|
if (r < 0) {
|
|
|
|
sc_log(p15card->card->ctx,
|
|
|
|
"Unable to select private key file");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (r == SC_SUCCESS)
|
|
|
|
r = sc_set_security_env(p15card->card, senv, 0);
|
|
|
|
|
|
|
|
if (r == SC_SUCCESS)
|
|
|
|
r = card_command(p15card->card, in, inlen, out, outlen);
|
|
|
|
|
|
|
|
if (revalidated_cached_pin)
|
|
|
|
/* only re-validate once */
|
|
|
|
break;
|
|
|
|
if (r == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) {
|
|
|
|
r = sc_pkcs15_pincache_revalidate(p15card, obj);
|
|
|
|
if (r < 0)
|
|
|
|
break;
|
|
|
|
revalidated_cached_pin = 1;
|
|
|
|
}
|
|
|
|
} while (revalidated_cached_pin);
|
|
|
|
|
|
|
|
sc_unlock(p15card->card);
|
|
|
|
|
2020-02-24 17:23:23 +00:00
|
|
|
LOG_FUNC_RETURN(p15card->card->ctx, r);
|
2015-12-03 16:51:10 +00:00
|
|
|
}
|
2015-12-04 08:22:15 +00:00
|
|
|
|
|
|
|
static int format_senv(struct sc_pkcs15_card *p15card,
|
|
|
|
const struct sc_pkcs15_object *obj,
|
|
|
|
sc_security_env_t *senv_out, sc_algorithm_info_t **alg_info_out)
|
2001-11-20 22:21:58 +00:00
|
|
|
{
|
2011-03-13 18:11:07 +00:00
|
|
|
sc_context_t *ctx = p15card->card->ctx;
|
2005-01-19 16:17:32 +00:00
|
|
|
const struct sc_pkcs15_prkey_info *prkey = (const struct sc_pkcs15_prkey_info *) obj->data;
|
2018-06-12 06:13:23 +00:00
|
|
|
const struct sc_pkcs15_skey_info *skey = (const struct sc_pkcs15_skey_info *) obj->data;
|
2010-12-01 20:08:42 +00:00
|
|
|
|
2015-12-04 08:22:15 +00:00
|
|
|
memset(senv_out, 0, sizeof(*senv_out));
|
2010-12-01 20:08:42 +00:00
|
|
|
|
2012-05-28 21:15:37 +00:00
|
|
|
/* Card driver should have the access to supported algorithms from 'tokenInfo'. So that
|
2011-01-14 17:12:04 +00:00
|
|
|
* it can get value of card specific 'AlgorithmInfo::algRef'. */
|
2015-12-04 08:22:15 +00:00
|
|
|
memcpy(senv_out->supported_algos, &p15card->tokeninfo->supported_algos, sizeof(senv_out->supported_algos));
|
|
|
|
|
2018-06-12 06:13:23 +00:00
|
|
|
if (!((obj->type & SC_PKCS15_TYPE_CLASS_MASK) == SC_PKCS15_TYPE_PRKEY || (obj->type & SC_PKCS15_TYPE_CLASS_MASK) == SC_PKCS15_TYPE_SKEY))
|
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_NOT_ALLOWED, "This is not a private or secret key");
|
2011-01-14 17:12:04 +00:00
|
|
|
|
2010-08-23 10:32:26 +00:00
|
|
|
/* If the key is not native, we can't operate with it. */
|
2002-04-17 09:06:55 +00:00
|
|
|
if (!prkey->native)
|
2011-03-13 18:11:07 +00:00
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "This key is not native, cannot operate with it");
|
2002-04-17 09:06:55 +00:00
|
|
|
|
2010-12-09 08:23:14 +00:00
|
|
|
switch (obj->type) {
|
|
|
|
case SC_PKCS15_TYPE_PRKEY_RSA:
|
2015-12-04 08:22:15 +00:00
|
|
|
*alg_info_out = sc_card_find_rsa_alg(p15card->card, prkey->modulus_length);
|
|
|
|
if (*alg_info_out == NULL) {
|
2017-03-14 19:02:30 +00:00
|
|
|
sc_log(ctx,
|
|
|
|
"Card does not support RSA with key length %"SC_FORMAT_LEN_SIZE_T"u",
|
|
|
|
prkey->modulus_length);
|
2011-03-13 18:11:07 +00:00
|
|
|
LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
|
2010-12-09 08:23:14 +00:00
|
|
|
}
|
2015-12-04 08:22:15 +00:00
|
|
|
senv_out->algorithm = SC_ALGORITHM_RSA;
|
2010-12-09 08:23:14 +00:00
|
|
|
break;
|
2010-12-01 20:08:42 +00:00
|
|
|
|
2010-12-09 08:23:14 +00:00
|
|
|
case SC_PKCS15_TYPE_PRKEY_GOSTR3410:
|
2015-12-04 08:22:15 +00:00
|
|
|
*alg_info_out = sc_card_find_gostr3410_alg(p15card->card, prkey->modulus_length);
|
2016-02-17 23:13:29 +00:00
|
|
|
if (*alg_info_out == NULL) {
|
2017-03-14 19:02:30 +00:00
|
|
|
sc_log(ctx,
|
|
|
|
"Card does not support GOSTR3410 with key length %"SC_FORMAT_LEN_SIZE_T"u",
|
|
|
|
prkey->modulus_length);
|
2011-03-13 18:11:07 +00:00
|
|
|
LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
|
2010-12-09 08:23:14 +00:00
|
|
|
}
|
2015-12-04 08:22:15 +00:00
|
|
|
senv_out->algorithm = SC_ALGORITHM_GOSTR3410;
|
2010-12-09 08:23:14 +00:00
|
|
|
break;
|
|
|
|
|
2020-02-24 17:29:32 +00:00
|
|
|
case SC_PKCS15_TYPE_PRKEY_EDDSA:
|
|
|
|
*alg_info_out = sc_card_find_eddsa_alg(p15card->card, prkey->field_length, NULL);
|
|
|
|
if (*alg_info_out == NULL) {
|
|
|
|
sc_log(ctx,
|
|
|
|
"Card does not support EDDSA with field_size %"SC_FORMAT_LEN_SIZE_T"u",
|
|
|
|
prkey->field_length);
|
|
|
|
LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
|
|
|
|
}
|
|
|
|
senv_out->algorithm = SC_ALGORITHM_EDDSA;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SC_PKCS15_TYPE_PRKEY_XEDDSA:
|
|
|
|
*alg_info_out = sc_card_find_xeddsa_alg(p15card->card, prkey->field_length, NULL);
|
|
|
|
if (*alg_info_out == NULL) {
|
|
|
|
sc_log(ctx,
|
|
|
|
"Card does not support XEDDSA with field_size %"SC_FORMAT_LEN_SIZE_T"u",
|
|
|
|
prkey->field_length);
|
|
|
|
LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
|
|
|
|
}
|
|
|
|
senv_out->algorithm = SC_ALGORITHM_XEDDSA;
|
|
|
|
break;
|
|
|
|
|
2015-12-04 08:22:15 +00:00
|
|
|
case SC_PKCS15_TYPE_PRKEY_EC:
|
|
|
|
*alg_info_out = sc_card_find_ec_alg(p15card->card, prkey->field_length, NULL);
|
|
|
|
if (*alg_info_out == NULL) {
|
2017-03-14 19:02:30 +00:00
|
|
|
sc_log(ctx,
|
|
|
|
"Card does not support EC with field_size %"SC_FORMAT_LEN_SIZE_T"u",
|
|
|
|
prkey->field_length);
|
2015-12-04 08:22:15 +00:00
|
|
|
LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
|
|
|
|
}
|
|
|
|
senv_out->algorithm = SC_ALGORITHM_EC;
|
|
|
|
|
|
|
|
senv_out->flags |= SC_SEC_ENV_ALG_REF_PRESENT;
|
|
|
|
senv_out->algorithm_ref = prkey->field_length;
|
|
|
|
break;
|
2018-06-12 06:13:23 +00:00
|
|
|
case SC_PKCS15_TYPE_SKEY_GENERIC:
|
|
|
|
if (obj->type == SC_PKCS15_TYPE_SKEY_GENERIC && skey->key_type != CKK_AES)
|
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Key type not supported");
|
|
|
|
*alg_info_out = sc_card_find_alg(p15card->card, SC_ALGORITHM_AES,
|
|
|
|
skey->value_len, NULL);
|
|
|
|
if (*alg_info_out == NULL) {
|
|
|
|
sc_log(ctx,
|
|
|
|
"Card does not support AES with key length %"SC_FORMAT_LEN_SIZE_T"u",
|
|
|
|
skey->value_len);
|
|
|
|
LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
|
|
|
|
}
|
|
|
|
senv_out->algorithm = SC_ALGORITHM_AES;
|
|
|
|
break;
|
2015-12-04 08:22:15 +00:00
|
|
|
/* add other crypto types here */
|
2010-12-09 08:23:14 +00:00
|
|
|
default:
|
2015-12-04 08:22:15 +00:00
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Key type not supported");
|
2002-04-23 08:17:06 +00:00
|
|
|
}
|
2015-12-04 08:22:15 +00:00
|
|
|
senv_out->flags |= SC_SEC_ENV_ALG_PRESENT;
|
2002-01-20 21:20:09 +00:00
|
|
|
|
2004-05-20 09:36:58 +00:00
|
|
|
/* optional keyReference attribute (the default value is -1) */
|
|
|
|
if (prkey->key_reference >= 0) {
|
2015-12-04 08:22:15 +00:00
|
|
|
senv_out->key_ref_len = 1;
|
|
|
|
senv_out->key_ref[0] = prkey->key_reference & 0xFF;
|
|
|
|
senv_out->flags |= SC_SEC_ENV_KEY_REF_PRESENT;
|
2004-05-20 09:36:58 +00:00
|
|
|
}
|
2015-12-04 08:22:15 +00:00
|
|
|
|
|
|
|
return SC_SUCCESS;
|
|
|
|
}
|
2018-06-12 06:13:23 +00:00
|
|
|
|
2015-12-04 08:22:15 +00:00
|
|
|
int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card,
|
|
|
|
const struct sc_pkcs15_object *obj,
|
|
|
|
unsigned long flags,
|
|
|
|
const u8 * in, size_t inlen, u8 *out, size_t outlen)
|
|
|
|
{
|
|
|
|
sc_context_t *ctx = p15card->card->ctx;
|
|
|
|
int r;
|
|
|
|
sc_algorithm_info_t *alg_info = NULL;
|
|
|
|
sc_security_env_t senv;
|
|
|
|
const struct sc_pkcs15_prkey_info *prkey = (const struct sc_pkcs15_prkey_info *) obj->data;
|
|
|
|
unsigned long pad_flags = 0, sec_flags = 0;
|
|
|
|
|
|
|
|
LOG_FUNC_CALLED(ctx);
|
2018-06-12 06:13:23 +00:00
|
|
|
|
2015-12-04 08:22:15 +00:00
|
|
|
if (!(prkey->usage & (SC_PKCS15_PRKEY_USAGE_DECRYPT|SC_PKCS15_PRKEY_USAGE_UNWRAP)))
|
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_NOT_ALLOWED, "This key cannot be used for decryption");
|
|
|
|
|
|
|
|
r = format_senv(p15card, obj, &senv, &alg_info);
|
|
|
|
LOG_TEST_RET(ctx, r, "Could not initialize security environment");
|
|
|
|
senv.operation = SC_SEC_OPERATION_DECIPHER;
|
|
|
|
|
|
|
|
r = sc_get_encoding_flags(ctx, flags, alg_info->flags, &pad_flags, &sec_flags);
|
|
|
|
LOG_TEST_RET(ctx, r, "cannot encode security operation flags");
|
|
|
|
senv.algorithm_flags = sec_flags;
|
2002-01-20 21:20:09 +00:00
|
|
|
|
2015-12-03 16:51:10 +00:00
|
|
|
r = use_key(p15card, obj, &senv, sc_decipher, in, inlen, out,
|
|
|
|
outlen);
|
|
|
|
LOG_TEST_RET(ctx, r, "use_key() failed");
|
2002-04-23 08:17:06 +00:00
|
|
|
|
|
|
|
/* Strip any padding */
|
|
|
|
if (pad_flags & SC_ALGORITHM_RSA_PAD_PKCS1) {
|
2010-04-02 13:33:27 +00:00
|
|
|
size_t s = r;
|
2013-05-22 10:10:26 +00:00
|
|
|
r = sc_pkcs1_strip_02_padding(ctx, out, s, out, &s);
|
2011-03-13 18:11:07 +00:00
|
|
|
LOG_TEST_RET(ctx, r, "Invalid PKCS#1 padding");
|
2002-04-23 08:17:06 +00:00
|
|
|
}
|
|
|
|
|
2011-03-13 18:11:07 +00:00
|
|
|
LOG_FUNC_RETURN(ctx, r);
|
2001-11-21 21:19:58 +00:00
|
|
|
}
|
|
|
|
|
2012-05-28 21:15:37 +00:00
|
|
|
/* derive one key from another. RSA can use decipher, so this is for only ECDH
|
|
|
|
* Since the value may be returned, and the call is expected to provide
|
|
|
|
* the buffer, we used the PKCS#11 convention of outlen == 0 and out == NULL
|
|
|
|
* to indicate that this is a request for the size.
|
|
|
|
* In that case r = 0, and *poutlen = expected size
|
|
|
|
*/
|
|
|
|
int sc_pkcs15_derive(struct sc_pkcs15_card *p15card,
|
2015-12-04 08:22:15 +00:00
|
|
|
const struct sc_pkcs15_object *obj,
|
|
|
|
unsigned long flags,
|
|
|
|
const u8 * in, size_t inlen, u8 *out,
|
2019-06-13 05:54:54 +00:00
|
|
|
size_t *poutlen)
|
2012-05-28 21:15:37 +00:00
|
|
|
{
|
|
|
|
sc_context_t *ctx = p15card->card->ctx;
|
|
|
|
int r;
|
2014-02-25 08:07:09 +00:00
|
|
|
sc_algorithm_info_t *alg_info = NULL;
|
2012-05-28 21:15:37 +00:00
|
|
|
sc_security_env_t senv;
|
|
|
|
const struct sc_pkcs15_prkey_info *prkey = (const struct sc_pkcs15_prkey_info *) obj->data;
|
|
|
|
unsigned long pad_flags = 0, sec_flags = 0;
|
|
|
|
|
|
|
|
LOG_FUNC_CALLED(ctx);
|
|
|
|
|
|
|
|
if (!(prkey->usage & (SC_PKCS15_PRKEY_USAGE_DERIVE)))
|
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_NOT_ALLOWED, "This key cannot be used for derivation");
|
|
|
|
|
|
|
|
switch (obj->type) {
|
|
|
|
case SC_PKCS15_TYPE_PRKEY_EC:
|
2020-02-24 17:29:32 +00:00
|
|
|
case SC_PKCS15_TYPE_PRKEY_XEDDSA:
|
2015-03-29 11:08:01 +00:00
|
|
|
if (out == NULL || *poutlen < (prkey->field_length + 7) / 8) {
|
2015-12-04 08:22:15 +00:00
|
|
|
*poutlen = (prkey->field_length + 7) / 8;
|
|
|
|
r = 0; /* say no data to return */
|
|
|
|
LOG_FUNC_RETURN(ctx, r);
|
2012-05-28 21:15:37 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED,"Key type not supported");
|
|
|
|
}
|
|
|
|
|
2015-12-04 08:22:15 +00:00
|
|
|
r = format_senv(p15card, obj, &senv, &alg_info);
|
|
|
|
LOG_TEST_RET(ctx, r, "Could not initialize security environment");
|
|
|
|
senv.operation = SC_SEC_OPERATION_DERIVE;
|
|
|
|
|
2012-05-28 21:15:37 +00:00
|
|
|
r = sc_get_encoding_flags(ctx, flags, alg_info->flags, &pad_flags, &sec_flags);
|
|
|
|
LOG_TEST_RET(ctx, r, "cannot encode security operation flags");
|
|
|
|
senv.algorithm_flags = sec_flags;
|
|
|
|
|
2015-12-03 16:51:10 +00:00
|
|
|
r = use_key(p15card, obj, &senv, sc_decipher, in, inlen, out,
|
|
|
|
*poutlen);
|
|
|
|
LOG_TEST_RET(ctx, r, "use_key() failed");
|
2012-05-28 21:15:37 +00:00
|
|
|
|
|
|
|
/* If card stores derived key on card, then no data is returned
|
2015-12-04 08:22:15 +00:00
|
|
|
* and the key must be used on the card. */
|
2012-05-28 21:15:37 +00:00
|
|
|
*poutlen = r;
|
|
|
|
LOG_FUNC_RETURN(ctx, r);
|
|
|
|
}
|
|
|
|
|
2017-09-22 12:03:31 +00:00
|
|
|
/*
|
|
|
|
* Unwrap a key into a key object on card.
|
|
|
|
* in holds the wrapped key data
|
|
|
|
* the target file that target_key points to must be created before calling this function
|
2020-08-29 08:34:51 +00:00
|
|
|
* Use pkcs15init to perform the complete unwrapping operation and create the pkcs#15 object for the new key.
|
2017-09-22 12:03:31 +00:00
|
|
|
*/
|
|
|
|
int sc_pkcs15_unwrap(struct sc_pkcs15_card *p15card,
|
|
|
|
const struct sc_pkcs15_object *key,
|
|
|
|
struct sc_pkcs15_object *target_key,
|
|
|
|
unsigned long flags,
|
2018-04-06 11:15:10 +00:00
|
|
|
const u8 * in, size_t inlen,
|
|
|
|
const u8 * param, size_t paramlen)
|
2017-09-22 12:03:31 +00:00
|
|
|
{
|
|
|
|
sc_context_t *ctx = p15card->card->ctx;
|
|
|
|
int r;
|
|
|
|
sc_algorithm_info_t *alg_info = NULL;
|
|
|
|
sc_security_env_t senv;
|
2018-06-12 06:13:23 +00:00
|
|
|
const struct sc_pkcs15_prkey_info *src_prkey = (const struct sc_pkcs15_prkey_info *) key->data;
|
|
|
|
const struct sc_pkcs15_skey_info *src_skey = (const struct sc_pkcs15_skey_info *) key->data;
|
2017-10-04 11:03:16 +00:00
|
|
|
const struct sc_pkcs15_skey_info *tkey = (const struct sc_pkcs15_skey_info *) target_key->data;
|
2017-09-22 12:03:31 +00:00
|
|
|
unsigned long pad_flags = 0, sec_flags = 0;
|
|
|
|
u8 *out = 0;
|
|
|
|
size_t poutlen = 0;
|
2017-10-04 11:03:16 +00:00
|
|
|
sc_path_t path, target_file_id;
|
2018-04-06 11:15:10 +00:00
|
|
|
sc_sec_env_param_t senv_param;
|
2017-09-22 12:03:31 +00:00
|
|
|
|
|
|
|
LOG_FUNC_CALLED(ctx);
|
|
|
|
|
2018-06-12 06:13:23 +00:00
|
|
|
if (key->type == SC_PKCS15_TYPE_PRKEY_RSA) {
|
|
|
|
if (!(src_prkey->usage & (SC_PKCS15_PRKEY_USAGE_UNWRAP)))
|
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_NOT_ALLOWED, "This key cannot be used for unwrapping");
|
2017-09-22 12:03:31 +00:00
|
|
|
}
|
2018-06-12 06:13:23 +00:00
|
|
|
else if ((key->type & SC_PKCS15_TYPE_CLASS_MASK) == SC_PKCS15_TYPE_SKEY) {
|
|
|
|
if (!(src_skey->usage & (SC_PKCS15_PRKEY_USAGE_UNWRAP)))
|
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_NOT_ALLOWED, "This key cannot be used for unwrapping");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Key type not supported");
|
2017-09-22 12:03:31 +00:00
|
|
|
|
|
|
|
r = format_senv(p15card, key, &senv, &alg_info);
|
|
|
|
LOG_TEST_RET(ctx, r, "Could not initialize security environment");
|
|
|
|
senv.operation = SC_SEC_OPERATION_UNWRAP;
|
|
|
|
|
2017-10-04 11:03:16 +00:00
|
|
|
memset(&path, 0, sizeof(sc_path_t));
|
|
|
|
memset(&target_file_id, 0, sizeof(sc_path_t));
|
|
|
|
|
|
|
|
if (!tkey->path.len && tkey->path.aid.len) {
|
|
|
|
/* Target key is a SDO allocated in application DF */
|
2018-04-06 11:15:10 +00:00
|
|
|
target_file_id = tkey->path;
|
2017-10-04 11:03:16 +00:00
|
|
|
}
|
|
|
|
else if (tkey->path.len == 2 && p15card->file_app != NULL) {
|
|
|
|
/* Path is relative to app. DF */
|
|
|
|
path = p15card->file_app->path;
|
|
|
|
target_file_id = tkey->path;
|
|
|
|
sc_append_path(&path, &target_file_id);
|
2018-04-06 11:15:10 +00:00
|
|
|
target_file_id = path;
|
2017-10-04 11:03:16 +00:00
|
|
|
}
|
|
|
|
else if (tkey->path.len > 2) {
|
|
|
|
path = tkey->path;
|
|
|
|
memcpy(target_file_id.value, tkey->path.value + tkey->path.len - 2, 2);
|
|
|
|
target_file_id.len = 2;
|
|
|
|
target_file_id.type = SC_PATH_TYPE_FILE_ID;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "invalid unwrapping target key path");
|
|
|
|
}
|
|
|
|
|
2018-10-01 12:27:09 +00:00
|
|
|
senv_param = (sc_sec_env_param_t) { SC_SEC_ENV_PARAM_TARGET_FILE, &target_file_id, sizeof(target_file_id)};
|
2018-04-06 11:15:10 +00:00
|
|
|
LOG_TEST_RET(ctx, sec_env_add_param(&senv, &senv_param), "failed to add target file path to security environment");
|
|
|
|
|
2018-06-12 06:13:23 +00:00
|
|
|
r = sc_get_encoding_flags(ctx, flags, alg_info->flags, &pad_flags, &sec_flags);
|
|
|
|
LOG_TEST_RET(ctx, r, "cannot encode security operation flags");
|
|
|
|
senv.algorithm_flags = sec_flags;
|
|
|
|
|
2018-05-29 13:23:57 +00:00
|
|
|
if ((sec_flags & (SC_ALGORITHM_AES_CBC | SC_ALGORITHM_AES_CBC_PAD)) > 0) {
|
2018-10-01 12:27:09 +00:00
|
|
|
senv_param = (sc_sec_env_param_t) { SC_SEC_ENV_PARAM_IV, (void*) param, paramlen };
|
2018-04-06 11:15:10 +00:00
|
|
|
LOG_TEST_RET(ctx, sec_env_add_param(&senv, &senv_param), "failed to add IV to security environment");
|
|
|
|
}
|
|
|
|
|
2018-06-12 06:13:23 +00:00
|
|
|
r = use_key(p15card, key, &senv, sc_unwrap, in, inlen, out,
|
|
|
|
poutlen);
|
|
|
|
LOG_TEST_RET(ctx, r, "use_key() failed");
|
2017-10-04 11:03:16 +00:00
|
|
|
|
2018-06-12 06:13:23 +00:00
|
|
|
LOG_FUNC_RETURN(ctx, r);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Wrap a key and return a cryptogram
|
|
|
|
* <key> is the wrapping key
|
|
|
|
* <target_key> is the key to be wrapped
|
|
|
|
* wrapped data is returned in <cryptogram>
|
|
|
|
*/
|
|
|
|
int sc_pkcs15_wrap(struct sc_pkcs15_card *p15card,
|
|
|
|
const struct sc_pkcs15_object *key,
|
|
|
|
struct sc_pkcs15_object *target_key,
|
|
|
|
unsigned long flags,
|
2019-06-13 05:54:54 +00:00
|
|
|
u8 *cryptogram, size_t *crgram_len,
|
|
|
|
const u8 *param, size_t paramlen) {
|
2018-06-12 06:13:23 +00:00
|
|
|
sc_context_t *ctx = p15card->card->ctx;
|
|
|
|
int r;
|
|
|
|
sc_algorithm_info_t *alg_info = NULL;
|
|
|
|
sc_security_env_t senv;
|
|
|
|
const struct sc_pkcs15_prkey_info *src_prkey = (const struct sc_pkcs15_prkey_info *) key->data;
|
|
|
|
const struct sc_pkcs15_skey_info *src_skey = (const struct sc_pkcs15_skey_info *) key->data;
|
|
|
|
const struct sc_pkcs15_prkey_info *target_prkey = (const struct sc_pkcs15_prkey_info *) target_key->data;
|
|
|
|
const struct sc_pkcs15_skey_info *target_skey = (const struct sc_pkcs15_skey_info *) target_key->data;
|
|
|
|
unsigned long pad_flags = 0, sec_flags = 0;
|
|
|
|
sc_path_t tkey_path;
|
|
|
|
sc_path_t path, target_file_id;
|
2018-04-06 11:15:10 +00:00
|
|
|
sc_sec_env_param_t senv_param;
|
2018-06-12 06:13:23 +00:00
|
|
|
|
|
|
|
LOG_FUNC_CALLED(ctx);
|
|
|
|
|
|
|
|
switch (key->type) {
|
|
|
|
case SC_PKCS15_TYPE_PRKEY_RSA:
|
|
|
|
if (!(src_prkey->usage & (SC_PKCS15_PRKEY_USAGE_WRAP)))
|
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_NOT_ALLOWED, "This key cannot be used for wrapping");
|
|
|
|
break;
|
|
|
|
case SC_PKCS15_TYPE_SKEY_DES:
|
|
|
|
case SC_PKCS15_TYPE_SKEY_3DES:
|
|
|
|
case SC_PKCS15_TYPE_SKEY_GENERIC:
|
|
|
|
if (!(src_skey->usage & (SC_PKCS15_PRKEY_USAGE_WRAP)))
|
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_NOT_ALLOWED, "This key cannot be used for wrapping");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Wrapping key type not supported");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(target_key->type == SC_PKCS15_TYPE_PRKEY_RSA ||
|
2018-06-12 05:58:45 +00:00
|
|
|
(target_key->type & SC_PKCS15_TYPE_CLASS_MASK) == SC_PKCS15_TYPE_SKEY)) {
|
2018-06-12 06:13:23 +00:00
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Target key type not supported");
|
|
|
|
}
|
|
|
|
|
|
|
|
r = format_senv(p15card, key, &senv, &alg_info);
|
|
|
|
LOG_TEST_RET(ctx, r, "Could not initialize security environment");
|
|
|
|
senv.operation = SC_SEC_OPERATION_WRAP;
|
|
|
|
|
|
|
|
memset(&path, 0, sizeof (sc_path_t));
|
|
|
|
memset(&target_file_id, 0, sizeof (sc_path_t));
|
|
|
|
|
|
|
|
switch (target_key->type) {
|
|
|
|
case SC_PKCS15_TYPE_PRKEY_RSA:
|
2018-10-01 12:27:09 +00:00
|
|
|
tkey_path = target_prkey->path;
|
|
|
|
break;
|
|
|
|
default: /* we already know it is a secret key */
|
|
|
|
tkey_path = target_skey->path;
|
|
|
|
break;
|
2018-06-12 06:13:23 +00:00
|
|
|
}
|
|
|
|
|
2018-04-06 11:15:10 +00:00
|
|
|
if (!tkey_path.len && tkey_path.aid.len) {
|
2018-06-12 06:13:23 +00:00
|
|
|
/* Target key is a SDO allocated in application DF */
|
2018-04-06 11:15:10 +00:00
|
|
|
target_file_id = tkey_path;
|
2018-06-12 06:13:23 +00:00
|
|
|
} else if (tkey_path.len == 2 && p15card->file_app != NULL) {
|
|
|
|
/* Path is relative to app. DF */
|
|
|
|
path = p15card->file_app->path;
|
|
|
|
target_file_id = tkey_path;
|
|
|
|
sc_append_path(&path, &target_file_id);
|
2018-04-06 11:15:10 +00:00
|
|
|
target_file_id = path;
|
2018-06-12 06:13:23 +00:00
|
|
|
} else if (tkey_path.len > 2) {
|
2018-04-06 11:15:10 +00:00
|
|
|
/*path = tkey_path;*/
|
2018-06-12 06:13:23 +00:00
|
|
|
memcpy(target_file_id.value, tkey_path.value + tkey_path.len - 2, 2);
|
|
|
|
target_file_id.len = 2;
|
|
|
|
target_file_id.type = SC_PATH_TYPE_FILE_ID;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "invalid unwrapping target key path");
|
|
|
|
}
|
2018-10-01 12:27:09 +00:00
|
|
|
senv_param = (sc_sec_env_param_t) { SC_SEC_ENV_PARAM_TARGET_FILE, &target_file_id, sizeof(target_file_id)};
|
2018-04-06 11:15:10 +00:00
|
|
|
LOG_TEST_RET(ctx, sec_env_add_param(&senv, &senv_param), "failed to add target file path to security environment");
|
2017-10-04 11:03:16 +00:00
|
|
|
|
2017-09-22 12:03:31 +00:00
|
|
|
r = sc_get_encoding_flags(ctx, flags, alg_info->flags, &pad_flags, &sec_flags);
|
|
|
|
LOG_TEST_RET(ctx, r, "cannot encode security operation flags");
|
|
|
|
senv.algorithm_flags = sec_flags;
|
|
|
|
|
2018-04-06 11:15:10 +00:00
|
|
|
if ((sec_flags & (SC_ALGORITHM_AES_CBC | SC_ALGORITHM_AES_CBC_PAD)) > 0) {
|
2018-10-18 13:56:06 +00:00
|
|
|
senv_param = (sc_sec_env_param_t) { SC_SEC_ENV_PARAM_IV, (void*) param, paramlen };
|
|
|
|
LOG_TEST_RET(ctx, sec_env_add_param(&senv, &senv_param), "failed to add IV to security environment");
|
2018-04-06 11:15:10 +00:00
|
|
|
}
|
|
|
|
|
2019-06-13 05:54:54 +00:00
|
|
|
r = use_key(p15card, key, &senv, sc_wrap, NULL, 0, cryptogram, crgram_len ? *crgram_len : 0);
|
2018-04-06 11:15:10 +00:00
|
|
|
|
2019-06-13 05:54:54 +00:00
|
|
|
if (r > -1 && crgram_len) {
|
|
|
|
if (*crgram_len < (size_t) r) {
|
|
|
|
*crgram_len = r;
|
|
|
|
if (cryptogram != NULL) /* if NULL, return success and required buffer length by PKCS#11 convention */
|
2018-10-18 13:56:06 +00:00
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_BUFFER_TOO_SMALL, "Buffer too small to hold the wrapped key.");
|
|
|
|
}
|
2019-06-13 05:54:54 +00:00
|
|
|
*crgram_len = r;
|
2018-10-18 13:56:06 +00:00
|
|
|
}
|
2017-09-22 12:03:31 +00:00
|
|
|
|
|
|
|
LOG_FUNC_RETURN(ctx, r);
|
|
|
|
}
|
|
|
|
|
2018-06-12 06:13:23 +00:00
|
|
|
|
2010-03-13 22:52:51 +00:00
|
|
|
/* copied from pkcs15-cardos.c */
|
|
|
|
#define USAGE_ANY_SIGN (SC_PKCS15_PRKEY_USAGE_SIGN|\
|
|
|
|
SC_PKCS15_PRKEY_USAGE_NONREPUDIATION)
|
|
|
|
#define USAGE_ANY_DECIPHER (SC_PKCS15_PRKEY_USAGE_DECRYPT|\
|
|
|
|
SC_PKCS15_PRKEY_USAGE_UNWRAP)
|
|
|
|
|
2001-11-21 21:19:58 +00:00
|
|
|
int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
|
2002-03-08 05:59:57 +00:00
|
|
|
const struct sc_pkcs15_object *obj,
|
|
|
|
unsigned long flags, const u8 *in, size_t inlen,
|
2002-01-20 21:20:09 +00:00
|
|
|
u8 *out, size_t outlen)
|
2001-11-21 21:19:58 +00:00
|
|
|
{
|
2011-03-13 18:11:07 +00:00
|
|
|
sc_context_t *ctx = p15card->card->ctx;
|
2001-11-21 21:19:58 +00:00
|
|
|
int r;
|
2005-03-08 20:59:35 +00:00
|
|
|
sc_security_env_t senv;
|
|
|
|
sc_algorithm_info_t *alg_info;
|
2005-01-19 16:17:32 +00:00
|
|
|
const struct sc_pkcs15_prkey_info *prkey = (const struct sc_pkcs15_prkey_info *) obj->data;
|
2012-11-28 10:52:43 +00:00
|
|
|
u8 buf[1024], *tmp;
|
2010-12-01 20:08:42 +00:00
|
|
|
size_t modlen;
|
2007-02-02 22:15:14 +00:00
|
|
|
unsigned long pad_flags = 0, sec_flags = 0;
|
2002-01-20 21:20:09 +00:00
|
|
|
|
2011-03-13 18:11:07 +00:00
|
|
|
LOG_FUNC_CALLED(ctx);
|
2002-04-17 09:06:55 +00:00
|
|
|
|
2003-04-23 08:47:57 +00:00
|
|
|
if (!(prkey->usage & (SC_PKCS15_PRKEY_USAGE_SIGN|SC_PKCS15_PRKEY_USAGE_SIGNRECOVER|
|
2015-12-04 08:22:15 +00:00
|
|
|
SC_PKCS15_PRKEY_USAGE_NONREPUDIATION)))
|
2011-03-13 18:11:07 +00:00
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_NOT_ALLOWED, "This key cannot be used for signing");
|
2003-04-17 12:38:08 +00:00
|
|
|
|
2015-12-04 08:22:15 +00:00
|
|
|
r = format_senv(p15card, obj, &senv, &alg_info);
|
|
|
|
LOG_TEST_RET(ctx, r, "Could not initialize security environment");
|
|
|
|
senv.operation = SC_SEC_OPERATION_SIGN;
|
|
|
|
|
2010-12-01 20:08:42 +00:00
|
|
|
switch (obj->type) {
|
|
|
|
case SC_PKCS15_TYPE_PRKEY_RSA:
|
Add support for PSS padding to RSA signatures
A card driver may declare support for computing the padding on the card,
or else the padding will be applied locally in padding.c. All five
PKCS11 PSS mechanisms are supported, for signature and verification.
There are a few limits on what we choose to support, in particular I
don't see a need for arbitrary combinations of MGF hash, data hash, and
salt length, so I've restricted it (for the user's benefit) to the only
cases that really matter, where salt_len = hash_len and the same hash is
used for the MGF and data hashing.
------------------------------------------------------------------------
Reworked and extended in 2018 by Jakub Jelen <jjelen@redhat.com> against
current OpenSC master, to actually work with existing PIV cards:
* extended of missing mechanisms (SHA224, possibility to select MGF1)
* compatibility with OpenSSL 1.1+
* Removed the ANSI padding
* Formatting cleanup, error checking
Based on the original work from
https://github.com/NWilson/OpenSC/commit/42f3199e66
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
2015-08-25 11:45:27 +00:00
|
|
|
modlen = (prkey->modulus_length + 7) / 8;
|
2010-12-01 20:08:42 +00:00
|
|
|
break;
|
2010-12-09 08:23:14 +00:00
|
|
|
case SC_PKCS15_TYPE_PRKEY_GOSTR3410:
|
|
|
|
modlen = (prkey->modulus_length + 7) / 8 * 2;
|
|
|
|
break;
|
2010-12-01 20:08:42 +00:00
|
|
|
case SC_PKCS15_TYPE_PRKEY_EC:
|
2020-02-24 17:29:32 +00:00
|
|
|
case SC_PKCS15_TYPE_PRKEY_EDDSA:
|
|
|
|
case SC_PKCS15_TYPE_PRKEY_XEDDSA:
|
|
|
|
modlen = ((prkey->field_length +7) / 8) * 2; /* 2*nLen */
|
2010-12-01 20:08:42 +00:00
|
|
|
break;
|
|
|
|
default:
|
2011-03-13 18:11:07 +00:00
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Key type not supported");
|
2002-03-08 05:59:57 +00:00
|
|
|
}
|
2002-04-11 15:13:09 +00:00
|
|
|
|
|
|
|
/* Probably never happens, but better make sure */
|
2007-02-02 22:15:14 +00:00
|
|
|
if (inlen > sizeof(buf) || outlen < modlen)
|
2011-03-13 18:11:07 +00:00
|
|
|
LOG_FUNC_RETURN(ctx, SC_ERROR_BUFFER_TOO_SMALL);
|
|
|
|
|
2002-03-08 05:59:57 +00:00
|
|
|
memcpy(buf, in, inlen);
|
2011-05-29 19:23:18 +00:00
|
|
|
|
|
|
|
/* revert data to sign when signing with the GOST key.
|
|
|
|
* TODO: can it be confirmed by the GOST standard?
|
|
|
|
* TODO: tested with RuTokenECP, has to be validated for RuToken. */
|
2018-06-12 06:13:23 +00:00
|
|
|
if (obj->type == SC_PKCS15_TYPE_PRKEY_GOSTR3410) {
|
2016-03-07 17:30:56 +00:00
|
|
|
r = sc_mem_reverse(buf, inlen);
|
|
|
|
LOG_TEST_RET(ctx, r, "Reverse memory error");
|
|
|
|
}
|
2011-05-29 19:23:18 +00:00
|
|
|
|
2007-02-02 22:15:14 +00:00
|
|
|
tmp = buf;
|
2003-11-23 16:11:32 +00:00
|
|
|
|
|
|
|
/* flags: the requested algo
|
2012-05-28 21:15:37 +00:00
|
|
|
* algo_info->flags: what is supported by the card
|
2003-11-23 16:11:32 +00:00
|
|
|
* senv.algorithm_flags: what the card will have to do */
|
|
|
|
|
2010-03-13 22:52:51 +00:00
|
|
|
/* if the card has SC_ALGORITHM_NEED_USAGE set, and the
|
2015-12-04 08:22:15 +00:00
|
|
|
* key is for signing and decryption, we need to emulate signing */
|
2010-03-13 22:52:51 +00:00
|
|
|
|
2011-03-13 18:11:07 +00:00
|
|
|
sc_log(ctx, "supported algorithm flags 0x%X, private key usage 0x%X", alg_info->flags, prkey->usage);
|
2021-05-15 18:41:36 +00:00
|
|
|
if (obj->type == SC_PKCS15_TYPE_PRKEY_RSA) {
|
2020-12-21 18:02:28 +00:00
|
|
|
if ((alg_info->flags & SC_ALGORITHM_NEED_USAGE) &&
|
|
|
|
((prkey->usage & USAGE_ANY_SIGN) &&
|
|
|
|
(prkey->usage & USAGE_ANY_DECIPHER)) ) {
|
|
|
|
size_t tmplen = sizeof(buf);
|
|
|
|
if (flags & SC_ALGORITHM_RSA_RAW) {
|
|
|
|
r = sc_pkcs15_decipher(p15card, obj, flags, in, inlen, out, outlen);
|
|
|
|
LOG_FUNC_RETURN(ctx, r);
|
|
|
|
}
|
|
|
|
if (modlen > tmplen)
|
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_NOT_ALLOWED, "Buffer too small, needs recompile!");
|
2011-03-13 18:11:07 +00:00
|
|
|
|
2020-12-21 18:02:28 +00:00
|
|
|
/* XXX Assuming RSA key here */
|
|
|
|
r = sc_pkcs1_encode(ctx, flags, in, inlen, buf, &tmplen, prkey->modulus_length);
|
2010-03-13 22:52:51 +00:00
|
|
|
|
2020-12-21 18:02:28 +00:00
|
|
|
/* no padding needed - already done */
|
|
|
|
flags &= ~SC_ALGORITHM_RSA_PADS;
|
|
|
|
/* instead use raw rsa */
|
|
|
|
flags |= SC_ALGORITHM_RSA_RAW;
|
2010-03-13 22:52:51 +00:00
|
|
|
|
2020-12-21 18:02:28 +00:00
|
|
|
LOG_TEST_RET(ctx, r, "Unable to add padding");
|
2011-03-13 18:11:07 +00:00
|
|
|
|
2020-12-21 18:02:28 +00:00
|
|
|
r = sc_pkcs15_decipher(p15card, obj, flags, buf, modlen, out, outlen);
|
|
|
|
LOG_FUNC_RETURN(ctx, r);
|
|
|
|
}
|
2012-05-28 21:15:37 +00:00
|
|
|
|
2010-03-13 22:52:51 +00:00
|
|
|
|
2020-12-21 18:02:28 +00:00
|
|
|
/* If the card doesn't support the requested algorithm, we normally add the
|
|
|
|
* padding here in software and ask the card to do a raw signature. There's
|
|
|
|
* one exception to that, where we might be able to get the signature to
|
|
|
|
* succeed by stripping padding if the card only offers higher-level
|
|
|
|
* signature operations. The only thing we can strip is the DigestInfo
|
|
|
|
* block from PKCS1 padding. */
|
|
|
|
if ((flags == (SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE)) &&
|
|
|
|
!(alg_info->flags & SC_ALGORITHM_RSA_RAW) &&
|
|
|
|
!(alg_info->flags & SC_ALGORITHM_RSA_HASH_NONE) &&
|
|
|
|
(alg_info->flags & SC_ALGORITHM_RSA_PAD_PKCS1)) {
|
|
|
|
unsigned int algo;
|
|
|
|
size_t tmplen = sizeof(buf);
|
|
|
|
|
|
|
|
r = sc_pkcs1_strip_digest_info_prefix(&algo, tmp, inlen, tmp, &tmplen);
|
|
|
|
if (r != SC_SUCCESS || algo == SC_ALGORITHM_RSA_HASH_NONE) {
|
|
|
|
sc_mem_clear(buf, sizeof(buf));
|
|
|
|
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
|
|
|
|
}
|
|
|
|
flags &= ~SC_ALGORITHM_RSA_HASH_NONE;
|
|
|
|
flags |= algo;
|
|
|
|
inlen = tmplen;
|
|
|
|
}
|
|
|
|
}
|
2011-03-13 18:11:07 +00:00
|
|
|
|
2020-12-21 18:02:28 +00:00
|
|
|
|
|
|
|
/* ECDSA sofware hash has already been done, or is not needed, or card will do hash */
|
|
|
|
/* if card can not do the hash, will use SC_ALGORITHM_ECDSA_RAW */
|
|
|
|
if (obj->type == SC_PKCS15_TYPE_PRKEY_EC) {
|
|
|
|
if ((alg_info->flags & SC_ALGORITHM_ECDSA_RAW)
|
|
|
|
&& !(flags & SC_ALGORITHM_ECDSA_HASHES & alg_info->flags)) {
|
|
|
|
sc_log(ctx, "ECDSA using SC_ALGORITHM_ECDSA_RAW flags before 0x%8.8lx", flags);
|
|
|
|
flags |= SC_ALGORITHM_ECDSA_RAW;
|
|
|
|
flags &= ~SC_ALGORITHM_ECDSA_HASHES;
|
2007-02-02 22:15:14 +00:00
|
|
|
}
|
2003-11-23 16:11:32 +00:00
|
|
|
}
|
|
|
|
|
2007-02-02 22:15:14 +00:00
|
|
|
r = sc_get_encoding_flags(ctx, flags, alg_info->flags, &pad_flags, &sec_flags);
|
|
|
|
if (r != SC_SUCCESS) {
|
|
|
|
sc_mem_clear(buf, sizeof(buf));
|
2011-03-13 18:11:07 +00:00
|
|
|
LOG_FUNC_RETURN(ctx, r);
|
2002-03-08 05:59:57 +00:00
|
|
|
}
|
2020-12-21 18:02:28 +00:00
|
|
|
/* senv now has flags card or driver will do */
|
2007-02-02 22:15:14 +00:00
|
|
|
senv.algorithm_flags = sec_flags;
|
2003-11-23 16:11:32 +00:00
|
|
|
|
2017-03-14 19:02:30 +00:00
|
|
|
sc_log(ctx, "DEE flags:0x%8.8lx alg_info->flags:0x%8.8x pad:0x%8.8lx sec:0x%8.8lx",
|
2010-12-01 20:08:42 +00:00
|
|
|
flags, alg_info->flags, pad_flags, sec_flags);
|
|
|
|
|
2007-02-02 22:15:14 +00:00
|
|
|
/* add the padding bytes (if necessary) */
|
|
|
|
if (pad_flags != 0) {
|
Add support for PSS padding to RSA signatures
A card driver may declare support for computing the padding on the card,
or else the padding will be applied locally in padding.c. All five
PKCS11 PSS mechanisms are supported, for signature and verification.
There are a few limits on what we choose to support, in particular I
don't see a need for arbitrary combinations of MGF hash, data hash, and
salt length, so I've restricted it (for the user's benefit) to the only
cases that really matter, where salt_len = hash_len and the same hash is
used for the MGF and data hashing.
------------------------------------------------------------------------
Reworked and extended in 2018 by Jakub Jelen <jjelen@redhat.com> against
current OpenSC master, to actually work with existing PIV cards:
* extended of missing mechanisms (SHA224, possibility to select MGF1)
* compatibility with OpenSSL 1.1+
* Removed the ANSI padding
* Formatting cleanup, error checking
Based on the original work from
https://github.com/NWilson/OpenSC/commit/42f3199e66
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
2015-08-25 11:45:27 +00:00
|
|
|
size_t tmplen = sizeof(buf);
|
2011-03-13 18:11:07 +00:00
|
|
|
|
Add support for PSS padding to RSA signatures
A card driver may declare support for computing the padding on the card,
or else the padding will be applied locally in padding.c. All five
PKCS11 PSS mechanisms are supported, for signature and verification.
There are a few limits on what we choose to support, in particular I
don't see a need for arbitrary combinations of MGF hash, data hash, and
salt length, so I've restricted it (for the user's benefit) to the only
cases that really matter, where salt_len = hash_len and the same hash is
used for the MGF and data hashing.
------------------------------------------------------------------------
Reworked and extended in 2018 by Jakub Jelen <jjelen@redhat.com> against
current OpenSC master, to actually work with existing PIV cards:
* extended of missing mechanisms (SHA224, possibility to select MGF1)
* compatibility with OpenSSL 1.1+
* Removed the ANSI padding
* Formatting cleanup, error checking
Based on the original work from
https://github.com/NWilson/OpenSC/commit/42f3199e66
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
2015-08-25 11:45:27 +00:00
|
|
|
/* XXX Assuming RSA key here */
|
|
|
|
r = sc_pkcs1_encode(ctx, pad_flags, tmp, inlen, tmp, &tmplen,
|
|
|
|
prkey->modulus_length);
|
2018-11-23 20:54:14 +00:00
|
|
|
LOG_TEST_RET(ctx, r, "Unable to add padding");
|
Add support for PSS padding to RSA signatures
A card driver may declare support for computing the padding on the card,
or else the padding will be applied locally in padding.c. All five
PKCS11 PSS mechanisms are supported, for signature and verification.
There are a few limits on what we choose to support, in particular I
don't see a need for arbitrary combinations of MGF hash, data hash, and
salt length, so I've restricted it (for the user's benefit) to the only
cases that really matter, where salt_len = hash_len and the same hash is
used for the MGF and data hashing.
------------------------------------------------------------------------
Reworked and extended in 2018 by Jakub Jelen <jjelen@redhat.com> against
current OpenSC master, to actually work with existing PIV cards:
* extended of missing mechanisms (SHA224, possibility to select MGF1)
* compatibility with OpenSSL 1.1+
* Removed the ANSI padding
* Formatting cleanup, error checking
Based on the original work from
https://github.com/NWilson/OpenSC/commit/42f3199e66
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
2015-08-25 11:45:27 +00:00
|
|
|
inlen = tmplen;
|
2012-05-28 21:15:37 +00:00
|
|
|
}
|
|
|
|
else if ( senv.algorithm == SC_ALGORITHM_RSA &&
|
Add support for PSS padding to RSA signatures
A card driver may declare support for computing the padding on the card,
or else the padding will be applied locally in padding.c. All five
PKCS11 PSS mechanisms are supported, for signature and verification.
There are a few limits on what we choose to support, in particular I
don't see a need for arbitrary combinations of MGF hash, data hash, and
salt length, so I've restricted it (for the user's benefit) to the only
cases that really matter, where salt_len = hash_len and the same hash is
used for the MGF and data hashing.
------------------------------------------------------------------------
Reworked and extended in 2018 by Jakub Jelen <jjelen@redhat.com> against
current OpenSC master, to actually work with existing PIV cards:
* extended of missing mechanisms (SHA224, possibility to select MGF1)
* compatibility with OpenSSL 1.1+
* Removed the ANSI padding
* Formatting cleanup, error checking
Based on the original work from
https://github.com/NWilson/OpenSC/commit/42f3199e66
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
2015-08-25 11:45:27 +00:00
|
|
|
(flags & SC_ALGORITHM_RSA_PADS) == SC_ALGORITHM_RSA_PAD_NONE) {
|
2007-02-02 22:15:14 +00:00
|
|
|
/* Add zero-padding if input is shorter than the modulus */
|
|
|
|
if (inlen < modlen) {
|
|
|
|
if (modlen > sizeof(buf))
|
2003-05-13 20:24:24 +00:00
|
|
|
return SC_ERROR_BUFFER_TOO_SMALL;
|
2007-02-02 22:15:14 +00:00
|
|
|
memmove(tmp+modlen-inlen, tmp, inlen);
|
|
|
|
memset(tmp, 0, modlen-inlen);
|
2003-05-13 20:24:24 +00:00
|
|
|
}
|
2011-05-20 11:24:46 +00:00
|
|
|
inlen = modlen;
|
2002-03-08 05:59:57 +00:00
|
|
|
}
|
2016-04-25 08:29:02 +00:00
|
|
|
/* PKCS#11 MECHANISMS V2.30: 6.3.1 EC Signatures
|
|
|
|
* If the length of the hash value is larger than the bit length of n, only
|
|
|
|
* the leftmost bits of the hash up to the length of n will be used. Any
|
|
|
|
* truncation is done by the token.
|
2020-12-21 18:02:28 +00:00
|
|
|
* But if card is going to do the hash, pass in all the data
|
2016-04-25 08:29:02 +00:00
|
|
|
*/
|
|
|
|
else if (senv.algorithm == SC_ALGORITHM_EC &&
|
2021-04-01 15:51:27 +00:00
|
|
|
(senv.algorithm_flags & SC_ALGORITHM_ECDSA_HASHES) == 0) {
|
2016-04-25 08:29:02 +00:00
|
|
|
inlen = MIN(inlen, (prkey->field_length+7)/8);
|
|
|
|
}
|
|
|
|
|
2003-11-23 16:11:32 +00:00
|
|
|
|
2015-12-03 16:51:10 +00:00
|
|
|
r = use_key(p15card, obj, &senv, sc_compute_signature, tmp, inlen,
|
|
|
|
out, outlen);
|
|
|
|
LOG_TEST_RET(ctx, r, "use_key() failed");
|
2018-04-09 01:15:13 +00:00
|
|
|
|
|
|
|
/* Some cards may return RSA signature as integer without leading zero bytes */
|
|
|
|
/* Already know outlen >= modlen and r >= 0 */
|
|
|
|
if (obj->type == SC_PKCS15_TYPE_PRKEY_RSA && (unsigned)r < modlen) {
|
|
|
|
memmove(out + modlen - r, out, r);
|
|
|
|
memset(out, 0, modlen - r);
|
|
|
|
r = modlen;
|
|
|
|
}
|
|
|
|
|
2005-09-17 10:44:45 +00:00
|
|
|
sc_mem_clear(buf, sizeof(buf));
|
2001-11-21 21:19:58 +00:00
|
|
|
|
2011-03-13 18:11:07 +00:00
|
|
|
LOG_FUNC_RETURN(ctx, r);
|
2001-11-20 22:21:58 +00:00
|
|
|
}
|