1 /* 2 * Based on certificate dump functionality from ucert.c: 3 * 4 * Copyright (C) 2018 Daniel Golle <daniel@makrotopia.org> 5 * SPDX-License-Identifier: GPL-3.0 6 * 7 */ 8 9 #include <stdio.h> 10 #include <stdint.h> 11 #include <stddef.h> 12 #include <libgen.h> 13 14 #include "blob.h" 15 #include "list.h" 16 #include "blobmsg_json.h" 17 18 #define CERT_BUF_LEN 4096 19 20 /* 21 * ucert structure 22 * | BLOB | 23 * | SIGNATURE | PAYLOAD | 24 * | |[ BLOBMSG CONTAINER ]| 25 * | |[[T,i,v,e,f,pubkey ]]| 26 */ 27 enum cert_attr { 28 CERT_ATTR_SIGNATURE, 29 CERT_ATTR_PAYLOAD, 30 CERT_ATTR_MAX 31 }; 32 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 }, 36 }; 37 38 enum cert_cont_attr { 39 CERT_CT_ATTR_PAYLOAD, 40 CERT_CT_ATTR_MAX 41 }; 42 43 enum cert_payload_attr { 44 CERT_PL_ATTR_CERTTYPE, 45 CERT_PL_ATTR_CERTID, 46 CERT_PL_ATTR_VALIDFROMTIME, 47 CERT_PL_ATTR_EXPIRETIME, 48 CERT_PL_ATTR_PUBKEY, 49 CERT_PL_ATTR_KEY_FINGERPRINT, 50 CERT_PL_ATTR_MAX 51 }; 52 53 enum certtype_id { 54 CERTTYPE_UNSPEC, 55 CERTTYPE_AUTH, 56 CERTTYPE_REVOKE 57 }; 58 59 /* list to store certificate chain at runtime */ 60 struct cert_object { 61 struct list_head list; 62 struct blob_attr *cert[CERT_ATTR_MAX]; 63 }; 64 65 static int cert_load(const char *certfile, struct list_head *chain) 66 { 67 FILE *f; 68 struct blob_attr *certtb[CERT_ATTR_MAX]; 69 struct blob_attr *bufpt; 70 struct cert_object *cobj; 71 char *filebuf = NULL; 72 int ret = 0, pret = 0; 73 size_t len, pos = 0; 74 75 f = fopen(certfile, "r"); 76 if (!f) 77 return 1; 78 79 filebuf = malloc(CERT_BUF_LEN+1); 80 if (!filebuf) 81 return 1; 82 83 len = fread(filebuf, 1, CERT_BUF_LEN, f); 84 if (len < 64) { 85 free(filebuf); 86 return 1; 87 } 88 89 ret = ferror(f) || !feof(f); 90 fclose(f); 91 if (ret) { 92 free(filebuf); 93 return 1; 94 } 95 96 bufpt = (struct blob_attr *)filebuf; 97 do { 98 pret = blob_parse_untrusted(bufpt, len, certtb, cert_policy, CERT_ATTR_MAX); 99 if (pret <= 0) 100 /* no attributes found */ 101 break; 102 103 if (pos + blob_pad_len(bufpt) > len) 104 /* blob exceeds filebuffer */ 105 break; 106 else 107 pos += blob_pad_len(bufpt); 108 109 if (!certtb[CERT_ATTR_SIGNATURE]) 110 /* no signature -> drop */ 111 break; 112 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]); 117 118 list_add_tail(&cobj->list, chain); 119 ret += pret; 120 /* repeat parsing while there is still enough remaining data in buffer */ 121 } while(len > pos + sizeof(struct blob_attr) && (bufpt = blob_next(bufpt))); 122 123 free(filebuf); 124 return (ret <= 0); 125 } 126 127 /* dump single chain element to console */ 128 static void cert_dump_blob(struct blob_attr *cert[CERT_ATTR_MAX]) 129 { 130 int i; 131 char *json = NULL; 132 133 for (i = 0; i < CERT_ATTR_MAX; i++) { 134 struct blob_attr *v = cert[i]; 135 136 if (!v) 137 continue; 138 139 switch(cert_policy[i].type) { 140 case BLOB_ATTR_BINARY: 141 fprintf(stdout, "signature:\n---\n%s---\n", (char *) blob_data(v)); 142 break; 143 case BLOB_ATTR_NESTED: 144 json = blobmsg_format_json_indent(blob_data(v), false, 0); 145 if (!json) 146 continue; 147 148 fprintf(stdout, "payload:\n---\n%s\n---\n", json); 149 free(json); 150 break; 151 } 152 } 153 } 154 155 static int cert_dump(const char *certfile) 156 { 157 struct cert_object *cobj; 158 static LIST_HEAD(certchain); 159 unsigned int count = 0; 160 161 if (cert_load(certfile, &certchain)) { 162 fprintf(stderr, "cannot parse cert %s\n", basename((char *) certfile)); 163 return 1; 164 } 165 166 list_for_each_entry(cobj, &certchain, list) { 167 fprintf(stdout, "=== CHAIN ELEMENT %02u ===\n", ++count); 168 cert_dump_blob(cobj->cert); 169 } 170 171 return 0; 172 } 173 174 int main(int argc, char *argv[]) 175 { 176 if (argc != 2) { 177 fprintf(stderr, "Usage: %s <cert.ucert>\n", argv[0]); 178 return 3; 179 } 180 181 cert_dump(argv[1]); 182 183 return 0; 184 } 185
This page was automatically generated by LXR 0.3.1. • OpenWrt