summaryrefslogtreecommitdiff
path: root/source/pdf
diff options
context:
space:
mode:
authorPaul Gardiner <paul.gardiner@artifex.com>2018-01-23 10:02:43 +0000
committerPaul Gardiner <paul.gardiner@artifex.com>2018-02-02 12:36:13 +0000
commit0312fb0efa320655905bd72b1af4228f017a8498 (patch)
tree4cadc1ad478bd6ccf42cbebbf755ac8e146e7d2a /source/pdf
parent8ac8d47f25b2868d464be71ed3b9ed04b71cb524 (diff)
downloadmupdf-0312fb0efa320655905bd72b1af4228f017a8498.tar.xz
Signature support: simplify pkcs7 api by the removal of byte ranges.
Rather than provide a stream and an explicitly defined set of byte ranges within that stream, provide a stream that gives access to just the bytes in the ranges.
Diffstat (limited to 'source/pdf')
-rw-r--r--source/pdf/pdf-form.c6
-rw-r--r--source/pdf/pdf-pkcs7.c162
-rw-r--r--source/pdf/pdf-signature.c22
3 files changed, 23 insertions, 167 deletions
diff --git a/source/pdf/pdf-form.c b/source/pdf/pdf-form.c
index 63562ef6..36d07ee1 100644
--- a/source/pdf/pdf-form.c
+++ b/source/pdf/pdf-form.c
@@ -1277,7 +1277,7 @@ void pdf_choice_widget_set_value(fz_context *ctx, pdf_document *doc, pdf_widget
}
}
-int pdf_signature_widget_byte_range(fz_context *ctx, pdf_document *doc, pdf_widget *widget, int (*byte_range)[2])
+int pdf_signature_widget_byte_range(fz_context *ctx, pdf_document *doc, pdf_widget *widget, fz_range *byte_range)
{
pdf_annot *annot = (pdf_annot *)widget;
pdf_obj *br = pdf_dict_getl(ctx, annot->obj, PDF_NAME_V, PDF_NAME_ByteRange, NULL);
@@ -1287,8 +1287,8 @@ int pdf_signature_widget_byte_range(fz_context *ctx, pdf_document *doc, pdf_widg
{
for (i = 0; i < n; i++)
{
- byte_range[i][0] = pdf_to_int(ctx, pdf_array_get(ctx, br, 2*i));
- byte_range[i][1] = pdf_to_int(ctx, pdf_array_get(ctx, br, 2*i+1));
+ byte_range[i].offset = pdf_to_int(ctx, pdf_array_get(ctx, br, 2*i));
+ byte_range[i].len = pdf_to_int(ctx, pdf_array_get(ctx, br, 2*i+1));
}
}
diff --git a/source/pdf/pdf-pkcs7.c b/source/pdf/pdf-pkcs7.c
index f095e586..7f4e15b1 100644
--- a/source/pdf/pdf-pkcs7.c
+++ b/source/pdf/pdf-pkcs7.c
@@ -167,137 +167,6 @@ static BIO *BIO_new_stream(fz_context *ctx, fz_stream *stm)
return bio;
}
-enum
-{
- SEG_START = 0,
- SEG_SIZE = 1
-};
-
-typedef struct bsegs_struct
-{
- int (*seg)[2];
- int nsegs;
- int current_seg;
- int seg_pos;
-} BIO_SEGS_CTX;
-
-static int bsegs_read(BIO *b, char *buf, int size)
-{
- BIO_SEGS_CTX *ctx = (BIO_SEGS_CTX *) BIO_get_data(b);
- int read = 0;
-
- while (size > 0 && ctx->current_seg < ctx->nsegs)
- {
- int nb = ctx->seg[ctx->current_seg][SEG_SIZE] - ctx->seg_pos;
-
- if (nb > size)
- nb = size;
-
- if (nb > 0)
- {
- if (ctx->seg_pos == 0)
- {
- if (BIO_seek(BIO_next(b), ctx->seg[ctx->current_seg][SEG_START]) < 0)
- return read;
- }
-
- nb = BIO_read(BIO_next(b), buf, nb);
- if (nb <= 0)
- return read;
-
- ctx->seg_pos += nb;
- read += nb;
- buf += nb;
- size -= nb;
- }
- else
- {
- ctx->current_seg++;
-
- if (ctx->current_seg < ctx->nsegs)
- ctx->seg_pos = 0;
- }
- }
-
- return read;
-}
-
-static long bsegs_ctrl(BIO *b, int cmd, long arg1, void *arg2)
-{
- return BIO_ctrl(BIO_next(b), cmd, arg1, arg2);
-}
-
-static int bsegs_new(BIO *b)
-{
- BIO_SEGS_CTX *ctx;
-
- ctx = (BIO_SEGS_CTX *)malloc(sizeof(BIO_SEGS_CTX));
- if (ctx == NULL)
- return 0;
-
- ctx->current_seg = 0;
- ctx->seg_pos = 0;
- ctx->seg = NULL;
- ctx->nsegs = 0;
-
- BIO_set_init(b, 1);
- BIO_set_data(b, ctx);
- BIO_clear_flags(b, INT_MAX);
-
- return 1;
-}
-
-static int bsegs_free(BIO *b)
-{
- if (b == NULL)
- return 0;
-
- free(BIO_get_data(b));
- BIO_set_data(b, NULL);
- BIO_set_init(b, 0);
- BIO_clear_flags(b, INT_MAX);
-
- return 1;
-}
-
-static long bsegs_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
-{
- return BIO_callback_ctrl(BIO_next(b), cmd, fp);
-}
-
-static BIO_METHOD *methods_bsegs = NULL;
-
-static BIO_METHOD *BIO_f_segments(void)
-{
- if (methods_bsegs)
- return methods_bsegs;
-
- methods_bsegs = BIO_meth_new(BIO_TYPE_NONE, "segment reader");
- if (!methods_bsegs)
- return NULL;
-
- if (!BIO_meth_set_read(methods_bsegs, bsegs_read) ||
- !BIO_meth_set_ctrl(methods_bsegs, bsegs_ctrl) ||
- !BIO_meth_set_create(methods_bsegs, bsegs_new) ||
- !BIO_meth_set_destroy(methods_bsegs, bsegs_free) ||
- !BIO_meth_set_callback_ctrl(methods_bsegs, bsegs_callback_ctrl))
-
- {
- BIO_meth_free(methods_bsegs);
- methods_bsegs = NULL;
- }
-
- return methods_bsegs;
-}
-
-static void BIO_set_segments(BIO *b, int (*seg)[2], int nsegs)
-{
- BIO_SEGS_CTX *ctx = (BIO_SEGS_CTX *) BIO_get_data(b);
-
- ctx->seg = seg;
- ctx->nsegs = nsegs;
-}
-
static int verify_callback(int ok, X509_STORE_CTX *ctx)
{
int err, depth;
@@ -498,12 +367,11 @@ exit:
return res;
}
-SignatureError pdf_pkcs7_check_digest(fz_context *ctx, fz_stream *stm, char *sig, int sig_len, int (*byte_range)[2], int byte_range_len)
+SignatureError pdf_pkcs7_check_digest(fz_context *ctx, fz_stream *stm, char *sig, int sig_len)
{
PKCS7 *pk7sig = NULL;
BIO *bsig = NULL;
BIO *bdata = NULL;
- BIO *bsegs = NULL;
STACK_OF(X509) *certs = NULL;
int res = SignatureError_Unknown;
@@ -516,19 +384,11 @@ SignatureError pdf_pkcs7_check_digest(fz_context *ctx, fz_stream *stm, char *sig
if (bdata == NULL)
goto exit;
- bsegs = BIO_new(BIO_f_segments());
- if (bsegs == NULL)
- goto exit;
-
- BIO_set_next(bsegs, bdata);
- BIO_set_segments(bsegs, byte_range, byte_range_len);
-
- res = pk7_verify_sig(pk7sig, bsegs);
+ res = pk7_verify_sig(pk7sig, bdata);
exit:
BIO_free(bsig);
BIO_free(bdata);
- BIO_free(bsegs);
PKCS7_free(pk7sig);
return res;
@@ -794,11 +654,10 @@ pdf_pkcs7_designated_name *pdf_pkcs7_signer_designated_name(fz_context *ctx, pdf
return x509_designated_name(ctx, signer->x509);
}
-int pdf_pkcs7_create_digest(fz_context *ctx, fz_stream *in, int brange[][2], int brange_len, pdf_pkcs7_signer *signer, unsigned char *digest, int *digest_len)
+int pdf_pkcs7_create_digest(fz_context *ctx, fz_stream *in, pdf_pkcs7_signer *signer, unsigned char *digest, int *digest_len)
{
int res = 0;
BIO *bdata = NULL;
- BIO *bsegs = NULL;
BIO *bp7in = NULL;
BIO *bp7 = NULL;
PKCS7 *p7 = NULL;
@@ -811,12 +670,6 @@ int pdf_pkcs7_create_digest(fz_context *ctx, fz_stream *in, int brange[][2], int
if (bdata == NULL)
goto exit;
- bsegs = BIO_new(BIO_f_segments());
- if (bsegs == NULL)
- goto exit;
-
- BIO_set_next(bsegs, bdata);
- BIO_set_segments(bsegs, brange, brange_len);
p7 = PKCS7_new();
if (p7 == NULL)
@@ -840,7 +693,7 @@ int pdf_pkcs7_create_digest(fz_context *ctx, fz_stream *in, int brange[][2], int
while(1)
{
char buf[4096];
- int n = BIO_read(bsegs, buf, sizeof(buf));
+ int n = BIO_read(bdata, buf, sizeof(buf));
if (n <= 0)
break;
BIO_write(bp7in, buf, n);
@@ -849,8 +702,6 @@ int pdf_pkcs7_create_digest(fz_context *ctx, fz_stream *in, int brange[][2], int
if (!PKCS7_dataFinal(p7, bp7in))
goto exit;
- BIO_free(bsegs);
- bsegs = NULL;
BIO_free(bdata);
bdata = NULL;
@@ -868,7 +719,6 @@ int pdf_pkcs7_create_digest(fz_context *ctx, fz_stream *in, int brange[][2], int
exit:
PKCS7_free(p7);
- BIO_free(bsegs);
BIO_free(bdata);
BIO_free(bp7in);
BIO_free(bp7);
@@ -911,7 +761,7 @@ int pdf_pkcs7_supported(fz_context *ctx)
#else /* HAVE_LIBCRYPTO */
-SignatureError pdf_pkcs7_check_digest(fz_context *ctx, fz_stream *stm, char *sig, int sig_len, int (*byte_range)[2], int byte_range_len)
+SignatureError pdf_pkcs7_check_digest(fz_context *ctx, fz_stream *stm, char *sig, int sig_len)
{
return SignatureError_Unknown;
}
@@ -949,7 +799,7 @@ pdf_pkcs7_designated_name *pdf_pkcs7_signer_designated_name(fz_context *ctx, pdf
return NULL;
}
-int pdf_pkcs7_create_digest(fz_context *ctx, fz_stream *in, int brange[][2], int brange_len, pdf_pkcs7_signer *signer, unsigned char *digest, int *digest_len)
+int pdf_pkcs7_create_digest(fz_context *ctx, fz_stream *in, pdf_pkcs7_signer *signer, unsigned char *digest, int *digest_len)
{
return 0;
}
diff --git a/source/pdf/pdf-signature.c b/source/pdf/pdf-signature.c
index ade5bc57..511023c1 100644
--- a/source/pdf/pdf-signature.c
+++ b/source/pdf/pdf-signature.c
@@ -27,7 +27,7 @@ static void pdf_print_designated_name(pdf_pkcs7_designated_name *name, char *buf
void pdf_write_digest(fz_context *ctx, fz_output *out, pdf_obj *byte_range, int hexdigest_offset, int hexdigest_length, pdf_pkcs7_signer *signer)
{
fz_stream *in = NULL;
- int (*brange)[2] = NULL;
+ fz_range *brange = NULL;
int brange_len = pdf_array_len(ctx, byte_range)/2;
unsigned char *digest = NULL;
int digest_len;
@@ -42,18 +42,18 @@ void pdf_write_digest(fz_context *ctx, fz_output *out, pdf_obj *byte_range, int
{
int i, res;
- in = fz_stream_from_output(ctx, out);
-
brange = fz_calloc(ctx, brange_len, sizeof(*brange));
for (i = 0; i < brange_len; i++)
{
- brange[i][0] = pdf_to_int(ctx, pdf_array_get(ctx, byte_range, 2*i));
- brange[i][1] = pdf_to_int(ctx, pdf_array_get(ctx, byte_range, 2*i+1));
+ brange[i].offset = pdf_to_int(ctx, pdf_array_get(ctx, byte_range, 2*i));
+ brange[i].len = pdf_to_int(ctx, pdf_array_get(ctx, byte_range, 2*i+1));
}
+ in = fz_open_null_n(ctx, fz_stream_from_output(ctx, out), brange, brange_len);
+
digest_len = (hexdigest_length - 2) / 2;
digest = fz_malloc(ctx, digest_len);
- res = pdf_pkcs7_create_digest(ctx, in, brange, brange_len, signer, digest, &digest_len);
+ res = pdf_pkcs7_create_digest(ctx, in, signer, digest, &digest_len);
if (!res)
fz_throw(ctx, FZ_ERROR_GENERIC, "pdf_pkcs7_create_digest failed");
@@ -79,8 +79,9 @@ void pdf_write_digest(fz_context *ctx, fz_output *out, pdf_obj *byte_range, int
int pdf_check_signature(fz_context *ctx, pdf_document *doc, pdf_widget *widget, char *ebuf, int ebufsize)
{
- int (*byte_range)[2] = NULL;
+ fz_range *byte_range = NULL;
int byte_range_len;
+ fz_stream *bytes = NULL;
char *contents = NULL;
int contents_len;
int res = 0;
@@ -94,6 +95,7 @@ int pdf_check_signature(fz_context *ctx, pdf_document *doc, pdf_widget *widget,
}
fz_var(byte_range);
+ fz_var(bytes);
fz_var(res);
fz_try(ctx)
{
@@ -107,7 +109,10 @@ int pdf_check_signature(fz_context *ctx, pdf_document *doc, pdf_widget *widget,
contents_len = pdf_signature_widget_contents(ctx, doc, widget, &contents);
if (byte_range && contents)
{
- SignatureError err = pdf_pkcs7_check_digest(ctx, doc->file, contents, contents_len, byte_range, byte_range_len);
+ SignatureError err;
+
+ bytes = fz_open_null_n(ctx, fz_keep_stream(ctx, doc->file), byte_range, byte_range_len);
+ err = pdf_pkcs7_check_digest(ctx, bytes, contents, contents_len);
if (err == SignatureError_Okay)
err = pdf_pkcs7_check_certificate(contents, contents_len);
switch (err)
@@ -170,6 +175,7 @@ int pdf_check_signature(fz_context *ctx, pdf_document *doc, pdf_widget *widget,
}
fz_always(ctx)
{
+ fz_drop_stream(ctx, bytes);
fz_free(ctx, byte_range);
}
fz_catch(ctx)