Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
ex_x509.c
Go to the documentation of this file.
1/*
2 * Nilorea Library
3 * Copyright (C) 2005-2026 Castagnier Mickael
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14 * implied. See the License for the specific language governing
15 * permissions and limitations under the License.
16 *
17 * SPDX-License-Identifier: Apache-2.0
18 */
19
27#include "nilorea/n_log.h"
28#include "nilorea/n_str.h"
29#include "nilorea/n_x509.h"
30
31#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
34#include <unistd.h>
35
36#include <openssl/pem.h>
37#include <openssl/x509.h>
38#include <openssl/x509_vfy.h>
39
40/* Parse the -V LOG_LEVEL verbosity argument. */
41void process_args(int argc, char** argv) {
42 int opt = 0;
43 while ((opt = getopt(argc, argv, "hvV:")) != EOF) {
44 switch (opt) {
45 case 'V':
46 if (!strncmp("LOG_NULL", optarg, 8))
48 else if (!strncmp("LOG_NOTICE", optarg, 10))
50 else if (!strncmp("LOG_INFO", optarg, 8))
52 else if (!strncmp("LOG_ERR", optarg, 7))
54 else if (!strncmp("LOG_DEBUG", optarg, 9))
56 else {
57 fprintf(stderr, "Unknown log level %s\n", optarg);
58 exit(1);
59 }
60 break;
61 case 'v':
62 fprintf(stderr, "ex_x509\n");
63 exit(1);
64 case 'h':
65 default:
66 fprintf(stderr, "usage: %s [-V LOG_LEVEL]\n", argv[0]);
67 break;
68 }
69 }
70}
71
72/* Verify that leaf_pem chains to ca_pem. Returns 1 on success, 0 otherwise. */
73static int verify_chain(const N_STR* ca_pem, const N_STR* leaf_pem) {
74 BIO* bca = BIO_new_mem_buf(ca_pem->data, (int)ca_pem->written);
75 BIO* bleaf = BIO_new_mem_buf(leaf_pem->data, (int)leaf_pem->written);
76 X509* ca = bca ? PEM_read_bio_X509(bca, NULL, NULL, NULL) : NULL;
77 X509* leaf = bleaf ? PEM_read_bio_X509(bleaf, NULL, NULL, NULL) : NULL;
78 X509_STORE* store = X509_STORE_new();
79 X509_STORE_CTX* ctx = X509_STORE_CTX_new();
80 int ok = 0;
81 if (ca && leaf && store && ctx) {
82 X509_STORE_add_cert(store, ca);
83 if (X509_STORE_CTX_init(ctx, store, leaf, NULL) == 1)
84 ok = (X509_verify_cert(ctx) == 1);
85 }
86 if (ctx)
87 X509_STORE_CTX_free(ctx);
88 if (store)
89 X509_STORE_free(store);
90 if (leaf)
91 X509_free(leaf);
92 if (ca)
93 X509_free(ca);
94 if (bleaf)
95 BIO_free(bleaf);
96 if (bca)
97 BIO_free(bca);
98 return ok;
99}
100
101int main(int argc, char** argv) {
102 N_STR* ca_cert = NULL;
103 N_STR* ca_key = NULL;
104 N_STR* key = NULL;
105 const char* hosts[] = {"example.com", "127.0.0.1"};
106 int failures = 0;
107 size_t i;
108
110 process_args(argc, argv);
111
112 if (n_x509_generate_ca("Nilorea Test CA", 3650, &ca_cert, &ca_key) != 0 || !ca_cert || !ca_key) {
113 n_log(LOG_ERR, "CA generation failed");
114 failures++;
115 } else {
116 n_log(LOG_NOTICE, "generated CA: cert %zu bytes, key %zu bytes", (size_t)ca_cert->written, (size_t)ca_key->written);
117 for (i = 0; i < sizeof(hosts) / sizeof(hosts[0]); i++) {
118 N_STR* leaf_cert = NULL;
119 N_STR* leaf_key = NULL;
120 if (n_x509_mint_host_cert(hosts[i], ca_cert, ca_key, 825, &leaf_cert, &leaf_key) != 0 || !leaf_cert || !leaf_key) {
121 n_log(LOG_ERR, "minting leaf for %s failed", hosts[i]);
122 failures++;
123 } else if (!verify_chain(ca_cert, leaf_cert)) {
124 n_log(LOG_ERR, "leaf for %s does not verify against the CA", hosts[i]);
125 failures++;
126 } else {
127 n_log(LOG_NOTICE, "minted and verified leaf for %s (%zu bytes)", hosts[i], (size_t)leaf_cert->written);
128 }
129 free_nstr(&leaf_cert);
130 free_nstr(&leaf_key);
131 }
132 }
133
134 if (n_x509_keypair_pem(2048, &key) != 0 || !key) {
135 n_log(LOG_ERR, "standalone keypair generation failed");
136 failures++;
137 } else {
138 n_log(LOG_NOTICE, "generated standalone key: %zu bytes", (size_t)key->written);
139 }
140
141 free_nstr(&key);
142 free_nstr(&ca_cert);
143 free_nstr(&ca_key);
144
145 if (failures) {
146 n_log(LOG_ERR, "ex_x509: %d failure(s)", failures);
147 return 1;
148 }
149 n_log(LOG_NOTICE, "ex_x509: all checks passed");
150 return 0;
151}
static int failures
int main(void)
void process_args(int argc, char **argv)
Definition ex_common.c:48
char * key
static int verify_chain(const N_STR *ca_pem, const N_STR *leaf_pem)
Definition ex_x509.c:73
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
Definition n_log.h:89
#define LOG_DEBUG
debug-level messages
Definition n_log.h:84
#define LOG_ERR
error conditions
Definition n_log.h:76
void set_log_level(const int log_level)
Set the global log level value ( static int LOG_LEVEL )
Definition n_log.c:121
#define LOG_NOTICE
normal but significant condition
Definition n_log.h:80
#define LOG_NULL
no log output
Definition n_log.h:46
#define LOG_INFO
informational
Definition n_log.h:82
size_t written
number of meaningful bytes in data, excluding the null terminator; the size including the null termin...
Definition n_str.h:68
char * data
the string
Definition n_str.h:63
#define free_nstr(__ptr)
free a N_STR structure and set the pointer to NULL
Definition n_str.h:203
A box including a string and his lenght.
Definition n_str.h:61
int n_x509_generate_ca(const char *cn, int days, N_STR **ca_cert_pem, N_STR **ca_key_pem)
Generate a self-signed certificate authority (CA) keypair and cert.
Definition n_x509.c:171
int n_x509_keypair_pem(int bits, N_STR **key_pem)
Generate an RSA private key and return it as a PEM string.
Definition n_x509.c:155
int n_x509_mint_host_cert(const char *host, const N_STR *ca_cert_pem, const N_STR *ca_key_pem, int days, N_STR **leaf_cert_pem, N_STR **leaf_key_pem)
Mint a per-host leaf certificate signed by the given CA.
Definition n_x509.c:229
Generic log system.
N_STR and string function declaration.
X.509 helpers: self-signed CA generation and per-host leaf minting.