rots-utils: initial commit

master
S.J.R. van Schaik 8 years ago
commit 5494d66eeb
  1. 45
      Makefile
  2. 3
      include/file.h
  3. 29
      include/image.h
  4. 4
      include/macros.h
  5. 3
      include/pack.h
  6. 3
      include/sign.h
  7. 3
      include/unpack.h
  8. 3
      include/verify.h
  9. 9
      include/x509.h
  10. 21
      source/file.c
  11. 205
      source/image.c
  12. 39
      source/main.c
  13. 104
      source/pack.c
  14. 196
      source/sign.c
  15. 100
      source/unpack.c
  16. 237
      source/verify.c
  17. 44
      source/x509.c

@ -0,0 +1,45 @@
BUILD ?= build
all: $(BUILD)/rots-util
CFLAGS += -Iinclude
CFLAGS += -Wall -Wundef -Wextra -Wshadow -Wimplicit-function-declaration
CFLAGS += -Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes
CFLAGS += -D_GNU_SOURCE
LIBS = -lcrypto -lssl
CC = gcc
LD = gcc
obj-y += source/file.o
obj-y += source/image.o
obj-y += source/main.o
obj-y += source/pack.o
obj-y += source/sign.o
obj-y += source/unpack.o
obj-y += source/verify.o
obj-y += source/x509.o
obj = $(addprefix $(BUILD)/, $(obj-y))
# Include the dependencies.
-include $(obj:.o=.d)
# Set up the toolchain.
.SECONDARY:
clean:
@echo "CLEAN"
@rm -rf $(BUILD)
# Rule to compile C source code.
$(BUILD)/%.o: %.c
@echo "CC $<"
@mkdir -p $(dir $@)
@$(CC) -c $< -o $@ $(CFLAGS) -MT $@ -MMD -MP -MF $(@:.o=.d)
$(BUILD)/rots-util: $(obj) $(LDSCRIPT)
@echo "LD $@"
@mkdir -p $(dir $@)
@$(LD) -o $@ $(CFLAGS) $(LDFLAGS) $(obj) $(LIBS)
.PHONY: clean

@ -0,0 +1,3 @@
#pragma once
int get_file_size(size_t *size, const char *path);

@ -0,0 +1,29 @@
#pragma once
#include <stdint.h>
#include <stdio.h>
#define ROTS_MAGIC "ROTS-IMG"
struct rots_hdr {
uint64_t size;
};
struct rots_sig_hdr {
char *name;
char *digest;
uint32_t size;
};
size_t read_u8(FILE *fp, uint8_t *val);
size_t read_u32(FILE *fp, uint32_t *val);
size_t read_u64(FILE *fp, uint64_t *val);
size_t write_u8(FILE *fp, uint8_t val);
size_t write_u32(FILE *fp, uint32_t val);
size_t write_u64(FILE *fp, uint64_t val);
int rots_read_hdr(FILE *fp, struct rots_hdr *hdr);
int rots_write_hdr(FILE *fp, struct rots_hdr *hdr);
int rots_read_sig_hdr(FILE *fp, struct rots_sig_hdr *sig_hdr);
int rots_write_sig_hdr(FILE *fp, struct rots_sig_hdr *sig_hdr);
void rots_cleanup_sig_hdr(struct rots_sig_hdr *sig_hdr);

@ -0,0 +1,4 @@
#pragma once
#define min(x, y) (((x) < (y)) ? (x) : (y))
#define max(x, y) (((x) > (y)) ? (x) : (y))

@ -0,0 +1,3 @@
#pragma once
int do_pack(int argc, char *argv[]);

@ -0,0 +1,3 @@
#pragma once
int do_sign(int argc, char *argv[]);

@ -0,0 +1,3 @@
#pragma once
int do_unpack(int argc, char *argv[]);

@ -0,0 +1,3 @@
#pragma once
int do_verify(int argc, char *argv[]);

@ -0,0 +1,9 @@
#pragma once
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
X509 *X509_open_cert(const char *path);
char *X509_get_common_name(X509 *cert);

@ -0,0 +1,21 @@
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <file.h>
int get_file_size(size_t *size, const char *path)
{
struct stat st;
if (!size || !path)
return -1;
if (stat(path, &st) < 0)
return -1;
*size = st.st_size;
return 0;
}

