tests: add test cases for blob parsing
Increasing test coverage. Signed-off-by: Petr Štetiar <ynezz@true.cz>
This commit is contained in:
parent
436d6363a1
commit
09ee90f8d6
4 changed files with 251 additions and 0 deletions
BIN
tests/cram/inputs/invalid.ucert
Normal file
BIN
tests/cram/inputs/invalid.ucert
Normal file
Binary file not shown.
BIN
tests/cram/inputs/key-build.ucert
Normal file
BIN
tests/cram/inputs/key-build.ucert
Normal file
Binary file not shown.
76
tests/cram/test_blob_parse.t
Normal file
76
tests/cram/test_blob_parse.t
Normal file
|
@ -0,0 +1,76 @@
|
|||
check that blob_parse is producing expected results:
|
||||
|
||||
$ [ -n "$TEST_BIN_DIR" ] && export PATH="$TEST_BIN_DIR:$PATH"
|
||||
$ export TEST_INPUTS="$TESTDIR/inputs"
|
||||
$ export FUZZ_CORPUS="$TESTDIR/../fuzz/corpus"
|
||||
|
||||
$ valgrind --quiet --leak-check=full test-blob-parse $TEST_INPUTS/key-build.ucert
|
||||
=== CHAIN ELEMENT 01 ===
|
||||
signature:
|
||||
---
|
||||
untrusted comment: signed by key 84bfc88a17166577
|
||||
RWSEv8iKFxZld+bQ+NTqCdDlHOuVYNw5Qw7Q8shjfMgFJcTqrzaqO0bysjIQhTadmcwvWiWvHlyMcwAXSix2BYdfghz/zhDjvgU=
|
||||
---
|
||||
payload:
|
||||
---
|
||||
"ucert": {
|
||||
\t"certtype": 1, (esc)
|
||||
\t"validfrom": 1546188410, (esc)
|
||||
\t"expiresat": 1577724410, (esc)
|
||||
\t"pubkey": "untrusted comment: Local build key\\nRWSEv8iKFxZld6vicE1icWhYNfEV9PM7C9MKUKl+YNEKB+PdAWGDF5Z9\\n" (esc)
|
||||
}
|
||||
---
|
||||
|
||||
$ valgrind --quiet --leak-check=full test-blob-parse $TEST_INPUTS/invalid.ucert
|
||||
cannot parse cert invalid.ucert
|
||||
|
||||
$ test-blob-parse-san $TEST_INPUTS/key-build.ucert
|
||||
=== CHAIN ELEMENT 01 ===
|
||||
signature:
|
||||
---
|
||||
untrusted comment: signed by key 84bfc88a17166577
|
||||
RWSEv8iKFxZld+bQ+NTqCdDlHOuVYNw5Qw7Q8shjfMgFJcTqrzaqO0bysjIQhTadmcwvWiWvHlyMcwAXSix2BYdfghz/zhDjvgU=
|
||||
---
|
||||
payload:
|
||||
---
|
||||
"ucert": {
|
||||
\t"certtype": 1, (esc)
|
||||
\t"validfrom": 1546188410, (esc)
|
||||
\t"expiresat": 1577724410, (esc)
|
||||
\t"pubkey": "untrusted comment: Local build key\\nRWSEv8iKFxZld6vicE1icWhYNfEV9PM7C9MKUKl+YNEKB+PdAWGDF5Z9\\n" (esc)
|
||||
}
|
||||
---
|
||||
|
||||
$ test-blob-parse-san $TEST_INPUTS/invalid.ucert
|
||||
cannot parse cert invalid.ucert
|
||||
|
||||
$ for blob in $(LC_ALL=C find $FUZZ_CORPUS -type f | sort ); do
|
||||
> valgrind --quiet --leak-check=full test-blob-parse $blob; \
|
||||
> test-blob-parse-san $blob; \
|
||||
> done
|
||||
cannot parse cert 71520a5c4b5ca73903216857abbad54a8002d44a
|
||||
cannot parse cert 71520a5c4b5ca73903216857abbad54a8002d44a
|
||||
cannot parse cert c1dfd96eea8cc2b62785275bca38ac261256e278
|
||||
cannot parse cert c1dfd96eea8cc2b62785275bca38ac261256e278
|
||||
cannot parse cert c42ac1c46f1d4e211c735cc7dfad4ff8391110e9
|
||||
cannot parse cert c42ac1c46f1d4e211c735cc7dfad4ff8391110e9
|
||||
cannot parse cert crash-1b8fb1be45db3aff7699100f497fb74138f3df4f
|
||||
cannot parse cert crash-1b8fb1be45db3aff7699100f497fb74138f3df4f
|
||||
cannot parse cert crash-4c4d2c3c9ade5da9347534e290305c3b9760f627
|
||||
cannot parse cert crash-4c4d2c3c9ade5da9347534e290305c3b9760f627
|
||||
cannot parse cert crash-5e9937b197c88bf4e7b7ee2612456cad4cb83f5b
|
||||
cannot parse cert crash-5e9937b197c88bf4e7b7ee2612456cad4cb83f5b
|
||||
cannot parse cert crash-75b146c4e6fac64d3e62236b27c64b50657bab2a
|
||||
cannot parse cert crash-75b146c4e6fac64d3e62236b27c64b50657bab2a
|
||||
cannot parse cert crash-813f3e68661da09c26d4a87dbb9d5099e92be50f
|
||||
cannot parse cert crash-813f3e68661da09c26d4a87dbb9d5099e92be50f
|
||||
cannot parse cert crash-98595faa58ba01d85ba4fd0b109cd3d490b45795
|
||||
cannot parse cert crash-98595faa58ba01d85ba4fd0b109cd3d490b45795
|
||||
cannot parse cert crash-d0f3aa7d60a094b021f635d4edb7807c055a4ea1
|
||||
cannot parse cert crash-d0f3aa7d60a094b021f635d4edb7807c055a4ea1
|
||||
cannot parse cert crash-df9d1243057b27bbad6211e5a23d1cb699028aa2
|
||||
cannot parse cert crash-df9d1243057b27bbad6211e5a23d1cb699028aa2
|
||||
cannot parse cert crash-e2fd5ecb3b37926743256f1083f47a07c39e10c2
|
||||
cannot parse cert crash-e2fd5ecb3b37926743256f1083f47a07c39e10c2
|
||||
cannot parse cert valid-blobmsg.bin
|
||||
cannot parse cert valid-blobmsg.bin
|
175
tests/test-blob-parse.c
Normal file
175
tests/test-blob-parse.c
Normal file
|
@ -0,0 +1,175 @@
|
|||
/*
|
||||
* Based on certificate dump functionality from ucert.c:
|
||||
*
|
||||
* Copyright (C) 2018 Daniel Golle <daniel@makrotopia.org>
|
||||
* SPDX-License-Identifier: GPL-3.0
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <libgen.h>
|
||||
|
||||
#include "blob.h"
|
||||
#include "list.h"
|
||||
#include "blobmsg_json.h"
|
||||
|
||||
#define CERT_BUF_LEN 4096
|
||||
|
||||
/*
|
||||
* ucert structure
|
||||
* | BLOB |
|
||||
* | SIGNATURE | PAYLOAD |
|
||||
* | |[ BLOBMSG CONTAINER ]|
|
||||
* | |[[T,i,v,e,f,pubkey ]]|
|
||||
*/
|
||||
enum cert_attr {
|
||||
CERT_ATTR_SIGNATURE,
|
||||
CERT_ATTR_PAYLOAD,
|
||||
CERT_ATTR_MAX
|
||||
};
|
||||
|
||||
static const struct blob_attr_info cert_policy[CERT_ATTR_MAX] = {
|
||||
[CERT_ATTR_SIGNATURE] = { .type = BLOB_ATTR_BINARY },
|
||||
[CERT_ATTR_PAYLOAD] = { .type = BLOB_ATTR_NESTED },
|
||||
};
|
||||
|
||||
enum cert_cont_attr {
|
||||
CERT_CT_ATTR_PAYLOAD,
|
||||
CERT_CT_ATTR_MAX
|
||||
};
|
||||
|
||||
enum cert_payload_attr {
|
||||
CERT_PL_ATTR_CERTTYPE,
|
||||
CERT_PL_ATTR_CERTID,
|
||||
CERT_PL_ATTR_VALIDFROMTIME,
|
||||
CERT_PL_ATTR_EXPIRETIME,
|
||||
CERT_PL_ATTR_PUBKEY,
|
||||
CERT_PL_ATTR_KEY_FINGERPRINT,
|
||||
CERT_PL_ATTR_MAX
|
||||
};
|
||||
|
||||
enum certtype_id {
|
||||
CERTTYPE_UNSPEC,
|
||||
CERTTYPE_AUTH,
|
||||
CERTTYPE_REVOKE
|
||||
};
|
||||
|
||||
/* list to store certificate chain at runtime */
|
||||
struct cert_object {
|
||||
struct list_head list;
|
||||
struct blob_attr *cert[CERT_ATTR_MAX];
|
||||
};
|
||||
|
||||
static int cert_load(const char *certfile, struct list_head *chain)
|
||||
{
|
||||
FILE *f;
|
||||
struct blob_attr *certtb[CERT_ATTR_MAX];
|
||||
struct blob_attr *bufpt;
|
||||
struct cert_object *cobj;
|
||||
char filebuf[CERT_BUF_LEN];
|
||||
int ret = 0, pret = 0;
|
||||
size_t len, pos = 0;
|
||||
|
||||
f = fopen(certfile, "r");
|
||||
if (!f)
|
||||
return 1;
|
||||
|
||||
len = fread(&filebuf, 1, CERT_BUF_LEN - 1, f);
|
||||
if (len < 64)
|
||||
return 1;
|
||||
|
||||
ret = ferror(f) || !feof(f);
|
||||
fclose(f);
|
||||
if (ret)
|
||||
return 1;
|
||||
|
||||
bufpt = (struct blob_attr *)filebuf;
|
||||
do {
|
||||
pret = blob_parse(bufpt, certtb, cert_policy, CERT_ATTR_MAX);
|
||||
if (pret <= 0)
|
||||
/* no attributes found */
|
||||
break;
|
||||
|
||||
if (pos + blob_pad_len(bufpt) > len)
|
||||
/* blob exceeds filebuffer */
|
||||
break;
|
||||
else
|
||||
pos += blob_pad_len(bufpt);
|
||||
|
||||
if (!certtb[CERT_ATTR_SIGNATURE])
|
||||
/* no signature -> drop */
|
||||
break;
|
||||
|
||||
cobj = calloc(1, sizeof(*cobj));
|
||||
cobj->cert[CERT_ATTR_SIGNATURE] = blob_memdup(certtb[CERT_ATTR_SIGNATURE]);
|
||||
if (certtb[CERT_ATTR_PAYLOAD])
|
||||
cobj->cert[CERT_ATTR_PAYLOAD] = blob_memdup(certtb[CERT_ATTR_PAYLOAD]);
|
||||
|
||||
list_add_tail(&cobj->list, chain);
|
||||
ret += pret;
|
||||
/* repeat parsing while there is still enough remaining data in buffer */
|
||||
} while(len > pos + sizeof(struct blob_attr) && (bufpt = blob_next(bufpt)));
|
||||
|
||||
return (ret <= 0);
|
||||
}
|
||||
|
||||
/* dump single chain element to console */
|
||||
static void cert_dump_blob(struct blob_attr *cert[CERT_ATTR_MAX])
|
||||
{
|
||||
int i;
|
||||
char *json = NULL;
|
||||
|
||||
for (i = 0; i < CERT_ATTR_MAX; i++) {
|
||||
struct blob_attr *v = cert[i];
|
||||
|
||||
if (!v)
|
||||
continue;
|
||||
|
||||
switch(cert_policy[i].type) {
|
||||
case BLOB_ATTR_BINARY:
|
||||
fprintf(stdout, "signature:\n---\n%s---\n", (char *) blob_data(v));
|
||||
break;
|
||||
case BLOB_ATTR_NESTED:
|
||||
json = blobmsg_format_json_indent(blob_data(v), false, 0);
|
||||
if (!json)
|
||||
continue;
|
||||
|
||||
fprintf(stdout, "payload:\n---\n%s\n---\n", json);
|
||||
free(json);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int cert_dump(const char *certfile)
|
||||
{
|
||||
struct cert_object *cobj;
|
||||
static LIST_HEAD(certchain);
|
||||
unsigned int count = 0;
|
||||
|
||||
if (cert_load(certfile, &certchain)) {
|
||||
fprintf(stderr, "cannot parse cert %s\n", basename((char *) certfile));
|
||||
return 1;
|
||||
}
|
||||
|
||||
list_for_each_entry(cobj, &certchain, list) {
|
||||
fprintf(stdout, "=== CHAIN ELEMENT %02u ===\n", ++count);
|
||||
cert_dump_blob(cobj->cert);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "Usage: %s <cert.ucert>\n", argv[0]);
|
||||
return 3;
|
||||
}
|
||||
|
||||
cert_dump(argv[1]);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue