Skip to content

Commit 9f9fd34

Browse files
committed
Add demos/der_print_flexi.c
Signed-off-by: Steffen Jaeckel <s@jaeckel.eu>
1 parent 32e6e63 commit 9f9fd34

File tree

7 files changed

+338
-2
lines changed

7 files changed

+338
-2
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ constants
3232
constants.exe
3333
crypt
3434
crypt.exe
35+
der_print_flexi
36+
der_print_flexi.exe
3537
hashsum
3638
hashsum.exe
3739
multi

demos/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ endif()
2828
#
2929
# Demos that are usable but only rarely make sense to be installed
3030
#
31-
# USEABLE_DEMOS = aesgcm constants crypt openssh-privkey openssl-enc pem-info sizes timing x509_verify
31+
# USEABLE_DEMOS = aesgcm constants crypt der_print_flexi openssh-privkey openssl-enc pem-info sizes timing x509_verify
3232
# -----------------------------------------------------------------------------
3333

3434
if(BUILD_USABLE_DEMOS)
@@ -38,6 +38,7 @@ if(BUILD_USABLE_DEMOS)
3838
aesgcm
3939
constants
4040
crypt
41+
der_print_flexi
4142
openssh-privkey
4243
openssl-enc
4344
pem-info

demos/der_print_flexi.c

Lines changed: 327 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,327 @@
1+
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2+
/* SPDX-License-Identifier: Unlicense */
3+
/* DER flexi-decode a certificate */
4+
#include "tomcrypt_private.h"
5+
#include <wchar.h>
6+
7+
#define ASN1_FMTSTRING_FMT "line: %d, type=%d, size=%lu, data=%p, self=%p, next=%p, prev=%p, parent=%p, child=%p"
8+
#define ASN1_FMTSTRING_VAL(l) __LINE__, (l)->type, (l)->size, (l)->data, (l), (l)->next, (l)->prev, (l)->parent, (l)->child
9+
10+
static void* s_xmalloc(int l)
11+
{
12+
void *r = XCALLOC(1, l);
13+
14+
#if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 3
15+
fprintf(stderr, "ALLOC %9d to %p\n", l, r);
16+
#endif
17+
if (!r) {
18+
fprintf(stderr, "Could not allocate %d bytes of memory\n", l);
19+
exit(EXIT_FAILURE);
20+
}
21+
return r;
22+
}
23+
24+
#ifndef S_FREE
25+
static void s_free(void *p)
26+
{
27+
#if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 3
28+
fprintf(stderr, "FREE %p\n", p);
29+
#endif
30+
XFREE(p);
31+
}
32+
#endif
33+
34+
static void s_der_print_flexi_i(const ltc_asn1_list* l, unsigned int level)
35+
{
36+
char *buf = NULL;
37+
const char *name = NULL;
38+
const char *text = NULL;
39+
ltc_asn1_list *ostring = NULL;
40+
unsigned int n;
41+
int slen;
42+
const wchar_t *wtmp;
43+
44+
switch (l->type)
45+
{
46+
case LTC_ASN1_EOL:
47+
name = "EOL";
48+
slen = snprintf(NULL, 0, ASN1_FMTSTRING_FMT "\n", ASN1_FMTSTRING_VAL(l));
49+
buf = s_xmalloc(slen);
50+
snprintf(buf, slen, ASN1_FMTSTRING_FMT "\n", ASN1_FMTSTRING_VAL(l));
51+
text = buf;
52+
break;
53+
case LTC_ASN1_BOOLEAN:
54+
name = "BOOLEAN";
55+
{
56+
if (*(int*) l->data)
57+
text = "true";
58+
else
59+
text = "false";
60+
}
61+
break;
62+
case LTC_ASN1_INTEGER:
63+
name = "INTEGER";
64+
buf = s_xmalloc(((ltc_mp_get_digit_count(l->data) + 1) * ltc_mp.bits_per_digit) / 3);
65+
ltc_mp_toradix(l->data, buf, 10);
66+
text = buf;
67+
break;
68+
case LTC_ASN1_SHORT_INTEGER:
69+
name = "SHORT INTEGER";
70+
break;
71+
case LTC_ASN1_BIT_STRING:
72+
name = "BIT STRING";
73+
if (l->size <= 16) {
74+
int r;
75+
int sz = l->size + 1;
76+
char *s = buf = s_xmalloc(sz);
77+
for (n = 0; n < l->size; ++n) {
78+
r = snprintf(s, sz, "%c", ((unsigned char*) l->data)[n] ? '1' : '0');
79+
if (r < 0 || r >= sz) {
80+
fprintf(stderr, "%s boom\n", name);
81+
exit(EXIT_FAILURE);
82+
}
83+
s += r;
84+
sz -= r;
85+
}
86+
} else {
87+
slen = snprintf(NULL, 0, "Length %lu", l->size);
88+
buf = s_xmalloc(slen);
89+
snprintf(buf, slen, "Length %lu", l->size);
90+
}
91+
text = buf;
92+
break;
93+
case LTC_ASN1_OCTET_STRING:
94+
name = "OCTET STRING";
95+
{
96+
unsigned long ostring_l = l->size;
97+
/* sometimes there's another sequence in an octet string...
98+
* try to decode that... if it fails print out the octet string
99+
*/
100+
if (der_decode_sequence_flexi(l->data, &ostring_l, &ostring) == CRYPT_OK) {
101+
text = "";
102+
} else {
103+
int r;
104+
int sz = l->size * 2 + 1;
105+
char *s = buf = s_xmalloc(sz);
106+
for (n = 0; n < l->size; ++n) {
107+
r = snprintf(s, sz, "%02X", ((unsigned char*) l->data)[n]);
108+
if (r < 0 || r >= sz) {
109+
fprintf(stderr, "%s boom\n", name);
110+
exit(EXIT_FAILURE);
111+
}
112+
s += r;
113+
sz -= r;
114+
}
115+
text = buf;
116+
}
117+
}
118+
break;
119+
case LTC_ASN1_NULL:
120+
name = "NULL";
121+
text = "";
122+
break;
123+
case LTC_ASN1_OBJECT_IDENTIFIER:
124+
name = "OBJECT IDENTIFIER";
125+
{
126+
unsigned long len = 0;
127+
if (pk_oid_num_to_str(l->data, l->size, buf, &len) != CRYPT_BUFFER_OVERFLOW) {
128+
fprintf(stderr, "%s WTF\n", name);
129+
exit(EXIT_FAILURE);
130+
}
131+
buf = s_xmalloc(len);
132+
if (pk_oid_num_to_str(l->data, l->size, buf, &len) != CRYPT_OK) {
133+
fprintf(stderr, "%s boom\n", name);
134+
exit(EXIT_FAILURE);
135+
}
136+
text = buf;
137+
}
138+
break;
139+
case LTC_ASN1_IA5_STRING:
140+
name = "IA5 STRING";
141+
text = l->data;
142+
break;
143+
case LTC_ASN1_PRINTABLE_STRING:
144+
name = "PRINTABLE STRING";
145+
text = l->data;
146+
break;
147+
case LTC_ASN1_UTF8_STRING:
148+
name = "UTF8 STRING";
149+
wtmp = l->data;
150+
slen = wcsrtombs(NULL, &wtmp, 0, NULL);
151+
if (slen != -1) {
152+
slen++;
153+
buf = s_xmalloc(slen);
154+
if (wcsrtombs(buf, &wtmp, slen, NULL) == (size_t)-1) {
155+
fprintf(stderr, "%s boom\n", name);
156+
exit(EXIT_FAILURE);
157+
}
158+
text = buf;
159+
}
160+
break;
161+
case LTC_ASN1_UTCTIME:
162+
name = "UTCTIME";
163+
{
164+
ltc_utctime *ut = l->data;
165+
slen = 32;
166+
buf = s_xmalloc(slen);
167+
snprintf(buf, slen, "%02d-%02d-%02d %02d:%02d:%02d %c%02d:%02d", ut->YY, ut->MM, ut->DD, ut->hh, ut->mm,
168+
ut->ss, ut->off_dir ? '-' : '+', ut->off_hh, ut->off_mm);
169+
text = buf;
170+
}
171+
break;
172+
case LTC_ASN1_GENERALIZEDTIME:
173+
name = "GENERALIZED TIME";
174+
{
175+
ltc_generalizedtime *gt = l->data;
176+
slen = 32;
177+
buf = s_xmalloc(slen);
178+
if (gt->fs)
179+
snprintf(buf, slen, "%04d-%02d-%02d %02d:%02d:%02d.%02dZ", gt->YYYY, gt->MM, gt->DD, gt->hh, gt->mm,
180+
gt->ss, gt->fs);
181+
else
182+
snprintf(buf, slen, "%04d-%02d-%02d %02d:%02d:%02dZ", gt->YYYY, gt->MM, gt->DD, gt->hh, gt->mm, gt->ss);
183+
text = buf;
184+
}
185+
break;
186+
case LTC_ASN1_CHOICE:
187+
name = "CHOICE";
188+
break;
189+
case LTC_ASN1_SEQUENCE:
190+
name = "SEQUENCE";
191+
text = "";
192+
break;
193+
case LTC_ASN1_SET:
194+
name = "SET";
195+
text = "";
196+
break;
197+
case LTC_ASN1_SETOF:
198+
name = "SETOF";
199+
text = "";
200+
break;
201+
case LTC_ASN1_RAW_BIT_STRING:
202+
name = "RAW BIT STRING";
203+
break;
204+
case LTC_ASN1_TELETEX_STRING:
205+
name = "TELETEX STRING";
206+
text = l->data;
207+
break;
208+
case LTC_ASN1_CUSTOM_TYPE:
209+
name = "NON STANDARD";
210+
{
211+
int r;
212+
int sz = 128;
213+
char *s = buf = s_xmalloc(sz);
214+
215+
r = snprintf(s, sz, "[%s %s %llu]", der_asn1_class_to_string_map[l->klass],
216+
der_asn1_pc_to_string_map[l->pc], l->tag);
217+
if (r < 0 || r >= sz) {
218+
fprintf(stderr, "%s boom\n", name);
219+
exit(EXIT_FAILURE);
220+
}
221+
222+
text = buf;
223+
}
224+
break;
225+
}
226+
227+
for (n = 0; n < level; ++n) {
228+
fprintf(stderr, " ");
229+
}
230+
if (name) {
231+
if (text)
232+
fprintf(stderr, "%s %s\n", name, text);
233+
else
234+
fprintf(stderr, "%s <missing decoding>\n", name);
235+
} else
236+
fprintf(stderr, "WTF type=%i\n", l->type);
237+
238+
if (buf) {
239+
s_free(buf);
240+
buf = NULL;
241+
}
242+
243+
if (ostring) {
244+
s_der_print_flexi_i(ostring, level + 1);
245+
der_free_sequence_flexi(ostring);
246+
}
247+
248+
if (l->child) s_der_print_flexi_i(l->child, level + 1);
249+
250+
if (l->next) s_der_print_flexi_i(l->next, level);
251+
}
252+
253+
#ifndef LTC_DER_PRINT_FLEXI_NO_MAIN
254+
255+
static void s_der_print_flexi(const ltc_asn1_list* l)
256+
{
257+
fprintf(stderr, "\n\n");
258+
s_der_print_flexi_i(l, 0);
259+
fprintf(stderr, "\n\n");
260+
}
261+
262+
#include <sys/mman.h>
263+
#include <sys/stat.h>
264+
#include <fcntl.h>
265+
#include <stdio.h>
266+
#include <stdlib.h>
267+
#include <unistd.h>
268+
269+
static int fd;
270+
static ltc_asn1_list *l;
271+
272+
static void print_err(const char *fmt, ...)
273+
{
274+
va_list args;
275+
276+
va_start(args, fmt);
277+
vfprintf(stderr, fmt, args);
278+
va_end(args);
279+
}
280+
281+
static void die_(int err, int line)
282+
{
283+
print_err("%3d: LTC sez %s\n", line, error_to_string(err));
284+
der_free_sequence_flexi(l);
285+
close(fd);
286+
exit(EXIT_FAILURE);
287+
}
288+
289+
#define die(i) do { die_(i, __LINE__); } while(0)
290+
#define DIE(s, ...) do { print_err("%3d: " s "\n", __LINE__, ##__VA_ARGS__); exit(EXIT_FAILURE); } while(0)
291+
292+
int main(int argc, char **argv)
293+
{
294+
void *addr;
295+
int err, argn = 1;
296+
struct stat sb;
297+
unsigned long len;
298+
299+
if ((err = register_all_hashes()) != CRYPT_OK) {
300+
die(err);
301+
}
302+
if ((err = crypt_mp_init("ltm")) != CRYPT_OK) {
303+
die(err);
304+
}
305+
if (argc > argn) fd = open(argv[argn], O_RDONLY);
306+
else fd = STDIN_FILENO;
307+
if (fd == -1) DIE("open sez no");
308+
if (fstat(fd, &sb) == -1) DIE("fstat");
309+
310+
addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
311+
if (addr == MAP_FAILED) DIE("mmap");
312+
313+
len = sb.st_size;
314+
315+
if ((err = der_decode_sequence_flexi(addr, &len, &l)) != CRYPT_OK) {
316+
die(err);
317+
}
318+
319+
s_der_print_flexi(l);
320+
321+
der_free_sequence_flexi(l);
322+
close(fd);
323+
324+
return 0;
325+
}
326+
327+
#endif /* LTC_DER_PRINT_FLEXI_NO_MAIN */

