- Change padding functions
git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@1264 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
parent
0a05d8340c
commit
95e2d8b78a
|
@ -32,7 +32,7 @@ bin_SCRIPTS = opensc-config
|
|||
lib_LTLIBRARIES = libopensc.la
|
||||
libopensc_la_SOURCES = sc.c ctx.c module.c asn1.c log.c base64.c \
|
||||
errors.c sec.c card.c iso7816.c dir.c \
|
||||
portability.c \
|
||||
portability.c padding.c \
|
||||
pkcs15.c pkcs15-cert.c pkcs15-data.c pkcs15-pin.c \
|
||||
pkcs15-prkey.c pkcs15-pubkey.c pkcs15-sec.c \
|
||||
pkcs15-wrap.c pkcs15-algo.c \
|
||||
|
|
|
@ -1071,11 +1071,10 @@ static int starcos_compute_signature(struct sc_card *card,
|
|||
/* create DigestInfo structure ? */
|
||||
if (mse->fix_digestInfo)
|
||||
{
|
||||
unsigned int flags = mse->fix_digestInfo & SC_ALGORITHM_RSA_HASHES;
|
||||
tmp_len = sizeof(sbuf);
|
||||
r = sc_add_padding(card->ctx, data, datalen,
|
||||
sbuf, &tmp_len,
|
||||
mse->fix_digestInfo & SC_ALGORITHM_RSA_HASHES,
|
||||
sizeof(sbuf));
|
||||
r = sc_pkcs1_encode(card->ctx, flags, data, datalen,
|
||||
sbuf, &tmp_len, sizeof(sbuf));
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -762,9 +762,20 @@ int sc_reset_retry_counter(struct sc_card *card, unsigned int type,
|
|||
int ref, const u8 *puk, size_t puklen,
|
||||
const u8 *newref, size_t newlen);
|
||||
int sc_build_pin(u8 *buf, size_t buflen, struct sc_pin_cmd_pin *pin, int pad);
|
||||
int sc_add_padding(struct sc_context *ctx, const u8 *in, size_t inlen, u8 *out,
|
||||
size_t *outlen, unsigned long flags, unsigned int mod_length);
|
||||
|
||||
/* 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);
|
||||
int sc_pkcs1_encode(struct sc_context *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);
|
||||
/* ISO 7816-9 */
|
||||
int sc_create_file(struct sc_card *card, struct sc_file *file);
|
||||
int sc_delete_file(struct sc_card *card, const struct sc_path *path);
|
||||
|
|
|
@ -0,0 +1,261 @@
|
|||
/*
|
||||
* sc-padding.c: miscellaneous padding functions
|
||||
*
|
||||
* Copyright (C) 2001, 2002 Juha Yrjölä <juha.yrjola@iki.fi>
|
||||
* Copyright (C) 2003 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
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "errors.h"
|
||||
#include "internal.h"
|
||||
#include "log.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_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] = {
|
||||
{ SC_ALGORITHM_RSA_HASH_NONE, NULL, 0, -1 },
|
||||
{ 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_RIPEMD160,hdr_ripemd160, sizeof(hdr_ripemd160), 20 },
|
||||
{ SC_ALGORITHM_RSA_HASH_MD5_SHA1, NULL, 0, 36 },
|
||||
{ 0, NULL, 0, -1 }
|
||||
};
|
||||
|
||||
/* 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)
|
||||
{
|
||||
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; /* XXX the leading zero octet does not really
|
||||
* belong to the pkcs1 BT01 padding -- Nils */
|
||||
*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(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 */
|
||||
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(const u8 *data, size_t len, u8 *out,
|
||||
size_t *out_len)
|
||||
{
|
||||
unsigned int n = 0;
|
||||
|
||||
if (data == NULL || len < 3)
|
||||
return SC_ERROR_INTERNAL;
|
||||
/* skip leading zero octet (not part of the pkcs1 BT02 padding) */
|
||||
if (*data == 0) {
|
||||
data++;
|
||||
len--;
|
||||
}
|
||||
if (data[0] != 0x02)
|
||||
return 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)
|
||||
return SC_ERROR_WRONG_PADDING;
|
||||
n++;
|
||||
if (out == NULL)
|
||||
/* just check the padding */
|
||||
return SC_SUCCESS;
|
||||
/* Now move decrypted contents to head of buffer */
|
||||
if (*out_len < len - n)
|
||||
return SC_ERROR_INTERNAL;
|
||||
memmove(out, data + n, len - n);
|
||||
return len - n;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < DIGEST_INFO_COUNT; 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; i < DIGEST_INFO_COUNT; 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;
|
||||
}
|
||||
|
||||
/* general PKCS#1 encoding function */
|
||||
int sc_pkcs1_encode(struct sc_context *ctx, unsigned long flags,
|
||||
const u8 *in, size_t in_len, u8 *out, size_t *out_len, size_t mod_len)
|
||||
{
|
||||
int i;
|
||||
size_t tmp_len = *out_len;
|
||||
const u8 *tmp = in;
|
||||
unsigned int hash_algo, pad_algo;
|
||||
|
||||
hash_algo = flags & SC_ALGORITHM_RSA_HASHES;
|
||||
pad_algo = flags & SC_ALGORITHM_RSA_PADS;
|
||||
|
||||
if (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) {
|
||||
error(ctx, "Unable to add digest info 0x%x\n",
|
||||
hash_algo);
|
||||
return i;
|
||||
}
|
||||
tmp = out;
|
||||
} else
|
||||
tmp_len = in_len;
|
||||
|
||||
switch(pad_algo) {
|
||||
case SC_ALGORITHM_RSA_PAD_NONE:
|
||||
/* padding done by card => nothing to do */
|
||||
*out_len = tmp_len;
|
||||
return SC_SUCCESS;
|
||||
case SC_ALGORITHM_RSA_PAD_PKCS1:
|
||||
/* add pkcs1 bt01 padding */
|
||||
return sc_pkcs1_add_01_padding(tmp, tmp_len, out, out_len,
|
||||
mod_len);
|
||||
default:
|
||||
/* currently only pkcs1 padding is supported */
|
||||
error(ctx, "Unsupported padding algorithm 0x%x\n", pad_algo);
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
while (*in == 0 && in_len) {
|
||||
in++;
|
||||
in_len--;
|
||||
}
|
||||
|
||||
if (*out_len < in_len)
|
||||
return SC_ERROR_INTERNAL;
|
||||
|
||||
memmove(out, in, in_len);
|
||||
*out_len = in_len;
|
||||
|
||||
return SC_SUCCESS;
|
||||
}
|
|
@ -29,54 +29,6 @@
|
|||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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_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] = {
|
||||
{ SC_ALGORITHM_RSA_HASH_NONE, NULL, 0, -1 },
|
||||
{ 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_RIPEMD160,hdr_ripemd160, sizeof(hdr_ripemd160), 20 },
|
||||
{ SC_ALGORITHM_RSA_HASH_MD5_SHA1, NULL, 0, 36 },
|
||||
{ 0, NULL, 0, -1 }
|
||||
};
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static int select_key_file(struct sc_pkcs15_card *p15card,
|
||||
const struct sc_pkcs15_prkey_info *prkey,
|
||||
struct sc_security_env *senv)
|
||||
|
@ -181,99 +133,13 @@ int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card,
|
|||
|
||||
/* Strip any padding */
|
||||
if (pad_flags & SC_ALGORITHM_RSA_PAD_PKCS1) {
|
||||
r = pkcs1_strip_padding(out, r);
|
||||
r = sc_pkcs1_strip_02_padding(out, r, out, &r);
|
||||
SC_TEST_RET(ctx, r, "Invalid PKCS#1 padding");
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* No padding required - card will add the padding itself
|
||||
*/
|
||||
static int add_no_padding(const struct digest_info_prefix *pfx,
|
||||
const u8 *in, size_t inlen,
|
||||
u8 *out, size_t *outlen,
|
||||
size_t mod_length)
|
||||
{
|
||||
size_t msglen = pfx->hdr_len + inlen;
|
||||
|
||||
if (msglen > mod_length)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
if (msglen > *outlen)
|
||||
return SC_ERROR_BUFFER_TOO_SMALL;
|
||||
memcpy(out, pfx->hdr, pfx->hdr_len);
|
||||
memcpy(out + pfx->hdr_len, in, inlen);
|
||||
|
||||
*outlen = msglen;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add pkcs1 padding
|
||||
*/
|
||||
static int add_pkcs1_padding(const struct digest_info_prefix *pfx,
|
||||
const u8 *in, size_t inlen,
|
||||
u8 *out, size_t *outlen,
|
||||
size_t mod_length)
|
||||
{
|
||||
size_t msglen = pfx->hdr_len + inlen;
|
||||
int i;
|
||||
|
||||
if (*outlen < mod_length)
|
||||
return SC_ERROR_BUFFER_TOO_SMALL;
|
||||
if (msglen + 11 > mod_length)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
*out++ = 0x00;
|
||||
*out++ = 0x01;
|
||||
|
||||
i = mod_length - 3 - msglen;
|
||||
memset(out, 0xFF, i);
|
||||
out += i;
|
||||
*out++ = 0x00;
|
||||
memcpy(out, pfx->hdr, pfx->hdr_len);
|
||||
memcpy(out + pfx->hdr_len, in, inlen);
|
||||
|
||||
*outlen = mod_length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add padding - we should probably move this to sec.c
|
||||
*/
|
||||
int sc_add_padding(struct sc_context *ctx, const u8 *in, size_t inlen, u8 *out,
|
||||
size_t *outlen, unsigned long flags, unsigned int mod_length)
|
||||
{
|
||||
const struct digest_info_prefix *pfx;
|
||||
int j, pad_algo;
|
||||
unsigned int hash_algo;
|
||||
|
||||
hash_algo = flags & SC_ALGORITHM_RSA_HASHES;
|
||||
pad_algo = flags & SC_ALGORITHM_RSA_PADS;
|
||||
|
||||
for (j = DIGEST_INFO_COUNT, pfx = digest_info_prefix; j-- >= 0; pfx++) {
|
||||
if (pfx->algorithm == hash_algo)
|
||||
break;
|
||||
}
|
||||
if (j < 0) {
|
||||
error(ctx, "Unsupported digest algorithm 0x%x\n", hash_algo);
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (pfx->hash_len > 0 && inlen != pfx->hash_len)
|
||||
return SC_ERROR_WRONG_LENGTH;
|
||||
|
||||
switch (pad_algo) {
|
||||
case SC_ALGORITHM_RSA_PAD_NONE: /* padding done by card */
|
||||
return add_no_padding(pfx, in, inlen, out, outlen, mod_length);
|
||||
case SC_ALGORITHM_RSA_PAD_PKCS1:
|
||||
return add_pkcs1_padding(pfx, in, inlen, out, outlen, mod_length);
|
||||
default:
|
||||
error(ctx, "Unsupported padding algorithm 0x%x\n", pad_algo);
|
||||
return SC_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
|
||||
const struct sc_pkcs15_object *obj,
|
||||
unsigned long flags, const u8 *in, size_t inlen,
|
||||
|
@ -378,8 +244,8 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
|
|||
}
|
||||
if (pad_flags) {
|
||||
buflen = sizeof(buf);
|
||||
r = sc_add_padding(ctx, in, inlen, buf, &buflen, pad_flags,
|
||||
prkey->modulus_length/8);
|
||||
r = sc_pkcs1_encode(ctx, pad_flags, in, inlen, buf, &buflen,
|
||||
prkey->modulus_length/8);
|
||||
SC_TEST_RET(ctx, r, "Unable to add padding");
|
||||
in = buf;
|
||||
inlen = buflen;
|
||||
|
|
Loading…
Reference in New Issue