@ -0,0 +1,205 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <image.h>
size_t read_u8(FILE *fp, uint8_t *val)
{
int byte;
size_t shift = 8, nbytes;
*val = 0;
for (nbytes = 0; nbytes < sizeof *val; ++nbytes) {
if ((byte = fgetc(fp)) == EOF)
return nbytes;
shift -= 8;
*val |= (byte & 0xff) << shift;
}
return nbytes;
}
size_t read_u32(FILE *fp, uint32_t *val)
{
int byte;
size_t shift = 32, nbytes;
*val = 0;
for (nbytes = 0; nbytes < sizeof *val; ++nbytes) {
if ((byte = fgetc(fp)) == EOF)
return nbytes;
shift -= 8;
*val |= (byte & 0xff) << shift;
}
return nbytes;
}
size_t read_u64(FILE *fp, uint64_t *val)
{
int byte;
size_t shift = 64, nbytes;
*val = 0;
for (nbytes = 0; nbytes < sizeof *val; ++nbytes) {
if ((byte = fgetc(fp)) == EOF)
return nbytes;
shift -= 8;
*val |= (byte & 0xff) << shift;
}
return nbytes;
}
size_t write_u8(FILE *fp, uint8_t val)
{
size_t shift = 8, nbytes;
for (nbytes = 0; nbytes < sizeof val; ++nbytes) {
shift -= 8;
if (fputc((val >> shift) & 0xff, fp) == EOF)
return nbytes;
}
return nbytes;
}
size_t write_u32(FILE *fp, uint32_t val)
{
size_t shift = 32, nbytes;
for (nbytes = 0; nbytes < sizeof val; ++nbytes) {
shift -= 8;
if (fputc((val >> shift) & 0xff, fp) == EOF)
return nbytes;
}
return nbytes;
}
size_t write_u64(FILE *fp, uint64_t val)
{
size_t shift = 64, nbytes;
for (nbytes = 0; nbytes < sizeof val; ++nbytes) {
shift -= 8;
if (fputc((val >> shift) & 0xff, fp) == EOF)
return nbytes;
}
return nbytes;
}
int rots_read_hdr(FILE *fp, struct rots_hdr *hdr)
{
char magic[8];
if (fread(magic, sizeof *magic, sizeof magic, fp) < sizeof magic)
return -1;
if (memcmp(magic, ROTS_MAGIC, 8) != 0)
return -1;
if (read_u64(fp, &hdr->size) < sizeof hdr->size)
return -1;
return 0;
}
int rots_write_hdr(FILE *fp, struct rots_hdr *hdr)
{
if (fwrite(ROTS_MAGIC, sizeof(char), 8, fp) < 8)
return -1;
if (write_u64(fp, hdr->size) < sizeof hdr->size)
return -1;
return 0;
}
int rots_read_sig_hdr(FILE *fp, struct rots_sig_hdr *sig_hdr)
{
uint8_t len;
if (read_u8(fp, &len) < 1)
return -1;
if (!(sig_hdr->name = calloc(len + 1, sizeof *sig_hdr->name)))
return -1;
if (fread(sig_hdr->name, sizeof *sig_hdr->name, len, fp) < len)
goto err_free_name;
if (read_u8(fp, &len) < 1)
goto err_free_name;
if (!(sig_hdr->digest = calloc(len + 1, sizeof *sig_hdr->digest)))
goto err_free_name;
if (fread(sig_hdr->digest, sizeof *sig_hdr->digest, len, fp) < len)
goto err_free_digest;
if (read_u32(fp, &sig_hdr->size) < sizeof sig_hdr->size)
goto err_free_digest;
return 0;
err_free_digest:
free(sig_hdr->digest);
err_free_name:
free(sig_hdr->name);
return -1;
}
int rots_write_sig_hdr(FILE *fp, struct rots_sig_hdr *sig_hdr)
{
size_t len;
len = strlen(sig_hdr->name);
if (write_u8(fp, len) < 1)
return -1;
if (fwrite(sig_hdr->name, sizeof *sig_hdr->name, len, fp) < len)
return -1;
len = strlen(sig_hdr->digest);
if (write_u8(fp, len) < 1)
return -1;
if (fwrite(sig_hdr->digest, sizeof *sig_hdr->digest, len, fp) < len)
return -1;
if (write_u32(fp, sig_hdr->size) < sizeof sig_hdr->size)
return -1;
return 0;
}
void rots_cleanup_sig_hdr(struct rots_sig_hdr *sig_hdr)
{
if (!sig_hdr)
return;
if (sig_hdr->name) {
free(sig_hdr->name);
sig_hdr->name = NULL;
}
if (sig_hdr->digest) {
free(sig_hdr->digest);
sig_hdr->digest = NULL;
}
}

