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"
|
|
|
|
|
2002-06-16 21:18:05 +00:00
|
|
|
static int select_key_file(struct sc_pkcs15_card *p15card,
|
2015-12-04 08:22:15 +00:00
|
|
|
const struct sc_pkcs15_prkey_info *prkey,
|
|
|
|
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;
|
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);
|
|
|
|
|
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 */
|
2015-12-04 08:22:15 +00:00
|
|
|
if (!prkey->path.len && prkey->path.aid.len) {
|
2012-05-28 21:15:37 +00:00
|
|
|
/* Private key is a SDO allocated in application DF */
|
|
|
|
path = prkey->path;
|
|
|
|
}
|
|
|
|
else if (prkey->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;
|
|
|
|
file_id = prkey->path;
|
|
|
|
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;
|
|
|
|
}
|
2015-12-04 08:22:15 +00:00
|
|
|
else if (prkey->path.len > 2) {
|
2002-06-16 21:18:05 +00:00
|
|
|
path = prkey->path;
|
|
|
|
memcpy(file_id.value, prkey->path.value + prkey->path.len - 2, 2);
|
|
|
|
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;
|
|
|
|
const struct sc_pkcs15_prkey_info *prkey = (const struct sc_pkcs15_prkey_info *) obj->data;
|
|
|
|
|
|
|
|
r = sc_lock(p15card->card);
|
|
|
|
LOG_TEST_RET(p15card->card->ctx, r, "sc_lock() failed");
|
|
|
|
|
|
|
|
do {
|
|
|
|
if (prkey->path.len != 0 || prkey->path.aid.len != 0) {
|
|
|
|
r = select_key_file(p15card, prkey, senv);
|
|
|
|
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);
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
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;
|
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));
|
|
|
|
|
|
|
|
if ((obj->type & SC_PKCS15_TYPE_CLASS_MASK) != SC_PKCS15_TYPE_PRKEY)
|
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_NOT_ALLOWED, "This is not a private 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;
|
|
|
|
|
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;
|
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
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,
|
|
|
|
unsigned long *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:
|
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
|
|
|
|
|
|
|
/* Strip any padding */
|
|
|
|
if (pad_flags & SC_ALGORITHM_RSA_PAD_PKCS1) {
|
|
|
|
size_t s = r;
|
2013-05-22 10:10:26 +00:00
|
|
|
r = sc_pkcs1_strip_02_padding(ctx, out, s, out, &s);
|
2012-05-28 21:15:37 +00:00
|
|
|
LOG_TEST_RET(ctx, r, "Invalid PKCS#1 padding");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
}
|
|
|
|
|
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:
|
|
|
|
modlen = prkey->modulus_length / 8;
|
|
|
|
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:
|
|
|
|
modlen = ((prkey->field_length +7) / 8) * 2; /* 2*nLen */
|
|
|
|
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. */
|
2016-03-07 17:30:56 +00:00
|
|
|
if (obj->type == SC_PKCS15_TYPE_PRKEY_GOSTR3410) {
|
|
|
|
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-12-01 20:08:42 +00:00
|
|
|
/* TODO: -DEE assume only RSA keys will ever use _NEED_USAGE */
|
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);
|
2012-05-28 21:15:37 +00:00
|
|
|
if ((alg_info->flags & SC_ALGORITHM_NEED_USAGE) &&
|
2010-03-13 22:52:51 +00:00
|
|
|
((prkey->usage & USAGE_ANY_SIGN) &&
|
|
|
|
(prkey->usage & USAGE_ANY_DECIPHER)) ) {
|
|
|
|
size_t tmplen = sizeof(buf);
|
|
|
|
if (flags & SC_ALGORITHM_RSA_RAW) {
|
2011-03-13 18:11:07 +00:00
|
|
|
r = sc_pkcs15_decipher(p15card, obj,flags, in, inlen, out, outlen);
|
|
|
|
LOG_FUNC_RETURN(ctx, r);
|
2010-03-13 22:52:51 +00:00
|
|
|
}
|
2011-03-13 18:11:07 +00:00
|
|
|
if (modlen > tmplen)
|
|
|
|
LOG_TEST_RET(ctx, SC_ERROR_NOT_ALLOWED, "Buffer too small, needs recompile!");
|
|
|
|
|
2010-03-13 22:52:51 +00:00
|
|
|
r = sc_pkcs1_encode(ctx, flags, in, inlen, buf, &tmplen, modlen);
|
|
|
|
|
|
|
|
/* no padding needed - already done */
|
|
|
|
flags &= ~SC_ALGORITHM_RSA_PADS;
|
|
|
|
/* instead use raw rsa */
|
|
|
|
flags |= SC_ALGORITHM_RSA_RAW;
|
|
|
|
|
2011-03-13 18:11:07 +00:00
|
|
|
LOG_TEST_RET(ctx, r, "Unable to add padding");
|
|
|
|
|
|
|
|
r = sc_pkcs15_decipher(p15card, obj,flags, buf, modlen, out, outlen);
|
|
|
|
LOG_FUNC_RETURN(ctx, r);
|
2010-03-13 22:52:51 +00:00
|
|
|
}
|
2012-05-28 21:15:37 +00:00
|
|
|
|
2010-03-13 22:52:51 +00:00
|
|
|
|
2003-11-23 16:11:32 +00:00
|
|
|
/* If the card doesn't support the requested algorithm, see if we
|
|
|
|
* can strip the input so a more restrictive algo can be used */
|
|
|
|
if ((flags == (SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE)) &&
|
2015-12-04 08:22:15 +00:00
|
|
|
!(alg_info->flags & (SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_HASH_NONE))) {
|
2003-12-18 21:37:34 +00:00
|
|
|
unsigned int algo;
|
2007-02-02 22:15:14 +00:00
|
|
|
size_t tmplen = sizeof(buf);
|
2011-03-13 18:11:07 +00:00
|
|
|
|
2007-02-02 22:15:14 +00:00
|
|
|
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));
|
2011-03-13 18:11:07 +00:00
|
|
|
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
|
2007-02-02 22:15:14 +00:00
|
|
|
}
|
2003-11-23 16:11:32 +00:00
|
|
|
flags &= ~SC_ALGORITHM_RSA_HASH_NONE;
|
|
|
|
flags |= algo;
|
2007-02-02 22:15:14 +00:00
|
|
|
inlen = tmplen;
|
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
|
|
|
}
|
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) {
|
|
|
|
size_t tmplen = sizeof(buf);
|
2011-03-13 18:11:07 +00:00
|
|
|
|
2007-02-02 22:15:14 +00:00
|
|
|
r = sc_pkcs1_encode(ctx, pad_flags, tmp, inlen, tmp, &tmplen, modlen);
|
2010-03-15 12:17:13 +00:00
|
|
|
SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Unable to add padding");
|
2011-03-13 18:11:07 +00:00
|
|
|
|
2007-02-02 22:15:14 +00:00
|
|
|
inlen = tmplen;
|
2012-05-28 21:15:37 +00:00
|
|
|
}
|
|
|
|
else if ( senv.algorithm == SC_ALGORITHM_RSA &&
|
2010-12-01 20:08:42 +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.
|
|
|
|
*/
|
|
|
|
else if (senv.algorithm == SC_ALGORITHM_EC &&
|
|
|
|
(flags & SC_ALGORITHM_ECDSA_HASH_NONE) != 0) {
|
|
|
|
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");
|
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
|
|
|
}
|