531 lines
16 KiB
C
531 lines
16 KiB
C
/*
|
|
* padding.c: miscellaneous padding functions
|
|
*
|
|
* Copyright (C) 2001, 2002 Juha Yrjölä <juha.yrjola@iki.fi>
|
|
* Copyright (C) 2003 - 2007 Nils Larsch <larsch@trustcenter.de>
|
|
*
|
|
* 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
|
|
*/
|
|
|
|
#if HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#ifdef ENABLE_OPENSSL
|
|
#include <openssl/evp.h>
|
|
#include <openssl/rand.h>
|
|
#include <openssl/sha.h>
|
|
#endif
|
|
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "internal.h"
|
|
|
|
/* TODO doxygen comments */
|
|
|
|
/*
|
|
* Prefixes for pkcs-v1 signatures
|
|
*/
|
|
static const u8 hdr_md5[] = {
|
|
0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7,
|
|
0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10
|
|
};
|
|
static const u8 hdr_sha1[] = {
|
|
0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a,
|
|
0x05, 0x00, 0x04, 0x14
|
|
};
|
|
static const u8 hdr_sha256[] = {
|
|
0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
|
|
0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
|
|
};
|
|
static const u8 hdr_sha384[] = {
|
|
0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
|
|
0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30
|
|
};
|
|
static const u8 hdr_sha512[] = {
|
|
0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
|
|
0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40
|
|
};
|
|
static const u8 hdr_sha224[] = {
|
|
0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
|
|
0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c
|
|
};
|
|
static const u8 hdr_ripemd160[] = {
|
|
0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03, 0x02, 0x01,
|
|
0x05, 0x00, 0x04, 0x14
|
|
};
|
|
|
|
|
|
static const struct digest_info_prefix {
|
|
unsigned int algorithm;
|
|
const u8 * hdr;
|
|
size_t hdr_len;
|
|
size_t hash_len;
|
|
} digest_info_prefix[] = {
|
|
{ SC_ALGORITHM_RSA_HASH_NONE, NULL, 0, 0 },
|
|
{ SC_ALGORITHM_RSA_HASH_MD5, hdr_md5, sizeof(hdr_md5), 16 },
|
|
{ SC_ALGORITHM_RSA_HASH_SHA1, hdr_sha1, sizeof(hdr_sha1), 20 },
|
|
{ SC_ALGORITHM_RSA_HASH_SHA256, hdr_sha256, sizeof(hdr_sha256), 32 },
|
|
{ SC_ALGORITHM_RSA_HASH_SHA384, hdr_sha384, sizeof(hdr_sha384), 48 },
|
|
{ SC_ALGORITHM_RSA_HASH_SHA512, hdr_sha512, sizeof(hdr_sha512), 64 },
|
|
{ SC_ALGORITHM_RSA_HASH_SHA224, hdr_sha224, sizeof(hdr_sha224), 28 },
|
|
{ SC_ALGORITHM_RSA_HASH_RIPEMD160,hdr_ripemd160, sizeof(hdr_ripemd160), 20 },
|
|
{ SC_ALGORITHM_RSA_HASH_MD5_SHA1, NULL, 0, 36 },
|
|
{ 0, NULL, 0, 0 }
|
|
};
|
|
|
|
/* add/remove pkcs1 BT01 padding */
|
|
|
|
static int sc_pkcs1_add_01_padding(const u8 *in, size_t in_len,
|
|
u8 *out, size_t *out_len, size_t mod_length)
|
|
{
|
|
size_t i;
|
|
|
|
if (*out_len < mod_length)
|
|
return SC_ERROR_BUFFER_TOO_SMALL;
|
|
if (in_len + 11 > mod_length)
|
|
return SC_ERROR_INVALID_ARGUMENTS;
|
|
i = mod_length - in_len;
|
|
memmove(out + i, in, in_len);
|
|
*out++ = 0x00;
|
|
*out++ = 0x01;
|
|
|
|
memset(out, 0xFF, i - 3);
|
|
out += i - 3;
|
|
*out = 0x00;
|
|
|
|
*out_len = mod_length;
|
|
return SC_SUCCESS;
|
|
}
|
|
|
|
int
|
|
sc_pkcs1_strip_01_padding(struct sc_context *ctx, const u8 *in_dat, size_t in_len,
|
|
u8 *out, size_t *out_len)
|
|
{
|
|
const u8 *tmp = in_dat;
|
|
size_t len;
|
|
|
|
if (in_dat == NULL || in_len < 10)
|
|
return SC_ERROR_INTERNAL;
|
|
/* skip leading zero byte */
|
|
if (*tmp == 0) {
|
|
tmp++;
|
|
in_len--;
|
|
}
|
|
len = in_len;
|
|
if (*tmp != 0x01)
|
|
return SC_ERROR_WRONG_PADDING;
|
|
for (tmp++, len--; *tmp == 0xff && len != 0; tmp++, len--)
|
|
;
|
|
if (!len || (in_len - len) < 9 || *tmp++ != 0x00)
|
|
return SC_ERROR_WRONG_PADDING;
|
|
len--;
|
|
if (out == NULL)
|
|
/* just check the padding */
|
|
return SC_SUCCESS;
|
|
if (*out_len < len)
|
|
return SC_ERROR_INTERNAL;
|
|
memmove(out, tmp, len);
|
|
*out_len = len;
|
|
return SC_SUCCESS;
|
|
}
|
|
|
|
|
|
/* remove pkcs1 BT02 padding (adding BT02 padding is currently not
|
|
* needed/implemented) */
|
|
int
|
|
sc_pkcs1_strip_02_padding(sc_context_t *ctx, const u8 *data, size_t len, u8 *out, size_t *out_len)
|
|
{
|
|
unsigned int n = 0;
|
|
|
|
LOG_FUNC_CALLED(ctx);
|
|
if (data == NULL || len < 3)
|
|
LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL);
|
|
|
|
/* skip leading zero byte */
|
|
if (*data == 0) {
|
|
data++;
|
|
len--;
|
|
}
|
|
if (data[0] != 0x02)
|
|
LOG_FUNC_RETURN(ctx, SC_ERROR_WRONG_PADDING);
|
|
/* skip over padding bytes */
|
|
for (n = 1; n < len && data[n]; n++)
|
|
;
|
|
/* Must be at least 8 pad bytes */
|
|
if (n >= len || n < 9)
|
|
LOG_FUNC_RETURN(ctx, SC_ERROR_WRONG_PADDING);
|
|
n++;
|
|
if (out == NULL)
|
|
/* just check the padding */
|
|
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
|
|
|
/* Now move decrypted contents to head of buffer */
|
|
if (*out_len < len - n)
|
|
LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL);
|
|
*out_len = len - n;
|
|
memmove(out, data + n, *out_len);
|
|
|
|
sc_log(ctx, "stripped output(%"SC_FORMAT_LEN_SIZE_T"u): %s", len - n,
|
|
sc_dump_hex(out, len - n));
|
|
LOG_FUNC_RETURN(ctx, len - n);
|
|
}
|
|
|
|
/* add/remove DigestInfo prefix */
|
|
static int sc_pkcs1_add_digest_info_prefix(unsigned int algorithm,
|
|
const u8 *in, size_t in_len, u8 *out, size_t *out_len)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; digest_info_prefix[i].algorithm != 0; i++) {
|
|
if (algorithm == digest_info_prefix[i].algorithm) {
|
|
const u8 *hdr = digest_info_prefix[i].hdr;
|
|
size_t hdr_len = digest_info_prefix[i].hdr_len,
|
|
hash_len = digest_info_prefix[i].hash_len;
|
|
|
|
if (in_len != hash_len || *out_len < (hdr_len + hash_len))
|
|
return SC_ERROR_INTERNAL;
|
|
|
|
memmove(out + hdr_len, in, hash_len);
|
|
memmove(out, hdr, hdr_len);
|
|
*out_len = hdr_len + hash_len;
|
|
|
|
return SC_SUCCESS;
|
|
}
|
|
}
|
|
|
|
return SC_ERROR_INTERNAL;
|
|
}
|
|
|
|
int sc_pkcs1_strip_digest_info_prefix(unsigned int *algorithm,
|
|
const u8 *in_dat, size_t in_len, u8 *out_dat, size_t *out_len)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; digest_info_prefix[i].algorithm != 0; i++) {
|
|
size_t hdr_len = digest_info_prefix[i].hdr_len,
|
|
hash_len = digest_info_prefix[i].hash_len;
|
|
const u8 *hdr = digest_info_prefix[i].hdr;
|
|
|
|
if (in_len == (hdr_len + hash_len) &&
|
|
!memcmp(in_dat, hdr, hdr_len)) {
|
|
if (algorithm)
|
|
*algorithm = digest_info_prefix[i].algorithm;
|
|
if (out_dat == NULL)
|
|
/* just check the DigestInfo prefix */
|
|
return SC_SUCCESS;
|
|
if (*out_len < hash_len)
|
|
return SC_ERROR_INTERNAL;
|
|
memmove(out_dat, in_dat + hdr_len, hash_len);
|
|
*out_len = hash_len;
|
|
return SC_SUCCESS;
|
|
}
|
|
}
|
|
return SC_ERROR_INTERNAL;
|
|
}
|
|
|
|
#ifdef ENABLE_OPENSSL
|
|
|
|
static const EVP_MD* hash_flag2md(unsigned int hash)
|
|
{
|
|
switch (hash & SC_ALGORITHM_RSA_HASHES) {
|
|
case SC_ALGORITHM_RSA_HASH_SHA1:
|
|
return EVP_sha1();
|
|
case SC_ALGORITHM_RSA_HASH_SHA224:
|
|
return EVP_sha224();
|
|
case SC_ALGORITHM_RSA_HASH_SHA256:
|
|
return EVP_sha256();
|
|
case SC_ALGORITHM_RSA_HASH_SHA384:
|
|
return EVP_sha384();
|
|
case SC_ALGORITHM_RSA_HASH_SHA512:
|
|
return EVP_sha512();
|
|
default:
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
static const EVP_MD* mgf1_flag2md(unsigned int mgf1)
|
|
{
|
|
switch (mgf1 & SC_ALGORITHM_MGF1_HASHES) {
|
|
case SC_ALGORITHM_MGF1_SHA1:
|
|
return EVP_sha1();
|
|
case SC_ALGORITHM_MGF1_SHA224:
|
|
return EVP_sha224();
|
|
case SC_ALGORITHM_MGF1_SHA256:
|
|
return EVP_sha256();
|
|
case SC_ALGORITHM_MGF1_SHA384:
|
|
return EVP_sha384();
|
|
case SC_ALGORITHM_MGF1_SHA512:
|
|
return EVP_sha512();
|
|
default:
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/* add PKCS#1 v2.0 PSS padding */
|
|
static int sc_pkcs1_add_pss_padding(unsigned int hash, unsigned int mgf1_hash,
|
|
const u8 *in, size_t in_len, u8 *out, size_t *out_len, size_t mod_bits)
|
|
{
|
|
/* hLen = sLen in our case */
|
|
int rv = SC_ERROR_INTERNAL, i, j, hlen, dblen, plen, round, mgf_rounds;
|
|
int mgf1_hlen;
|
|
const EVP_MD* md, *mgf1_md;
|
|
EVP_MD_CTX* ctx = NULL;
|
|
u8 buf[8];
|
|
u8 salt[EVP_MAX_MD_SIZE], mask[EVP_MAX_MD_SIZE];
|
|
size_t mod_length = (mod_bits + 7) / 8;
|
|
|
|
if (*out_len < mod_length)
|
|
return SC_ERROR_BUFFER_TOO_SMALL;
|
|
|
|
md = hash_flag2md(hash);
|
|
if (md == NULL)
|
|
return SC_ERROR_NOT_SUPPORTED;
|
|
hlen = EVP_MD_size(md);
|
|
dblen = mod_length - hlen - 1; /* emLen - hLen - 1 */
|
|
plen = mod_length - 2*hlen - 1;
|
|
if (in_len != (unsigned)hlen)
|
|
return SC_ERROR_INVALID_ARGUMENTS;
|
|
if (2 * (unsigned)hlen + 2 > mod_length)
|
|
/* RSA key too small for chosen hash (1296 bits or higher needed for
|
|
* signing SHA-512 hashes) */
|
|
return SC_ERROR_NOT_SUPPORTED;
|
|
|
|
if (RAND_bytes(salt, hlen) != 1)
|
|
return SC_ERROR_INTERNAL;
|
|
|
|
/* Hash M' to create H */
|
|
if (!(ctx = EVP_MD_CTX_create()))
|
|
goto done;
|
|
memset(buf, 0x00, 8);
|
|
if (EVP_DigestInit_ex(ctx, md, NULL) != 1 ||
|
|
EVP_DigestUpdate(ctx, buf, 8) != 1 ||
|
|
EVP_DigestUpdate(ctx, in, hlen) != 1 || /* mHash */
|
|
EVP_DigestUpdate(ctx, salt, hlen) != 1) {
|
|
goto done;
|
|
}
|
|
|
|
/* Construct padding2, salt, H, and BC in the output block */
|
|
/* DB = PS || 0x01 || salt */
|
|
memset(out, 0x00, plen - 1); /* emLen - sLen - hLen - 2 */
|
|
out[plen - 1] = 0x01;
|
|
memcpy(out + plen, salt, hlen);
|
|
if (EVP_DigestFinal_ex(ctx, out + dblen, NULL) != 1) { /* H */
|
|
goto done;
|
|
}
|
|
out[dblen + hlen] = 0xBC;
|
|
/* EM = DB* || H || 0xbc
|
|
* *the first part is masked later */
|
|
|
|
/* Construct the DB mask block by block and XOR it in. */
|
|
mgf1_md = mgf1_flag2md(mgf1_hash);
|
|
if (mgf1_md == NULL)
|
|
return SC_ERROR_NOT_SUPPORTED;
|
|
mgf1_hlen = EVP_MD_size(mgf1_md);
|
|
|
|
mgf_rounds = (dblen + mgf1_hlen - 1) / mgf1_hlen; /* round up */
|
|
for (round = 0; round < mgf_rounds; ++round) {
|
|
buf[0] = (round&0xFF000000U) >> 24;
|
|
buf[1] = (round&0x00FF0000U) >> 16;
|
|
buf[2] = (round&0x0000FF00U) >> 8;
|
|
buf[3] = (round&0x000000FFU);
|
|
if (EVP_DigestInit_ex(ctx, mgf1_md, NULL) != 1 ||
|
|
EVP_DigestUpdate(ctx, out + dblen, hlen) != 1 || /* H (Z parameter of MGF1) */
|
|
EVP_DigestUpdate(ctx, buf, 4) != 1 || /* C */
|
|
EVP_DigestFinal_ex(ctx, mask, NULL) != 1) {
|
|
goto done;
|
|
}
|
|
/* this is no longer part of the MGF1, but actually
|
|
* XORing mask with DB to create maskedDB inplace */
|
|
for (i = round * mgf1_hlen, j = 0; i < dblen && j < mgf1_hlen; ++i, ++j) {
|
|
out[i] ^= mask[j];
|
|
}
|
|
}
|
|
|
|
/* Set leftmost N bits in leftmost octet in maskedDB to zero
|
|
* to make sure the result is smaller than the modulus ( +1)
|
|
*/
|
|
out[0] &= (0xff >> (8 * mod_length - mod_bits + 1));
|
|
|
|
*out_len = mod_length;
|
|
rv = SC_SUCCESS;
|
|
|
|
done:
|
|
OPENSSL_cleanse(salt, sizeof(salt));
|
|
OPENSSL_cleanse(mask, sizeof(mask));
|
|
if (ctx) {
|
|
EVP_MD_CTX_destroy(ctx);
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
static int hash_len2algo(size_t hash_len)
|
|
{
|
|
switch (hash_len) {
|
|
case SHA_DIGEST_LENGTH:
|
|
return SC_ALGORITHM_RSA_HASH_SHA1;
|
|
case SHA224_DIGEST_LENGTH:
|
|
return SC_ALGORITHM_RSA_HASH_SHA224;
|
|
case SHA256_DIGEST_LENGTH:
|
|
return SC_ALGORITHM_RSA_HASH_SHA256;
|
|
case SHA384_DIGEST_LENGTH:
|
|
return SC_ALGORITHM_RSA_HASH_SHA384;
|
|
case SHA512_DIGEST_LENGTH:
|
|
return SC_ALGORITHM_RSA_HASH_SHA512;
|
|
}
|
|
/* Should never happen -- the mechanism and data should be already
|
|
* verified to match one of the above. If not, we will fail later
|
|
*/
|
|
return SC_ALGORITHM_RSA_HASH_NONE;
|
|
}
|
|
#endif
|
|
|
|
/* general PKCS#1 encoding function */
|
|
int sc_pkcs1_encode(sc_context_t *ctx, unsigned long flags,
|
|
const u8 *in, size_t in_len, u8 *out, size_t *out_len, size_t mod_bits)
|
|
{
|
|
int rv, i;
|
|
size_t tmp_len = *out_len;
|
|
const u8 *tmp = in;
|
|
unsigned int hash_algo, pad_algo;
|
|
size_t mod_len = (mod_bits + 7) / 8;
|
|
#ifdef ENABLE_OPENSSL
|
|
unsigned int mgf1_hash;
|
|
#endif
|
|
|
|
LOG_FUNC_CALLED(ctx);
|
|
|
|
hash_algo = flags & SC_ALGORITHM_RSA_HASHES;
|
|
pad_algo = flags & SC_ALGORITHM_RSA_PADS;
|
|
if (pad_algo == 0)
|
|
pad_algo = SC_ALGORITHM_RSA_PAD_NONE;
|
|
sc_log(ctx, "hash algorithm 0x%X, pad algorithm 0x%X", hash_algo, pad_algo);
|
|
|
|
if ((pad_algo == SC_ALGORITHM_RSA_PAD_PKCS1 || pad_algo == SC_ALGORITHM_RSA_PAD_NONE) &&
|
|
hash_algo != SC_ALGORITHM_RSA_HASH_NONE) {
|
|
i = sc_pkcs1_add_digest_info_prefix(hash_algo, in, in_len, out, &tmp_len);
|
|
if (i != SC_SUCCESS) {
|
|
sc_log(ctx, "Unable to add digest info 0x%x", hash_algo);
|
|
LOG_FUNC_RETURN(ctx, i);
|
|
}
|
|
tmp = out;
|
|
} else {
|
|
tmp_len = in_len;
|
|
}
|
|
|
|
switch(pad_algo) {
|
|
case SC_ALGORITHM_RSA_PAD_NONE:
|
|
/* padding done by card => nothing to do */
|
|
if (out != tmp)
|
|
memcpy(out, tmp, tmp_len);
|
|
*out_len = tmp_len;
|
|
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
|
case SC_ALGORITHM_RSA_PAD_PKCS1:
|
|
/* add pkcs1 bt01 padding */
|
|
rv = sc_pkcs1_add_01_padding(tmp, tmp_len, out, out_len, mod_len);
|
|
LOG_FUNC_RETURN(ctx, rv);
|
|
case SC_ALGORITHM_RSA_PAD_PSS:
|
|
/* add PSS padding */
|
|
#ifdef ENABLE_OPENSSL
|
|
mgf1_hash = flags & SC_ALGORITHM_MGF1_HASHES;
|
|
if (hash_algo == SC_ALGORITHM_RSA_HASH_NONE) {
|
|
/* this is generic RSA_PKCS1_PSS mechanism with hash
|
|
* already done outside of the module. The parameters
|
|
* were already checked so we need to adjust the hash
|
|
* algorithm to do the padding with the correct hash
|
|
* function.
|
|
*/
|
|
hash_algo = hash_len2algo(tmp_len);
|
|
}
|
|
rv = sc_pkcs1_add_pss_padding(hash_algo, mgf1_hash,
|
|
tmp, tmp_len, out, out_len, mod_bits);
|
|
#else
|
|
rv = SC_ERROR_NOT_SUPPORTED;
|
|
#endif
|
|
LOG_FUNC_RETURN(ctx, rv);
|
|
default:
|
|
/* We shouldn't be called with an unexpected padding type, we've already
|
|
* returned SC_ERROR_NOT_SUPPORTED if the card can't be used. */
|
|
LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL);
|
|
}
|
|
}
|
|
|
|
int sc_get_encoding_flags(sc_context_t *ctx,
|
|
unsigned long iflags, unsigned long caps,
|
|
unsigned long *pflags, unsigned long *sflags)
|
|
{
|
|
LOG_FUNC_CALLED(ctx);
|
|
if (pflags == NULL || sflags == NULL)
|
|
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
|
|
|
|
sc_log(ctx, "iFlags 0x%lX, card capabilities 0x%lX", iflags, caps);
|
|
|
|
/* For ECDSA and GOSTR, we don't do any padding or hashing ourselves, the
|
|
* card has to support the requested operation. Similarly, for RSA with
|
|
* raw padding (raw RSA) and ISO9796, we require the card to do it for us.
|
|
* Finally, for PKCS1 (v1.5 and PSS) and ASNI X9.31 we can apply the padding
|
|
* ourselves if the card supports raw RSA. */
|
|
|
|
/* TODO: Could convert GOSTR3410_HASH_GOSTR3411 -> GOSTR3410_RAW and
|
|
* ECDSA_HASH_ -> ECDSA_RAW using OpenSSL (not much benefit though). */
|
|
|
|
if ((caps & iflags) == iflags) {
|
|
/* Card supports the signature operation we want to do, great, let's
|
|
* go with it then. */
|
|
*sflags = iflags;
|
|
*pflags = 0;
|
|
|
|
} else if ((caps & SC_ALGORITHM_RSA_PAD_PSS) &&
|
|
(iflags & SC_ALGORITHM_RSA_PAD_PSS)) {
|
|
*sflags |= SC_ALGORITHM_RSA_PAD_PSS;
|
|
*sflags |= iflags & SC_ALGORITHM_MGF1_HASHES;
|
|
*pflags = iflags & ~(iflags & (SC_ALGORITHM_MGF1_HASHES | SC_ALGORITHM_RSA_PAD_PSS));
|
|
|
|
} else if ((caps & SC_ALGORITHM_RSA_RAW) &&
|
|
(iflags & SC_ALGORITHM_RSA_PAD_PKCS1
|
|
|| iflags & SC_ALGORITHM_RSA_PAD_PSS
|
|
|| iflags & SC_ALGORITHM_RSA_PAD_NONE)) {
|
|
/* Use the card's raw RSA capability on the padded input */
|
|
*sflags = SC_ALGORITHM_RSA_PAD_NONE;
|
|
*pflags = iflags;
|
|
/* TODO emulate the OAEP decryption */
|
|
|
|
} else if ((caps & (SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE)) &&
|
|
(iflags & SC_ALGORITHM_RSA_PAD_PKCS1)) {
|
|
/* A corner case - the card can partially do PKCS1, if we prepend the
|
|
* DigestInfo bit it will do the rest. */
|
|
*sflags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE;
|
|
*pflags = iflags & SC_ALGORITHM_RSA_HASHES;
|
|
|
|
} else if ((iflags & SC_ALGORITHM_AES) == SC_ALGORITHM_AES) { /* TODO: seems like this constant does not belong to the same set of flags used form asymmetric algos. Fix this! */
|
|
*sflags = 0;
|
|
*pflags = 0;
|
|
|
|
} else if ((iflags & SC_ALGORITHM_AES_FLAGS) > 0) {
|
|
*sflags = iflags & SC_ALGORITHM_AES_FLAGS;
|
|
if (iflags & SC_ALGORITHM_AES_CBC_PAD)
|
|
*pflags = SC_ALGORITHM_AES_CBC_PAD;
|
|
else
|
|
*pflags = 0;
|
|
|
|
} else {
|
|
LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "unsupported algorithm");
|
|
}
|
|
|
|
sc_log(ctx, "pad flags 0x%lX, secure algorithm flags 0x%lX", *pflags, *sflags);
|
|
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
|
|
}
|