@ -0,0 +1,39 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pack.h>
#include <sign.h>
#include <unpack.h>
#include <verify.h>
struct entry_point {
const char *cmd;
int (* main)(int argc, char *argv[]);
};
struct entry_point entries[] = {
{ "pack", do_pack },
{ "sign", do_sign },
{ "unpack", do_unpack },
{ "verify", do_verify },
{ NULL, NULL },
};
int main(int argc, char *argv[])
{
struct entry_point *entry;
if (argc < 2) {
fprintf(stderr, "usage: %s <command>\n", argv[0]);
return -1;
}
for (entry = entries; entry->cmd; ++entry) {
if (strcmp(entry->cmd, argv[1]) == 0)
return entry->main(argc, argv);
}
fprintf(stderr, "usage: %s <command>\n", argv[0]);
return -1;
}

@ -0,0 +1,104 @@
#include <stdio.h>
#include <getopt.h>
#include <file.h>
#include <image.h>
#include <pack.h>
enum {
OPTION_HELP = 'h',
OPTION_OUTPUT = 'o',
};
struct args {
const char *input, *output;
};
static int parse_args(struct args *args, int argc, char *argv[])
{
struct option options[] = {
{ "help", no_argument, NULL, OPTION_HELP },
{ "output", required_argument, 0, OPTION_OUTPUT },
{ NULL, 0, 0, 0 },
};
int ret;
while ((ret = getopt_long(argc, (char * const *)argv, "ho:", options,
NULL)) >= 0) {
switch (ret) {
case OPTION_HELP: return -1;
case OPTION_OUTPUT: args->output = optarg; break;
default: break;
}
}
if (optind >= argc)
return -1;
++optind;
if (optind >= argc)
return -1;
args->input = argv[optind];
return 0;
}
int do_pack(int argc, char *argv[])
{
char data[4096];
struct rots_hdr hdr;
struct args args;
FILE *input, *output;
size_t nbytes, size;
if (parse_args(&args, argc, argv) < 0) {
fprintf(stderr, "invalid\n");
return -1;
}
if (!(input = fopen(args.input, "rb"))) {
fprintf(stderr, "unable to open '%s' for reading.\n", args.input);
return -1;
}
if (!(output = fopen(args.output, "wb"))) {
fprintf(stderr, "unable to open '%s' for writing.\n", args.output);
goto err_close_input;
}
get_file_size(&size, args.input);
hdr.size = size;
if (rots_write_hdr(output, &hdr) < 0)
goto err_close_output;
while (size) {
nbytes = fread(data, sizeof *data, sizeof data, input);
if (nbytes == 0) {
fprintf(stderr, "unable to read the next chunk\n");
goto err_close_output;
}
if (fwrite(data, sizeof *data, nbytes, output) < nbytes) {
fprintf(stderr, "unable to write the current chunk\n");
goto err_close_output;
}
size -= nbytes;
}
fclose(output);
fclose(input);
return 0;
err_close_output:
fclose(output);
err_close_input:
fclose(input);
return -1;
}

