From patchwork Thu Dec 19 21:58:22 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Petr_=C5=A0tetiar?= X-Patchwork-Id: 1213731 X-Patchwork-Delegate: ynezz@true.cz Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.openwrt.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=true.cz Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="O3qZJfDG"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 47f5S31j4Tz9sPT for ; Fri, 20 Dec 2019 09:01:23 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Subject:MIME-Version:References: In-Reply-To:Message-Id:Date:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=orHf0nAiqjM3EMlbkJ8IB5pfcbVo31ZfLRiJmRTSe4I=; b=O3qZJfDGBNYvfL TD6refHTD/0ZpSqkWmOGQw6avBRd8841Fot3aTuLx6hkMdTcVmGTPCQ4YOA23Z0QOk7s1iMob+cH7 kJIjxPXj5tJUoXSvR7u7r08wSAwkwT/BjCB4gNq4prrgGnttDRRk37HU7WjvX+oUuhI+1qL7CoTUG UDKq7hcEnby2Cqp/mG2ziCrWJ1bGQvwvK3iPsnMak4pQnAD8pPcKmmurIQyDIQ5224Eu1qcMuT2A8 b3vPGP66ojzw15+gPS+xgN376Q8iKmI5ipWV0IbTOGhZAATH+j0hk77j0vSAjLx8mnhpC6Jss9SBt x59CEo3lVXVmvtANNJKg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1ii3rA-0005aK-1z; Thu, 19 Dec 2019 22:01:16 +0000 Received: from smtp-out.xnet.cz ([178.217.244.18]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1ii3oq-0000tY-Ei for openwrt-devel@lists.openwrt.org; Thu, 19 Dec 2019 21:58:57 +0000 Received: from meh.true.cz (meh.true.cz [108.61.167.218]) (Authenticated sender: petr@true.cz) by smtp-out.xnet.cz (Postfix) with ESMTPSA id F16A44B48; Thu, 19 Dec 2019 22:58:46 +0100 (CET) Received: by meh.true.cz (OpenSMTPD) with ESMTP id ecd318df; Thu, 19 Dec 2019 22:58:34 +0100 (CET) From: =?utf-8?q?Petr_=C5=A0tetiar?= To: openwrt-devel@lists.openwrt.org Date: Thu, 19 Dec 2019 22:58:22 +0100 Message-Id: <20191219215836.21773-7-ynezz@true.cz> In-Reply-To: <20191219215836.21773-1-ynezz@true.cz> References: <20191219215836.21773-1-ynezz@true.cz> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20191219_135852_677059_3818EB4C X-CRM114-Status: GOOD ( 16.02 ) X-Spam-Score: 0.0 (/) X-Spam-Report: SpamAssassin version 3.4.2 on bombadil.infradead.org summary: Content analysis details: (0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [178.217.244.18 listed in list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 SPF_NONE SPF: sender does not publish an SPF Record Subject: [OpenWrt-Devel] [PATCH libubox 06/20] tests: add test cases for blob parsing X-BeenThere: openwrt-devel@lists.openwrt.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?utf-8?q?Petr_=C5=A0tetiar?= Sender: "openwrt-devel" Errors-To: openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org Increasing test coverage. Signed-off-by: Petr Štetiar --- tests/cram/inputs/invalid.ucert | Bin 0 -> 362 bytes tests/cram/inputs/key-build.ucert | Bin 0 -> 356 bytes tests/cram/test_blob_parse.t | 76 +++++++++++++ tests/test-blob-parse.c | 175 ++++++++++++++++++++++++++++++ 4 files changed, 251 insertions(+) create mode 100644 tests/cram/inputs/invalid.ucert create mode 100644 tests/cram/inputs/key-build.ucert create mode 100644 tests/cram/test_blob_parse.t create mode 100644 tests/test-blob-parse.c diff --git a/tests/cram/inputs/invalid.ucert b/tests/cram/inputs/invalid.ucert new file mode 100644 index 0000000000000000000000000000000000000000..dbdeb725d490b51fb442ae3c5a5b90a32376f108 GIT binary patch literal 362 zcmZwDyHbNt5P;!Lp`+9mmXtaa8pj0Uj74IIQG^6@K{AdraLxfvJmkVPPw-31Uf?$C_TsUrr8PYjbt&|wj_P)<(Qp~$*0OhO zXW{fp_l6esQJNUkNV+UjQQEv4(A7!H#E$FbN4eLYChq8*g9^aM6Tmxc#fStEyaMdO z&U%cp1t~8t0WSdiu$x$nVkemUn|OclmH&3KTF`)mRcW& zjx5I8F=cqI|BJ0B6vY_z0WNxQ Amp~XIs#+bmp7r6D(2X7dCdj<@`gJN|wF2w-=WI2*4D{^NeTL^k7{gfd*& r|CMc|6e)FzOyAO7W!fBSQm3h@6O{>;uBdHch+F1Ww 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 diff --git a/tests/test-blob-parse.c b/tests/test-blob-parse.c new file mode 100644 index 000000000000..6b1fb56485da --- /dev/null +++ b/tests/test-blob-parse.c @@ -0,0 +1,175 @@ +/* + * Based on certificate dump functionality from ucert.c: + * + * Copyright (C) 2018 Daniel Golle + * SPDX-License-Identifier: GPL-3.0 + * + */ + +#include +#include +#include +#include + +#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 \n", argv[0]); + return 3; + } + + cert_dump(argv[1]); + + return 0; +}