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

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
Loading
Loading
Loading
Loading

include/cert.h

0 → 100644
+11 −0
Original line number Diff line number Diff line
#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 */
+7 −1
Original line number Diff line number Diff line
@@ -14,6 +14,12 @@
// capacity to choose for the first allocation in array of fields
#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

include/contents.h

0 → 100644
+11 −0
Original line number Diff line number Diff line
#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
+13 −0
Original line number Diff line number Diff line
@@ -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 */

lib/cert.c

0 → 100644
+128 −0
Original line number Diff line number Diff line
#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
Loading