@ -0,0 +1,196 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <image.h>
#include <macros.h>
#include <sign.h>
#include <x509.h>
enum {
OPTION_HELP = 'h',
OPTION_IMAGE = 'i',
OPTION_DIGEST = 'd',
OPTION_KEY = 'k',
OPTION_CERT = 'c',
};
struct args {
const char *image, *digest, *key, *cert;
};
static int parse_args(struct args *args, int argc, char *argv[])
{
struct option options[] = {
{ "help", no_argument, NULL, OPTION_HELP },
{ "image", required_argument, 0, OPTION_IMAGE },
{ "digest", required_argument, 0, OPTION_DIGEST },
{ "key", required_argument, 0, OPTION_KEY },
{ "cert", required_argument, 0, OPTION_CERT },
{ NULL, 0, 0, 0 },
};
int ret;
while ((ret = getopt_long(argc, (char * const *)argv, "hi:d:k:", options,
NULL)) >= 0) {
switch (ret) {
case OPTION_HELP: return -1;
case OPTION_IMAGE: args->image = optarg; break;
case OPTION_DIGEST: args->digest = optarg; break;
case OPTION_KEY: args->key = optarg; break;
case OPTION_CERT: args->cert = optarg; break;
default: break;
}
}
return 0;
}
static EVP_PKEY *open_priv_key(const char *path)
{
EVP_PKEY *key;
FILE *fp;
if (!(fp = fopen(path, "r")))
return NULL;
PEM_read_PrivateKey(fp, &key, NULL, NULL);
fclose(fp);
return key;
}
static int sign(const char *image, const char *name, const char *digest_name,
EVP_PKEY *key)
{
char data[512];
struct rots_hdr hdr;
struct rots_sig_hdr sig_hdr;
const EVP_MD *digest;
FILE *fp;
unsigned char *sig;
EVP_MD_CTX *ctx = NULL;
size_t nbytes, size, sig_len = 0;
if (!image || !digest_name || !key)
return -1;
if (!(fp = fopen(image, "r+b")))
return -1;
if (rots_read_hdr(fp, &hdr) < 0)
goto err_close_image;
size = hdr.size;
if (!(ctx = EVP_MD_CTX_create()))
goto err_close_image;
if (!(digest = EVP_get_digestbyname(digest_name)))
goto err_destroy_ctx;
if (!(EVP_DigestSignInit(ctx, NULL, digest, NULL, key)))
goto err_destroy_ctx;
while (size) {
nbytes = fread(data, sizeof *data, min(size, sizeof data), fp);
if (nbytes == 0)
return -1;
if (!(EVP_DigestSignUpdate(ctx, data, nbytes)))
goto err_destroy_ctx;
size -= nbytes;
}
if (!(EVP_DigestSignFinal(ctx, NULL, &sig_len)))
goto err_destroy_ctx;
if (!(sig = malloc(sizeof(char) * sig_len)))
goto err_destroy_ctx;
if (!(EVP_DigestSignFinal(ctx, sig, &sig_len)))
goto err_free_sig;
if (fseek(fp, 0, SEEK_END) < 0)
goto err_free_sig;
sig_hdr.name = name;
sig_hdr.digest = digest_name;
sig_hdr.size = sig_len;
if (rots_write_sig_hdr(fp, &sig_hdr) < 0)
goto err_free_sig;
if (fwrite(sig, sizeof *sig, sig_len, fp) < sig_len)
goto err_free_sig;
free(sig);
EVP_MD_CTX_destroy(ctx);
fclose(fp);
return 0;
err_free_sig:
free(sig);
err_destroy_ctx:
EVP_MD_CTX_destroy(ctx);
err_close_image:
fclose(fp);
return -1;
}
int do_sign(int argc, char *argv[])
{
struct args args;
EVP_PKEY *key;
X509 *cert;
char *cn;
if (parse_args(&args, argc, argv) < 0) {
fprintf(stderr, "invalid\n");
return -1;
}
OpenSSL_add_all_algorithms();
if (!(key = open_priv_key(args.key))) {
fprintf(stderr, "error: unable to read the private key.\n");
return -1;
}
if (!(cert = X509_open_cert(args.cert))) {
fprintf(stderr, "error: unable to read the X509 certificate.\n");
OPENSSL_free(key);
return -1;
}
if (!(cn = X509_get_common_name(cert))) {
fprintf(stderr, "error: unable to get the common name.\n");
OPENSSL_free(cert);
OPENSSL_free(key);
return -1;
}
if (sign(args.image, cn, args.digest, key) < 0) {
fprintf(stderr, "error: unable to sign the payload.\n");
OPENSSL_free(cn);
OPENSSL_free(cert);
OPENSSL_free(key);
return -1;
}
OPENSSL_free(cn);
OPENSSL_free(cert);
OPENSSL_free(key);
return 0;
}

