From 7f6453d715e77b9ef69d6da59c39b8aab93cf81b Mon Sep 17 00:00:00 2001 From: okir Date: Tue, 23 Apr 2002 08:17:06 +0000 Subject: [PATCH] - sc_pkcs15_decipher now takes a flags argument, so we know when to strip off any pkcs#1 padding. git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@585 c6295689-39f2-0310-b995-f0e70906c6a9 --- src/libopensc/errors.h | 1 + src/libopensc/pkcs15-sec.c | 52 +++++++++++++++++++++++++++++++++++ src/libopensc/pkcs15.h | 1 + src/pkcs11/framework-pkcs15.c | 1 + src/tools/pkcs15-crypt.c | 4 ++- 5 files changed, 58 insertions(+), 1 deletion(-) diff --git a/src/libopensc/errors.h b/src/libopensc/errors.h index db1f73ba..0db6bb11 100644 --- a/src/libopensc/errors.h +++ b/src/libopensc/errors.h @@ -75,6 +75,7 @@ extern "C" { #define SC_ERROR_NOT_SUPPORTED -1408 #define SC_ERROR_PASSPHRASE_REQUIRED -1409 #define SC_ERROR_EXTRACTABLE_KEY -1410 +#define SC_ERROR_DECRYPT_FAILED -1411 /* Relating to PKCS #15 init stuff */ #define SC_ERROR_PKCS15INIT -1500 diff --git a/src/libopensc/pkcs15-sec.c b/src/libopensc/pkcs15-sec.c index 29c2c6f6..ebb264a0 100644 --- a/src/libopensc/pkcs15-sec.c +++ b/src/libopensc/pkcs15-sec.c @@ -27,15 +27,37 @@ #include #include +static int pkcs1_strip_padding(u8 *data, size_t len) +{ + unsigned int n = 0; + + if (data[0] != 0x00 && data[1] != 0x02) + return SC_ERROR_DECRYPT_FAILED; + /* Skip over padding bytes */ + for (n = 2; n < len && data[n]; n++) + ; + /* Must be at least 8 pad bytes */ + if (n >= len || n < 10) + return SC_ERROR_DECRYPT_FAILED; + n++; + + /* Now move decrypted contents to head of buffer */ + memmove(data, data + n, len - n); + return len - n; +} + 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) { int r; + struct sc_algorithm_info *alg_info; struct sc_security_env senv; struct sc_context *ctx = p15card->card->ctx; struct sc_path path, file_id; const struct sc_pkcs15_prkey_info *prkey = (const struct sc_pkcs15_prkey_info *) obj->data; + unsigned long pad_flags = 0; /* If the key is extractable, the caller should extract the * key and do the crypto himself */ @@ -53,9 +75,32 @@ int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card, file_id.len = 2; path.len -= 2; } + + alg_info = _sc_card_find_rsa_alg(p15card->card, prkey->modulus_length); + if (alg_info == NULL) { + error(ctx, "Card does not support RSA with key length %d\n", prkey->modulus_length); + 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)) { + error(ctx, "Only PKCS #1 padding method supported\n"); + return SC_ERROR_NOT_SUPPORTED; + } else { + if (!(alg_info->flags & SC_ALGORITHM_RSA_RAW)) { + error(ctx, "Card requires RSA padding\n"); + return SC_ERROR_NOT_SUPPORTED; + } + senv.algorithm_flags |= SC_ALGORITHM_RSA_RAW; + } + senv.file_ref = file_id; senv.operation = SC_SEC_OPERATION_DECIPHER; senv.key_ref_len = 1; @@ -75,6 +120,13 @@ int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card, SC_TEST_RET(ctx, r, "sc_set_security_env() failed"); r = sc_decipher(p15card->card, in, inlen, out, outlen); SC_TEST_RET(ctx, r, "sc_decipher() failed"); + + /* Strip any padding */ + if (pad_flags & SC_ALGORITHM_RSA_PAD_PKCS1) { + r = pkcs1_strip_padding(out, r); + SC_TEST_RET(ctx, r, "Invalid PKCS#1 padding"); + } + return r; } diff --git a/src/libopensc/pkcs15.h b/src/libopensc/pkcs15.h index ed5b9ec6..ed3f9cde 100644 --- a/src/libopensc/pkcs15.h +++ b/src/libopensc/pkcs15.h @@ -353,6 +353,7 @@ void sc_pkcs15_print_card(const struct sc_pkcs15_card *card); int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_object *prkey_obj, + unsigned long flags, const u8 *in, size_t inlen, u8 *out, size_t outlen); int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card, diff --git a/src/pkcs11/framework-pkcs15.c b/src/pkcs11/framework-pkcs15.c index 9be5d4a5..1c1cfce1 100644 --- a/src/pkcs11/framework-pkcs15.c +++ b/src/pkcs11/framework-pkcs15.c @@ -1184,6 +1184,7 @@ pkcs15_prkey_unwrap(struct sc_pkcs11_session *ses, void *obj, p15card = (struct sc_pkcs15_card*) ses->slot->card->fw_data; prkey = (struct pkcs15_prkey_object *) obj; rv = sc_pkcs15_decipher(p15card, prkey->prkey_object, + SC_ALGORITHM_RSA_PAD_PKCS1, pData, ulDataLen, unwrapped_key, sizeof(unwrapped_key)); debug(context, "Key unwrap complete. Result %d.\n", rv); diff --git a/src/tools/pkcs15-crypt.c b/src/tools/pkcs15-crypt.c index c2fc4054..636ed1e6 100644 --- a/src/tools/pkcs15-crypt.c +++ b/src/tools/pkcs15-crypt.c @@ -371,7 +371,9 @@ int decipher(struct sc_pkcs15_object *obj) r = SC_ERROR_NOT_SUPPORTED; #endif } else { - r = sc_pkcs15_decipher(p15card, obj, buf, c, out, len); + r = sc_pkcs15_decipher(p15card, obj, + opt_crypt_flags & SC_ALGORITHM_RSA_PAD_PKCS1, + buf, c, out, len); } if (r < 0) {