libekmfweb: Add EKMFWeb client library

The EKMFWeb client library provides functions to communicate
with an EKMF Web server via REST calls over HTTPS. EKMF Web stands
for IBM Enterprise Key Management Foundation - Web Edition and is
used to manage keys in an enterprise.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
Ingo Franzki
2020-04-03 11:11:29 +02:00
committed by Jan Höppner
parent 91b1692b16
commit cbf7f02d69
9 changed files with 1282 additions and 5 deletions

View File

@@ -3,7 +3,7 @@ ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/ar
# Include common definitions
include common.mak
LIB_DIRS = libvtoc libutil libzds libdasd libvmdump libccw libvmcp
LIB_DIRS = libvtoc libutil libzds libdasd libvmdump libccw libvmcp libekmfweb
TOOL_DIRS = zipl zdump fdasd dasdfmt dasdview tunedasd \
tape390 osasnmpd qetharp ip_watcher qethconf scripts zconf \
vmconvert vmcp man mon_tools dasdinfo vmur cpuplugd ipl_tools \

View File

@@ -243,6 +243,12 @@ Package contents
Provides simple tools to create a binary that can be used to implement
simple network boot setups following the PXELINUX conventions.
* libekmfweb:
A shared library that provides functions to communicate with an EKMF Web
server via REST calls over HTTPS. EKMF Web stands for IBM Enterprise Key
Management Foundation - Web Edition, and is used to manage keys in an
enterprise.
For more information refer to the following publications:
* "Device Drivers, Features, and Commands" chapter "Useful Linux commands"
@@ -267,10 +273,11 @@ build options:
| pfm | `HAVE_PFM` | cpacfstats |
| net-snmp | `HAVE_SNMP` | osasnmpd |
| glibc-static | `HAVE_LIBC_STATIC` | zfcpdump |
| openssl | `HAVE_OPENSSL` | genprotimg,zkey |
| openssl | `HAVE_OPENSSL` | genprotimg, zkey, libekmfweb |
| cryptsetup | `HAVE_CRYPTSETUP2` | zkey-cryptsetup |
| json-c | `HAVE_JSONC` | zkey-cryptsetup |
| json-c | `HAVE_JSONC` | zkey-cryptsetup, libekmfweb |
| glib2 | `HAVE_GLIB2` | genprotimg |
| libcurl | `HAVE_LIBCURL` | libekmfweb |
This table lists additional build or install options:
@@ -397,3 +404,11 @@ the different tools are provided:
tool must be added to this group. The owner of the default key repository
'/etc/zkey/repository' must be set to group 'zkeyadm' with write permission
for this group.
* libekmfweb:
For building the libekmfweb shared library you need openssl version 1.1.1 or
newer installed (openssl-devel.rpm). Also required are json-c version 0.13 or
newer (json-c-devel.rpm), and libcurl version 7.59 or newer
(libcurl-devel.rpm).
Tip: you may skip the libekmfweb build by adding `HAVE_OPENSSL=0`,
`HAVE_JSONC=0`, or `HAVE_LIBCURL=0` to the make invocation.

View File

@@ -163,6 +163,7 @@ USRSBINDIR = $(INSTALLDIR)/usr/sbin
USRBINDIR = $(INSTALLDIR)/usr/bin
BINDIR = $(INSTALLDIR)/sbin
LIBDIR = $(INSTALLDIR)/lib
LIB64DIR = $(INSTALLDIR)/lib64
SYSCONFDIR = $(INSTALLDIR)/etc
MANDIR = $(INSTALLDIR)/usr/share/man
VARDIR = $(INSTALLDIR)/var
@@ -172,14 +173,16 @@ ZFCPDUMP_DIR = $(TOOLS_LIBDIR)/zfcpdump
# Systemd support files are installed only if a directory is specified
# for SYSTEMDSYSTEMUNITDIR (e.g. /lib/systemd/system)
SYSTEMDSYSTEMUNITDIR =
USRINCLUDEDIR = $(INSTALLDIR)/usr/include
INSTDIRS = $(USRSBINDIR) $(USRBINDIR) $(BINDIR) $(LIBDIR) $(MANDIR) \
$(SYSCONFDIR) $(SYSCONFDIR)/sysconfig \
$(TOOLS_LIBDIR) $(TOOLS_DATADIR) \
$(ZFCPDUMP_DIR) $(SYSTEMDSYSTEMUNITDIR)
$(ZFCPDUMP_DIR) $(SYSTEMDSYSTEMUNITDIR) \
$(LIB64DIR) $(USRINCLUDEDIR)
OWNER = $(shell id -un)
GROUP = $(shell id -gn)
export INSTALLDIR BINDIR LIBDIR MANDIR OWNER GROUP
export INSTALLDIR BINDIR LIBDIR LIB64DIR MANDIR OWNER GROUP
# Special defines for zfcpdump
ZFCPDUMP_IMAGE = zfcpdump-image
@@ -339,6 +342,10 @@ $(rootdir)/libvmcp/libvmcp.a: $(rootdir)/libvmcp
$(MAKE) -C $(rootdir)/libvmcp/ libvmcp.a
.PHONY: $(rootdir)/libvmcp
$(rootdir)/libekmfweb/libekmfweb.so: $(rootdir)/libekmfweb
$(MAKE) -C $(rootdir)/libekmfweb/ libekmfweb.so
.PHONY: $(rootdir)/libekmfweb
$(rootdir)/zipl/boot/data.o:
$(MAKE) -C $(rootdir)/zipl/boot/ data.o

