From 0312fb0efa320655905bd72b1af4228f017a8498 Mon Sep 17 00:00:00 2001 From: Paul Gardiner Date: Tue, 23 Jan 2018 10:02:43 +0000 Subject: 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. --- source/pdf/pdf-form.c | 6 +- source/pdf/pdf-pkcs7.c | 162 ++------------------------------------------- source/pdf/pdf-signature.c | 22 +++--- 3 files changed, 23 insertions(+), 167 deletions(-) (limited to 'source/pdf') 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) -- cgit v1.2.3