Skip to content

Commit

Permalink
Add TLS support w/ OpenSSL
Browse files Browse the repository at this point in the history
  • Loading branch information
mdavidsaver committed Apr 22, 2024
1 parent 30307ea commit e149caa
Show file tree
Hide file tree
Showing 32 changed files with 2,455 additions and 173 deletions.
102 changes: 102 additions & 0 deletions documentation/pkcs12.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# PKCS#12 files in brief

The following is based on a reading of [RFC7292](https://datatracker.ietf.org/doc/html/rfc7292) as of July 2014.
Also on observation of OpenSSL circa 3.1 and keytool circa Java 17.

End users do not need to know this.

## File Structure

Each `PKCS#12` file contains a list of `AuthenticatedSafe` entries (aka. "Safes").

```
PKCS#12 file
AuthenticatedSafe (unencrypted)
...
AuthenticatedSafe (password encrypted)
...
AuthenticatedSafe (public key encrypted)
```

Each Safe may be: unencrypted, encrypted with a password, or encrypted with a public key.

Each Safe contains a list of `SafeBag` entries (aka. "Bags").

```
PKCS#12 file
AuthenticatedSafe
*Bag
attributes...
value
```

Each Bag has an a list of "Attributes" and a "value".

RFC7292 defines two attributes `friendlyName` and `localKeyId`.
Additionally, Java defines another `oracle-jdk-trustedkeyusage` or `ORACLE_TrustedKeyUsage`.

```
PKCS#12 file
AuthenticatedSafe
keyBag (unencrypted private key)
pkcs8ShroudedKeyBag (encrypted private key)
certBag (certificate, usually X509)
crlBag (certificate revocation list, usually X509CRL)
secretBag (arbitrary encrypted bytes)
safeContentsBag
... recursive list of Bags
```

RFC7292 defines 6 types of Bag, and leaves open the possibility of more.


## Bag Attributes

`friendlyName` is a string labeling a Bag.
Java keytool uses these (via. `-alias`) to distinguish multiple private keys within one file.
OpenSSL ignores them, and gets confused if multiple private keys are present.

`localKeyId` is meant to identifies pairs of private key and certificate.

`oracle-jdk-trustedkeyusage` has the same value as the X509 `extendedKeyUsage` extension.

Released version of OpenSSL as of 3.1 circa Aug. 2023 [do not understand](https://github.com/openssl/openssl/issues/6684) `oracle-jdk-trustedkeyusage`.
This is feature [planned for 3.2](https://github.com/openssl/openssl/pull/19025).

TODO: keytool has been observed setting this to "6". OpenSSL 3.2 set `anyExtendedKeyUsage`, aka. 1.

## File Structure as Observed

The structures of files created by `openssl pkcs12` and `keytool` are almost identical.

For example, a file with a certificate/key pair, and an associated CA certificate is structured like:

```
PKCS#12
AuthenticatedSafe (unencrypted)
pkcs8ShroudedKeyBag
attributes
friendlyName = "my:cert:name" (Java only)
localKeyId = ... (value will match the associated keyBag or pkcs8ShroudedKeyBag
value = private key...
AuthenticatedSafe (encrypted)
certBag
attributes
friendlyName = "my:cert:name" (Java only)
localKeyId = ... (value will match the associated certBag
value = X509 certificate
certBag
attributes
friendlyName = "my:ca" (Java only)
oracle-jdk-trustedkeyusage = ... (Java only)
value = X509 certificate
```

Notes...

This structure leaves the friendlyName (aka `-alias`) and localKeyId associated with a private key unencrypted in all cases.

Java keytool has been observed (after an `-importcert`) to put almost two certBag entries with the same certificate.
One with the friendlyName from `-alias` and `oracle-jdk-trustedkeyusage` set,
and a second with friendlyName set to the distinguishing name (eg. `CN=foo,O=bar`) and no `oracle-jdk-trustedkeyusage`.
keytool seems to ignore any entries without `oracle-jdk-trustedkeyusage`, but OpenSSL reads them.
17 changes: 17 additions & 0 deletions ioc/iochooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,20 @@ void pvxrefdiff() {
}
}

void pvxreconfigure()
{
Guard (pvxServer->lock);
auto& srv = pvxServer->srv;

if (srv) {
printf("Reconfiguring QSRV\n");
srv.reconfigure(server::Config::from_env());
pvxsr(0); // print new configuration
} else {
fprintf(stderr, "Warning: QSRV not running\n");
}
}

} // namespace

static
Expand Down Expand Up @@ -468,6 +482,9 @@ void pvxsBaseRegistrar() noexcept {
"Save the current set of instance counters for reference by later pvxrefdiff.\n").implementation<&pvxrefsave>();
IOCShCommand<>("pvxrefdiff",
"Show different of current instance counts with those when pvxrefsave was called.\n").implementation<&pvxrefdiff>();
IOCShCommand<>("pvxreconfigure",
"Reconfigure QSRV using current values of EPICS_PVA*. Only disconnects TLS clients\n")
.implementation<&pvxreconfigure>();

// Initialise the PVXS Server
initialisePvxsServer();
Expand Down
14 changes: 10 additions & 4 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ ifeq (YES,$(EVENT2_HAS_OPENSSL))
USR_CPPFLAGS += -DPVXS_ENABLE_OPENSSL
endif

# set to NO to disable handling of $SSLKEYLOGFILE
PVXS_ENABLE_SSLKEYLOGFILE ?= YES

PVXS_ENABLE_SSLKEYLOGFILE_YES = -DPVXS_ENABLE_SSLKEYLOGFILE
USR_CPPFLAGS += $(PVXS_ENABLE_SSLKEYLOGFILE_$(PVXS_ENABLE_SSLKEYLOGFILE))

ifdef T_A
ifneq ($(CONFIG_LOADED),YES)
$(warning Toolchain inspection failed $(MAKEFILE_LIST))
Expand All @@ -34,10 +40,6 @@ endif
# breaks on older ncurses (circa RHEL6) not using the INPUT() trick to pull in libtinfo.so
#USR_LDFLAGS_Linux += -Wl,--no-undefined -Wl,--no-allow-shlib-undefined

ifeq (,$(PVXS_MAJOR_VERSION))
$(error PVXS_MAJOR_VERSION undefined, problem reading cfg/CONFIG_PVXS_VERSION)
endif

# see below for special case versionNum.h
EXPAND += describe.h

Expand Down Expand Up @@ -111,6 +113,10 @@ LIB_SRCS += clientget.cpp
LIB_SRCS += clientmon.cpp
LIB_SRCS += clientdiscover.cpp

ifeq (YES,$(EVENT2_HAS_OPENSSL))
LIB_SRCS += ossl.cpp
endif

LIB_LIBS += Com

# special case matching configure/RULES_PVXS_MODULE
Expand Down
Loading

0 comments on commit e149caa

Please sign in to comment.