1 /* radare2 - LGPL - Copyright 2017-2018 - wargio */
2 
3 #include <r_util.h>
4 #include <r_cons.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include "./x509.h"
8 
r_x509_parse_validity(RX509Validity * validity,RASN1Object * object)9 static bool r_x509_parse_validity(RX509Validity *validity, RASN1Object *object) {
10 	RASN1Object *o;
11 	if (!validity || !object || object->list.length != 2) {
12 		return false;
13 	}
14 	if (object->klass == CLASS_UNIVERSAL &&
15 		object->tag == TAG_SEQUENCE &&
16 		object->form == FORM_CONSTRUCTED) {
17 		o = object->list.objects[0];
18 		if (o->klass == CLASS_UNIVERSAL && o->form == FORM_PRIMITIVE) {
19 			if (o->tag == TAG_UTCTIME) {
20 				validity->notBefore = r_asn1_stringify_utctime (o->sector, o->length);
21 			} else if (o->tag == TAG_GENERALIZEDTIME) {
22 				validity->notBefore = r_asn1_stringify_time (o->sector, o->length);
23 			}
24 		}
25 		o = object->list.objects[1];
26 		if (o->klass == CLASS_UNIVERSAL && o->form == FORM_PRIMITIVE) {
27 			if (o->tag == TAG_UTCTIME) {
28 				validity->notAfter = r_asn1_stringify_utctime (o->sector, o->length);
29 			} else if (o->tag == TAG_GENERALIZEDTIME) {
30 				validity->notAfter = r_asn1_stringify_time (o->sector, o->length);
31 			}
32 		}
33 	}
34 	return true;
35 }
36 
is_oid_object(RASN1Object * object)37 static inline bool is_oid_object (RASN1Object *object) {
38 	return object->list.objects[0] &&
39 		object->list.objects[0]->klass == CLASS_UNIVERSAL &&
40 		object->list.objects[0]->tag == TAG_OID;
41 }
42 
r_x509_parse_algorithmidentifier(RX509AlgorithmIdentifier * ai,RASN1Object * object)43 bool r_x509_parse_algorithmidentifier (RX509AlgorithmIdentifier *ai, RASN1Object *object) {
44 	r_return_val_if_fail (ai && object, false);
45 
46 	if (object->list.length < 1 || !object->list.objects || !is_oid_object (object)) {
47 			return false;
48 	}
49 
50 	ai->algorithm = r_asn1_stringify_oid (object->list.objects[0]->sector, object->list.objects[0]->length);
51 	ai->parameters = NULL; // TODO
52 	//ai->parameters = asn1_stringify_sector (object->list.objects[1]);
53 	return true;
54 }
55 
r_x509_parse_subjectpublickeyinfo(RX509SubjectPublicKeyInfo * spki,RASN1Object * object)56 bool r_x509_parse_subjectpublickeyinfo (RX509SubjectPublicKeyInfo *spki, RASN1Object *object) {
57 	RASN1Object *o;
58 	if (!spki || !object || object->list.length != 2) {
59 		return false;
60 	}
61 	r_x509_parse_algorithmidentifier (&spki->algorithm, object->list.objects[0]);
62 	if (object->list.objects[1]) {
63 		o = object->list.objects[1];
64 		spki->subjectPublicKey = r_asn1_create_binary (o->sector, o->length);
65 		if (o->list.length == 1 && o->list.objects[0] && o->list.objects[0]->list.length == 2) {
66 			o = o->list.objects[0];
67 			if (o->list.objects[0]) {
68 				spki->subjectPublicKeyExponent = r_asn1_create_binary (o->list.objects[0]->sector, o->list.objects[0]->length);
69 			}
70 			if (o->list.objects[1]) {
71 				spki->subjectPublicKeyModule = r_asn1_create_binary (o->list.objects[1]->sector, o->list.objects[1]->length);
72 			}
73 		}
74 	}
75 	return true;
76 }
77 
r_x509_parse_name(RX509Name * name,RASN1Object * object)78 bool r_x509_parse_name (RX509Name *name, RASN1Object *object) {
79 	ut32 i;
80 	if (!name || !object || !object->list.length) {
81 		return false;
82 	}
83 	if (object->klass == CLASS_UNIVERSAL && object->tag == TAG_SEQUENCE) {
84 		name->length = object->list.length;
85 		name->names = (RASN1String **)calloc (name->length, sizeof (RASN1String *));
86 		if (!name->names) {
87 			name->length = 0;
88 			return false;
89 		}
90 		name->oids = (RASN1String **)calloc (name->length, sizeof (RASN1String *));
91 		if (!name->oids) {
92 			name->length = 0;
93 			R_FREE (name->names);
94 			return false;
95 		}
96 		for (i = 0; i < object->list.length; i++) {
97 			RASN1Object *o = object->list.objects[i];
98 			if (o && o->klass == CLASS_UNIVERSAL &&
99 				o->tag == TAG_SET &&
100 				o->form == FORM_CONSTRUCTED &&
101 				o->list.length == 1) {
102 				o = o->list.objects[0];
103 				if (o && o->list.length > 1 &&
104 					o->klass == CLASS_UNIVERSAL &&
105 					o->tag == TAG_SEQUENCE) {
106 					if (o->list.objects[0]->klass == CLASS_UNIVERSAL &&
107 						o->list.objects[0]->tag == TAG_OID) {
108 						name->oids[i] = r_asn1_stringify_oid (o->list.objects[0]->sector, o->list.objects[0]->length);
109 					}
110 					RASN1Object *obj1 = o->list.objects[1];
111 					if (obj1 && obj1->klass == CLASS_UNIVERSAL) {
112 						name->names[i] = r_asn1_stringify_string (obj1->sector, obj1->length);
113 					}
114 				}
115 			}
116 		}
117 	}
118 	return true;
119 }
120 
r_x509_parse_extension(RX509Extension * ext,RASN1Object * object)121 bool r_x509_parse_extension (RX509Extension *ext, RASN1Object *object) {
122 	RASN1Object *o;
123 	if (!ext || !object || object->list.length < 2) {
124 		return false;
125 	}
126 	o = object->list.objects[0];
127 	if (o && o->tag == TAG_OID) {
128 		ext->extnID = r_asn1_stringify_oid (o->sector, o->length);
129 		o = object->list.objects[1];
130 		if (o->tag == TAG_BOOLEAN && object->list.length > 2) {
131 			//This field is optional (so len must be 3)
132 			ext->critical = o->sector[0] != 0;
133 			o = object->list.objects[2];
134 		}
135 		if (o->tag == TAG_OCTETSTRING) {
136 			ext->extnValue = r_asn1_create_binary (o->sector, o->length);
137 		}
138 	}
139 	return true;
140 }
141 
r_x509_parse_extensions(RX509Extensions * ext,RASN1Object * object)142 bool r_x509_parse_extensions (RX509Extensions *ext, RASN1Object *object) {
143 	ut32 i;
144 	if (!ext || !object || object->list.length != 1 || !object->list.objects[0]->length) {
145 		return false;
146 	}
147 	object = object->list.objects[0];
148 	ext->extensions = (RX509Extension **)calloc (object->list.length, sizeof (RX509Extension *));
149 	if (!ext->extensions) {
150 		return false;
151 	}
152 	ext->length = object->list.length;
153 	for (i = 0; i < object->list.length; i++) {
154 		ext->extensions[i] = R_NEW0 (RX509Extension);
155 		if (!r_x509_parse_extension (ext->extensions[i], object->list.objects[i])) {
156 			r_x509_free_extension (ext->extensions[i]);
157 			ext->extensions[i] = NULL;
158 		}
159 	}
160 	return true;
161 }
162 
r_x509_parse_tbscertificate(RX509TBSCertificate * tbsc,RASN1Object * object)163 bool r_x509_parse_tbscertificate (RX509TBSCertificate *tbsc, RASN1Object *object) {
164 	RASN1Object **elems;
165 	ut32 i;
166 	ut32 shift = 0;
167 	if (!tbsc || !object || object->list.length < 6) {
168 		return false;
169 	}
170 	elems = object->list.objects;
171 	//Following RFC
172 	if (elems[0]->list.length == 1 &&
173 		elems[0]->klass == CLASS_CONTEXT &&
174 		elems[0]->form == FORM_CONSTRUCTED &&
175 		elems[0]->list.objects[0]->tag == TAG_INTEGER &&
176 		elems[0]->list.objects[0]->length == 1) {
177 		//Integer inside a CLASS_CONTEXT
178 		tbsc->version = (ut32)elems[0]->list.objects[0]->sector[0];
179 		shift = 1;
180 	} else {
181 		tbsc->version = 0;
182 	}
183 	if (shift < object->list.length && elems[shift]->klass == CLASS_UNIVERSAL && elems[shift]->tag == TAG_INTEGER) {
184 		tbsc->serialNumber = r_asn1_stringify_integer (elems[shift]->sector, elems[shift]->length);
185 	}
186 	r_x509_parse_algorithmidentifier (&tbsc->signature, elems[shift + 1]);
187 	r_x509_parse_name (&tbsc->issuer, elems[shift + 2]);
188 	r_x509_parse_validity (&tbsc->validity, elems[shift + 3]);
189 	r_x509_parse_name (&tbsc->subject, elems[shift + 4]);
190 	r_x509_parse_subjectpublickeyinfo (&tbsc->subjectPublicKeyInfo, elems[shift + 5]);
191 	if (tbsc->version > 0) {
192 		for (i = shift + 6; i < object->list.length; i++) {
193 			if (!elems[i] || elems[i]->klass != CLASS_CONTEXT) {
194 				continue;
195 			}
196 			if (elems[i]->tag == 1) {
197 				tbsc->issuerUniqueID = r_asn1_create_binary (object->list.objects[i]->sector, object->list.objects[i]->length);
198 			}
199 			if (!elems[i]) {
200 				continue;
201 			}
202 			if (elems[i]->tag == 2) {
203 				tbsc->subjectUniqueID = r_asn1_create_binary (object->list.objects[i]->sector, object->list.objects[i]->length);
204 			}
205 			if (!elems[i]) {
206 				continue;
207 			}
208 			if (tbsc->version == 2 && elems[i]->tag == 3 && elems[i]->form == FORM_CONSTRUCTED) {
209 				r_x509_parse_extensions (&tbsc->extensions, elems[i]);
210 			}
211 		}
212 	}
213 	return true;
214 }
215 
r_x509_parse_certificate(RASN1Object * object)216 RX509Certificate *r_x509_parse_certificate (RASN1Object *object) {
217 	if (!object) {
218 		return NULL;
219 	}
220 	RX509Certificate *cert = R_NEW0 (RX509Certificate);
221 	if (!cert) {
222 		goto fail;
223 	}
224 	if (object->klass != CLASS_UNIVERSAL || object->form != FORM_CONSTRUCTED || object->list.length != 3) {
225 		R_FREE (cert);
226 		goto fail;
227 	}
228 	RASN1Object *tmp = object->list.objects[2];
229 	if (!tmp) {
230 		R_FREE (cert);
231 		goto fail;
232 	}
233 	if (tmp->klass != CLASS_UNIVERSAL || tmp->form != FORM_PRIMITIVE || tmp->tag != TAG_BITSTRING) {
234 		R_FREE (cert);
235 		goto fail;
236 	}
237 	cert->signature = r_asn1_create_binary (object->list.objects[2]->sector, object->list.objects[2]->length);
238 	r_x509_parse_tbscertificate (&cert->tbsCertificate, object->list.objects[0]);
239 
240 	if (!r_x509_parse_algorithmidentifier (&cert->algorithmIdentifier, object->list.objects[1])) {
241 		R_FREE (cert);
242 	}
243 fail:
244 	r_asn1_free_object (object);
245 	return cert;
246 }
247 
r_x509_parse_certificate2(const ut8 * buffer,ut32 length)248 RX509Certificate *r_x509_parse_certificate2 (const ut8 *buffer, ut32 length) {
249 	RX509Certificate *certificate;
250 	RASN1Object *object;
251 	if (!buffer || !length) {
252 		return NULL;
253 	}
254 	object = r_asn1_create_object (buffer, length, buffer);
255 	certificate = r_x509_parse_certificate (object);
256 	//object freed by r_x509_parse_certificate
257 	return certificate;
258 }
259 
r_x509_parse_crlentry(RASN1Object * object)260 RX509CRLEntry *r_x509_parse_crlentry (RASN1Object *object) {
261 	RX509CRLEntry *entry;
262 	if (!object || object->list.length != 2) {
263 		return NULL;
264 	}
265 	entry = (RX509CRLEntry *)malloc (sizeof (RX509CRLEntry));
266 	if (!entry) {
267 		return NULL;
268 	}
269 	entry->userCertificate = r_asn1_create_binary (object->list.objects[0]->sector, object->list.objects[0]->length);
270 	entry->revocationDate = r_asn1_stringify_utctime (object->list.objects[1]->sector, object->list.objects[1]->length);
271 	return entry;
272 }
273 
r_x509_parse_crl(RASN1Object * object)274 R_API RX509CertificateRevocationList *r_x509_parse_crl(RASN1Object *object) {
275 	RX509CertificateRevocationList *crl;
276 	RASN1Object **elems;
277 	if (!object || object->list.length < 4) {
278 		return NULL;
279 	}
280 	crl = (RX509CertificateRevocationList *)malloc (sizeof (RX509CertificateRevocationList));
281 	if (!crl) {
282 		return NULL;
283 	}
284 	memset (crl, 0, sizeof (RX509CertificateRevocationList));
285 	elems = object->list.objects;
286 	r_x509_parse_algorithmidentifier (&crl->signature, elems[0]);
287 	r_x509_parse_name (&crl->issuer, elems[1]);
288 	crl->lastUpdate = r_asn1_stringify_utctime (elems[2]->sector, elems[2]->length);
289 	crl->nextUpdate = r_asn1_stringify_utctime (elems[3]->sector, elems[3]->length);
290 	if (object->list.length > 4 && object->list.objects[4]) {
291 		ut32 i;
292 		crl->revokedCertificates = calloc (object->list.objects[4]->list.length, sizeof (RX509CRLEntry *));
293 		if (!crl->revokedCertificates) {
294 			free (crl);
295 			return NULL;
296 		}
297 		crl->length = object->list.objects[4]->list.length;
298 		for (i = 0; i < object->list.objects[4]->list.length; i++) {
299 			crl->revokedCertificates[i] = r_x509_parse_crlentry (object->list.objects[4]->list.objects[i]);
300 		}
301 	}
302 	return crl;
303 }
304 
r_x509_free_algorithmidentifier(RX509AlgorithmIdentifier * ai)305 void r_x509_free_algorithmidentifier (RX509AlgorithmIdentifier *ai) {
306 	if (ai) {
307 		// no need to free ai, since this functions is used internally
308 		r_asn1_free_string (ai->algorithm);
309 		r_asn1_free_string (ai->parameters);
310 	}
311 }
312 
r_x509_free_validity(RX509Validity * validity)313 static void r_x509_free_validity(RX509Validity *validity) {
314 	if (validity) {
315 		// not freeing validity since it's not allocated dinamically
316 		r_asn1_free_string (validity->notAfter);
317 		r_asn1_free_string (validity->notBefore);
318 	}
319 }
320 
r_x509_free_name(RX509Name * name)321 void r_x509_free_name (RX509Name *name) {
322 	ut32 i;
323 	if (!name) {
324 		return;
325 	}
326 	if (name->names) {
327 		for (i = 0; i < name->length; i++) {
328 			r_asn1_free_string (name->oids[i]);
329 			r_asn1_free_string (name->names[i]);
330 		}
331 		R_FREE (name->names);
332 		R_FREE (name->oids);
333 	}
334 	// not freeing name since it's not allocated dinamically
335 }
336 
r_x509_free_extension(RX509Extension * ex)337 void r_x509_free_extension (RX509Extension *ex) {
338 	if (ex) {
339 		r_asn1_free_string (ex->extnID);
340 		r_asn1_free_binary (ex->extnValue);
341 		//this is allocated dinamically so, i'll free
342 		free (ex);
343 	}
344 }
345 
r_x509_free_extensions(RX509Extensions * ex)346 void r_x509_free_extensions (RX509Extensions *ex) {
347 	ut32 i;
348 	if (!ex) {
349 		return;
350 	}
351 	if (ex->extensions) {
352 		for (i = 0; i < ex->length; i++) {
353 			r_x509_free_extension (ex->extensions[i]);
354 		}
355 		free (ex->extensions);
356 	}
357 	//no need to free ex, since this functions is used internally
358 }
359 
r_x509_free_subjectpublickeyinfo(RX509SubjectPublicKeyInfo * spki)360 void r_x509_free_subjectpublickeyinfo (RX509SubjectPublicKeyInfo *spki) {
361 	if (spki) {
362 		r_x509_free_algorithmidentifier (&spki->algorithm);
363 		r_asn1_free_binary (spki->subjectPublicKey);
364 		r_asn1_free_binary (spki->subjectPublicKeyExponent);
365 		r_asn1_free_binary (spki->subjectPublicKeyModule);
366 		// No need to free spki, since it's a static variable.
367 	}
368 }
369 
r_x509_free_tbscertificate(RX509TBSCertificate * tbsc)370 void r_x509_free_tbscertificate (RX509TBSCertificate *tbsc) {
371 	if (tbsc) {
372 		//  version is ut32
373 		r_asn1_free_string (tbsc->serialNumber);
374 		r_x509_free_algorithmidentifier (&tbsc->signature);
375 		r_x509_free_name (&tbsc->issuer);
376 		r_x509_free_validity (&tbsc->validity);
377 		r_x509_free_name (&tbsc->subject);
378 		r_x509_free_subjectpublickeyinfo (&tbsc->subjectPublicKeyInfo);
379 		r_asn1_free_binary (tbsc->subjectUniqueID);
380 		r_asn1_free_binary (tbsc->issuerUniqueID);
381 		r_x509_free_extensions (&tbsc->extensions);
382 		//no need to free tbsc, since this functions is used internally
383 	}
384 }
385 
r_x509_free_certificate(RX509Certificate * certificate)386 void r_x509_free_certificate (RX509Certificate *certificate) {
387 	if (certificate) {
388 		r_asn1_free_binary (certificate->signature);
389 		r_x509_free_algorithmidentifier (&certificate->algorithmIdentifier);
390 		r_x509_free_tbscertificate (&certificate->tbsCertificate);
391 		free (certificate);
392 	}
393 }
394 
r_x509_free_crlentry(RX509CRLEntry * entry)395 static void r_x509_free_crlentry(RX509CRLEntry *entry) {
396 	if (entry) {
397 		r_asn1_free_binary (entry->userCertificate);
398 		r_asn1_free_string (entry->revocationDate);
399 		free (entry);
400 	}
401 }
402 
r_x509_free_crl(RX509CertificateRevocationList * crl)403 void r_x509_free_crl (RX509CertificateRevocationList *crl) {
404 	ut32 i;
405 	if (crl) {
406 		r_x509_free_algorithmidentifier (&crl->signature);
407 		r_x509_free_name (&crl->issuer);
408 		r_asn1_free_string (crl->nextUpdate);
409 		r_asn1_free_string (crl->lastUpdate);
410 		if (crl->revokedCertificates) {
411 			for (i = 0; i < crl->length; i++) {
412 				r_x509_free_crlentry (crl->revokedCertificates[i]);
413 				crl->revokedCertificates[i] = NULL;
414 			}
415 			R_FREE (crl->revokedCertificates);
416 		}
417 		free (crl);
418 	}
419 }
420 
r_x509_validity_dump(RX509Validity * validity,const char * pad,RStrBuf * sb)421 static void r_x509_validity_dump(RX509Validity *validity, const char *pad, RStrBuf *sb) {
422 	if (!validity) {
423 		return;
424 	}
425 	if (!pad) {
426 		pad = "";
427 	}
428 	const char *b = validity->notBefore ? validity->notBefore->string : "Missing";
429 	const char *a = validity->notAfter ? validity->notAfter->string : "Missing";
430 	r_strbuf_appendf (sb, "%sNot Before: %s\n%sNot After: %s\n", pad, b, pad, a);
431 }
432 
r_x509_name_dump(RX509Name * name,const char * pad,RStrBuf * sb)433 void r_x509_name_dump (RX509Name *name, const char *pad, RStrBuf *sb) {
434 	ut32 i;
435 	if (!name) {
436 		return;
437 	}
438 	if (!pad) {
439 		pad = "";
440 	}
441 	for (i = 0; i < name->length; i++) {
442 		if (!name->oids[i] || !name->names[i]) {
443 			continue;
444 		}
445 		r_strbuf_appendf (sb, "%s%s: %s\n", pad, name->oids[i]->string, name->names[i]->string);
446 	}
447 }
448 
r_x509_subjectpublickeyinfo_dump(RX509SubjectPublicKeyInfo * spki,const char * pad,RStrBuf * sb)449 static void r_x509_subjectpublickeyinfo_dump(RX509SubjectPublicKeyInfo *spki, const char *pad, RStrBuf *sb) {
450 	const char *a;
451 	if (!spki) {
452 		return;
453 	}
454 	if (!pad) {
455 		pad = "";
456 	}
457 	a = spki->algorithm.algorithm ? spki->algorithm.algorithm->string : "Missing";
458 	RASN1String *m = NULL;
459 	if (spki->subjectPublicKeyModule) {
460 		m = r_asn1_stringify_integer (spki->subjectPublicKeyModule->binary, spki->subjectPublicKeyModule->length);
461 	}
462 	//	RASN1String* e = r_asn1_stringify_bytes (spki->subjectPublicKeyExponent->sector, spki->subjectPublicKeyExponent->length);
463 	//	r = snprintf (buffer, length, "%sAlgorithm: %s\n%sModule: %s\n%sExponent: %u bytes\n%s\n", pad, a, pad, m->string,
464 	//				pad, spki->subjectPublicKeyExponent->length - 1, e->string);
465 	r_strbuf_appendf (sb, "%sAlgorithm: %s\n%sModule: %s\n%sExponent: %u bytes\n", pad, a, pad, m ? m->string : "Missing",
466 		pad, spki->subjectPublicKeyExponent ? spki->subjectPublicKeyExponent->length - 1 : 0);
467 	r_asn1_free_string (m);
468 	//	r_asn1_free_string (e);
469 }
470 
r_x509_extensions_dump(RX509Extensions * exts,const char * pad,RStrBuf * sb)471 static void r_x509_extensions_dump(RX509Extensions *exts, const char *pad, RStrBuf *sb) {
472 	ut32 i;
473 	if (!exts) {
474 		return;
475 	}
476 	if (!pad) {
477 		pad = "";
478 	}
479 	for (i = 0; i < exts->length; i++) {
480 		RX509Extension *e = exts->extensions[i];
481 		if (!e) {
482 			continue;
483 		}
484 		//TODO handle extensions..
485 		//s = r_asn1_stringify_bytes (e->extnValue->sector, e->extnValue->length);
486 		r_strbuf_appendf (sb, "%s%s: %s\n%s%u bytes\n", pad,
487 			e->extnID ? e->extnID->string : "Missing",
488 			e->critical ? "critical" : "",
489 			pad, e->extnValue ? e->extnValue->length : 0);
490 		//r_asn1_free_string (s);
491 	}
492 }
493 
r_x509_tbscertificate_dump(RX509TBSCertificate * tbsc,const char * pad,RStrBuf * sb)494 static void r_x509_tbscertificate_dump(RX509TBSCertificate *tbsc, const char *pad, RStrBuf *sb) {
495 	RASN1String *sid = NULL, *iid = NULL;
496 	if (!tbsc) {
497 		return;
498 	}
499 	if (!pad) {
500 		pad = "";
501 	}
502 	char *pad2 = r_str_newf ("%s  ", pad);
503 	if (!pad2) {
504 		return;
505 	}
506 	r_strbuf_appendf (sb, "%sVersion: v%u\n"
507 			      "%sSerial Number:\n%s  %s\n"
508 			      "%sSignature Algorithm:\n%s  %s\n"
509 			      "%sIssuer:\n",
510 		pad, tbsc->version + 1,
511 		pad, pad, tbsc->serialNumber ? tbsc->serialNumber->string : "Missing",
512 		pad, pad, tbsc->signature.algorithm ? tbsc->signature.algorithm->string : "Missing",
513 		pad);
514 	r_x509_name_dump (&tbsc->issuer, pad2, sb);
515 
516 	r_strbuf_appendf (sb, "%sValidity:\n", pad);
517 	r_x509_validity_dump (&tbsc->validity, pad2, sb);
518 
519 	r_strbuf_appendf (sb, "%sSubject:\n", pad);
520 	r_x509_name_dump (&tbsc->subject, pad2, sb);
521 
522 	r_strbuf_appendf (sb, "%sSubject Public Key Info:\n", pad);
523 	r_x509_subjectpublickeyinfo_dump (&tbsc->subjectPublicKeyInfo, pad2, sb);
524 
525 	if (tbsc->issuerUniqueID) {
526 		iid = r_asn1_stringify_integer (tbsc->issuerUniqueID->binary, tbsc->issuerUniqueID->length);
527 		if (iid) {
528 			r_strbuf_appendf (sb, "%sIssuer Unique ID:\n%s  %s", pad, pad, iid->string);
529 			r_asn1_free_string (iid);
530 		}
531 	}
532 	if (tbsc->subjectUniqueID) {
533 		sid = r_asn1_stringify_integer (tbsc->subjectUniqueID->binary, tbsc->subjectUniqueID->length);
534 		if (sid) {
535 			r_strbuf_appendf (sb, "%sSubject Unique ID:\n%s  %s", pad, pad, sid->string);
536 			r_asn1_free_string (sid);
537 		}
538 	}
539 
540 	r_strbuf_appendf (sb, "%sExtensions:\n", pad);
541 	r_x509_extensions_dump (&tbsc->extensions, pad2, sb);
542 	free (pad2);
543 }
544 
r_x509_certificate_dump(RX509Certificate * cert,const char * pad,RStrBuf * sb)545 void r_x509_certificate_dump (RX509Certificate *cert, const char *pad, RStrBuf *sb) {
546 	RASN1String *algo = NULL;
547 	char *pad2;
548 	if (!cert) {
549 		return;
550 	}
551 	if (!pad) {
552 		pad = "";
553 	}
554 	pad2 = r_str_newf ("%s  ", pad);
555 	if (!pad2) {
556 		return;
557 	}
558 	r_strbuf_appendf (sb, "%sTBSCertificate:\n", pad);
559 	r_x509_tbscertificate_dump (&cert->tbsCertificate, pad2, sb);
560 
561 	algo = cert->algorithmIdentifier.algorithm;
562 	//	signature = r_asn1_stringify_bytes (certificate->signature->binary, certificate->signature->length);
563 	//	eprintf ("%sAlgorithm:\n%s%s\n%sSignature: %u bytes\n%s\n",
564 	//				pad, pad2, algo ? algo->string : "",
565 	//				pad, certificate->signature->length, signature ? signature->string : "");
566 	r_strbuf_appendf (sb, "%sAlgorithm:\n%s%s\n%sSignature: %u bytes\n",
567 		pad, pad2, algo ? algo->string : "", pad, cert->signature->length);
568 	free (pad2);
569 	//	r_asn1_free_string (signature);
570 }
571 
r_x509_crlentry_dump(RX509CRLEntry * crle,const char * pad,RStrBuf * sb)572 void r_x509_crlentry_dump (RX509CRLEntry *crle, const char *pad, RStrBuf *sb) {
573 	RASN1String *id = NULL, *utc = NULL;
574 	if (!crle) {
575 		return;
576 	}
577 	if (!pad) {
578 		pad = "";
579 	}
580 	utc = crle->revocationDate;
581 	if (crle->userCertificate) {
582 		id = r_asn1_stringify_integer (crle->userCertificate->binary, crle->userCertificate->length);
583 	}
584 	r_strbuf_appendf (sb, "%sUser Certificate:\n%s  %s\n"
585 			      "%sRevocation Date:\n%s  %s\n",
586 		pad, pad, id ? id->string : "Missing",
587 		pad, pad, utc ? utc->string : "Missing");
588 	r_asn1_free_string (id);
589 }
590 
r_x509_crl_to_string(RX509CertificateRevocationList * crl,const char * pad)591 R_API char *r_x509_crl_to_string(RX509CertificateRevocationList *crl, const char *pad) {
592 	RASN1String *algo = NULL, *last = NULL, *next = NULL;
593 	ut32 i;
594 	char *pad2, *pad3;
595 	if (!crl) {
596 		return NULL;
597 	}
598 	if (!pad) {
599 		pad = "";
600 	}
601 	pad3 = r_str_newf ("%s    ", pad);
602 	if (!pad3) {
603 		return NULL;
604 	}
605 	pad2 = pad3 + 2;
606 	algo = crl->signature.algorithm;
607 	last = crl->lastUpdate;
608 	next = crl->nextUpdate;
609 	RStrBuf *sb = r_strbuf_new ("");
610 	r_strbuf_appendf (sb, "%sCRL:\n%sSignature:\n%s%s\n%sIssuer\n", pad, pad2, pad3,
611 		algo ? algo->string : "", pad2);
612 	r_x509_name_dump (&crl->issuer, pad3, sb);
613 
614 	r_strbuf_appendf (sb, "%sLast Update: %s\n%sNext Update: %s\n%sRevoked Certificates:\n",
615 		pad2, last ? last->string : "Missing",
616 		pad2, next ? next->string : "Missing", pad2);
617 
618 	for (i = 0; i < crl->length; i++) {
619 		r_x509_crlentry_dump (crl->revokedCertificates[i], pad3, sb);
620 	}
621 
622 	free (pad3);
623 	return r_strbuf_drain (sb);
624 }
625 
r_x509_validity_json(PJ * pj,RX509Validity * validity)626 R_API void r_x509_validity_json(PJ *pj, RX509Validity *validity) {
627 	if (validity) {
628 		if (validity->notBefore) {
629 			pj_ks (pj, "NotBefore", validity->notBefore->string);
630 		}
631 		if (validity->notAfter) {
632 			pj_ks (pj, "NotAfter", validity->notAfter->string);
633 		}
634 	}
635 }
636 
r_x509_name_json(PJ * pj,RX509Name * name)637 R_API void r_x509_name_json(PJ *pj, RX509Name *name) {
638 	ut32 i;
639 	for (i = 0; i < name->length; i++) {
640 		if (!name->oids[i] || !name->names[i]) {
641 			continue;
642 		}
643 		pj_ks (pj, name->oids[i]->string, name->names[i]->string);
644 	}
645 }
646 
r_x509_subjectpublickeyinfo_json(PJ * pj,RX509SubjectPublicKeyInfo * spki)647 R_API void r_x509_subjectpublickeyinfo_json(PJ *pj, RX509SubjectPublicKeyInfo *spki) {
648 	RASN1String *m = NULL;
649 	if (spki) {
650 		if (spki->algorithm.algorithm) {
651 			pj_ks (pj, "Algorithm", spki->algorithm.algorithm->string);
652 		}
653 		if (spki->subjectPublicKeyModule) {
654 			m = r_asn1_stringify_integer (spki->subjectPublicKeyModule->binary, spki->subjectPublicKeyModule->length);
655 			if (m) {
656 				pj_ks (pj, "Module", m->string);
657 			}
658 			r_asn1_free_string (m);
659 		}
660 		if (spki->subjectPublicKeyExponent) {
661 			m = r_asn1_stringify_integer (spki->subjectPublicKeyExponent->binary, spki->subjectPublicKeyExponent->length);
662 			if (m) {
663 				pj_ks (pj, "Exponent", m->string);
664 			}
665 			r_asn1_free_string (m);
666 		}
667 	}
668 }
669 
r_x509_extensions_json(PJ * pj,RX509Extensions * exts)670 R_API void r_x509_extensions_json(PJ *pj, RX509Extensions *exts) {
671 	if (exts) {
672 		RASN1String *m = NULL;
673 		ut32 i;
674 		pj_a (pj);
675 		for (i = 0; i < exts->length; i++) {
676 			RX509Extension *e = exts->extensions[i];
677 			if (!e) {
678 				continue;
679 			}
680 			pj_o (pj);
681 			if (e->extnID) {
682 				pj_ks (pj, "OID", e->extnID->string);
683 			}
684 			if (e->critical) {
685 				pj_kb (pj, "Critical", e->critical);
686 			}
687 			//TODO handle extensions correctly..
688 			if (e->extnValue) {
689 				m = r_asn1_stringify_integer (e->extnValue->binary, e->extnValue->length);
690 				if (m) {
691 					pj_ks (pj, "Value", m->string);
692 				}
693 				r_asn1_free_string (m);
694 			}
695 			pj_end (pj);
696 		}
697 		pj_end (pj);
698 		pj_end (pj);
699 	}
700 }
701 
r_x509_crlentry_json(PJ * pj,RX509CRLEntry * crle)702 R_API void r_x509_crlentry_json(PJ *pj, RX509CRLEntry *crle) {
703 	RASN1String *m = NULL;
704 	if (crle) {
705 		if (crle->userCertificate) {
706 			m = r_asn1_stringify_integer (crle->userCertificate->binary, crle->userCertificate->length);
707 			if (m) {
708 				pj_ks (pj, "UserCertificate", m->string);
709 			}
710 			r_asn1_free_string (m);
711 		}
712 		if (crle->revocationDate) {
713 			pj_ks (pj, "RevocationDate", crle->revocationDate->string);
714 		}
715 	}
716 }
717 
r_x509_crl_json(PJ * pj,RX509CertificateRevocationList * crl)718 R_API void r_x509_crl_json(PJ *pj, RX509CertificateRevocationList *crl) {
719 	ut32 i;
720 	if (crl) {
721 		if (crl->signature.algorithm) {
722 			pj_ks (pj, "Signature", crl->signature.algorithm->string);
723 		}
724 		pj_k (pj, "Issuer");
725 		pj_o (pj);
726 		r_x509_name_json (pj, &crl->issuer);
727 		pj_end (pj);
728 		if (crl->lastUpdate) {
729 			pj_ks (pj, "LastUpdate", crl->lastUpdate->string);
730 		}
731 		if (crl->nextUpdate) {
732 			pj_ks (pj, "NextUpdate", crl->nextUpdate->string);
733 		}
734 		pj_k (pj, "RevokedCertificates");
735 		pj_a (pj);
736 		for (i = 0; i < crl->length; i++) {
737 			r_x509_crlentry_json (pj, crl->revokedCertificates[i]);
738 		}
739 		pj_end (pj);
740 	}
741 }
742 
r_x509_tbscertificate_json(PJ * pj,RX509TBSCertificate * tbsc)743 R_API void r_x509_tbscertificate_json(PJ *pj, RX509TBSCertificate *tbsc) {
744 	pj_o (pj);
745 	RASN1String *m = NULL;
746 	if (tbsc) {
747 		pj_ki (pj, "Version", tbsc->version + 1);
748 		if (tbsc->serialNumber) {
749 			pj_ks (pj, "SerialNumber", tbsc->serialNumber->string);
750 		}
751 		if (tbsc->signature.algorithm) {
752 			pj_ks (pj, "SignatureAlgorithm", tbsc->signature.algorithm->string);
753 		}
754 		pj_k (pj, "Issuer");
755 		pj_o (pj);
756 		r_x509_name_json (pj, &tbsc->issuer);
757 		pj_end (pj);
758 		pj_k (pj, "Validity");
759 		pj_o (pj);
760 		r_x509_validity_json (pj, &tbsc->validity);
761 		pj_end (pj);
762 		pj_k (pj, "Subject");
763 		pj_o (pj);
764 		r_x509_name_json (pj, &tbsc->subject);
765 		pj_end (pj);
766 		pj_k (pj, "SubjectPublicKeyInfo");
767 		pj_o (pj);
768 		r_x509_subjectpublickeyinfo_json (pj, &tbsc->subjectPublicKeyInfo);
769 		pj_end (pj);
770 		if (tbsc->issuerUniqueID) {
771 			m = r_asn1_stringify_integer (tbsc->issuerUniqueID->binary, tbsc->issuerUniqueID->length);
772 			if (m) {
773 				pj_ks (pj, "IssuerUniqueID", m->string);
774 			}
775 			r_asn1_free_string (m);
776 		}
777 		if (tbsc->subjectUniqueID) {
778 			m = r_asn1_stringify_integer (tbsc->subjectUniqueID->binary, tbsc->subjectUniqueID->length);
779 			if (m) {
780 				pj_ks (pj, "SubjectUniqueID", m->string);
781 			}
782 			r_asn1_free_string (m);
783 		}
784 		pj_k (pj, "Extensions");
785 		r_x509_extensions_json (pj, &tbsc->extensions);
786 	}
787 }
788 
r_x509_certificate_json(PJ * pj,RX509Certificate * certificate)789 R_API void r_x509_certificate_json(PJ *pj, RX509Certificate *certificate) {
790 	if (!certificate) {
791 		return;
792 	}
793 	RASN1String *m = NULL;
794 	pj_o (pj);
795 	pj_k (pj, "TBSCertificate");
796 	r_x509_tbscertificate_json (pj, &certificate->tbsCertificate);
797 	if (certificate->algorithmIdentifier.algorithm) {
798 		pj_ks (pj, "Algorithm", certificate->algorithmIdentifier.algorithm->string);
799 	}
800 	if (certificate->signature) {
801 		m = r_asn1_stringify_integer (certificate->signature->binary, certificate->signature->length);
802 		if (m) {
803 			pj_ks (pj, "Signature", m->string);
804 		}
805 		r_asn1_free_string (m);
806 	}
807 	pj_end (pj);
808 }
809