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
;
72 int ret
= 0, pret
= 0;
75 f
= fopen(certfile
, "r");
79 filebuf
= malloc(CERT_BUF_LEN
+1);
83 len
= fread(filebuf
, 1, CERT_BUF_LEN
, f
);
89 ret
= ferror(f
) || !feof(f
);
96 bufpt
= (struct blob_attr
*)filebuf
;
98 pret
= blob_parse_untrusted(bufpt
, len
, certtb
, cert_policy
, CERT_ATTR_MAX
);
100 /* no attributes found */
103 if (pos
+ blob_pad_len(bufpt
) > len
)
104 /* blob exceeds filebuffer */
107 pos
+= blob_pad_len(bufpt
);
109 if (!certtb
[CERT_ATTR_SIGNATURE
])
110 /* no signature -> drop */
113 cobj
= calloc(1, sizeof(*cobj
));
114 cobj
->cert
[CERT_ATTR_SIGNATURE
] = blob_memdup(certtb
[CERT_ATTR_SIGNATURE
]);
115 if (certtb
[CERT_ATTR_PAYLOAD
])
116 cobj
->cert
[CERT_ATTR_PAYLOAD
] = blob_memdup(certtb
[CERT_ATTR_PAYLOAD
]);
118 list_add_tail(&cobj
->list
, chain
);
120 /* repeat parsing while there is still enough remaining data in buffer */
121 } while(len
> pos
+ sizeof(struct blob_attr
) && (bufpt
= blob_next(bufpt
)));
127 /* dump single chain element to console */
128 static void cert_dump_blob(struct blob_attr
*cert
[CERT_ATTR_MAX
])
133 for (i
= 0; i
< CERT_ATTR_MAX
; i
++) {
134 struct blob_attr
*v
= cert
[i
];
139 switch(cert_policy
[i
].type
) {
140 case BLOB_ATTR_BINARY
:
141 fprintf(stdout
, "signature:\n---\n%s---\n", (char *) blob_data(v
));
143 case BLOB_ATTR_NESTED
:
144 json
= blobmsg_format_json_indent(blob_data(v
), false, 0);
148 fprintf(stdout
, "payload:\n---\n%s\n---\n", json
);
155 static int cert_dump(const char *certfile
)
157 struct cert_object
*cobj
;
158 static LIST_HEAD(certchain
);
159 unsigned int count
= 0;
161 if (cert_load(certfile
, &certchain
)) {
162 fprintf(stderr
, "cannot parse cert %s\n", basename((char *) certfile
));
166 list_for_each_entry(cobj
, &certchain
, list
) {
167 fprintf(stdout
, "=== CHAIN ELEMENT %02u ===\n", ++count
);
168 cert_dump_blob(cobj
->cert
);
174 int main(int argc
, char *argv
[])
177 fprintf(stderr
, "Usage: %s <cert.ucert>\n", argv
[0]);