makefile.mingw

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,8 @@ timing.exe: demos/timing.o $(LIBMAIN_S)
303303
$(CC) demos/timing.o $(LIBMAIN_S) $(LTC_LDFLAGS) -o $@
304304
x509_verify.exe: demos/x509_verify.o $(LIBMAIN_S)
305305
$(CC) demos/x509_verify.o $(LIBMAIN_S) $(LTC_LDFLAGS) -o $@
306+
der_print_flexi.exe: demos/der_print_flexi.o $(LIBMAIN_S)
307+
$(CC) demos/der_print_flexi.o $(LIBMAIN_S) $(LTC_LDFLAGS) -o $@
306308

307309
#Tests
308310
test.exe: $(TOBJECTS) $(LIBMAIN_S)

makefile.msvc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,8 @@ timing.exe: demos/timing.c $(LIBMAIN_S)
290290
cl $(LTC_CFLAGS) demos/timing.c tests/common.c $(LIBMAIN_S) $(LTC_LDFLAGS) /Fe$@
291291
x509_verify.exe: demos/x509_verify.c $(LIBMAIN_S)
292292
cl $(LTC_CFLAGS) demos/x509_verify.c tests/common.c $(LIBMAIN_S) $(LTC_LDFLAGS) /Fe$@
293+
der_print_flexi.exe: demos/der_print_flexi.c $(LIBMAIN_S)
294+
cl $(LTC_CFLAGS) demos/der_print_flexi.c tests/common.c $(LIBMAIN_S) $(LTC_LDFLAGS) /Fe$@
293295

294296
#Tests
295297
test.exe: $(LIBMAIN_S) $(TOBJECTS)

makefile.unix

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,8 @@ timing: demos/timing.o $(LIBMAIN_S)
314314
$(CC) demos/timing.o $(LIBMAIN_S) $(LTC_LDFLAGS) -o $@
315315
x509_verify: demos/x509_verify.o $(LIBMAIN_S)
316316
$(CC) demos/x509_verify.o $(LIBMAIN_S) $(LTC_LDFLAGS) -o $@
317+
der_print_flexi: demos/der_print_flexi.o $(LIBMAIN_S)
318+
$(CC) demos/der_print_flexi.o $(LIBMAIN_S) $(LTC_LDFLAGS) -o $@
317319

318320
#Tests
319321
test: $(TOBJECTS) $(LIBMAIN_S)

makefile_include.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ TEST=test
174174
USEFUL_DEMOS = hashsum
175175

176176
# Demos that are usable but only rarely make sense to be installed
177-
USEABLE_DEMOS = aesgcm constants crypt openssh-privkey openssl-enc pem-info sizes timing x509_verify
177+
USEABLE_DEMOS = aesgcm constants crypt der_print_flexi openssh-privkey openssl-enc pem-info sizes timing x509_verify
178178

179179
# Demos that are used for testing or measuring
180180
TEST_DEMOS = small tv_gen

0 commit comments

Comments
 (0)