2 * Based on certificate dump functionality from ucert.c:
4 * Copyright (C) 2018 Daniel Golle <daniel@makrotopia.org>
5 * SPDX-License-Identifier: GPL-3.0
16 #include "blobmsg_json.h"
18 #define CERT_BUF_LEN 4096
23 * | SIGNATURE | PAYLOAD |
24 * | |[ BLOBMSG CONTAINER ]|
25 * | |[[T,i,v,e,f,pubkey ]]|
33 static const struct blob_attr_info cert_policy
[CERT_ATTR_MAX
] = {
34 [CERT_ATTR_SIGNATURE
] = { .type
= BLOB_ATTR_BINARY
},
35 [CERT_ATTR_PAYLOAD
] = { .type
= BLOB_ATTR_NESTED
},
43 enum cert_payload_attr
{
44 CERT_PL_ATTR_CERTTYPE
,
46 CERT_PL_ATTR_VALIDFROMTIME
,
47 CERT_PL_ATTR_EXPIRETIME
,
49 CERT_PL_ATTR_KEY_FINGERPRINT
,
59 /* list to store certificate chain at runtime */
61 struct list_head list
;
62 struct blob_attr
*cert
[CERT_ATTR_MAX
];
65 static int cert_load(const char *certfile
, struct list_head
*chain
)
68 struct blob_attr
*certtb
[CERT_ATTR_MAX
];
69 struct blob_attr
*bufpt
;
70 struct cert_object
*cobj
;
71 char filebuf
[CERT_BUF_LEN
];
72 int ret
= 0, pret
= 0;
75 f
= fopen(certfile
, "r");
79 len
= fread(&filebuf
, 1, CERT_BUF_LEN
- 1, f
);
83 ret
= ferror(f
) || !feof(f
);
88 bufpt
= (struct blob_attr
*)filebuf
;
90 pret
= blob_parse(bufpt
, certtb
, cert_policy
, CERT_ATTR_MAX
);
92 /* no attributes found */
95 if (pos
+ blob_pad_len(bufpt
) > len
)
96 /* blob exceeds filebuffer */
99 pos
+= blob_pad_len(bufpt
);
101 if (!certtb
[CERT_ATTR_SIGNATURE
])
102 /* no signature -> drop */
105 cobj
= calloc(1, sizeof(*cobj
));
106 cobj
->cert
[CERT_ATTR_SIGNATURE
] = blob_memdup(certtb
[CERT_ATTR_SIGNATURE
]);
107 if (certtb
[CERT_ATTR_PAYLOAD
])
108 cobj
->cert
[CERT_ATTR_PAYLOAD
] = blob_memdup(certtb
[CERT_ATTR_PAYLOAD
]);
110 list_add_tail(&cobj
->list
, chain
);
112 /* repeat parsing while there is still enough remaining data in buffer */
113 } while(len
> pos
+ sizeof(struct blob_attr
) && (bufpt
= blob_next(bufpt
)));
118 /* dump single chain element to console */
119 static void cert_dump_blob(struct blob_attr
*cert
[CERT_ATTR_MAX
])
124 for (i
= 0; i
< CERT_ATTR_MAX
; i
++) {
125 struct blob_attr
*v
= cert
[i
];
130 switch(cert_policy
[i
].type
) {
131 case BLOB_ATTR_BINARY
:
132 fprintf(stdout
, "signature:\n---\n%s---\n", (char *) blob_data(v
));
134 case BLOB_ATTR_NESTED
:
135 json
= blobmsg_format_json_indent(blob_data(v
), false, 0);
139 fprintf(stdout
, "payload:\n---\n%s\n---\n", json
);
146 static int cert_dump(const char *certfile
)
148 struct cert_object
*cobj
;
149 static LIST_HEAD(certchain
);
150 unsigned int count
= 0;
152 if (cert_load(certfile
, &certchain
)) {
153 fprintf(stderr
, "cannot parse cert %s\n", basename((char *) certfile
));
157 list_for_each_entry(cobj
, &certchain
, list
) {
158 fprintf(stdout
, "=== CHAIN ELEMENT %02u ===\n", ++count
);
159 cert_dump_blob(cobj
->cert
);
165 int main(int argc
, char *argv
[])
168 fprintf(stderr
, "Usage: %s <cert.ucert>\n", argv
[0]);