Commit 5be1315c authored by Tomáš Stefan's avatar Tomáš Stefan

Read data for PKCS#1 verification

Read /Cert, /Contents and /ByteRange from signature dictionary. This
still needs to be improved, but looks like it at least partially works.
parent 0d8311c5
#ifndef PDF_SIGIL_CERT_H
#define PDF_SIGIL_CERT_H
#include "types.h"
sigil_err_t parse_certs(sigil_t *sgl);
int sigil_sigil_self_test(int verbosity);
#endif /* PDF_SIGIL_CERT_H */
......@@ -12,7 +12,13 @@
#define XREF_PREALLOCATION 10
// capacity to choose for the first allocation in array of fields
#define REF_ARRAY_PREALLOCATION 10
#define REF_ARRAY_PREALLOCATION 10
// capacity to choose for the first allocation of array for certificates
#define CERT_HEX_PREALLOCATION 1024
// capacity to choose for the first allocation of array for contents
#define CONTENTS_PREALLOCATION 1024
// threshold in bytes for loading whole file into buffer
#define THRESHOLD_FILE_BUFFERING 10485760
......
#ifndef PDF_SIGIL_CONTENTS_H
#define PDF_SIGIL_CONTENTS_H
#include "types.h"
sigil_err_t parse_contents(sigil_t *sgl);
int sigil_sigil_self_test(int verbosity);
#endif //PDF_SIGIL_CONTENTS_H
......@@ -21,6 +21,17 @@ typedef struct {
size_t generation_num;
} reference_t;
typedef struct {
char *contents_hex;
size_t capacity;
} contents_t;
typedef struct cert_t {
char *cert_hex;
size_t capacity;
struct cert_t *next;
} cert_t;
typedef struct range_t {
size_t start;
size_t length;
......@@ -71,6 +82,8 @@ typedef struct {
size_t sig_flags;
subfilter_t subfilter;
range_t *byte_range;
cert_t *certificates;
contents_t *contents;
} sigil_t;
#endif /* PDF_SIGIL_TYPES_H */
#include <stdlib.h>
#include <types.h>
#include "auxiliary.h"
#include "cert.h"
#include "config.h"
#include "constants.h"
#include "types.h"
sigil_err_t parse_one_cert(sigil_t *sgl, cert_t **result)
{
sigil_err_t err;
char c;
char **data;
size_t position;
if (sgl == NULL || result == NULL)
return ERR_PARAMETER;
if (*result != NULL)
; // TODO free result
*result = NULL;
if ((err = parse_word(sgl, "<")) != ERR_NO)
return err;
*result = malloc(sizeof(**result));
if (*result == NULL)
return ERR_ALLOCATION;
sigil_zeroize(*result, sizeof(**result));
data = &((*result)->cert_hex);
*data = malloc(sizeof(*(*result)->cert_hex)
* CERT_HEX_PREALLOCATION);
if (*data == NULL)
return ERR_ALLOCATION;
sigil_zeroize(*data, sizeof(**data) * CERT_HEX_PREALLOCATION);
(*result)->capacity = CERT_HEX_PREALLOCATION;
position = 0;
while (1) {
if ((err = pdf_get_char(sgl, &c)) != ERR_NO)
return err;
// not enough space, allocate double
if (position >= (*result)->capacity) {
*data = realloc(*data, sizeof(**data) * (*result)->capacity * 2);
if (*data == NULL)
return ERR_ALLOCATION;
sigil_zeroize(*data + (*result)->capacity,
sizeof(**data) * (*result)->capacity);
(*result)->capacity *= 2;
}
if (c == '>') {
(*data)[position] = '\0';
return ERR_NO;
}
(*data)[position] = c;
position++;
}
}
sigil_err_t parse_certs(sigil_t *sgl)
{
sigil_err_t err;
int additional_certs;
cert_t **next_cert;
char c;
if (sgl == NULL)
return ERR_PARAMETER;
additional_certs = 0;
if ((err = skip_leading_whitespaces(sgl)) != ERR_NO)
return err;
if ((err = pdf_peek_char(sgl, &c)) != ERR_NO)
return err;
if (c == '[') // multiple certs
additional_certs = 1;
if ((err = pdf_move_pos_rel(sgl, 1)) != ERR_NO)
return err;
// read signing certificate
err = parse_one_cert(sgl, &(sgl->certificates));
if (err != ERR_NO)
return err;
if (!additional_certs)
return ERR_NO;
next_cert = &(sgl->certificates);
// read other following certs for verifying authenticity of the signing one
while (1) {
next_cert = &((*next_cert)->next);
if ((err = skip_leading_whitespaces(sgl)) != ERR_NO)
return err;
if ((err = pdf_peek_char(sgl, &c)) != ERR_NO)
return err;
if (c == ']') {
if ((err = pdf_move_pos_rel(sgl, 1)) != ERR_NO)
return err;
return ERR_NO;
}
err = parse_one_cert(sgl, next_cert);
if (err != ERR_NO)
return err;
}
}
\ No newline at end of file
......@@ -30,13 +30,29 @@ int sigil_config_self_test(int verbosity)
print_test_result(1, verbosity);
// TEST: REF_ARRAY_PREALLOCATION
print_test_item("FIELDS_PREALLOCATION", verbosity);
print_test_item("REF_ARRAY_PREALLOCATION", verbosity);
if (REF_ARRAY_PREALLOCATION < 1)
goto failed;
print_test_result(1, verbosity);
// TEST: CERT_HEX_PREALLOCATION
print_test_item("CERT_HEX_PREALLOCATION", verbosity);
if (CERT_HEX_PREALLOCATION < 1)
goto failed;
print_test_result(1, verbosity);
// TEST: CONTENTS_PREALLOCATION
print_test_item("CONTENTS_PREALLOCATION", verbosity);
if (CONTENTS_PREALLOCATION < 1)
goto failed;
print_test_result(1, verbosity);
// TEST: THRESHOLD_FILE_BUFFERING
print_test_item("THRESHOLD_FILE_BUFFERING", verbosity);
......@@ -45,6 +61,14 @@ int sigil_config_self_test(int verbosity)
print_test_result(1, verbosity);
// TEST: MAX_FILE_UPDATES
print_test_item("MAX_FILE_UPDATES", verbosity);
if (MAX_FILE_UPDATES < 1)
goto failed;
print_test_result(1, verbosity);
// all tests done
print_module_result(1, verbosity);
return 0;
......
#include <stdlib.h>
#include <types.h>
#include "auxiliary.h"
#include "config.h"
#include "constants.h"
#include "contents.h"
#include "types.h"
sigil_err_t parse_contents(sigil_t *sgl)
{
sigil_err_t err;
char **data;
char c;
size_t position;
if (sgl == NULL)
return ERR_PARAMETER;
if ((err = skip_leading_whitespaces(sgl)) != ERR_NO)
return err;
if (sgl->contents != NULL)
; // TODO free contents
if ((err = parse_word(sgl, "<")) != ERR_NO)
return err;
sgl->contents = malloc(sizeof(*(sgl->contents)));
if (sgl->contents == NULL)
return ERR_ALLOCATION;
sigil_zeroize(sgl->contents, sizeof(*(sgl->contents)));
data = &(sgl->contents->contents_hex);
*data = malloc(sizeof(**data) * CONTENTS_PREALLOCATION);
if (*data == NULL)
return ERR_ALLOCATION;
sigil_zeroize(*data, sizeof(**data) * CONTENTS_PREALLOCATION);
sgl->contents->capacity = CONTENTS_PREALLOCATION;
position = 0;
while (1) {
if ((err = pdf_get_char(sgl, &c)) != ERR_NO)
return err;
// not enough space, allocate double
if (position >= sgl->contents->capacity) {
*data = realloc(*data, sizeof(**data) * sgl->contents->capacity * 2);
if (*data == NULL)
return ERR_ALLOCATION;
sigil_zeroize(*data + sgl->contents->capacity,
sizeof(**data) * sgl->contents->capacity);
sgl->contents->capacity *= 2;
}
if (c == '>') {
(*data)[position] = '\0';
return ERR_NO;
}
(*data)[position] = c;
position++;
}
}
\ No newline at end of file
......@@ -2,12 +2,15 @@
#include <string.h>
#include <types.h>
#include "auxiliary.h"
#include "cert.h"
#include "contents.h"
#include "constants.h"
#include "sig_dict.h"
#include "types.h"
#define SUBFILTER_MAX 30
static sigil_err_t parse_subfilter(sigil_t *sgl)
{
sigil_err_t err;
......@@ -73,6 +76,8 @@ static sigil_err_t parse_byte_range(sigil_t *sgl)
if (err != ERR_NO)
return err;
// TODO add some checks for start and length
if (*byte_range == NULL) {
*byte_range = malloc(sizeof(**byte_range));
if (*byte_range == NULL)
......@@ -114,23 +119,30 @@ sigil_err_t process_sig_dict(sigil_t *sgl)
case DICT_KEY_SubFilter:
if ((err = parse_subfilter(sgl)) != ERR_NO)
return err;
break;
case DICT_KEY_Cert:
err = parse_certs(sgl);
if (err != ERR_NO)
return err;
break;
case DICT_KEY_Contents:
err = parse_contents(sgl);
if (err != ERR_NO)
return err;
break;
case DICT_KEY_ByteRange:
if ((err = parse_byte_range(sgl)) != ERR_NO)
return err;
break;
case DICT_KEY_UNKNOWN:
err = skip_dict_unknown_value(sgl);
if (err != ERR_NO)
return err;
break;
default:
return ERR_PDF_CONTENT;
......
......@@ -41,15 +41,21 @@ sigil_err_t sigil_init(sigil_t **sgl)
(*sgl)->ref_catalog_dict.generation_num = 0;
(*sgl)->ref_acroform.object_num = 0;
(*sgl)->ref_acroform.generation_num = 0;
(*sgl)->offset_acroform = 0;
(*sgl)->ref_sig_field.object_num = 0;
(*sgl)->ref_sig_field.generation_num = 0;
(*sgl)->ref_sig_dict.object_num = 0;
(*sgl)->ref_sig_dict.generation_num = 0;
(*sgl)->offset_sig_dict = 0;
(*sgl)->fields.entry = NULL;
(*sgl)->fields.capacity = 0;
(*sgl)->pdf_start_offset = 0;
(*sgl)->startxref = 0;
(*sgl)->sig_flags = 0;
(*sgl)->subfilter = SUBFILTER_UNKNOWN;
(*sgl)->byte_range = NULL;
(*sgl)->certificates = NULL;
(*sgl)->contents = NULL;
return ERR_NO;
}
......@@ -254,6 +260,29 @@ sigil_err_t sigil_verify(sigil_t *sgl)
return ERR_NO;
}
static void range_free(range_t *range)
{
if (range == NULL)
return;
range_free(range->next);
free(range);
}
static void cert_free(cert_t *cert)
{
if (cert == NULL)
return;
cert_free(cert->next);
if (cert->cert_hex != NULL)
free(cert->cert_hex);
free(cert);
}
void sigil_free(sigil_t **sgl)
{
if (sgl == NULL || *sgl == NULL)
......@@ -268,15 +297,32 @@ void sigil_free(sigil_t **sgl)
(*sgl)->pdf_data.deallocation_info ^= DEALLOCATE_BUFFER;
}
if ((*sgl)->xref)
if ((*sgl)->xref != NULL)
xref_free((*sgl)->xref);
if ((*sgl)->fields.capacity > 0) {
for (size_t i = 0; i < (*sgl)->fields.capacity; i++) {
if ((*sgl)->fields.entry[i] != NULL) {
free((*sgl)->fields.entry[i]);
}
}
if ((*sgl)->fields.entry != NULL)
free((*sgl)->fields.entry);
}
if ((*sgl)->byte_range != NULL)
range_free((*sgl)->byte_range);
if ((*sgl)->certificates != NULL)
cert_free((*sgl)->certificates);
if ((*sgl)->contents != NULL) {
if ((*sgl)->contents->contents_hex != NULL)
free((*sgl)->contents->contents_hex);
free((*sgl)->contents);
}
free(*sgl);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment