Skip to content

Commit 32e6e63

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

File tree

7 files changed

+152
-2
lines changed

7 files changed

+152
-2
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ tv_gen
5252
tv_gen.exe
5353
timing
5454
timing.exe
55+
x509_verify
56+
x509_verify.exe
5557

5658
# Visual Studio special files
5759
# ignore user specific settings

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
31+
# USEABLE_DEMOS = aesgcm constants crypt openssh-privkey openssl-enc pem-info sizes timing x509_verify
3232
# -----------------------------------------------------------------------------
3333

3434
if(BUILD_USABLE_DEMOS)
@@ -43,6 +43,7 @@ if(BUILD_USABLE_DEMOS)
4343
pem-info
4444
sizes
4545
timing
46+
x509_verify
4647
)
4748
endif()
4849

demos/x509_verify.c

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2+
/* SPDX-License-Identifier: Unlicense */
3+
/* load a X.509 certificate chain and verify its validity */
4+
#include <tomcrypt.h>
5+
#include <stdarg.h>
6+
7+
#ifdef LTC_QUIET
8+
static void print_err(const char *fmt, ...)
9+
{
10+
LTC_UNUSED_PARAM(fmt);
11+
}
12+
13+
#define print_stderr(...)
14+
#else
15+
static void print_err(const char *fmt, ...)
16+
{
17+
va_list args;
18+
19+
va_start(args, fmt);
20+
vfprintf(stderr, fmt, args);
21+
va_end(args);
22+
}
23+
24+
#define print_stderr(...) fprintf(stderr, ##__VA_ARGS__)
25+
#endif
26+
27+
28+
static unsigned long num_certs;
29+
static const ltc_x509_certificate *cert[32] = {0};
30+
static FILE *f;
31+
32+
static void die_(int err, int line)
33+
{
34+
unsigned long n;
35+
print_err("%3d: LTC sez %s\n", line, error_to_string(err));
36+
for (n = num_certs; n --> 0;) {
37+
x509_free(&cert[n]);
38+
}
39+
if (f) fclose(f);
40+
exit(EXIT_FAILURE);
41+
}
42+
43+
#define die(i) do { die_(i, __LINE__); } while(0)
44+
#define DIE(s, ...) do { print_err("%3d: " s "\n", __LINE__, ##__VA_ARGS__); exit(EXIT_FAILURE); } while(0)
45+
#ifndef LTC_ARRAY_SIZE
46+
#define LTC_ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
47+
#endif
48+
49+
int main(int argc, char **argv)
50+
{
51+
const unsigned char zero_cert_buf[sizeof(cert)] = {0};
52+
int err, argn = 1;
53+
unsigned long len, processed, n;
54+
long tell, tot_data = 0;
55+
56+
if ((err = register_all_hashes()) != CRYPT_OK) {
57+
die(err);
58+
}
59+
if ((err = crypt_mp_init("ltm")) != CRYPT_OK) {
60+
die(err);
61+
}
62+
63+
next:
64+
tot_data = processed = num_certs = n = 0;
65+
if (argc > argn) f = fopen(argv[argn], "r");
66+
else f = stdin;
67+
if (f == NULL) DIE("fopen sez no");
68+
if (f != stdin) {
69+
fseek(f, 0, SEEK_END);
70+
tot_data = ftell(f);
71+
rewind(f);
72+
tell = 0;
73+
} else {
74+
tell = -1;
75+
}
76+
77+
print_stderr("-=-=-=-=-=-=-\nDecode %s\n=-=-=-=-=-=-=\n", argv[argn]);
78+
79+
while (tell != tot_data && (err = x509_import_pem_filehandle(f, &cert[n])) == CRYPT_OK) {
80+
if (f != stdin) {
81+
tell = ftell(f);
82+
print_stderr("len: %ld - tot: %ld - processed: %lu\n", tell, tot_data, processed);
83+
len = tell - processed;
84+
processed += len;
85+
}
86+
n++;
87+
if (n == LTC_ARRAY_SIZE(cert))
88+
break;
89+
}
90+
num_certs = n;
91+
print_stderr("len: %ld - tot: %ld - processed: %lu\n", tell, tot_data, processed);
92+
if (err && argc > argn) goto check_next;
93+
if (err && err != CRYPT_NOP) die(err);
94+
for (n = 0; n < num_certs; ++n) {
95+
unsigned long m = n + 1 == num_certs ? n : n + 1;
96+
int stat;
97+
if ((err = x509_cert_is_signed_by(cert[n], &cert[m]->tbs_certificate.subject_public_key_info, &stat)) != CRYPT_OK) {
98+
print_err("%3d: LTC sez %s\n", __LINE__, error_to_string(err));
99+
if (m == n) {
100+
print_stderr("Cert is last in chain, but not self-signed.\n");
101+
} else {
102+
break;
103+
}
104+
}
105+
{
106+
const ltc_x509_string *subjects[4];
107+
int issuer_matches_subject = x509_cmp_name(&cert[n]->tbs_certificate.issuer, &cert[m]->tbs_certificate.subject);
108+
x509_name_detail_get(&cert[n]->tbs_certificate.subject, LTC_X509_CN, &subjects[0]);
109+
x509_name_detail_get(&cert[n]->tbs_certificate.subject, LTC_X509_O, &subjects[2]);
110+
if (n != m) {
111+
x509_name_detail_get(&cert[m]->tbs_certificate.subject, LTC_X509_CN, &subjects[1]);
112+
x509_name_detail_get(&cert[m]->tbs_certificate.subject, LTC_X509_O, &subjects[3]);
113+
} else {
114+
x509_name_detail_get(&cert[m]->tbs_certificate.issuer, LTC_X509_CN, &subjects[1]);
115+
x509_name_detail_get(&cert[m]->tbs_certificate.issuer, LTC_X509_O, &subjects[3]);
116+
}
117+
#define X509_STRING_STR(s) (s) ? (s)->str : "NULL"
118+
print_stderr("Cert: %s - %s\nCA: %s - %s\nIssuer matches subject: %s\nVerify: %s\n",
119+
X509_STRING_STR(subjects[0]), X509_STRING_STR(subjects[2]),
120+
X509_STRING_STR(subjects[1]), X509_STRING_STR(subjects[3]),
121+
issuer_matches_subject ? "True" : "False", stat ? "Success" : "Failed");
122+
/* In case of LTC_QUIET this would show up as unused. */
123+
LTC_UNUSED_PARAM(issuer_matches_subject);
124+
}
125+
}
126+
check_next:
127+
for (n = num_certs; n --> 0;) {
128+
x509_free(&cert[n]);
129+
}
130+
if (XMEMCMP(cert, zero_cert_buf, sizeof(zero_cert_buf))) {
131+
DIE("cert buf not completely cleaned");
132+
}
133+
if (f != stdin) {
134+
fclose(f);
135+
argn++;
136+
if (argc > argn) {
137+
goto next;
138+
}
139+
}
140+
return 0;
141+
}

makefile.mingw

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,8 @@ constants.exe: demos/constants.o $(LIBMAIN_S)
301301
$(CC) demos/constants.o $(LIBMAIN_S) $(LTC_LDFLAGS) -o $@
302302
timing.exe: demos/timing.o $(LIBMAIN_S)
303303
$(CC) demos/timing.o $(LIBMAIN_S) $(LTC_LDFLAGS) -o $@
304+
x509_verify.exe: demos/x509_verify.o $(LIBMAIN_S)
305+
$(CC) demos/x509_verify.o $(LIBMAIN_S) $(LTC_LDFLAGS) -o $@
304306

305307
#Tests
306308
test.exe: $(TOBJECTS) $(LIBMAIN_S)

makefile.msvc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,8 @@ constants.exe: demos/constants.c $(LIBMAIN_S)
288288
cl $(LTC_CFLAGS) demos/constants.c tests/common.c $(LIBMAIN_S) $(LTC_LDFLAGS) /Fe$@
289289
timing.exe: demos/timing.c $(LIBMAIN_S)
290290
cl $(LTC_CFLAGS) demos/timing.c tests/common.c $(LIBMAIN_S) $(LTC_LDFLAGS) /Fe$@
291+
x509_verify.exe: demos/x509_verify.c $(LIBMAIN_S)
292+
cl $(LTC_CFLAGS) demos/x509_verify.c tests/common.c $(LIBMAIN_S) $(LTC_LDFLAGS) /Fe$@
291293

292294
#Tests
293295
test.exe: $(LIBMAIN_S) $(TOBJECTS)

makefile.unix

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,8 @@ constants: demos/constants.o $(LIBMAIN_S)
312312
$(CC) demos/constants.o $(LIBMAIN_S) $(LTC_LDFLAGS) -o $@
313313
timing: demos/timing.o $(LIBMAIN_S)
314314
$(CC) demos/timing.o $(LIBMAIN_S) $(LTC_LDFLAGS) -o $@
315+
x509_verify: demos/x509_verify.o $(LIBMAIN_S)
316+
$(CC) demos/x509_verify.o $(LIBMAIN_S) $(LTC_LDFLAGS) -o $@
315317

316318
#Tests
317319
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
177+
USEABLE_DEMOS = aesgcm constants crypt 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)