@ -0,0 +1,100 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <image.h>
#include <macros.h>
#include <unpack.h>
enum {
OPTION_HELP = 'h',
OPTION_IMAGE = 'i',
OPTION_OUTPUT = 'o',
};
struct args {
const char *image, *output;
};
static int parse_args(struct args *args, int argc, char *argv[])
{
struct option options[] = {
{ "help", no_argument, NULL, OPTION_HELP },
{ "image", required_argument, NULL, OPTION_IMAGE },
{ "output", required_argument, NULL, OPTION_OUTPUT },
{ NULL, 0, 0, 0 },
};
int ret;
while ((ret = getopt_long(argc, (char * const *)argv, "hi:o:", options,
NULL)) >= 0) {
switch (ret) {
case OPTION_HELP: return -1;
case OPTION_IMAGE: args->image = optarg; break;
case OPTION_OUTPUT: args->output = optarg; break;
default: break;
}
}
return 0;
}
int do_unpack(int argc, char *argv[])
{
char data[512];
struct rots_hdr hdr;
FILE *in, *out;
struct args args;
size_t nbytes, size;
if (parse_args(&args, argc, argv) < 0) {
fprintf(stderr, "invalid\n");
return -1;
}
if (!(in = fopen(args.image, "rb"))) {
fprintf(stderr, "error: file '%s' not found.\n", args.image);
return -1;
}
if (!(out = fopen(args.output, "wb"))) {
fprintf(stderr, "error: cannot open '%s' for writing.\n", args.output);
goto err_close_in;
}
if (rots_read_hdr(in, &hdr) < 0) {
fprintf(stderr, "error: file '%s' is not a ROTS-image.\n", args.image);
goto err_close_out;
}
size = hdr.size;
while (size) {
nbytes = fread(data, sizeof *data, min(size, sizeof data), in);
if (nbytes == 0) {
fprintf(stderr, "error: cannot read the next chunk.\n");
goto err_close_out;
}
if (fwrite(data, sizeof *data, nbytes, out) < nbytes) {
fprintf(stderr, "error: cannot write the current chunk.\n");
goto err_close_out;
}
size -= nbytes;
}
fclose(out);
fclose(in);
return 0;
err_close_out:
fclose(out);
err_close_in:
fclose(in);
return -1;
}