91
include/ekmfweb/ekmfweb.h Normal file
View File

@@ -0,0 +1,91 @@
/*
* libekmfweb - EKMFWeb client library
*
* Copyright IBM Corp. 2020
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#ifndef LIB_EKMFWEB_H
#define LIB_EKMFWEB_H
#include <stddef.h>
#include <stdbool.h>
struct ekmf_config {
/** The base URL of the server. Should use https:// ! */
const char *base_url;
/** Optional: File name of the CA bundle PEM file, or a name of a
* directory the multiple CA certificates. If this is NULL, then the
* default system path for CA certificates is used */
const char *tls_ca;
/** Optional: File name of the client certificate PEM file */
const char *tls_client_cert;
/** Optional: File name of the clients key PEM file */
const char *tls_client_key;
/** Optional: Passphrase to read the clients key PEM file */
const char *tls_client_key_passphrase;
/** Optional: File name of a PEM file holding a CA certificate of the
* issuer */
const char *tls_issuer_cert;
/** Optional: File name of a PEM file containing the servers pinned
* public key. Public key pinning requires that verify_peer or
* verify_host (or both) is true. */
const char *tls_pinned_pubkey;
/** Optional: File name of a PEM file containing the server's
* certificate. This can be used to allow peer verification with
* self-signed server certificates */
const char *tls_server_cert;
/** If true, the peer certificate is verified */
bool tls_verify_peer;
/** If true, that the server certificate is for the server it is known
* as (i.e. the hostname in the url) */
bool tls_verify_host;
/** Maximum number of redirects to follow. Zero means that redirects are
* not followed. -1 means to infinitely follow redirects. */
long max_redirs;
};
/**
* Connects to the specified server url and obtains the servers certificate
* and its chain of signing certificates and stores them in the specified
* PEM files.
*
* @param config the configuration structure. Only the base_url must
* be specified, all others are optional.
* @param server_cert_pem Optional: name of a PEM file to store the servers
* certificate
* @param server_pubkey_pem Optional: name of a PEM file to store the servers
* public key (can be used for public key pinning)
* @param ca_bundle_pem Optional: name of a PEM file to store the CA
* certificate chain as a bundle
* @param verified On return: If the server 's certificate has been
* verified using the CA specification from the config
* (if ca = NULL: default system CAs, otherwise path
* or file to CAs).
* @param error_msg on return: If not NULL, then a textual error message
* is returned in case of a failing request. The caller
* must free the error string when it is not NULL.
* @param verbose if true, verbose messages are printed
*
* @returns zero for success, a negative errno in case of an error.
*/
int ekmf_get_server_cert_chain(const struct ekmf_config *config,
const char *server_cert_pem,
const char *server_pubkey_pem,
const char *ca_bundle_pem,
bool *verified, char **error_msg, bool verbose);
/**
* Print the certificate(s) contained in the specified PEM file.
*
* @param cert_pem the file name of the PEM file to print
* @param verbose if true, verbose messages are printed
*
* @returns -EIO if the file could not be opened. -ENOENT if the PEM file
* does not contain any certificates. 0 if success.
*/
int ekmf_print_certificates(const char *cert_pem, bool verbose);
#endif

84
libekmfweb/Makefile Normal file
View File

