From a2f622a21521cb350541894d80e3266b5f2f5612 Mon Sep 17 00:00:00 2001 From: nils Date: Fri, 2 Feb 2007 22:15:14 +0000 Subject: [PATCH] implement support for SHA2 (still experimental) git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@3115 c6295689-39f2-0310-b995-f0e70906c6a9 --- src/libopensc/card-cardos.c | 13 ++- src/libopensc/card-incrypto34.c | 13 ++- src/libopensc/internal.h | 31 ++++-- src/libopensc/opensc.h | 6 +- src/libopensc/padding.c | 94 ++++++++++++------ src/libopensc/pkcs15-sec.c | 164 ++++++++------------------------ src/pkcs11/framework-pkcs15.c | 9 ++ src/pkcs11/openssl.c | 41 ++++++++ src/pkcs11/pkcs11-display.c | 6 ++ src/pkcs11/pkcs11.h | 15 +++ src/tools/pkcs11-tool.c | 9 ++ src/tools/pkcs15-crypt.c | 24 +++++ 12 files changed, 259 insertions(+), 166 deletions(-) diff --git a/src/libopensc/card-cardos.c b/src/libopensc/card-cardos.c index 018bb93e..92f05776 100644 --- a/src/libopensc/card-cardos.c +++ b/src/libopensc/card-cardos.c @@ -783,11 +783,16 @@ cardos_compute_signature(sc_card_t *card, const u8 *data, size_t datalen, /* remove padding: first try pkcs1 bt01 padding */ r = sc_pkcs1_strip_01_padding(data, datalen, buf, &tmp_len); if (r != SC_SUCCESS) { - /* no pkcs1 bt01 padding => let's try zero padding */ + const u8 *p = data; + /* no pkcs1 bt01 padding => let's try zero padding + * This can only work if the data tbs doesn't have a + * leading 0 byte. */ tmp_len = buf_len; - r = sc_strip_zero_padding(data, datalen, buf, &tmp_len); - if (r != SC_SUCCESS) - SC_FUNC_RETURN(ctx, 4, r); + while (*p == 0 && tmp_len != 0) { + ++p; + --tmp_len; + } + memcpy(buf, p, tmp_len); } sc_ctx_suppress_errors_on(ctx); r = do_compute_signature(card, buf, tmp_len, out, outlen); diff --git a/src/libopensc/card-incrypto34.c b/src/libopensc/card-incrypto34.c index 59fca2be..e54b5991 100644 --- a/src/libopensc/card-incrypto34.c +++ b/src/libopensc/card-incrypto34.c @@ -568,11 +568,16 @@ incrypto34_compute_signature(sc_card_t *card, const u8 *data, size_t datalen, /* remove padding: first try pkcs1 bt01 padding */ r = sc_pkcs1_strip_01_padding(data, datalen, buf, &tmp_len); if (r != SC_SUCCESS) { - /* no pkcs1 bt01 padding => let's try zero padding */ + const u8 *p = data; + /* no pkcs1 bt01 padding => let's try zero padding. + * This can only work if the data tbs doesn't have a + * leading 0 byte. */ tmp_len = buf_len; - r = sc_strip_zero_padding(data, datalen, buf, &tmp_len); - if (r != SC_SUCCESS) - SC_FUNC_RETURN(ctx, 4, r); + while (*p == 0 && tmp_len != 0) { + ++p; + --tmp_len; + } + memcpy(buf, p, tmp_len); } sc_ctx_suppress_errors_on(ctx); r = do_compute_signature(card, buf, tmp_len, out, outlen); diff --git a/src/libopensc/internal.h b/src/libopensc/internal.h index ff98318c..2ab29938 100644 --- a/src/libopensc/internal.h +++ b/src/libopensc/internal.h @@ -123,19 +123,38 @@ int sc_asn1_read_tag(const u8 ** buf, size_t buflen, unsigned int *cla_out, /* pkcs1 padding/encoding functions */ /********************************************************************/ -int sc_pkcs1_add_01_padding(const u8 *in, size_t in_len, u8 *out, - size_t *out_len, size_t mod_length); int sc_pkcs1_strip_01_padding(const u8 *in_dat, size_t in_len, u8 *out_dat, size_t *out_len); int sc_pkcs1_strip_02_padding(const u8 *data, size_t len, u8 *out_dat, size_t *out_len); -int sc_pkcs1_add_digest_info_prefix(unsigned int algorithm, const u8 *in_dat, - size_t in_len, u8 *out_dat, size_t *out_len); 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); + +/** + * PKCS1 encodes the given data. + * @param ctx IN sc_context_t object + * @param flags IN the algorithm to use + * @param in IN input buffer + * @param inlen IN length of the input + * @param out OUT output buffer (in == out is allowed) + * @param outlen OUT length of the output buffer + * @param modlen IN length of the modulus in bytes + * @return SC_SUCCESS on success and an error code otherwise + */ 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_len); -int sc_strip_zero_padding(const u8 *in,size_t in_len, u8 *out, size_t *out_len); + const u8 *in, size_t inlen, u8 *out, size_t *outlen, size_t modlen); +/** + * Get the necessary padding and sec. env. flags. + * @param ctx IN sc_contex_t object + * @param iflags IN the desired algorithms flags + * @param caps IN the card / key capabilities + * @param pflags OUT the padding flags to use + * @param salg OUT the security env. algorithm flag to use + * @return SC_SUCCESS on success and an error code otherwise + */ +int sc_get_encoding_flags(sc_context_t *ctx, + unsigned long iflags, unsigned long caps, + unsigned long *pflags, unsigned long *salg); /********************************************************************/ /* mutex functions */ diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index bff2017a..39055c53 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -181,11 +181,15 @@ extern "C" { /* If the card is willing to produce a cryptogram with the following * hash values, set these flags accordingly. */ #define SC_ALGORITHM_RSA_HASH_NONE 0x00000010 -#define SC_ALGORITHM_RSA_HASHES 0x000001E0 #define SC_ALGORITHM_RSA_HASH_SHA1 0x00000020 #define SC_ALGORITHM_RSA_HASH_MD5 0x00000040 #define SC_ALGORITHM_RSA_HASH_MD5_SHA1 0x00000080 #define SC_ALGORITHM_RSA_HASH_RIPEMD160 0x00000100 +#define SC_ALGORITHM_RSA_HASH_SHA256 0x00000200 +#define SC_ALGORITHM_RSA_HASH_SHA384 0x00000400 +#define SC_ALGORITHM_RSA_HASH_SHA512 0x00000800 +#define SC_ALGORITHM_RSA_HASH_SHA224 0x00001000 +#define SC_ALGORITHM_RSA_HASHES 0x00001FE0 /* Event masks for sc_wait_for_event() */ #define SC_EVENT_CARD_INSERTED 0x0001 diff --git a/src/libopensc/padding.c b/src/libopensc/padding.c index e46e9b25..f213841c 100644 --- a/src/libopensc/padding.c +++ b/src/libopensc/padding.c @@ -1,8 +1,8 @@ /* - * sc-padding.c: miscellaneous padding functions + * padding.c: miscellaneous padding functions * * Copyright (C) 2001, 2002 Juha Yrjölä - * Copyright (C) 2003 Nils Larsch + * Copyright (C) 2003 - 2007 Nils Larsch * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,7 +22,6 @@ #include "internal.h" #include #include -#include /* TODO doxygen comments */ @@ -37,22 +36,41 @@ 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 }; -#define DIGEST_INFO_COUNT 6 static const struct digest_info_prefix { unsigned int algorithm; const u8 * hdr; size_t hdr_len; size_t hash_len; -} digest_info_prefix[DIGEST_INFO_COUNT] = { +} 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 } @@ -60,8 +78,8 @@ static const struct digest_info_prefix { /* add/remove pkcs1 BT01 padding */ -int sc_pkcs1_add_01_padding(const u8 *in, size_t in_len, u8 *out, - size_t *out_len, size_t mod_length) +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; @@ -82,15 +100,15 @@ int sc_pkcs1_add_01_padding(const u8 *in, size_t in_len, u8 *out, return SC_SUCCESS; } -int sc_pkcs1_strip_01_padding(const u8 *in_dat, size_t in_len, u8 *out, - size_t *out_len) +int sc_pkcs1_strip_01_padding(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; - /* ignore leading zero byte */ + /* skip leading zero byte */ if (*tmp == 0) { tmp++; in_len--; @@ -122,7 +140,7 @@ int sc_pkcs1_strip_02_padding(const u8 *data, size_t len, u8 *out, if (data == NULL || len < 3) return SC_ERROR_INTERNAL; - /* skip leading zero octet (not part of the pkcs1 BT02 padding) */ + /* skip leading zero byte */ if (*data == 0) { data++; len--; @@ -147,12 +165,12 @@ int sc_pkcs1_strip_02_padding(const u8 *data, size_t len, u8 *out, } /* add/remove DigestInfo prefix */ -int sc_pkcs1_add_digest_info_prefix(unsigned int algorithm, const u8 *in, - size_t in_len, u8 *out, size_t *out_len) +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; i < DIGEST_INFO_COUNT; 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, @@ -175,7 +193,7 @@ int sc_pkcs1_strip_digest_info_prefix(unsigned int *algorithm, { int i; - for (i = 0; i < DIGEST_INFO_COUNT; 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; @@ -239,21 +257,43 @@ int sc_pkcs1_encode(sc_context_t *ctx, unsigned long flags, } } -/* strip leading zero padding (does only really work when a DigestInfo - * value has been padded */ -int sc_strip_zero_padding(const u8 *in, size_t in_len, u8 *out, - size_t *out_len) +int sc_get_encoding_flags(sc_context_t *ctx, + unsigned long iflags, unsigned long caps, + unsigned long *pflags, unsigned long *sflags) { - while (*in == 0 && in_len) { - in++; - in_len--; + size_t i; + + if (pflags == NULL || sflags == NULL) + return SC_ERROR_INVALID_ARGUMENTS; + + for (i = 0; digest_info_prefix[i].algorithm != 0; i++) { + if (iflags & digest_info_prefix[i].algorithm) { + if (digest_info_prefix[i].algorithm != SC_ALGORITHM_RSA_HASH_NONE && + caps & digest_info_prefix[i].algorithm) + *sflags |= digest_info_prefix[i].algorithm; + else + *pflags |= digest_info_prefix[i].algorithm; + break; + } } - if (*out_len < in_len) - return SC_ERROR_INTERNAL; - - memmove(out, in, in_len); - *out_len = in_len; + if (iflags & SC_ALGORITHM_RSA_PAD_PKCS1) { + if (caps & SC_ALGORITHM_RSA_PAD_PKCS1) + *sflags |= SC_ALGORITHM_RSA_PAD_PKCS1; + else + *pflags |= SC_ALGORITHM_RSA_PAD_PKCS1; + } else if ((iflags & SC_ALGORITHM_RSA_PADS) == SC_ALGORITHM_RSA_PAD_NONE) { + if (!(caps & SC_ALGORITHM_RSA_RAW)) { + sc_error(ctx, "raw RSA is not supported"); + return SC_ERROR_NOT_SUPPORTED; + } + *sflags |= SC_ALGORITHM_RSA_RAW; + /* in case of raw RSA there is nothing to pad */ + *pflags = 0; + } else { + sc_error(ctx, "unsupported algorithm"); + return SC_ERROR_NOT_SUPPORTED; + } return SC_SUCCESS; } diff --git a/src/libopensc/pkcs15-sec.c b/src/libopensc/pkcs15-sec.c index 1f711791..7d08bc73 100644 --- a/src/libopensc/pkcs15-sec.c +++ b/src/libopensc/pkcs15-sec.c @@ -2,6 +2,7 @@ * pkcs15-sec.c: PKCS#15 cryptography functions * * Copyright (C) 2001, 2002 Juha Yrjölä + * Copyrigth (C) 2007 Nils Larsch * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,7 +21,6 @@ #include "internal.h" #include "pkcs15.h" -#include #include #include #include @@ -68,7 +68,7 @@ int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card, sc_security_env_t senv; sc_context_t *ctx = p15card->card->ctx; const struct sc_pkcs15_prkey_info *prkey = (const struct sc_pkcs15_prkey_info *) obj->data; - unsigned long pad_flags = 0; + unsigned long pad_flags = 0, sec_flags = 0; SC_FUNC_CALLED(ctx, 1); /* If the key is extractable, the caller should extract the @@ -87,27 +87,14 @@ int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card, return SC_ERROR_NOT_SUPPORTED; } senv.algorithm = SC_ALGORITHM_RSA; - senv.algorithm_flags = 0; - if (flags & SC_ALGORITHM_RSA_PAD_PKCS1) { - if (!(alg_info->flags & SC_ALGORITHM_RSA_PAD_PKCS1)) - pad_flags |= SC_ALGORITHM_RSA_PAD_PKCS1; - else - senv.algorithm_flags |= SC_ALGORITHM_RSA_PAD_PKCS1; - } else if ((flags & SC_ALGORITHM_RSA_PAD_ANSI) || - (flags & SC_ALGORITHM_RSA_PAD_ISO9796)) { - sc_error(ctx, "Only PKCS #1 padding method supported\n"); - return SC_ERROR_NOT_SUPPORTED; - } else { - if (!(alg_info->flags & SC_ALGORITHM_RSA_RAW)) { - sc_error(ctx, "Card requires RSA padding\n"); - return SC_ERROR_NOT_SUPPORTED; - } - senv.algorithm_flags |= SC_ALGORITHM_RSA_RAW; - } + r = sc_get_encoding_flags(ctx, flags, alg_info->flags, &pad_flags, &sec_flags); + if (r != SC_SUCCESS) + return r; - senv.operation = SC_SEC_OPERATION_DECIPHER; - senv.flags = 0; + senv.algorithm_flags = sec_flags; + senv.operation = SC_SEC_OPERATION_DECIPHER; + senv.flags = 0; /* optional keyReference attribute (the default value is -1) */ if (prkey->key_reference >= 0) { senv.key_ref_len = 1; @@ -140,7 +127,7 @@ int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card, /* Strip any padding */ if (pad_flags & SC_ALGORITHM_RSA_PAD_PKCS1) { r = sc_pkcs1_strip_02_padding(out, (size_t)r, out, (size_t *) &r); - SC_TEST_RET(ctx, r, "Invalid PKCS#1 padding"); + SC_TEST_RET(ctx, r, "Invalid PKCS#1 padding"); } return r; @@ -156,9 +143,9 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card, sc_context_t *ctx = p15card->card->ctx; sc_algorithm_info_t *alg_info; const struct sc_pkcs15_prkey_info *prkey = (const struct sc_pkcs15_prkey_info *) obj->data; - u8 buf[512], *tmpin, *tmpout, *help; - size_t tmpoutlen; - unsigned long pad_flags = 0; + u8 buf[512], *tmp; + size_t modlen = prkey->modulus_length / 8; + unsigned long pad_flags = 0, sec_flags = 0; SC_FUNC_CALLED(ctx, 1); /* If the key is extractable, the caller should extract the @@ -180,13 +167,10 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card, senv.algorithm = SC_ALGORITHM_RSA; /* Probably never happens, but better make sure */ - if (inlen > sizeof(buf)) + if (inlen > sizeof(buf) || outlen < modlen) return SC_ERROR_BUFFER_TOO_SMALL; memcpy(buf, in, inlen); - tmpin = buf; - if (outlen < (prkey->modulus_length + 7) / 8) - return SC_ERROR_BUFFER_TOO_SMALL; - tmpout = out; + tmp = buf; /* flags: the requested algo * algo_info->flags: what is supported by the card @@ -197,92 +181,38 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card, if ((flags == (SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE)) && !(alg_info->flags & (SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_HASH_NONE))) { unsigned int algo; - tmpoutlen = sizeof(buf); - r = sc_pkcs1_strip_digest_info_prefix(&algo, tmpin, inlen, tmpout, &tmpoutlen); - if (r != SC_SUCCESS || algo == SC_ALGORITHM_RSA_HASH_NONE) + 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)); return SC_ERROR_INVALID_DATA; - help = tmpin; - tmpin = tmpout; - tmpout = help; - inlen = tmpoutlen; + } flags &= ~SC_ALGORITHM_RSA_HASH_NONE; flags |= algo; + inlen = tmplen; } - senv.algorithm_flags = 0; - if (flags & SC_ALGORITHM_RSA_HASH_SHA1) { - if (inlen != 20) - SC_FUNC_RETURN(ctx, 0, SC_ERROR_WRONG_LENGTH); - if (!(alg_info->flags & SC_ALGORITHM_RSA_HASH_SHA1)) - pad_flags |= SC_ALGORITHM_RSA_HASH_SHA1; - else - senv.algorithm_flags |= SC_ALGORITHM_RSA_HASH_SHA1; - } else if (flags & SC_ALGORITHM_RSA_HASH_MD5) { - if (inlen != 16) - SC_FUNC_RETURN(ctx, 0, SC_ERROR_WRONG_LENGTH); - if (!(alg_info->flags & SC_ALGORITHM_RSA_HASH_MD5)) - pad_flags |= SC_ALGORITHM_RSA_HASH_MD5; - else - senv.algorithm_flags |= SC_ALGORITHM_RSA_HASH_MD5; - } else if (flags & SC_ALGORITHM_RSA_HASH_RIPEMD160) { - if (inlen != 20) - SC_FUNC_RETURN(ctx, 0, SC_ERROR_WRONG_LENGTH); - if (!(alg_info->flags & SC_ALGORITHM_RSA_HASH_RIPEMD160)) - pad_flags |= SC_ALGORITHM_RSA_HASH_RIPEMD160; - else - senv.algorithm_flags |= SC_ALGORITHM_RSA_HASH_RIPEMD160; - } else if (flags & SC_ALGORITHM_RSA_HASH_MD5_SHA1) { - if (inlen != 36) - SC_FUNC_RETURN(ctx, 0, SC_ERROR_WRONG_LENGTH); - if (!(alg_info->flags & SC_ALGORITHM_RSA_HASH_MD5_SHA1)) - pad_flags |= SC_ALGORITHM_RSA_HASH_MD5_SHA1; - else - senv.algorithm_flags |= SC_ALGORITHM_RSA_HASH_MD5_SHA1; - } else if (flags & SC_ALGORITHM_RSA_HASH_NONE || - (flags & SC_ALGORITHM_RSA_HASHES) == 0) { - pad_flags |= SC_ALGORITHM_RSA_HASH_NONE; + r = sc_get_encoding_flags(ctx, flags, alg_info->flags, &pad_flags, &sec_flags); + if (r != SC_SUCCESS) { + sc_mem_clear(buf, sizeof(buf)); + return r; } + senv.algorithm_flags = sec_flags; - if (flags & SC_ALGORITHM_RSA_PAD_PKCS1) { - if (!(alg_info->flags & SC_ALGORITHM_RSA_PAD_PKCS1)) - pad_flags |= SC_ALGORITHM_RSA_PAD_PKCS1; - else - senv.algorithm_flags |= SC_ALGORITHM_RSA_PAD_PKCS1; - } else if ((flags & SC_ALGORITHM_RSA_PAD_ANSI) || - (flags & SC_ALGORITHM_RSA_PAD_ISO9796)) { - sc_error(ctx, "Only PKCS #1 padding method supported\n"); - return SC_ERROR_NOT_SUPPORTED; - } else { - if (!(alg_info->flags & SC_ALGORITHM_RSA_RAW)) { - sc_error(ctx, "Card requires RSA padding\n"); - return SC_ERROR_NOT_SUPPORTED; - } - senv.algorithm_flags |= SC_ALGORITHM_RSA_RAW; - pad_flags = 0; - - /* Add zero-padding if input shorter than modulus */ - if (inlen < prkey->modulus_length/8) { - unsigned int modulus_len = prkey->modulus_length/8; - if (modulus_len > sizeof(buf)) - return SC_ERROR_BUFFER_TOO_SMALL; - memset(tmpout, 0, sizeof(buf)); - memcpy(tmpout + modulus_len - inlen, tmpin, inlen); - inlen = modulus_len; - help = tmpin; - tmpin = tmpout; - tmpout = help; - } - } - - if (pad_flags) { - tmpoutlen = sizeof(buf); - r = sc_pkcs1_encode(ctx, pad_flags, tmpin, inlen, tmpout, &tmpoutlen, - prkey->modulus_length/8); + /* add the padding bytes (if necessary) */ + if (pad_flags != 0) { + size_t tmplen = sizeof(buf); + r = sc_pkcs1_encode(ctx, pad_flags, tmp, inlen, tmp, &tmplen, modlen); SC_TEST_RET(ctx, r, "Unable to add padding"); - help = tmpin; - tmpin = tmpout; - tmpout = help; - inlen = tmpoutlen; + inlen = tmplen; + } else if ((flags & SC_ALGORITHM_RSA_PADS) == SC_ALGORITHM_RSA_PAD_NONE) { + /* Add zero-padding if input is shorter than the modulus */ + if (inlen < modlen) { + if (modlen > sizeof(buf)) + return SC_ERROR_BUFFER_TOO_SMALL; + memmove(tmp+modlen-inlen, tmp, inlen); + memset(tmp, 0, modlen-inlen); + } } senv.operation = SC_SEC_OPERATION_SIGN; @@ -298,8 +228,7 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card, r = sc_lock(p15card->card); SC_TEST_RET(ctx, r, "sc_lock() failed"); - if (prkey->path.len != 0) - { + if (prkey->path.len != 0) { r = select_key_file(p15card, prkey, &senv); if (r < 0) { sc_unlock(p15card->card); @@ -313,20 +242,7 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card, SC_TEST_RET(ctx, r, "sc_set_security_env() failed"); } - /* XXX: Should we adjust outlen to match the size of - * the signature we expect? CardOS for instance will - * barf if the LE value doesn't match the size of the - * signature exactly. - * - * Right now we work around this by assuming that eToken keys - * always have algorithm RSA_PURE_SIG so the input buffer - * is padded and has the same length as the signature. --okir - */ - if (tmpin == out) { - memcpy(tmpout, tmpin, inlen); - tmpin = tmpout; - } - r = sc_compute_signature(p15card->card, tmpin, inlen, out, outlen); + r = sc_compute_signature(p15card->card, tmp, inlen, out, outlen); sc_mem_clear(buf, sizeof(buf)); sc_unlock(p15card->card); SC_TEST_RET(ctx, r, "sc_compute_signature() failed"); diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index 04ee2f21..4cb0b6fb 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -1947,6 +1947,15 @@ static CK_RV pkcs15_prkey_sign(struct sc_pkcs11_session *ses, void *obj, case CKM_SHA1_RSA_PKCS: flags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_SHA1; break; + case CKM_SHA256_RSA_PKCS: + flags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_SHA256; + break; + case CKM_SHA384_RSA_PKCS: + flags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_SHA384; + break; + case CKM_SHA512_RSA_PKCS: + flags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_SHA512; + break; case CKM_RIPEMD160_RSA_PKCS: flags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_RIPEMD160; break; diff --git a/src/pkcs11/openssl.c b/src/pkcs11/openssl.c index c8cf2b3a..4768920c 100644 --- a/src/pkcs11/openssl.c +++ b/src/pkcs11/openssl.c @@ -12,6 +12,7 @@ #include #include #include +#include static CK_RV sc_pkcs11_openssl_md_init(sc_pkcs11_operation_t *); static CK_RV sc_pkcs11_openssl_md_update(sc_pkcs11_operation_t *, @@ -30,6 +31,38 @@ static sc_pkcs11_mechanism_type_t openssl_sha1_mech = { sc_pkcs11_openssl_md_final }; +#if OPENSSL_VERSION_NUMBER >= 0x00908000L +static sc_pkcs11_mechanism_type_t openssl_sha256_mech = { + CKM_SHA256, + { 0, 0, CKF_DIGEST }, 0, + sizeof(struct sc_pkcs11_operation), + sc_pkcs11_openssl_md_release, + sc_pkcs11_openssl_md_init, + sc_pkcs11_openssl_md_update, + sc_pkcs11_openssl_md_final +}; + +static sc_pkcs11_mechanism_type_t openssl_sha384_mech = { + CKM_SHA384, + { 0, 0, CKF_DIGEST }, 0, + sizeof(struct sc_pkcs11_operation), + sc_pkcs11_openssl_md_release, + sc_pkcs11_openssl_md_init, + sc_pkcs11_openssl_md_update, + sc_pkcs11_openssl_md_final +}; + +static sc_pkcs11_mechanism_type_t openssl_sha512_mech = { + CKM_SHA512, + { 0, 0, CKF_DIGEST }, 0, + sizeof(struct sc_pkcs11_operation), + sc_pkcs11_openssl_md_release, + sc_pkcs11_openssl_md_init, + sc_pkcs11_openssl_md_update, + sc_pkcs11_openssl_md_final +}; +#endif + static sc_pkcs11_mechanism_type_t openssl_md5_mech = { CKM_MD5, { 0, 0, CKF_DIGEST }, 0, @@ -55,6 +88,14 @@ sc_pkcs11_register_openssl_mechanisms(struct sc_pkcs11_card *card) { openssl_sha1_mech.mech_data = EVP_sha1(); sc_pkcs11_register_mechanism(card, &openssl_sha1_mech); +#if OPENSSL_VERSION_NUMBER >= 0x00908000L + openssl_sha256_mech.mech_data = EVP_sha256(); + sc_pkcs11_register_mechanism(card, &openssl_sha256_mech); + openssl_sha384_mech.mech_data = EVP_sha384(); + sc_pkcs11_register_mechanism(card, &openssl_sha384_mech); + openssl_sha512_mech.mech_data = EVP_sha512(); + sc_pkcs11_register_mechanism(card, &openssl_sha512_mech); +#endif openssl_md5_mech.mech_data = EVP_md5(); sc_pkcs11_register_mechanism(card, &openssl_md5_mech); openssl_ripemd160_mech.mech_data = EVP_ripemd160(); diff --git a/src/pkcs11/pkcs11-display.c b/src/pkcs11/pkcs11-display.c index 12eb68a2..49638204 100644 --- a/src/pkcs11/pkcs11-display.c +++ b/src/pkcs11/pkcs11-display.c @@ -230,6 +230,9 @@ enum_specs ck_mec_s[] = { { CKM_MD2_RSA_PKCS , "CKM_MD2_RSA_PKCS " }, { CKM_MD5_RSA_PKCS , "CKM_MD5_RSA_PKCS " }, { CKM_SHA1_RSA_PKCS , "CKM_SHA1_RSA_PKCS " }, + { CKM_SHA256_RSA_PKCS , "CKM_SHA256_RSA_PKCS " }, + { CKM_SHA384_RSA_PKCS , "CKM_SHA384_RSA_PKCS " }, + { CKM_SHA512_RSA_PKCS , "CKM_SHA512_RSA_PKCS " }, { CKM_RIPEMD128_RSA_PKCS , "CKM_RIPEMD128_RSA_PKCS " }, { CKM_RIPEMD160_RSA_PKCS , "CKM_RIPEMD160_RSA_PKCS " }, { CKM_RSA_PKCS_OAEP , "CKM_RSA_PKCS_OAEP " }, @@ -238,6 +241,9 @@ enum_specs ck_mec_s[] = { { CKM_SHA1_RSA_X9_31 , "CKM_SHA1_RSA_X9_31 " }, { CKM_RSA_PKCS_PSS , "CKM_RSA_PKCS_PSS " }, { CKM_SHA1_RSA_PKCS_PSS , "CKM_SHA1_RSA_PKCS_PSS " }, + { CKM_SHA256_RSA_PKCS_PSS , "CKM_SHA256_RSA_PKCS_PSS " }, + { CKM_SHA384_RSA_PKCS_PSS , "CKM_SHA384_RSA_PKCS_PSS " }, + { CKM_SHA512_RSA_PKCS_PSS , "CKM_SHA512_RSA_PKCS_PSS " }, { CKM_DSA_KEY_PAIR_GEN , "CKM_DSA_KEY_PAIR_GEN " }, { CKM_DSA , "CKM_DSA " }, { CKM_DSA_SHA1 , "CKM_DSA_SHA1 " }, diff --git a/src/pkcs11/pkcs11.h b/src/pkcs11/pkcs11.h index 115c309e..7d18f231 100644 --- a/src/pkcs11/pkcs11.h +++ b/src/pkcs11/pkcs11.h @@ -498,6 +498,12 @@ typedef unsigned long ck_mechanism_type_t; #define CKM_X9_42_DH_DERIVE (0x31) #define CKM_X9_42_DH_HYBRID_DERIVE (0x32) #define CKM_X9_42_MQV_DERIVE (0x33) +#define CKM_SHA256_RSA_PKCS (0x40) +#define CKM_SHA384_RSA_PKCS (0x41) +#define CKM_SHA512_RSA_PKCS (0x42) +#define CKM_SHA256_RSA_PKCS_PSS (0x43) +#define CKM_SHA384_RSA_PKCS_PSS (0x44) +#define CKM_SHA512_RSA_PKCS_PSS (0x45) #define CKM_RC2_KEY_GEN (0x100) #define CKM_RC2_ECB (0x101) #define CKM_RC2_CBC (0x102) @@ -540,6 +546,15 @@ typedef unsigned long ck_mechanism_type_t; #define CKM_RIPEMD160 (0x240) #define CKM_RIPEMD160_HMAC (0x241) #define CKM_RIPEMD160_HMAC_GENERAL (0x242) +#define CKM_SHA256 (0x250) +#define CKM_SHA256_HMAC (0x251) +#define CKM_SHA256_HMAC_GENERAL (0x252) +#define CKM_SHA384 (0x260) +#define CKM_SHA384_HMAC (0x261) +#define CKM_SHA384_HMAC_GENERAL (0x262) +#define CKM_SHA512 (0x270) +#define CKM_SHA512_HMAC (0x271) +#define CKM_SHA512_HMAC_GENERAL (0x272) #define CKM_CAST_KEY_GEN (0x300) #define CKM_CAST_ECB (0x301) #define CKM_CAST_CBC (0x302) diff --git a/src/tools/pkcs11-tool.c b/src/tools/pkcs11-tool.c index 504a5622..01a7036e 100644 --- a/src/tools/pkcs11-tool.c +++ b/src/tools/pkcs11-tool.c @@ -3329,6 +3329,9 @@ static struct mech_info p11_mechanisms[] = { { CKM_MD2_RSA_PKCS, "MD2-RSA-PKCS", NULL }, { CKM_MD5_RSA_PKCS, "MD5-RSA-PKCS", "rsa-md5" }, { CKM_SHA1_RSA_PKCS, "SHA1-RSA-PKCS", "rsa-sha1" }, + { CKM_SHA256_RSA_PKCS, "SHA256-RSA-PKCS", "rsa-sha256" }, + { CKM_SHA384_RSA_PKCS, "SHA384-RSA-PKCS", "rsa-sha384" }, + { CKM_SHA512_RSA_PKCS, "SHA512-RSA-PKCS", "rsa-sha512" }, { CKM_RIPEMD128_RSA_PKCS, "RIPEMD128-RSA-PKCS", NULL }, { CKM_RIPEMD160_RSA_PKCS, "RIPEMD160-RSA-PKCS", "rsa-ripemd160" }, { CKM_RSA_PKCS_OAEP, "RSA-PKCS-OAEP", NULL }, @@ -3337,6 +3340,9 @@ static struct mech_info p11_mechanisms[] = { { CKM_SHA1_RSA_X9_31, "SHA1-RSA-X9-31", NULL }, { CKM_RSA_PKCS_PSS, "RSA-PKCS-PSS", NULL }, { CKM_SHA1_RSA_PKCS_PSS, "SHA1-RSA-PKCS-PSS", NULL }, + { CKM_SHA256_RSA_PKCS, "SHA256-RSA-PKCS-PSS", NULL }, + { CKM_SHA384_RSA_PKCS, "SHA384-RSA-PKCS-PSS", NULL }, + { CKM_SHA512_RSA_PKCS, "SHA512-RSA-PKCS-PSS", NULL }, { CKM_DSA_KEY_PAIR_GEN, "DSA-KEY-PAIR-GEN", NULL }, { CKM_DSA, "DSA", NULL }, { CKM_DSA_SHA1, "DSA-SHA1", NULL }, @@ -3382,6 +3388,9 @@ static struct mech_info p11_mechanisms[] = { { CKM_SHA_1, "SHA-1", NULL }, { CKM_SHA_1_HMAC, "SHA-1-HMAC", NULL }, { CKM_SHA_1_HMAC_GENERAL, "SHA-1-HMAC-GENERAL", NULL }, + { CKM_SHA256, "SHA256", NULL }, + { CKM_SHA384, "SHA384", NULL }, + { CKM_SHA512, "SHA512", NULL }, { CKM_RIPEMD128, "RIPEMD128", NULL }, { CKM_RIPEMD128_HMAC, "RIPEMD128-HMAC", NULL }, { CKM_RIPEMD128_HMAC_GENERAL,"RIPEMD128-HMAC-GENERAL", NULL }, diff --git a/src/tools/pkcs15-crypt.c b/src/tools/pkcs15-crypt.c index df7d9b82..5f7ab8a0 100644 --- a/src/tools/pkcs15-crypt.c +++ b/src/tools/pkcs15-crypt.c @@ -46,6 +46,10 @@ int opt_crypt_flags = 0; enum { OPT_SHA1 = 0x100, + OPT_SHA256, + OPT_SHA384, + OPT_SHA512, + OPT_SHA224, OPT_MD5, OPT_PKCS1, }; @@ -59,6 +63,10 @@ const struct option options[] = { { "output", 1, 0, 'o' }, { "raw", 0, 0, 'R' }, { "sha-1", 0, 0, OPT_SHA1 }, + { "sha-256", 0, 0, OPT_SHA256 }, + { "sha-384", 0, 0, OPT_SHA384 }, + { "sha-512", 0, 0, OPT_SHA512 }, + { "sha-224", 0, 0, OPT_SHA224 }, { "md5", 0, 0, OPT_MD5 }, { "pkcs1", 0, 0, OPT_PKCS1 }, { "pin", 1, 0, 'p' }, @@ -76,6 +84,10 @@ const char *option_help[] = { "Outputs to file ", "Outputs raw 8 bit data", "Input file is a SHA-1 hash", + "Input file is a SHA-256 hash", + "Input file is a SHA-384 hash", + "Input file is a SHA-512 hash", + "Input file is a SHA-224 hash", "Input file is a MD5 hash", "Use PKCS #1 v1.5 padding", "Uses password (PIN) (use - for reading PIN from STDIN)", @@ -510,6 +522,18 @@ int main(int argc, char * const argv[]) case OPT_SHA1: opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_SHA1; break; + case OPT_SHA256: + opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_SHA256; + break; + case OPT_SHA384: + opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_SHA384; + break; + case OPT_SHA512: + opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_SHA512; + break; + case OPT_SHA224: + opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_SHA224; + break; case OPT_MD5: opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_MD5; break;