@ -0,0 +1,237 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <getopt.h>
#include <sys/types.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <image.h>
#include <macros.h>
#include <verify.h>
#include <x509.h>
enum {
OPTION_HELP = 'h',
OPTION_IMAGE = 'i',
OPTION_CERTS = 'c',
};
struct args {
const char *image, *digest, *certs;
};
static int parse_args(struct args *args, int argc, char *argv[])
{
struct option options[] = {
{ "help", no_argument, NULL, OPTION_HELP },
{ "image", required_argument, 0, OPTION_IMAGE },
{ "certs", required_argument, 0, OPTION_CERTS },
{ NULL, 0, 0, 0 },
};
int ret;
while ((ret = getopt_long(argc, (char * const *)argv, "hi:d:c:", options,
NULL)) >= 0) {
switch (ret) {
case OPTION_HELP: return -1;
case OPTION_IMAGE: args->image = optarg; break;
case OPTION_CERTS: args->certs = optarg; break;
default: break;
}
}
return 0;
}
static X509 *X509_find_cert_by_common_name(const char *path, const char *name)
{
DIR *dir;
struct dirent *dirent;
X509 *cert = NULL;
char *fpath, *cn;
if (!(dir = opendir(path)))
return NULL;
while ((dirent = readdir(dir))) {
if (asprintf(&fpath, "%s/%s", path, dirent->d_name) < 0)
continue;
if (!(cert = X509_open_cert(fpath)))
continue;
if (!(cn = X509_get_common_name(cert))) {
free(cert); cert = NULL;
continue;
}
if (strcmp(cn, name) == 0)
break;
}
closedir(dir);
return cert;
}
static int verify(const char *image, const char *digest_name, EVP_PKEY *key,
unsigned char *sig, size_t sig_len)
{
char data[512];
struct rots_hdr hdr;
const EVP_MD *digest;
FILE *fp;
EVP_MD_CTX *ctx = NULL;
size_t nbytes, size;
int ret;
if (!image || !digest_name || !key || !sig || !sig_len)
return -1;
if (!(fp = fopen(image, "rb")))
return -1;
if (rots_read_hdr(fp, &hdr) < 0)
goto err_close_image;
size = hdr.size;
if (!(ctx = EVP_MD_CTX_create()))
goto err_close_image;
if (!(digest = EVP_get_digestbyname(digest_name)))
goto err_destroy_ctx;
if (!(EVP_DigestVerifyInit(ctx, NULL, digest, NULL, key)))
goto err_destroy_ctx;
while (size) {
nbytes = fread(data, sizeof *data, min(size, sizeof data), fp);
if (nbytes == 0)
goto err_destroy_ctx;
if (!(EVP_DigestVerifyUpdate(ctx, data, nbytes)))
goto err_destroy_ctx;
size -= nbytes;
}
if (EVP_DigestVerifyFinal(ctx, sig, sig_len) == 1) {
ret = 0;
} else {
ret = -1;
}
EVP_MD_CTX_destroy(ctx);
fclose(fp);
return ret;
err_destroy_ctx:
EVP_MD_CTX_destroy(ctx);
err_close_image:
fclose(fp);
return -1;
}
static int verify_all(size_t *count, size_t *total, const char *ca_path, const char *image)
{
struct rots_hdr hdr;
struct rots_sig_hdr sig_hdr;
unsigned char *sig;
FILE *fp;
EVP_PKEY *key;
X509 *cert;
int ret;
*count = *total = 0;
if (!(fp = fopen(image, "rb")))
return -1;
if (rots_read_hdr(fp, &hdr) < 0)
goto err_close_image;
if (fseek(fp, hdr.size, SEEK_CUR) < 0)
goto err_close_image;
while (rots_read_sig_hdr(fp, &sig_hdr) == 0) {
if (!(cert = X509_find_cert_by_common_name(ca_path, sig_hdr.name))) {
rots_cleanup_sig_hdr(&sig_hdr);
fseek(fp, sig_hdr.size, SEEK_CUR);
++*total;
continue;
}
if (X509_check_issued(cert, cert) == X509_V_OK) {
printf("self-signed certificate\n");
} else {
printf("root-signed certificate\n");
}
if (!(key = X509_get_pubkey(cert))) {
free(cert);
rots_cleanup_sig_hdr(&sig_hdr);
fseek(fp, sig_hdr.size, SEEK_CUR);
++*total;
continue;
}
if (!(sig = malloc(sig_hdr.size * sizeof *sig))) {
free(cert);
rots_cleanup_sig_hdr(&sig_hdr);
goto err_close_image;
}
if (fread(sig, sizeof *sig, sig_hdr.size, fp) < sig_hdr.size) {
free(sig);
goto err_close_image;
}
ret = verify(image, sig_hdr.digest, key, sig, sig_hdr.size);
free(sig);
if (ret == 0)
++*count;
++*total;
rots_cleanup_sig_hdr(&sig_hdr);
}
fclose(fp);
return 0;
err_close_image:
fclose(fp);
return -1;
}
int do_verify(int argc, char *argv[])
{
struct args args;
size_t count, total;
if (parse_args(&args, argc, argv) < 0) {
fprintf(stderr, "invalid\n");
return -1;
}
OpenSSL_add_all_algorithms();
if (verify_all(&count, &total, args.certs, args.image) < 0) {
fprintf(stderr, "error: unable to verify the signature(s).\n");
return -1;
}
printf("%zu/%zu signatures are correct.\n", count, total);
return 0;
}

@ -0,0 +1,44 @@
#include <stdlib.h>
#include <string.h>
#include <x509.h>
X509 *X509_open_cert(const char *path)
{
X509 *cert;
FILE *fp;
if (!(fp = fopen(path, "r")))
return NULL;
cert = PEM_read_X509(fp, NULL, NULL, NULL);
fclose(fp);
return cert;
}
char *X509_get_common_name(X509 *cert)
{
X509_NAME *subj;
X509_NAME_ENTRY *entry;
ASN1_STRING *data;
unsigned char *cn;
int idx;
if (!(subj = X509_get_subject_name(cert)))
return NULL;
if ((idx = X509_NAME_get_index_by_NID(subj, NID_commonName, -1)) < 0)
return NULL;
if (!(entry = X509_NAME_get_entry(subj, idx)))
return NULL;
if (!(data = X509_NAME_ENTRY_get_data(entry)))
return NULL;
if (ASN1_STRING_to_UTF8(&cn, data) == 0)
return NULL;
return (char *)cn;
}
Loading…
Cancel
Save