@@ -0,0 +1,84 @@
include ../common.mak
ifneq (${HAVE_OPENSSL},0)
ifneq (${HAVE_JSONC},0)
ifneq (${HAVE_LIBCURL},0)
BUILD_TARGETS += libekmfweb.so
INSTALL_TARGETS += install-libekmfweb.so
else
BUILD_TARGETS += skip-libekmfweb-curl
INSTALL_TARGETS += skip-libekmfweb-curl
endif
else
BUILD_TARGETS += skip-libekmfweb-jsonc
INSTALL_TARGETS += skip-libekmfweb-jsonc
endif
else
BUILD_TARGETS += skip-libekmfweb-openssl
INSTALL_TARGETS += skip-libekmfweb-openssl
endif
libs = $(rootdir)/libutil/libutil.a
detect-openssl-version.dep:
echo "#include <openssl/opensslv.h>" > detect-openssl-version.dep
echo "#include <openssl/evp.h>" >> detect-openssl-version.dep
echo "#if OPENSSL_VERSION_NUMBER < 0x10101000L" >> detect-openssl-version.dep
echo " #error openssl version 1.1.1 is required" >> detect-openssl-version.dep
echo "#endif" >> detect-openssl-version.dep
echo "static void __attribute__((unused)) test(void) {" >> detect-openssl-version.dep
echo " EVP_PKEY_meth_remove(NULL);" >> detect-openssl-version.dep
echo "}" >> detect-openssl-version.dep
check-dep-libekmfweb: detect-openssl-version.dep
$(call check_dep, \
"libekmfweb", \
"detect-openssl-version.dep", \
"openssl-devel version >= 1.1.1", \
"HAVE_OPENSSL=0", \
-I. -lcrypto)
$(call check_dep, \
"libekmfweb", \
"json-c/json.h", \
"json-c-devel", \
"HAVE_JSONC=0")
$(call check_dep, \
"libekmfweb", \
"curl/curl.h", \
"libcurl-devel", \
"HAVE_LIBCURL=0")
touch check-dep-libekmfweb
skip-libekmfweb-openssl:
echo " SKIP libekmfweb due to HAVE_OPENSSL=0"
skip-libekmfweb-jsonc:
echo " SKIP libekmfweb due to HAVE_JSONC=0"
skip-libekmfweb-curl:
echo " SKIP libekmfweb due to HAVE_LIBCURL=0"
all: $(BUILD_TARGETS)
ekmfweb.o: check-dep-libekmfweb ekmfweb.c utilities.h $(rootdir)include/ekmfweb/ekmfweb.h
utilities.o: check-dep-libekmfweb utilities.c utilities.h
libekmfweb.so: ALL_CFLAGS += -fPIC
libekmfweb.so: LDLIBS = -ljson-c -lcrypto -lssl -lcurl -shared
libekmfweb.so: LDFLAGS = -shared -Wl,--version-script=libekmfweb.map \
-Wl,-z,defs,-Bsymbolic
libekmfweb.so: ekmfweb.o utilities.o
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@
install-libekmfweb.so: libekmfweb.so
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 -T libekmfweb.so $(DESTDIR)$(LIB64DIR)/libekmfweb.so
$(INSTALL) -d -m 770 $(DESTDIR)$(USRINCLUDEDIR)/ekmfweb
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 $(rootdir)include/ekmfweb/ekmfweb.h $(DESTDIR)$(USRINCLUDEDIR)/ekmfweb
install: all $(INSTALL_TARGETS)
clean:
rm -f *.o libekmfweb.so check-dep-libekmfweb detect-openssl-version.dep
.PHONY: all install clean skip-libekmfweb-openssl skip-libekmfweb-jsonc \
skip-libekmfweb-curl install-libekmfweb.so

1006
libekmfweb/ekmfweb.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,6 @@
LIBEKMFWEB_1.0 {
global:
ekmf_get_server_cert_chain;
ekmf_print_certificates;
local: *;
};

48
libekmfweb/utilities.c Normal file
View File

@@ -0,0 +1,48 @@
/*
* libekmfweb - EKMFWeb client library
*
* Copyright IBM Corp. 2020
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include "utilities.h"
/**
* Reads a X.509 certificate from the specified PEM file.
*
* @param pem_filename the name of the PEM file to read
* @param cert on Return: the X.509 certificate object
*
* @returns zero for success, a negative errno in case of an error:
* -EINVAL: invalid parameter
* -EIO: error during reading in the certificate
* any other errno as returned by fopen
*/
int read_x509_certificate(const char *pem_filename, X509 **cert)
{
FILE *fp;
if (pem_filename == NULL || cert == NULL)
return -EINVAL;
fp = fopen(pem_filename, "r");
if (fp == NULL)
return -errno;
*cert = PEM_read_X509(fp, NULL, NULL, NULL);
fclose(fp);
if (*cert == NULL)
return -EIO;
return 0;
}

20
libekmfweb/utilities.h Normal file
View File

@@ -0,0 +1,20 @@
/*
* libekmfweb - EKMFWeb client library
*
* Copyright IBM Corp. 2020
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#ifndef UTILITIES_H
#define UTILITIES_H
#include <stddef.h>
#include <stdbool.h>
#include <openssl/x509.h>
int read_x509_certificate(const char *pem_filename, X509 **cert);
#endif