Compare commits

...

104 Commits

Author SHA1 Message Date
Steffen Eiden
9eea78b3ad New release s390-tools-2.32.0
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2024-04-03 16:18:09 +02:00
Steffen Eiden
0a3a556879 rust/Cargo.lock: Update curl-sys crate
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2024-04-03 16:18:09 +02:00
Steffen Eiden
aba8900074 rust/pv_core: Remove mockito dependency
With f6c6f0cc71 ("rust/pv/test: Code + Certificate refactoring")
no code uses mockito anymore, but it's dependency was not removed.

Remove the mockito dependency from the rust workspace.

Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2024-04-03 16:18:09 +02:00
Dan Horák
f5744b95db genprotimg: Fix build with OpenSSL 1.1
OpenSSL 1.1 seems to use a non-const parameter to X509_name_dup(), but
x509_armonk_locality_fixup() is passing a const there. The compile then
fails on "discards 'const' qualifier", when -Werror is used. Thus
resolve with a type-cast like in c2b_name().

Fixes: https://github.com/ibm-s390-linux/s390-tools/pull/167
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Dan Horák <dan@danny.cz>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2024-04-02 17:37:53 +02:00
Dan Horák
13d721afd3 libpv: Fix build with OpenSSL 1.1
OpenSSL 1.1 seems to use a non-const parameter to X509_name_dup(), but
x509_armonk_locality_fixup() is passing a const there. The compile then
fails on "discards 'const' qualifier", when -Werror is used. Thus
resolve with a type-cast like in pv_c2b_name().

GitHub-ID: https://github.com/ibm-s390-linux/s390-tools/pull/167
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Dan Horák <dan@danny.cz>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2024-04-02 17:37:53 +02:00
Eduard Shishkin
90a2e6d70e zipl/src: Fix leak of files
Fix leak of temporary files: if prepare_build_program_table_file()
is called in no dry-run mode and there was an error then the file
@filename will not be deleted in free_bootloader()).

Fix leak of renamed files as well as corruption of previously
created bootmap files with the same name in case of unsuccessful
IPL installation.

Add a special flag to keep a track of file's "temporary" state;
Base the cleanup decision on this flag instead of checking dry-run;
Release resources captured by prepare_bootloader() in the error path;
Move the final rename to be called only after successful installation.

                    Original logic:

prepare_bootloader_ipl():
prepare_bootloader_ngdump():

  always create temporary @filename
  if (!dry-run) rename @filename;
  install;
  cleanup: if (dry_run) drop @filename (*** LEAK ***)

prepare_bootloader_device():

  if (dry_run) create temporary @filename
  install, don't rename;
  cleanup: if (dry_run) drop @filename

                    New logic:

prepare_bootloader_ipl():
prepare_bootloader_ngdump():

  always create temporary @filename and set @tmp_filename_created;
  install;
  if (!dry_run) rename @filename and clear @tmp_filename_created;
  cleanup: if (@tmp_filename_created is set), drop @filename

prepare_bootloader_device():

  if (dry_run) create @filename and set @tmp_filename_created;
  install, don't rename;
  cleanup: if (@tmp_filename_created is set) drop @filename.

Fixes: https://github.com/ibm-s390-tools/s390-tools/issues/165
Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Acked-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2024-04-02 17:37:53 +02:00
Marc Hartmayer
bc9f8a8100 genprotimg: Fix out-of-disk space handling
Convert the assertion to a GError since an out-of-disk-space situation
is a valid situation that should be handled.

ERROR:utils/crypto.c:1843:__encrypt_decrypt_bio: assertion failed: (num_bytes_written == out_len)
Bail out! ERROR:utils/crypto.c:1843:__encrypt_decrypt_bio: assertion failed: (num_bytes_written == out_len)

Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2024-04-02 17:37:53 +02:00
Steffen Eiden
2b5e7b0491 pvattest: Fix root-ca parsing
The parser setup falsely set the argument type as filename array, but
code expected a single filename. Fixed by setting up the parser
correctly to expect a single file name.

Fixes: 3ab06d77fb ("pvattest: Create, perform, and verify attestation measurements")
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2024-03-22 12:07:29 +01:00
Steffen Eiden
d7c95265cd libpv: Support Armonk in IBM signing key subject
New IBM signing keys will have Armonk as locality in the subject.
Ensure that CRLs with Poughkeepsie as issuer locality are still
discovered if they are signed with the signing keys private key.
Also, drop the check for issuer/subject comparison and only rely on
validity period and cryptographic signatures.

Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Christoph Schlameuss <schlameuss@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2024-03-22 12:07:29 +01:00
Marc Hartmayer
8751cfc409 genprotimg/samples/check_hostkeydoc: code formatting
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Christoph Schlameuss <schlameuss@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2024-03-22 12:07:29 +01:00
Marc Hartmayer
01f96d30f6 genprotimg/samples/check_hostkeydoc: fix ShellCheck findings
Fix ShellCheck findings and two typos. White spaces in filenames are now
supported properly.

Reviewed-by: Christoph Schlameuss <schlameuss@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2024-03-22 12:07:29 +01:00
Marc Hartmayer
fffbd93f12 genprotimg/samples/check_hostkeydoc: improve argument parsing
+ use `getopts` POSIX builtin instead of external program
+ improve error reporting
+ support white spaces in the script name

Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Christoph Schlameuss <schlameuss@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2024-03-22 12:07:29 +01:00
Marc Hartmayer
ddcfbdc8d2 genprotimg/samples/check_hostkeydoc: support Armonk in IBM signing key subject
Newer IBM signing keys use `Armonk` in their subject therefore add
support for it.

Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Christoph Schlameuss <schlameuss@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2024-03-22 12:07:29 +01:00
Marc Hartmayer
173fd7cdca genprotimg/samples/check_hostkeydoc: set LC_ALL=C for the sort command
Set `LC_ALL=C` for the `sort` command to get a stable sort order. See
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/sort.html for
details on the effect of LC_* on `sort`. Adapt the default issuer
accordingly.

Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2024-03-22 12:07:29 +01:00
Marc Hartmayer
d14e7593cc genprotimg: support Armonk in IBM signing key subject
New IBM signing certificates will have 'Armonk' as locality in the
subject. Make sure that certificate revocations lists (CRL) with
'Poughkeepsie' as issuer locality are still considered as valid as long
as they are signed with the IBM signing keys private key. In addition,
drop the check for 'issuer(HKD) == subject(HKSK)' as it doesn't improve
security. While at it, remove now unused functions and fix a memory leak
of @akid in `check_crl_issuer`.

Reviewed-by: Christoph Schlameuss <schlameuss@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2024-03-22 12:07:29 +01:00
Steffen Eiden
1a3d0b74f7 rust/pv: Support Armonk in IBM signing key subject
New IBM signing keys will have Armonk as locality in the subject.
Ensure that CRLs with Poughkeepsie as issuer locality are still
discovered if they are signed with the signing keys private key.
Also, drop the check for issuer/subject comparison and only rely on
validity period and cryptographic signatures.

Reviewed-by: Christoph Schlameuss <schlameuss@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2024-03-22 12:07:29 +01:00
Marc Hartmayer
f6c6f0cc71 rust/pv/test: Code + Certificate refactoring
* Get rid of Mockito
* create certs with AKID
* simplify things in the `create_certs.py` script

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2024-03-22 12:07:29 +01:00
Thomas Richter
966e67a252 cpumf/lscpumf: add support for machine type 3932
Add support for machine type 3932 and list the
CPU Measurement facility counter sets.

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Acked-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2024-03-22 12:07:29 +01:00
Joern Siglen
1c128c0d11 dbginfo.sh: dash compatible copy sequence
rewrite the copy of dbginfo.sh for dash compatibility

Reviewed-by: Mike Storzer <MSTORZER@de.ibm.com>
Reviewed-by: Mario Held <mario.held@de.ibm.com>
Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2024-03-22 12:07:29 +01:00
VasiliyS
a3199d58db rust/pv_core: Fix UvDeviceInfo::get() method.
`ATTESTATION_NR` flag was not set properly in case the device
didn't support `Info` IOCTL call.

Closes: https://github.com/ibm-s390-linux/s390-tools/pull/163
Signed-off-by: Vasiliy Suvorov <vsuvorov@gmail.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2024-03-22 12:07:29 +01:00
Vineeth Vijayan
659483031e zdev: Rearrange the options alphabetically in man page
re-arrange options in zdev manpages in the alphabetical order.

Signed-off-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2024-03-15 15:11:43 +01:00
Ingo Franzki
7dc2513205 zkey: Detect FIPS mode and generate PBKDF for luksFormat according to it
For LUKS2 volumes, zkey generates 'cryptsetup luksFormat' commands with
options '--pbkdf argon2i --pbkdf-memory 32 --pbkdf-force-iterations 4'
for low memory and time requirements. Using the default Argon2i options
might cause out-of-memory errors when multiple encrypted volumes are
unlocked automatically at boot through /etc/crypttab.

When the system runs in FIPS mode, which is indicated by file
/proc/sys/crypto/fips_enabled containing '1', the Argon2i password based
key derivation function might be disabled by a policy, and such
'cryptsetup luksFormat' commands might fail.

Generate '--pbkdf pbkdf2' instead if the system runs in FIPS mode.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2024-03-15 15:11:43 +01:00
Marc Hartmayer
0748d365a6 genprotimg/**/Makefile: Fix staged installs
Fix the support for staged installs. The Makefile variable `PKGDATADIR`
uses `DESTDIR` for all Makefile target, but actually it should only be
used for the `install*` and `uninstall*` targets. [1] Fix this by using
`DESTDIR` only for `install*` targets - uninstall* targets are not
supported by s390-tools.

Before this change, if `DESTDIR` was set for staged installs,
`genprotimg` has tried to find the bootloader binaries at the temporary
installation path `$DESTDIR$(TOOLS_DATADIR)/genprotimg/` instead of
`$(TOOLS_DATADIR)/genprotimg`.

[1] https://www.gnu.org/prep/standards/html_node/DESTDIR.html

Fixes: 65b9fc442c ("genprotimg: introduce new tool for the creation of PV images")
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2024-03-15 15:11:38 +01:00
Marc Hartmayer
94a404ed10 pvattest: Makefile: Remove unused variable and CFLAGS
Remove unused variables and unused compiler flags.

Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2024-03-15 15:11:34 +01:00
Thomas Richter
ef1799f31f s390-tools/libutil: Add machine type 3932
Add support for machine type 3932.
Print identical product name for machine types 8561 and 8562.

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Suggested-by: Christian Borntraeger <borntraeger@linux.ibm.com>
Acked-by: Christian Borntraeger <borntraeger@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2024-03-15 15:11:34 +01:00
Mikhail Zaslonko
47b0960cc7 zdump: Make ngdump_get_part_path() public
Make ngdump_get_part_path() public in order for unit-tests to access it.

Signed-off-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2024-03-15 15:11:34 +01:00
Mikhail Zaslonko
2288331a6f zipl: Clear CCW-type DASD dumper upon ldipl-dump tool installation
Clear CCW-type DASD standalone dumper (if installed on the DASD) upon
successful installation of the List-Directed ECKD dump tool on the same
device. This helps to avoid 'zgetdump -d' confusion and have only one
'active' dump tool per disk.

Signed-off-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Acked-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2024-03-15 15:11:34 +01:00
Mikhail Zaslonko
23e9156f43 s390_dump.h: Add DF_S390_DUMPER_MAGIC_SIZE constant
Add DF_S390_DUMPER_MAGIC_SIZE constant to s390_dump.h.
Use it instead of hardcoded length when processing dumper magics
in zgetdump code.

Signed-off-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Acked-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2024-03-15 15:11:34 +01:00
Mikhail Zaslonko
8f99e7c4ea zdump: Move DUMPER_MAGIC constants to include/dump/s390_dump.h
Move DUMPER_MAGIC constants from df_s390.h to the global header
include/dump/s390_dump.h in order to reuse it in zipl code.

Signed-off-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2024-03-15 15:11:34 +01:00
Mikhail Zaslonko
f3bcd94524 zdump: Add zgetdump -d support for ECKD ldipl-dump
Make 'zgetdump -d' to identify ldipl-dump tool (ngdump) installed on DASD
volume just like it does for NVMe ngdump.

Output sample:
-------------
Dump device info:
  Dump tool.........: Next Generation (NGDump) dump tool
  Version...........: 1
  Architecture......: s390x (64 bit)

Partition info:
  Partition number..: 2

Signed-off-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2024-03-15 15:11:34 +01:00
Mikhail Zaslonko
a2f8b19c2a dumpconf: Update the man page and etc/sysconfig/dumpconf template
Update dumpconf man page with list-directed ECKD dump information (new
attributes and configuration example for ECKD LDIPL dump).
Update etc/sysconfig/dumpconf with list-directed ECKD dump configuration
example.

Signed-off-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2024-03-15 15:11:34 +01:00
Mikhail Zaslonko
588d720517 dumpconf: Process br_chr and bootprog eckd attributes
- Write the following sysfs attributes for list-directed ECKD devices
  introducing setup_eckd_device() function.
    br_chr: location of boot record
    bootprog: boot program selector
- Remove redundant parameters from setup_ccw_device() and setup_fcp_device()
  functioins.

Signed-off-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2024-03-15 15:11:34 +01:00
Ingo Franzki
cd822cb770 zkey: Fix convert command to accept only keys of type CCA-AESDATA
Reject conversion of other key types with a proper error message.
Also fix a typo in another error message of the convert command.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2024-03-15 15:11:34 +01:00
Ingo Franzki
b27b8e3cd3 zkey: Fix typos in error message
Use a colon instead of a semicolon in the message.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2024-03-15 15:11:34 +01:00
Steffen Maier
7a2c5dc980 zdev/dracut: Fix file mode of non-executable shell library zdev-lib.sh
Use similar `install` mode option in Makefile as in commit
9b2fb1d4d2 ("zdev: add helper to convert from dasd_mod.dasd to zdev
config").

Fixes: 73c46a3056 ("zdev/dracut: fix kdump by only activating required devices")
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2024-03-15 15:11:28 +01:00
Jan Höppner
d9e3763d1c Prepare for next release
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-02-02 17:49:44 +01:00
Jan Höppner
6f15ed3264 New release s390-tools-2.31.0
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-02-02 17:49:44 +01:00
Joern Siglen
0d2b5af007 dbginfo.sh: check for DPM mode
check if the LPAR is running in DPM mode and reflect this in the summary.

Suggested-by: Mike Storzer <MSTORZER@de.ibm.com>
Acked-by: Eberhard Pasch <epasch@de.ibm.com>
Reviewed-by: Mario Held <mario.held@de.ibm.com>
Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-02-02 16:11:22 +01:00
Jan Höppner
9e7a8f48e8 common.mak: Set default C/C++ standard to gnu11/gnu++11
s390-tools doesn't define a common C/C++ standard at the moment.
Set the standard to gnu11/gnu++11, which is also used by the Kernel, and
establish a common baseline for all tools.

The -std flag is added to ALL_CFLAGS and ALL_CXXFLAGS to avoid losing it
in case CFLAGS are set by an outside entity.
It is also added to CLAGS_FOR_BUILD for this one special cross build
case.

The -std flag is removed from all tools that set it manually until now.

Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Benjamin Block <bblock@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-02-02 16:11:22 +01:00
Steffen Eiden
98f7a0569c rust/pvsecret: User defined signatures and verifications
Introduces the ability to `pvsecret` to add a signature (ecdsa or rsa)
to the program-reserved space (user-data) of an add-secret request
during the request creation. Additionally, some arbitrary data may be
inserted.

The new command `verify` checks if add-secret requests are sane (e.g.
start with the correct magic value). If the request contains a
user-signature `verify` will also verify this signature.

Acked-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-02-02 16:11:22 +01:00
Steffen Eiden
551f66282e rust/pvsecret: Streamline man and README
Makes the source for the manfiles&README more readable. Fixes some nits
like double spaces, unnessecary indentations, line breaks, ...
Removes pvsecret-version.1 as this command maps to the --version
option.

Acked-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-02-02 16:11:22 +01:00
Steffen Eiden
3d2ba5aaed rust/pvsecret: Sync man and help
The output of --help and man pages got out of sync.
Apply changes to the help output to fix this.

Acked-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-02-02 16:11:22 +01:00
Steffen Eiden
94942a48ab rust/pv: Add function to read a private key
Add a function to read a private key in PEM or DER format.

While at it, fix some documentation issues in read_{certs, crls}.

Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-02-02 16:11:22 +01:00
Steffen Eiden
ab8984a7a3 rust/pv: Remove unused functions
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-02-02 16:11:22 +01:00
Marc Hartmayer
4990f643c1 rust/pv: Add-Secret: Add user-data and user-defined signing keys
User-data can be added to add-secret requests. User-data can be unsigned
or containing a signature of the request using a custom private key.

The user-data is placed at offset 0x218 and 0x200 bytes long.

Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-02-02 16:11:22 +01:00
Steffen Eiden
34bef977e8 rust/pv: User-data signing and verifying
Add the ability to generate signed user-data and to verify the
signature.

Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-02-02 16:11:22 +01:00
Steffen Eiden
f36c34038b rust/pv: Add-Secret: Add user-data types
Add four new user-data types an add-secret request could have:
Unsigned, Signed(EcSECP521R1, Rsa(2048, 3072))

As the user-data enum was not marked as non-exaustive this might be a
breaking change for users. (Not for any crate in this repo though).

The addition of such user-data is provided by following patches.

Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-02-02 16:11:22 +01:00
Steffen Eiden
bfd0e12d22 rust/pv: Signing messages
Adds the ability to sign and verify messages using ECDH or RSA keys.

Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-02-02 16:11:21 +01:00
Steffen Eiden
1450f85ada rust/pv: Fix documentation issue
Add the missing plaintext flags to the request description.

Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-02-02 16:11:21 +01:00
Marc Hartmayer
2a0f1e6977 pvsecret: improve warning if host key document contains multiple certificates
Improve the warning for the case where a host key document contains
multiple certificates (only possible for a PEM file). In case there are
multiple host key document only the first certificate is used.

Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-02-02 16:11:21 +01:00
Marc Hartmayer
0f433b1142 pvsecret: fix panic if empty file is used as host key document
Fix a panic in `pvsecret` when a empty file is used as a host key
document.

$ touch hkd
$ pvsecret create --no-verify -k hkd --output req.bin --hdr sehdr
...
The host key document in 'bla' contains more than one certificate!
thread 'main' panicked at pvsecret/src/cmd/create.rs:192:31:

Fixes: dd82c26f87 ("rust: Add tool to manage UV-secrets")
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-02-02 16:11:21 +01:00
Marc Hartmayer
ab6bcad263 pv/error.rs: fix typo
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-02-02 16:11:21 +01:00
Marc Hartmayer
e40a3e0621 pvapconfig/tests: use a temporary directory for tests
Use the `TemporaryDirectory` type to create a temporary directory. This
type has the advantage that the directory is automatically removed once
it goes out of scope. The old implementation in test_sysfs_write_i32
leaks a directory if a previous subtest failed. Also, using a temporary
directory for the LockFile test fixes the following error:

  $ RUST_BACKTRACE=1 cargo test -- helper::tests::test_lockfile
  ...
  running 1 test
  test helper::tests::test_lockfile ... FAILED

  failures:

  ---- helper::tests::test_lockfile stdout ----
  thread 'helper::tests::test_lockfile' panicked at pvapconfig/src/helper.rs:265:9:
  assertion failed: r1.is_ok()
  stack backtrace:
     0: rust_begin_unwind
	       at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/std/src/panicking.rs:597:5
     1: core::panicking::panic_fmt
	       at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/core/src/panicking.rs:72:14
     2: core::panicking::panic
	       at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/core/src/panicking.rs:127:5
     3: pvapconfig::helper::tests::test_lockfile
	       at ./src/helper.rs:265:9
     4: pvapconfig::helper::tests::test_lockfile::{{closure}}
	       at ./src/helper.rs:263:24
     5: core::ops::function::FnOnce::call_once
	       at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/core/src/ops/function.rs:250:5
     6: core::ops::function::FnOnce::call_once
	       at /rustc/79e9716c980570bfd1f666e3b16ac583f0168962/library/core/src/ops/function.rs:250:5
  note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-By: Harald Freudenberger <freude@de.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-02-02 16:11:21 +01:00
Marc Hartmayer
e56acf4f14 pv_core: add TemporaryDirectory
Add the type `TemporaryDirectory` that creates a temporary directory
that is automatically removed when it goes out of scope.

Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-By: Harald Freudenberger <freude@de.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-02-02 16:11:21 +01:00
Finn Callies
17977eda30 cpacfstats: Fix typo PCMKO to PCKMO
This commit fixes a typo in the cpacfstats.c client application and its
respective manpage cpacfstats.1.

Signed-off-by: Finn Callies <fcallies@linux.ibm.com>
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
Reviewed-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-02-02 16:11:21 +01:00
Steffen Eiden
459a257568 rust/pvapconfig: Fix typos and clippy findings
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-02-02 16:11:21 +01:00
Steffen Eiden
fb65b53b9b rust/pvapconfig: use pv_base instead of pv crate
Replace the pv crate with the pv_core crate.

Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-02-02 16:11:21 +01:00
Steffen Eiden
c8d4062f73 rust/pv: bump up crate version to 1.0.0
Recent changes makes it reasonable to update the version string of pv
and pv_base to 1.0.0. Recent changes introduced some non-backwards
compatible changes, like move some Error definition from pv to the new
pv_core crate. Also, the pv crates seem to be in a good shape to be
considered released.

Therefore, move up the Semver to 1.0.0.
See also:
https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html

NOTE: As these crates are not published to `crates.io` as of now, the
version number is meaningless, as cargo will not pull them from
anywhere and just use the files provided by this repository.

Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-02-02 16:11:21 +01:00
Steffen Eiden
c8e0992814 rust/Cargo.lock: Update zerocopy crate
Update the zerocopy dependency from v0.6.* to the non forward compatible
v0.7.*. Incompatible changes are the requirment of the FromZeroes trait
for FromBytes trait and the non-default derive feature which this
patches handles as well.

Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-02-02 16:11:21 +01:00
Steffen Eiden
c0a12b29d0 rust/pv: Reorganize some tests
Use a static Mockito server instead of creating multiple on-the-fly
during testing. Add the `mockito_server_available` test to quickly
verify that the mockito server could be constructed.  Relocate the
verifier API test to the test folder as it tests the public API. Also,
make the Debug impl for CertVerifier public. The test relocation
requires this. Before, there could be a test local implementation of the
Debug impl as it was in the same crate.

While at it, get rid of the lazy_static crate in favor of the once_cell
crate. As the new std lib implementation is very near to the one from
once cell. The project will switch to the std impl when v1.70 is
available in all supported distros. See:
https://doc.rust-lang.org/std/sync/struct.OnceLock.html

Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-02-02 16:11:21 +01:00
Steffen Eiden
02dded11a5 rust/pv: Replace libc wherever possible
Replace all libc references to rust-std references if available.
This eliminates the need to include libc in the pv crate.
However, pv_base still refers to libc::ioctl and libc::ENOTTY.

Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-02-02 16:11:21 +01:00
Steffen Eiden
b71279cda5 rust/pv: Remove memeq function
The rust std lib already provides functionality to compare two slies.
Replace all `memeq` invocations with == and remove the `memeq` function.
As a side effect this eliminates some unsafe code in this crate.

Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-02-02 16:11:21 +01:00
Steffen Eiden
c70477f8c6 rust/pv: Fix 'elided_lifetimes_in_associated_constant' warning
Fixes "warning: `&` without an explicit lifetime name cannot be used
here". This warning will become a hard error in "the future". For more
information, see issue #115010 <https://github.com/rust-lang/rust/issues/115010>

Closes: https://github.com/ibm-s390-linux/s390-tools/issues/162
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-02-02 16:11:21 +01:00
Steffen Eiden
9b51b8b882 rust/pv: Refactor pv crate
Big refactoring patch of the pv crate. The main reason behind this
refactoring is to simplify testing and maintaining the pv crate while
keeping OpenSSL/libcurl dependencies optional. Using crate features
increases the number of targets that have to be tested. This refactoring
eliminates the use of features by splitting the functionality of pv into
a use OpenSSL and no-use-OpenSSL crate.

Split off some code from the pv crate into a pv_core crate. pv requires
pv_core and reexports all symbols. pv_base contains all code from former
pv that does not use OpenSSL or libcurl functionalities. The refactored
pv crate contains functionalities to generate requests and validate host
key documents. All features from pv are dropped as they are not needed
anymore and to streamline the codebase for easier use and testing. While
at it fix some documentation issues.

Users (pvsecret & pvapconfig) have next to no code change, besides the
different import of the crate.

Acked-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-02-02 16:11:21 +01:00
Steffen Eiden
48539596ef rust/pv: Use constants for invalid secret types
Add local constants for the reserved, and Null secret type and use
them.

Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-02-02 16:11:21 +01:00
Steffen Eiden
cafa99774c rust/pv: Replace file-macros with functions
A function does the job as well. This improves code readability and
useability. While at it remove the implicit Buffer wrapper. Users are
currently not use the benefits of a buffered write. Also, streamline the
write_out helper function.

Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-02-02 16:11:21 +01:00
Tobias Huschle
b5f7ac95d8 cpuplugd: adjust to CPU 0 being no longer hotpluggable
With kernel commit 496bb034f4ff ("s390/smp: disallow CPU hotplug
of CPU 0") it is no longer possible to hotplug CPU 0.

As a side effect, the sysfs handle /sys/devices/system/cpu/cpu0/online
does no longer exist. Since cpuplugd relies on checking all online
handles of all CPUs, this change causes cpuplugd to fail as it
interprets a non existing online file as an indicator that no other CPUs
with higher IDs exist as well. This leads to cpuplugd assuming that
there are no CPUs available.

Instead of checking for the online file, it is preferable to check for
the existence of the parent folder to verify the existence of a CPU.
As a consequence, all other checks for non-existing online files must
now imply that the CPU is online, but not hotpluggable.

Signed-off-by: Tobias Huschle <huschle@linux.ibm.com>
Tested-by: Mete Durlu <meted@linux.ibm.com>
Reviewed-by: Gerald Schaefer <gerald.schaefer@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-02-02 16:11:21 +01:00
Thomas Richter
e984b97db0 s390-tools/cpumf: set exit code on pai data collection error
When pai records data it may fail in select() system call.
This error is not reported and the pai program exits with success.
Change this and exit with proper exit code.

Fixes: d7b1cbad8b ("cpumf/pai: Add Processor Activity Instrumentation tool")
Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Acked-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-02-02 16:11:21 +01:00
Thomas Richter
64d4e02b4f cpumf/pai: Handle perf records type PERF_RECORD_SWITCH
Running command pai -r <file> might encounter entries of type
PERF_RECORD_SWITCH. Entries of that type are currently not handled
and cause an error message:

 # pai -r ~/paicrypto.000
 unknown header-type 14 unknown header-type 14 \
 unknown header-type 14 ...

The error message is not terminated by a newline.

Handle entries of this type PERF_RECORD_SWITCH. These records
do not carry any payload at all, just a bit is set in the
header::misc member. This bit set determines context switch out.

Output after:
 # ./pai -r ~/paicrypto.000
 0x4b814018f4f3 6 cs-out
 0x4b817bc3c936 6 cs-in
 0x4b817bc5246c 6 cs-out
 0x4b817bd90e9a 6 cs-in
 ....
 #

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Acked-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-02-02 16:11:21 +01:00
Marc Hartmayer
90ddef5a41 pre-commit: Provide pre-commit configuration
Add pre-commit (https://pre-commit.com/) configuration to allow
developers to run certain checks on their commits automatically.

Currently enabled checks and hooks are:
- Generic checks (e.g. merge-conflicts, trailing whitespace, etc.)
- git clang-format
- Codespell
- Shellcheck (https://www.shellcheck.net/)

Note: For some hooks Rust is excluded as a lot of false positives are
produced at the moment.

Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-02-02 16:11:21 +01:00
Joern Siglen
58ef99f76b dbginfo.sh: handle relative and absolute calling path
include the dbginfo.sh script used - enabled for relative paths

Reviewed-by: Michael Storzer <mstorzer@de.ibm.com>
Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-01-12 14:10:52 +01:00
Joern Siglen
43c34956fb dbginfo.sh: adding new step to man page
step "initrd config files" was added as 19th step to our data collection
updating for newer date and distro version in the sample output

Reviewed-by: Michael Storzer <mstorzer@de.ibm.com>
Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-01-12 14:10:52 +01:00
Joern Siglen
d7dee1b9d3 dbginfo.sh: change copyright for 2024
prepare for the next updates

Reviewed-by: Michael Storzer <mstorzer@de.ibm.com>
Signed-off-by: Joern Siglen <siglen@de.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-01-12 14:10:52 +01:00
Harald Freudenberger
94a38ebc3a rust/pvapconfig: Introduce new tool pvapconfig
pvapconfig is a new tool for automatically configuring the APQNs
within an Secure Execution KVM guest with AP pass-through support.
Based on a given AP configuration it tries to find a matching
APQN and bind and associate it with the correct secret.

Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Reviewed-by: Ingo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: Holger Dengler <dengler@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-01-12 14:10:52 +01:00
Steffen Eiden
0764460eaf rust/pv: Provide access for SecretList members
Adds getter for SecretList and SecretEntry.
Adds enum to represent secret types.
Add Iterator functionality for SecretList.

While at it, make the datatype of the capacity of the list transparent
for users.

Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-01-12 14:10:52 +01:00
Steffen Eiden
6fd02279da rust/Makefile: Fix CC/AR variables for TEST_TARGETS
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2024-01-12 14:10:52 +01:00
Yaakov Selkowitz
6274294bc5 libkmipclient: Fix build with libxml2-2.12.0
https://gitlab.gnome.org/GNOME/libxml2/-/releases/v2.12.0

"Several cyclic dependencies in public header files were fixed. As a
result, certain headers won't include other headers as before."

Closes: https://github.com/ibm-s390-linux/s390-tools/pull/160
Signed-off-by: Yaakov Selkowitz <yselkowi@redhat.com>
Reviewed-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-12-20 18:32:34 +01:00
Steffen Maier
27708026d4 zdev/dracut: state requirement for sed during kdump initrd build
v2.27.0 commit 73c46a3056 ("zdev/dracut: fix kdump by only activating
required devices") started using `sed` during kdump initrd build time.
It works, but explicitly add the tool as a requirement.

Fixes: 73c46a3056 ("zdev/dracut: fix kdump by only activating required devices")
Closes: https://github.com/ibm-s390-linux/s390-tools/pull/158
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Acked-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Acked-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-12-14 15:25:22 +01:00
Steffen Maier
849aa5b105 zdev/dracut: put temporary files under the subdir ${DRACUT_TMPDIR}
This way, dracut cleans up everything just in case the "rm" here fails.

Github-ID: https://github.com/ibm-s390-linux/s390-tools/pull/158
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Acked-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Acked-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-12-14 15:25:22 +01:00
Steffen Maier
0be83bfbba dbginfo.sh: collect migration backups & logs from old persistent config
Complements commits
("zdev/dracut: add rd.zfcp cmdline option handling")
("zdev/dracut: add rd.dasd cmdline option handling")
and s390utils commits
("zfcp: migrate to consolidated persistent device config with
zdev (#1937046,#1937048)")
("dasd: migrate to consolidated persistent device config with
zdev (#1937046,#1937048)")
.

Github-ID: https://github.com/ibm-s390-linux/s390-tools/pull/158
Reviewed-by: Fedor Loshakov <loshakov@linux.ibm.com>
Acked-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Acked-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-12-14 15:25:22 +01:00
Steffen Maier
f8592be43d dbginfo.sh: collect file list and config files from initrd-s
For each initrd, collect verbose content listing as well as
the content of files matching the file glob patterns in $CONFIGFILES.
For dracut-squash such as RHEL kdump, this includes squashfs content.

Code is intentionally compatible with dash, so no bashisms.

Ubuntu initramfs has zdev persistent device configuration udev rules under
/lib/udev/rules.d/ (as opposed to /etc/udev/rules.d/).
Ubuntu initramfs stores configuration under /conf/.
Ubuntu kdump-tools have initrds under /var/lib/kdump/.

SLES auxiliary boot stage with grub2-s390x-emu has initrds under /boot/zipl/.

Dracut initramfs stores configuration under /etc/cmdline.d/ and /etc/conf.d/.
Dracut kdump have initrds under /boot/.

Github-ID: https://github.com/ibm-s390-linux/s390-tools/pull/158
Reviewed-by: Fedor Loshakov <loshakov@linux.ibm.com>
Acked-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Acked-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-12-14 15:25:22 +01:00
Steffen Maier
647ad51423 dbginfo.sh: collect other config data from zdev in initrd
Complements commit ("zdev/dracut: retain early persistent config over
switch root").

Github-ID: https://github.com/ibm-s390-linux/s390-tools/pull/158
Reviewed-by: Fedor Loshakov <loshakov@linux.ibm.com>
Acked-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Acked-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-12-14 15:25:22 +01:00
Steffen Maier
73f51e45a8 zdev: add helper to convert from zdev config to rd.znet
Converts zdev configuration into the syntax of the dracut cmdline option
rd.znet. Only znet options with non-default values are emitted. The result
string occurs on stdout. It represents one device-specification for the
given network interface name.

Example:
/lib/s390-tools/zdev-to-rd.znet persistent encbdf0
qeth,0.0.bdf0,0.0.bdf1,0.0.bdf2,layer2=1

User:
https://github.com/rhinstaller/anaconda/pull/5250
to generate dracut cmdline entries such as
rd.znet=qeth,0.0.bdf0,0.0.bdf1,0.0.bdf2,layer2=1

Github-ID: https://github.com/ibm-s390-linux/s390-tools/pull/158
Acked-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Acked-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-12-14 15:25:22 +01:00
Steffen Maier
bc4f455151 zdev/dracut: retain early persistent config over switch root
Useful for debugging (what happened during early boot).

Also useful for distro installers, which can import the early config into
their own environment early after starting:
chzdev --import /run/zdev.initrd.config --persistent --yes \
       --no-root-update --force --verbose

After that, distro installers can modify/add the device config based
on interactive or unattended installation choices using
chzdev --enable --active --persistent ...

Finally, distro installers can likewise transfer the entire device config
to the installed system mounted under $SYSROOT:
chzdev --export /tmp/zdev.config --all --type --persistent --verbose

Github-ID: https://github.com/ibm-s390-linux/s390-tools/pull/158
Acked-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Acked-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-12-14 15:25:22 +01:00
Steffen Maier
b4b5e0b6aa zdev/dracut: produce helpful user information on parsing rd.zfcp
It builds on the previously added helper function in parse-dasd.sh, which
gets sourced first by dracut so the function is also available to the later
parsing hook parse-zfcp.sh.

Github-ID: https://github.com/ibm-s390-linux/s390-tools/pull/158
Acked-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Acked-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-12-14 15:25:22 +01:00
Steffen Maier
9927023680 zdev/dracut: add rd.dasd cmdline option handling
Add parsing of dracut cmdline option "rd.dasd=..." at initrd runtime.
It delegates configuration to chzdev.

Implement `dracut --print-cmdline` and `dracut --hostonly-cmdline` for
initrd build time. Emit an rd.dasd option for each DASD disk in dracut's
device dependency graph (to mount the root-fs, or to access the kdump
target).

This allows a distribution independent device configuration.
Configuration is consistent by using chzdev as backend.
It also prevents duplicate activations of the same device.

Copy the udev rule for unique DASD device nodes under /dev/disk/
[59-dasd.rules] into initrd for the same functionality like 95dasd or
95dasd_rules.

Along with the existing functionality of zdev/dracut, it makes the
following dracut modules superfluous:
https://github.com/dracutdevs/dracut/tree/master/modules.d/95dasd
https://github.com/dracutdevs/dracut/tree/master/modules.d/95dasd_mod
https://github.com/dracutdevs/dracut/tree/master/modules.d/95dasd_rules

Github-ID: https://github.com/ibm-s390-linux/s390-tools/pull/158
Acked-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Acked-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-12-14 15:25:22 +01:00
Steffen Maier
9b2fb1d4d2 zdev: add helper to convert from dasd_mod.dasd to zdev config
Shell library, which can be sourced by other POSIX compatible shell
scripts. Provide helper function parsing its stdin based on the syntax of
kernel device driver parameter dasd_mod.dasd= and invoking chzdev to
produce corresponding persistent device configurations. The helper function
takes one argument, which is either "globals" or "ranges". For a complete
configuration, call the function twice, first with "globals" and then with
"ranges".

The new script library file should be packaged in a core (sub)package of
s390-tools so the script is available for initrd environments.

Users with examples:

Subsequent commit ("zdev/dracut: add rd.dasd parsing") introduces
zdev/dracut/95zdev/parse-dasd.sh performing:
zdev_parse_rd_dasd | zdev_parse_dasd_list globals 2>&1 | zdev_vinfo
zdev_parse_rd_dasd | zdev_parse_dasd_list ranges 2>&1 | zdev_vinfo

https://github.com/dracutdevs/dracut/pull/2534 updates
modules.d/80cms/cmssetup.sh performing:
echo "$DASD" | zdev_parse_dasd_list globals 2>&1 | vinfo
echo "$DASD" | zdev_parse_dasd_list ranges 2>&1 | vinfo

The parsing code for rd.dasd using the same syntax as dasd_mod.dasd=
is inspired by the own implementation that used to be in linuxrc.s390
of https://github.com/rhinstaller/anaconda.
https://web.archive.org/web/20190721154444/https://www.redhat.com/archives/anaconda-devel-list/2009-February/msg00392.html
https://www.spinics.net/linux/fedora/anaconda-devel/msg08316.html
("Re: Improved linuxrc.s390 (third try)")
=> 9249e40f42ff ("IBM improvements to linuxrc.s390 (#475350)")
https://web.archive.org/web/20190721150254/https://www.redhat.com/archives/anaconda-devel-list/2009-July/msg00310.html
=> 5f0fcf6688d0 ("Update linuxrc.s390 and friends to reflect review comments.")
https://web.archive.org/web/20190721125255/https://www.redhat.com/archives/anaconda-devel-list/2009-August/msg00158.html
=> 523095c86876 ("Handle activation of DASDs in linuxrc.s390 since loader no longer works")

Github-ID: https://github.com/ibm-s390-linux/s390-tools/pull/158
Acked-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Acked-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-12-14 15:25:22 +01:00
Steffen Maier
689b894506 zdev: add helper to convert from zdev config to dasd_mod.dasd
Converts zdev configuration into the syntax of the kernel module parameter
dasd_mod.dasd. Only DASD options with non-default values are emitted. The
result string occurs on stdout. It represents one device-specification for
the given DASD device bus-ID.

Example:
/lib/s390-tools/zdev-to-dasd_mod.dasd persistent 0.0.da5d
0.0.da5d(erplog)

User:
https://github.com/storaged-project/blivet/pull/1162
to generate dracut cmdline entries such as rd.dasd=0.0.da5d(erplog)

Github-ID: https://github.com/ibm-s390-linux/s390-tools/pull/158
Acked-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Acked-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-12-14 15:25:22 +01:00
Steffen Maier
06a30ae529 zdev/dracut: add rd.zfcp cmdline option handling
Add parsing of dracut cmdline option "rd.zfcp=..." at initrd runtime.
It delegates configuration to chzdev.

Implement `dracut --print-cmdline` and `dracut --hostonly-cmdline` for
initrd build time. Emit an rd.zfcp option for each zfcp-attached SCSI disk
in dracut's device dependency graph (to mount the root-fs, or to access the
kdump target).

This allows a distribution independent device configuration.
Configuration is consistent by using chzdev as backend.
It also prevents duplicate activations of the same device.

Along with the existing functionality of zdev/dracut, it makes the
following dracut modules superfluous:
https://github.com/dracutdevs/dracut/tree/master/modules.d/95zfcp
[rd.zfcp.conf is no longer needed and thus ignored here; the preceding
 ("zdev/dracut: fix marking hostonly files so delete option works")
 makes rd.hostonly=0 work as a generic replacement]
https://github.com/dracutdevs/dracut/tree/master/modules.d/95zfcp_rules

Github-ID: https://github.com/ibm-s390-linux/s390-tools/pull/158
Acked-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Acked-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-12-14 15:25:22 +01:00
Steffen Maier
ed106d7f28 zdev/dracut: add site support for early devices to the kdump case
The existing code can already determine the required devices for the
actively running system, but this does not work for execution environments
in different (disaster recovery) sites.

Kdump likely does not notice when running in a different site and does not
re-generate the kdump initrd (because the kdump config itself does not
change).

The new code allows users to explicitly specify devices required for early
boot in initrd on different sites. Assuming this is a small number of
devices and could even overlap between the root-fs and the kdump case, do
not further distinguish those two sets of devices, but simply use the same
marker attribute "zdev:early=1" for both cases. With all this site
information available at the (initial) kdump initrd generation, the
resulting kdump initrd can work on any site without having to re-generate.

Complements commit 3c7adcc3c81d ("zdev: dracut: modifiy the
module-setup.sh").

Github-ID: https://github.com/ibm-s390-linux/s390-tools/pull/158
Reviewed-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Acked-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Acked-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-12-14 15:25:22 +01:00
Steffen Maier
9d08fd8c7e zdev/dracut: import persistent config of early devices into kdump initrd
The existing code can already determine the required devices for the
actively running system. In case users would have a need to configure
additional devices for early boot in kdump initrd, import those devices
marked with "zdev:early=1" for completeness. Assuming this is a small
number of devices and could even overlap between the root-fs and the kdump
case, do not further distinguish those two sets of devices.

Github-ID: https://github.com/ibm-s390-linux/s390-tools/pull/158
Reviewed-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Acked-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Acked-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-12-14 15:25:22 +01:00
Steffen Maier
7e8126704b zdev/dracut: fix to not depend on existing chzdev persistent config
Dracut knows exactly what dependencies it needs. Do not break it by
accidentally missing parts in the chzdev persistent configuration
(/etc/udev/rules.d/41-*.rules). Depicted as mathematical sets:

+-------------------------------+
| active                        |
|            +---------------------------------+
|            |                  |   persistent |
|   +------------------------------------+     |
|   |      root / kdump dependencies     |     |
|   | was    |                  |        |     |
|   | missing|   zdev so far    |   DR   |     |
|   +------------------------------------+     |
|            |                  |              |
+-------------------------------+              |
             |                                 |
             +---------------------------------+

Github-ID: https://github.com/ibm-s390-linux/s390-tools/pull/158
Reviewed-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Acked-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Acked-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-12-14 15:25:22 +01:00
Steffen Maier
d96767ee45 zdev/dracut: fix marking hostonly files so delete option works
Chzdev import generates persistent device configuration which are hostonly
files. Dracut cmdline rd.hostonly=0 should be able to delete those.

Github-ID: https://github.com/ibm-s390-linux/s390-tools/pull/158
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Acked-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Acked-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-12-14 15:25:22 +01:00
Steffen Maier
63f31bf73e zdev/dracut: add field debugging capabilities with logging
Additional debugging output can be generated with e.g. dracut option
"--stdlog 5" (or short -L5). It shows the chzdev export result, the output
of chzdev imports, and an overview of the resulting persistent config
within the initrd.
On systems, which default to using dracut option "--quiet", you might need
an additional "--verbose" to counter "--quiet" so -L5 has effect.
Typically combined with "--debug" to get a shell trace from building an
initrd (Note: --debug does not increase the log levels).

Github-ID: https://github.com/ibm-s390-linux/s390-tools/pull/158
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Reviewed-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Acked-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Acked-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-12-14 15:25:22 +01:00
Steffen Maier
7ecfe2353f zdev/dracut: respect hostonly mode choice
Otherwise it risks adding arbitrary persistent configuration of the build
host into generic dracut initrds such as those for distro installers.

Github-ID: https://github.com/ibm-s390-linux/s390-tools/pull/158
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Acked-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Acked-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-12-14 15:25:22 +01:00
Steffen Maier
7bec672c7e zdev/dracut: fix kernel module install even for hostonly mode
Otherwise, dracut skips modules that are "not hostonly", i.e. not used /
loaded on the system when running dracut to build an initrd.
Without the fix, zdev device auto configuration only works for device
types for which a device driver happened to be loaded when building an
initrd. Likewise for specifying rd.* boot options.

Hostonly mode is often the default in Linux distributions.
Make zdev device auto configuration work nonetheless without users
having to know about and tweak dracut modes for initrd generation.

On the typical sloppy hostonly mode, the code disables hostonly for
installing kernel modules. This covers building regular initrds, where zdev
device auto configuration should even work for device types, for which
device drivers were not loaded when an initrd was generated. This can
happen when new devices of new types are configured for a DPM logical
partition. Also, users could want to start using dracut cmdline options
rd.{dasd,zfcp,znet} for a device type that was not used when the initrd was
built.

The special strict hostonly mode is used by some kdump implementations. In
that case, hostonly remains in effect intentionally because only support
for the really required devices as determined by dracut module 95zdev-kdump
should be included in a kdump initrd due to the memory-constrained kdump
environment. Cf. commit 73c46a3056 ("zdev/dracut: fix kdump by only
activating required devices"), which also provides more references on
strict hostonly mode. Even for non-kdump cases, let strict hostonly mode be
effective here in 95zdev in case some future use case appears for this
special mode beyond kdump.

Github-ID: https://github.com/ibm-s390-linux/s390-tools/pull/158
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Acked-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Acked-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-12-14 15:25:22 +01:00
Steffen Maier
5aac5deb75 zdev/dracut/module-setup.sh: add comments for dracut called functions
Add a short explaining comment to those functions, which are just callbacks
invoked by the dracut core infrastructure. So nobody wonders how these
functions get called, especially if there are no local callers here in the
code.

Cf. dracut commit
https://github.com/dracutdevs/dracut/commit/8bcfd683bd0c
("*/module-setup.sh: add comments for dracut called functions")

For more information about the dracut module callback functions:
https://github.com/dracutdevs/dracut/blob/master/man/dracut.modules.7.asc#writing-a-module
https://github.com/dracutdevs/dracut/blob/master/docs/HACKING.md#writing-modules

Github-ID: https://github.com/ibm-s390-linux/s390-tools/pull/158
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Acked-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Acked-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-12-14 15:25:22 +01:00
Steffen Maier
54e016ae71 zdev/dracut: use namespace prefix in functions of zdev-lib.sh
Use namespace prefix in functions of zdev-lib.sh to avoid collisions with
different modules being sourced in the shell.

Github-ID: https://github.com/ibm-s390-linux/s390-tools/pull/158
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Acked-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Acked-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-12-14 15:25:22 +01:00
Steffen Maier
6b53378839 zdev/dracut/95zdev: non-functional changes and annotations for shellcheck
Clears all shellcheck reports in old existing code so newly added code can
use shellcheck to find newly introduced suboptimal shell code.

Github-ID: https://github.com/ibm-s390-linux/s390-tools/pull/158
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Reviewed-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Acked-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Acked-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-12-14 15:25:22 +01:00
Steffen Maier
1266f86444 zdev/dracut: add shellcheck annotations for recently added code
The annotations and the one non-functional code change in
zdev/dracut/95zdev-kdump/module-setup.sh check() clear all shellcheck
reports.

complements
73c46a3056 ("zdev/dracut: fix kdump by only activating required devices")

Github-ID: https://github.com/ibm-s390-linux/s390-tools/pull/158
Reviewed-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Acked-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Acked-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-12-14 15:25:22 +01:00
Steffen Maier
231c02cdeb zdev: fix typo for example in chzdev man page
Github-ID: https://github.com/ibm-s390-linux/s390-tools/pull/158
Reviewed-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Acked-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Acked-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Steffen Maier <maier@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-12-14 15:25:22 +01:00
Marc Hartmayer
454a8d9d7b systemd/cpi.service: add missing Requires=sysinit.target
`After=sysinit.target` configures only the order but not that the
systemd unit is required and must be activated. Therefore add the
missing `Requires=sysinit.target`. It probably does not fix anything
because sysinit.target should always be activated anyway but it's
cleaner to have it. See
https://www.freedesktop.org/software/systemd/man/systemd.unit.html for
details.

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-12-14 15:25:22 +01:00
Marc Hartmayer
bbe92b9cd3 systemd/cpi.service: fix race condition between stopping unit and shutdown
There is a race condition between stopping the cpi systemd service and
systemd getting a request to exit the main loop, so it may proceed with
shutdown before all pending stop jobs have been processed. Therefore,
add `Before=shutdown.target` as it would have been added by
the (deactivated) default dependencies. [1]

While at it, sort the directives.

[1] https://www.freedesktop.org/software/systemd/man/systemd.service.html#Default%20Dependencies

Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-12-14 15:25:22 +01:00
Jan Höppner
7bb41732fb Prepare for next release
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2023-12-01 15:03:39 +01:00
191 changed files with 9716 additions and 3452 deletions

View File

@@ -1,5 +1,3 @@
parm
parms
crate
ser
deriver

35
.pre-commit-config.yaml Normal file
View File

@@ -0,0 +1,35 @@
---
exclude: \.(crt|crl)$
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.1.0
hooks:
- id: check-merge-conflict
- id: end-of-file-fixer
- id: mixed-line-ending
- id: trailing-whitespace
- id: check-executables-have-shebangs
- id: check-shebang-scripts-are-executable
exclude_types: ['rust']
- repo: local
hooks:
- id: git-clang-format
name: git-clang-format
description: Run git-clang-format
entry: git
args: [clang-format, --staged, --]
pass_filenames: true
language: system
require_serial: true
minimum_pre_commit_version: "2.9.0"
types_or: [c++, c]
- repo: https://github.com/codespell-project/codespell
rev: v2.2.1
hooks:
- id: codespell
exclude_types: ['rust']
- repo: https://github.com/jumanjihouse/pre-commit-hooks
rev: 3.0.0
hooks:
- id: shellcheck
args: ["--external-sources"]

View File

@@ -36,6 +36,7 @@ List of all individuals having contributed content to s390-tools
- Farhan Ali
- Fedor Loshakov
- Felix Beck
- Finn Callies
- Frank Blaschka
- Frank Heimes
- Frank Munzert
@@ -127,6 +128,7 @@ List of all individuals having contributed content to s390-tools
- Thomas Spatzier
- Thomas Weber
- Thorsten Winkler
- Tobias Huschle
- Tuan Hoang
- Ursula Braun
- Utz Bacher
@@ -137,3 +139,4 @@ List of all individuals having contributed content to s390-tools
- Volker Sameske
- Wenjia Zhang
- Wolfgang Taphorn
- Yaakov Selkowitz

View File

@@ -1,6 +1,48 @@
Release history for s390-tools (MIT version)
--------------------------------------------
* __v2.32.0 (2024-04-03)__
For Linux kernel version: 6.8
Changes of existing tools:
- cpumf/lscpumf: add support for machine type 3932
- genprotimg, pvattest, and pvsecret accept IBM signing key with Armonk as
subject locality
- zdump/zipl: Support for List-Directed dump from ECKD DASD
- zkey: Detect FIPS mode and generate PBKDF for luksFormat according to it
Bug Fixes:
- dbginfo.sh: dash compatible copy sequence
- rust/pv_core: Fix UvDeviceInfo::get() method
- zipl/src: Fix leak of files if run with a broken configuration
- zkey: Fix convert command to accept only keys of type CCA-AESDATA
* __v2.31.0 (2024-02-02)__
For Linux kernel version: 6.7
General:
- common.mak: Set default C/C++ standard to gnu11/gnu++11
Add new tools / libraries:
- pvapconfig: Tool to automatically configure APQNs in SE KVM guests
- s390-tools: Provide pre-commit configuration
Changes of existing tools:
- cpuplugd: Adjust to CPU 0 being no longer hotpluggable
- dbginfo.sh: Check for Dynamic Partition Mode
- dbginfo.sh: Update man page and copyright
- rust/pv: Add user-data signing and verifying
- rust/pvsecret: Add user defined signatures and verifications
- zdev/dracut: Consolidate device configuration
Bug Fixes:
- dbginfo.sh: Fix relative path on script copy
- libkmipclient: Fix build with libxml2-2.12.0
- pvsecret: Fix panic if empty file is used as host key document
- rust/pv: Fix 'elided_lifetimes_in_associated_constant' warning
* __v2.30.0 (2023-12-01)__
For Linux kernel version: 6.6
@@ -22,6 +64,7 @@ Release history for s390-tools (MIT version)
- zipl/boot: compile the bootloaders only if HOST_ARCH is s390x
- zipl: Add --no-compress option to zipl command
- zkey: Also check for deconfigured and check-stopped cards
- dbginfo.sh: fix relative path on script copy
Bug Fixes:
- ap_tools/ap-check: handle get-attributes between pre and post event

View File

@@ -32,7 +32,7 @@ endif
# The variable "DISTRELEASE" should be overwritten in rpm spec files with:
# "make DISTRELEASE=%{release}" and "make install DISTRELEASE=%{release}"
VERSION = 2
RELEASE = 30
RELEASE = 32
PATCHLEVEL = 0
DISTRELEASE = build-$(shell date +%Y%m%d)
S390_TOOLS_RELEASE = $(VERSION).$(RELEASE).$(PATCHLEVEL)-$(DISTRELEASE)
@@ -304,7 +304,7 @@ ZFCPDUMP_FLAVOR = zfcpdump
export ZFCPDUMP_DIR ZFCPDUMP_IMAGE ZFCPDUMP_INITRD ZFCPDUMP_FLAVOR
CFLAGS ?= $(DEFAULT_CFLAGS) $(OPT_FLAGS)
CFLAGS_FOR_BUILD ?= $(DEFAULT_CFLAGS) $(OPT_FLAGS)
CFLAGS_FOR_BUILD ?= -std=gnu11 $(DEFAULT_CFLAGS) $(OPT_FLAGS)
CPPFLAGS ?= $(DEFAULT_CPPFLAGS)
LDFLAGS ?= $(DEFAULT_LDFLAGS)
@@ -313,14 +313,14 @@ ALL_CFLAGS = -DS390_TOOLS_RELEASE=$(S390_TOOLS_RELEASE) \
-DS390_TOOLS_DATADIR=$(TOOLS_DATADIR) \
-DS390_TOOLS_SYSCONFDIR=$(SYSCONFDIR) \
-DS390_TOOLS_BINDIR=$(BINDIR) \
$(CFLAGS)
-std=gnu11 $(CFLAGS)
CXXFLAGS ?= $(DEFAULT_CFLAGS) $(OPT_FLAGS)
ALL_CXXFLAGS = -DS390_TOOLS_RELEASE=$(S390_TOOLS_RELEASE) \
-DS390_TOOLS_LIBDIR=$(TOOLS_LIBDIR) \
-DS390_TOOLS_DATADIR=$(TOOLS_DATADIR) \
-DS390_TOOLS_SYSCONFDIR=$(SYSCONFDIR) \
-DS390_TOOLS_BINDIR=$(BINDIR) \
$(CXXFLAGS)
-std=gnu++11 $(CXXFLAGS)
ALL_CPPFLAGS = -I $(rootdir)include $(CPPFLAGS)
ALL_LDFLAGS = $(LDFLAGS)

View File

@@ -355,13 +355,13 @@ PCKMO DES,
.IP \(bu
PCKMO 2key TDES,
.IP \(bu
PCMKO TDES,
PCKMO TDES,
.IP \(bu
PCKMO AES 128bit,
.IP \(bu
PCKMO AES 192bit,
.IP \(bu
PCMKO AES 256bit,
PCKMO AES 256bit,
.IP \(bu
PCKMO ECC P256,
.IP \(bu

View File

@@ -204,10 +204,10 @@ static const char *const pai_str[] = {
[142] = "KDSA EdDSA Sign Ed448 protected key",
[143] = "PCKMO DES",
[144] = "PCKMO 2key TDES",
[145] = "PCMKO TDES",
[145] = "PCKMO TDES",
[146] = "PCKMO AES 128bit",
[147] = "PCKMO AES 192bit",
[148] = "PCMKO AES 256bit",
[148] = "PCKMO AES 256bit",
[149] = "PCKMO ECC P256",
[150] = "PCKMO ECC P384",
[151] = "PCKMO ECC P521",

View File

@@ -3473,6 +3473,7 @@ static struct counters *get_counter(int ctrset, size_t *len)
read_ccerror(cp, *len);
break;
case UTIL_ARCH_MACHINE_TYPE_Z16:
case UTIL_ARCH_MACHINE_TYPE_Z16_A02:
cp = cpumcf_z16_counters;
*len = ARRAY_SIZE(cpumcf_z16_counters);
}

View File

@@ -320,7 +320,7 @@ static void readmap(int fd)
* ring buffer per event, sleep some short time and always read all
* ring buffer for new contents.
*/
static void collect(unsigned long cnt)
static int collect(unsigned long cnt)
{
fd_set r_fds, e_fds, a_fds;
struct pai_event *p;
@@ -328,6 +328,7 @@ static void collect(unsigned long cnt)
int rc, max_fd;
do {
rc = -1;
max_fd = -1;
tv.tv_sec = read_interval / 1000;
tv.tv_usec = (1000 * read_interval) % 1000000;
@@ -357,6 +358,7 @@ static void collect(unsigned long cnt)
}
}
} while (rc != -1 && --cnt > 0);
return rc;
}
static void lookup_event(__u64 evtnum, __u16 ctr, __u64 value)
@@ -449,6 +451,11 @@ static void evt_show(__u64 evtnum, const char *evtsel, struct pai_event_out *ev)
ev->u.s_comm.tid);
break;
case PERF_RECORD_SWITCH:
printf("cs-%s",
(ev->misc & PERF_RECORD_MISC_SWITCH_OUT) ? "out" : "in");
break;
case PERF_RECORD_SWITCH_CPU_WIDE:
if (ev->misc & PERF_RECORD_MISC_SWITCH_OUT) {
short p = PERF_RECORD_MISC_SWITCH_OUT_PREEMPT;
@@ -549,6 +556,9 @@ static int evt_scan(char *fn, unsigned char *buf, size_t len,
offset -= sizeof(__u64);
break;
case PERF_RECORD_SWITCH:
break;
case PERF_RECORD_SWITCH_CPU_WIDE:
memcpy(&ev.u, buf + offset, sizeof(ev.u.s_cs));
offset += sizeof(ev.u.s_cs);
@@ -583,7 +593,7 @@ static int evt_scan(char *fn, unsigned char *buf, size_t len,
break;
default:
printf("unknown header-type %d ", hdr->type);
printf("unknown header-type %d\n", hdr->type);
offset += hdr->size - sizeof(*hdr);
goto bypass;
}
@@ -1115,12 +1125,12 @@ int main(int argc, char **argv)
ev_install(group);
ev_enable();
collect(loop_count);
ch = collect(loop_count);
ev_disable();
ev_deinstall();
ev_dealloc();
return EXIT_SUCCESS;
return ch < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
/* Must be reporting */

View File

@@ -25,7 +25,7 @@ int get_numcpus()
for (i = 0; ; i++) {
/* check whether file exists and is readable */
sprintf(path, "/sys/devices/system/cpu/cpu%d/online", i);
sprintf(path, "/sys/devices/system/cpu/cpu%d", i);
if (access(path, R_OK) == 0)
number++;
else
@@ -45,11 +45,13 @@ int get_num_online_cpus()
int status = 0;
int value_of_onlinefile, rc;
for (i = 0; i <= get_numcpus(); i++) {
for (i = 0; i < get_numcpus(); i++) {
/* check wether file exists and is readable */
sprintf(path, "/sys/devices/system/cpu/cpu%d/online", i);
if (access(path, R_OK) != 0)
if (access(path, R_OK) != 0) {
status++;
continue;
}
filp = fopen(path, "r");
if (!filp)
cpuplugd_exit("Cannot open cpu online file: "
@@ -101,10 +103,8 @@ int hotplug(int cpuid)
cpuid);
return -1;
}
} else {
cpuplugd_error("hotplugging cpu with id %d failed\n", cpuid);
return -1;
}
cpuplugd_debug("cpu with id %d cannot be hotplugged\n", cpuid);
return -1;
}
@@ -135,9 +135,8 @@ int hotunplug(int cpuid)
fclose(filp);
if (state == 0)
return 1;
} else {
cpuplugd_error("unplugging cpu with id %d failed\n", cpuid);
}
cpuplugd_debug("cpu with id %d cannot be hotunplugged\n", cpuid);
return retval;
}
@@ -163,6 +162,8 @@ int is_online(int cpuid)
retval = 0;
}
fclose(filp);
} else {
retval = 1;
}
return retval;
}

View File

@@ -1,7 +1,7 @@
# Common definitions
include ../../common.mak
ALL_CPPFLAGS += -I../include -std=gnu99 -Wno-unused-parameter
ALL_CPPFLAGS += -I../include -Wno-unused-parameter
LDLIBS += -lpthread -lrt
ifneq ($(HAVE_ZLIB),0)
ALL_CPPFLAGS += -DHAVE_ZLIB

View File

@@ -28,6 +28,15 @@
# DEVICE=0.0.4e13
# DELAY_MINUTES=5
#
# Dump on ECKD device (DASD)
#
#ON_PANIC=dump
#DUMP_TYPE=eckd
#DEVICE=0.0.1004
#BOOTPROG=0
#BR_CHR=auto
#
# Dump on fcp device (SCSI Disk)
#

View File

@@ -3,7 +3,7 @@ include ../common.mak
.DEFAULT_GOAL := all
PKGDATADIR := "$(DESTDIR)$(TOOLS_DATADIR)/genprotimg"
PKGDATADIR := "$(TOOLS_DATADIR)/genprotimg"
TESTS :=
SUBDIRS := boot src man
RECURSIVE_TARGETS := all-recursive install-recursive clean-recursive
@@ -11,8 +11,8 @@ RECURSIVE_TARGETS := all-recursive install-recursive clean-recursive
all: all-recursive
install: install-recursive
$(INSTALL) -d -m 755 "$(PKGDATADIR)"
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 samples/check_hostkeydoc "$(PKGDATADIR)"
$(INSTALL) -d -m 755 "$(DESTDIR)$(PKGDATADIR)"
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 samples/check_hostkeydoc "$(DESTDIR)$(PKGDATADIR)"
clean: clean-recursive

View File

@@ -7,7 +7,7 @@ DEBUG_FILES := $(addsuffix .debug,$(FILES))
ifeq ($(HOST_ARCH),s390x)
ZIPL_DIR := $(rootdir)/zipl
ZIPL_BOOT_DIR := $(ZIPL_DIR)/boot
PKGDATADIR := $(DESTDIR)$(TOOLS_DATADIR)/genprotimg
PKGDATADIR := $(TOOLS_DATADIR)/genprotimg
INCLUDE_PATHS := $(ZIPL_BOOT_DIR) $(ZIPL_DIR)/include $(rootdir)/include
INCLUDE_PARMS := $(addprefix -I,$(INCLUDE_PATHS))
@@ -86,9 +86,9 @@ stage3b.elf: head.o $(ZIPL_OBJS)
@chmod a-x $@
install: stage3a.bin stage3b_reloc.bin
$(INSTALL) -d -m 755 "$(PKGDATADIR)"
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 stage3a.bin "$(PKGDATADIR)"
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 stage3b_reloc.bin "$(PKGDATADIR)"
$(INSTALL) -d -m 755 "$(DESTDIR)$(PKGDATADIR)"
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 stage3a.bin "$(DESTDIR)$(PKGDATADIR)"
$(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 stage3b_reloc.bin "$(DESTDIR)$(PKGDATADIR)"
else
# Don't generate the dependency files (see `common.mak` for the

View File

@@ -4,7 +4,7 @@
#
# Sample script to verify that a host key document is genuine by
# verifying the issuer, the validity date and the signature.
# Optionally verify the full trust chain using a CA certficate.
# Optionally verify the full trust chain using a CA certificate.
#
# Sample invocation:
#
@@ -15,31 +15,33 @@
# s390-tools is free software; you can redistribute it and/or modify
# it under the terms of the MIT license. See LICENSE for details.
# Allocate temporary files
ISSUER_PUBKEY_FILE=$(mktemp)
SIGNATURE_FILE=$(mktemp)
BODY_FILE=$(mktemp)
ISSUER_DN_FILE=$(mktemp)
SUBJECT_DN_FILE=$(mktemp)
DEF_ISSUER_DN_FILE=$(mktemp)
DEF_ISSUER_ARMONK_DN_FILE=$(mktemp)
DEF_ISSUER_POUGHKEEPSIE_DN_FILE=$(mktemp)
CANONICAL_ISSUER_DN_FILE=$(mktemp)
CRL_SERIAL_FILE=$(mktemp)
# Cleanup on exit
cleanup()
{
rm -f $ISSUER_PUBKEY_FILE $SIGNATURE_FILE $BODY_FILE \
$ISSUER_DN_FILE $SUBJECT_DN_FILE $DEF_ISSUER_DN_FILE \
$CANONICAL_ISSUER_DN_FILE $CRL_SERIAL_FILE
rm -f "$ISSUER_PUBKEY_FILE" "$SIGNATURE_FILE" "$BODY_FILE" \
"$ISSUER_DN_FILE" "$SUBJECT_DN_FILE" "$DEF_ISSUER_ARMONK_DN_FILE" "$DEF_ISSUER_POUGHKEEPSIE_DN_FILE" \
"$CANONICAL_ISSUER_DN_FILE" "$CRL_SERIAL_FILE"
}
trap cleanup EXIT
# Enhanced error checking for bash
if [ -n "${BASH}" ]
then
if [ -n "${BASH}" ]; then
# shellcheck disable=SC3040
set -o posix
# shellcheck disable=SC3040
set -o pipefail
# shellcheck disable=SC3040
set -o nounset
fi
set -e
@@ -47,8 +49,8 @@ set -e
# Usage
usage()
{
cat <<-EOF
Usage: `basename $1` [-d] [-c CA-cert] [-r CRL] host-key-doc signing-key-cert
cat <<-EOF
Usage: $(basename "$1") [-d] [-c CA-cert] [-r CRL] host-key-doc signing-key-cert
Verify an IBM Secure Execution host key document against
a signing key.
@@ -71,8 +73,7 @@ check_verify_chain()
{
# Verify certificate chain in case a CA certificate file/bundle
# was specified on the command line.
if [ $# = 1 ]
then
if [ -z "$2" ]; then
cat >&2 <<-EOF
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
No CA certificate specified! Skipping trust chain verification.
@@ -80,37 +81,37 @@ Make sure that '$1' is a valid certificate.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
EOF
else
openssl verify -crl_download -crl_check $2 &&
openssl verify -crl_download -crl_check -untrusted $2 $1 ||
exit 1
openssl verify -crl_download -crl_check "$2" &&
openssl verify -crl_download -crl_check -untrusted "$2" "$1" ||
exit 1
fi
}
extract_pubkey()
{
openssl x509 -in $1 -pubkey -noout > $2
openssl x509 -in "$1" -pubkey -noout >"$2"
}
extract_signature()
{
# Assuming that the last field is the signature
SIGOFFSET=$(openssl asn1parse -in $1 | tail -1 | cut -d : -f 1)
SIGOFFSET=$(openssl asn1parse -in "$1" | tail -1 | cut -d : -f 1)
openssl asn1parse -in $1 -out $2 -strparse $SIGOFFSET -noout
openssl asn1parse -in "$1" -out "$2" -strparse "$SIGOFFSET" -noout
}
extract_body()
{
# Assuming that the first field is the full cert body
SIGOFFSET=$(openssl asn1parse -in $1 | head -2 | tail -1 | cut -d : -f 1)
SIGOFFSET=$(openssl asn1parse -in "$1" | head -2 | tail -1 | cut -d : -f 1)
openssl asn1parse -in $1 -out $2 -strparse $SIGOFFSET -noout
openssl asn1parse -in "$1" -out "$2" -strparse "$SIGOFFSET" -noout
}
verify_signature()
{
# Assuming that the signature algorithm is SHA512 with RSA
openssl sha512 -verify $1 -signature $2 $3
openssl sha512 -verify "$1" -signature "$2" "$3"
}
canonical_dn()
@@ -120,18 +121,30 @@ canonical_dn()
DNTYPE=$3
OUTPUT=$4
openssl $OBJTYPE -in $OBJ -$DNTYPE -noout -nameopt multiline \
| sort | grep -v $DNTYPE= > $OUTPUT
openssl "$OBJTYPE" -in "$OBJ" -"$DNTYPE" -noout -nameopt multiline |
LC_ALL=C sort | grep -v "$DNTYPE"= >"$OUTPUT"
}
default_issuer()
default_issuer_armonk()
{
cat <<-EOF
commonName = International Business Machines Corporation
countryName = US
localityName = Armonk
organizationName = International Business Machines Corporation
organizationalUnitName = Key Signing Service
stateOrProvinceName = New York
EOF
}
default_issuer_pougkeepsie()
{
cat <<-EOF
commonName = International Business Machines Corporation
countryName = US
localityName = Poughkeepsie
organizationalUnitName = Key Signing Service
organizationName = International Business Machines Corporation
organizationalUnitName = Key Signing Service
stateOrProvinceName = New York
EOF
}
@@ -141,42 +154,37 @@ EOF
# stripping off the prefix
verify_default_issuer()
{
default_issuer > $DEF_ISSUER_DN_FILE
default_issuer_pougkeepsie >"$DEF_ISSUER_POUGHKEEPSIE_DN_FILE"
default_issuer_armonk >"$DEF_ISSUER_ARMONK_DN_FILE"
sed "s/\(^[ ]*organizationalUnitName[ ]*=[ ]*\).*\(Key Signing Service$\)/\1\2/" \
$ISSUER_DN_FILE > $CANONICAL_ISSUER_DN_FILE
"$ISSUER_DN_FILE" >"$CANONICAL_ISSUER_DN_FILE"
if ! diff $CANONICAL_ISSUER_DN_FILE $DEF_ISSUER_DN_FILE
then
if ! {
diff "$CANONICAL_ISSUER_DN_FILE" "$DEF_ISSUER_POUGHKEEPSIE_DN_FILE" ||
diff "$CANONICAL_ISSUER_DN_FILE" "$DEF_ISSUER_ARMONK_DN_FILE"
} >/dev/null 2>&1; then
echo Incorrect default issuer >&2 && exit 1
fi
}
verify_issuer_files()
{
if [ $1 -eq 1 ]
then
verify_default_issuer
fi
if diff $ISSUER_DN_FILE $SUBJECT_DN_FILE
then
echo Issuer verification OK
else
echo Issuer verification failed >&2 && exit 1
if [ "$1" -eq 1 ]; then
verify_default_issuer
fi
}
cert_time()
{
DATE=$(openssl x509 -in $1 -$2 -noout | sed "s/^.*=//")
DATE=$(openssl x509 -in "$1" -"$2" -noout | sed "s/^.*=//")
date -d "$DATE" +%s
}
crl_time()
{
DATE=$(openssl crl -in $1 -$2 -noout | sed "s/^.*=//")
DATE=$(openssl crl -in "$1" -"$2" -noout | sed "s/^.*=//")
date -d "$DATE" +%s
}
@@ -188,8 +196,7 @@ verify_dates()
MSG="${3:-Certificate}"
NOW=$(date +%s)
if [ $START -le $NOW -a $NOW -le $END ]
then
if [ "$START" -le "$NOW" ] && [ "$NOW" -le "$END" ]; then
echo "${MSG} dates are OK"
else
echo "${MSG} date verification failed" >&2 && exit 1
@@ -198,22 +205,21 @@ verify_dates()
crl_serials()
{
openssl crl -in $1 -text -noout | \
grep "Serial Number" > $CRL_SERIAL_FILE
openssl crl -in "$1" -text -noout |
grep "Serial Number" >"$CRL_SERIAL_FILE"
}
check_serial()
{
CERT_SERIAL=$(openssl x509 -in $1 -noout -serial | cut -d = -f 2)
CERT_SERIAL=$(openssl x509 -in "$1" -noout -serial | cut -d = -f 2)
grep -q $CERT_SERIAL $CRL_SERIAL_FILE
grep -q "$CERT_SERIAL" "$CRL_SERIAL_FILE"
}
check_file()
{
[ $# = 0 ] ||
[ -e "$1" ] ||
(echo "File '$1' not found" >&2 && exit 1)
(echo "File '$1' not found" >&2 && exit 1)
}
# check args
@@ -221,28 +227,25 @@ CRL_FILE=
CA_FILE=
CHECK_DEFAULT_ISSUER=1
args=$(getopt -qu "dr:c:h" $*)
if [ $? = 0 ]
then
set -- $args
while [ $1 != "" ]
do
case $1 in
-d) CHECK_DEFAULT_ISSUER=0; shift;;
-r) CRL_FILE=$2; shift 2;;
-c) CA_FILE=$2; shift 2;;
-h) usage $0; exit 0;;
--) shift; break;;
esac
done
else
usage $0 >&2
exit 1
fi
while getopts 'dr:c:h' opt; do
case $opt in
d) CHECK_DEFAULT_ISSUER=0 ;;
r) CRL_FILE=$OPTARG ;;
c) CA_FILE=$OPTARG ;;
h)
usage "$0"
exit 0
;;
?)
usage "$0"
exit 1
;;
esac
done
shift "$((OPTIND - 1))"
if [ $# -ne 2 ]
then
usage $0 >&2
if [ $# -ne 2 ]; then
usage "$0" >&2
exit 1
fi
@@ -250,51 +253,51 @@ HKD_FILE=$1
HKSK_FILE=$2
# Check whether all specified files exist
check_file $HKD_FILE
check_file $HKSK_FILE
check_file $CA_FILE
check_file $CRL_FILE
check_file "$HKD_FILE"
check_file "$HKSK_FILE"
# CA and CRL are optional arguments
[ -n "$CA_FILE" ] && check_file "$CA_FILE"
[ -n "$CRL_FILE" ] && check_file "$CRL_FILE"
# Check trust chain
check_verify_chain $HKSK_FILE $CA_FILE
check_verify_chain "$HKSK_FILE" "$CA_FILE"
# Verify host key document signature
echo -n "Checking host key document signature: "
extract_pubkey $HKSK_FILE $ISSUER_PUBKEY_FILE &&
extract_signature $HKD_FILE $SIGNATURE_FILE &&
extract_body $HKD_FILE $BODY_FILE &&
verify_signature $ISSUER_PUBKEY_FILE $SIGNATURE_FILE $BODY_FILE ||
exit 1
printf "Checking host key document signature: "
extract_pubkey "$HKSK_FILE" "$ISSUER_PUBKEY_FILE" &&
extract_signature "$HKD_FILE" "$SIGNATURE_FILE" &&
extract_body "$HKD_FILE" "$BODY_FILE" &&
verify_signature "$ISSUER_PUBKEY_FILE" "$SIGNATURE_FILE" "$BODY_FILE" ||
exit 1
# Verify the issuer
canonical_dn x509 $HKD_FILE issuer $ISSUER_DN_FILE
canonical_dn x509 $HKSK_FILE subject $SUBJECT_DN_FILE
canonical_dn x509 "$HKD_FILE" issuer "$ISSUER_DN_FILE"
canonical_dn x509 "$HKSK_FILE" subject "$SUBJECT_DN_FILE"
verify_issuer_files $CHECK_DEFAULT_ISSUER
# Verify dates
verify_dates $(cert_time $HKD_FILE startdate) $(cert_time $HKD_FILE enddate)
verify_dates "$(cert_time "$HKD_FILE" startdate)" "$(cert_time "$HKD_FILE" enddate)"
# Check CRL if specified
if [ -n "$CRL_FILE" ]
then
echo -n "Checking CRL signature: "
extract_signature $CRL_FILE $SIGNATURE_FILE &&
extract_body $CRL_FILE $BODY_FILE &&
verify_signature $ISSUER_PUBKEY_FILE $SIGNATURE_FILE $BODY_FILE ||
exit 1
if [ -n "$CRL_FILE" ]; then
printf "Checking CRL signature: "
extract_signature "$CRL_FILE" "$SIGNATURE_FILE" &&
extract_body "$CRL_FILE" "$BODY_FILE" &&
verify_signature "$ISSUER_PUBKEY_FILE" "$SIGNATURE_FILE" "$BODY_FILE" ||
exit 1
echo -n "CRL "
canonical_dn crl $CRL_FILE issuer $ISSUER_DN_FILE
canonical_dn x509 $HKSK_FILE subject $SUBJECT_DN_FILE
printf "CRL "
canonical_dn crl "$CRL_FILE" issuer "$ISSUER_DN_FILE"
canonical_dn x509 "$HKSK_FILE" subject "$SUBJECT_DN_FILE"
verify_issuer_files $CHECK_DEFAULT_ISSUER
verify_dates $(crl_time $CRL_FILE lastupdate) $(crl_time $CRL_FILE nextupdate) 'CRL'
verify_dates "$(crl_time "$CRL_FILE" lastupdate)" "$(crl_time "$CRL_FILE" nextupdate)" 'CRL'
crl_serials $CRL_FILE
check_serial $HKD_FILE &&
echo "Certificate is revoked, do not use it anymore!" >&2 &&
exit 1
crl_serials "$CRL_FILE"
check_serial "$HKD_FILE" &&
echo "Certificate is revoked, do not use it anymore!" >&2 &&
exit 1
fi
# We made it
echo All checks reqested for \'$HKD_FILE\' were successful
echo All checks requested for \'"$HKD_FILE"\' were successful

View File

@@ -3,7 +3,7 @@ include ../../common.mak
bin_PROGRAM = genprotimg
PKGDATADIR ?= "$(DESTDIR)$(TOOLS_DATADIR)/genprotimg"
PKGDATADIR ?= "$(TOOLS_DATADIR)/genprotimg"
SRC_DIR := $(dir $(realpath $(firstword $(MAKEFILE_LIST))))
TOP_SRCDIR := $(SRC_DIR)/../
ROOT_DIR = $(TOP_SRC_DIR)/../../
@@ -27,7 +27,7 @@ $(bin_PROGRAM)_SRCS := $(bin_PROGRAM).c pv/pv_stage3.c pv/pv_image.c \
$(NULL)
$(bin_PROGRAM)_OBJS := $($(bin_PROGRAM)_SRCS:.c=.o)
ALL_CFLAGS += -std=gnu11 -DPKGDATADIR=$(PKGDATADIR) \
ALL_CFLAGS += -DPKGDATADIR=$(PKGDATADIR) \
$(GLIB2_CFLAGS) $(LIBCRYPTO_CFLAGS) $(LIBCURL_CFLAGS) \
-DOPENSSL_API_COMPAT=0x10100000L \
$(WARNINGS) \

View File

@@ -17,7 +17,8 @@
/* IBM signing key subject */
#define PV_IBM_Z_SUBJECT_COMMON_NAME "International Business Machines Corporation"
#define PV_IBM_Z_SUBJECT_COUNTRY_NAME "US"
#define PV_IBM_Z_SUBJECT_LOCALITY_NAME "Poughkeepsie"
#define PV_IBM_Z_SUBJECT_LOCALITY_NAME_POUGHKEEPSIE "Poughkeepsie"
#define PV_IBM_Z_SUBJECT_LOCALITY_NAME_ARMONK "Armonk"
#define PV_IBM_Z_SUBJECT_ORGANIZATIONONAL_UNIT_NAME_SUFFIX "Key Signing Service"
#define PV_IBM_Z_SUBJECT_ORGANIZATION_NAME "International Business Machines Corporation"
#define PV_IBM_Z_SUBJECT_STATE "New York"

View File

@@ -664,62 +664,9 @@ static gboolean x509_name_data_by_nid_equal(X509_NAME *name, gint nid,
return memcmp(data, y, data_len) == 0;
}
static gboolean own_X509_NAME_ENTRY_equal(const X509_NAME_ENTRY *x,
const X509_NAME_ENTRY *y)
{
const ASN1_OBJECT *x_obj = X509_NAME_ENTRY_get_object(x);
const ASN1_STRING *x_data = X509_NAME_ENTRY_get_data(x);
const ASN1_OBJECT *y_obj = X509_NAME_ENTRY_get_object(y);
const ASN1_STRING *y_data = X509_NAME_ENTRY_get_data(y);
gint x_len = ASN1_STRING_length(x_data);
gint y_len = ASN1_STRING_length(y_data);
if (x_len < 0 || x_len != y_len)
return FALSE;
/* ASN1_STRING_cmp(x_data, y_data) == 0 doesn't work because it also
* compares the type, which is sometimes different.
*/
return OBJ_cmp(x_obj, y_obj) == 0 &&
memcmp(ASN1_STRING_get0_data(x_data),
ASN1_STRING_get0_data(y_data),
(unsigned long)x_len) == 0;
}
static gboolean own_X509_NAME_equal(const X509_NAME *x, const X509_NAME *y)
{
gint x_count = X509_NAME_entry_count(x);
gint y_count = X509_NAME_entry_count(y);
if (x != y && (!x || !y))
return FALSE;
if (x_count != y_count)
return FALSE;
for (gint i = 0; i < x_count; i++) {
const X509_NAME_ENTRY *entry_i = X509_NAME_get_entry(x, i);
gboolean entry_found = FALSE;
for (gint j = 0; j < y_count; j++) {
const X509_NAME_ENTRY *entry_j =
X509_NAME_get_entry(y, j);
if (own_X509_NAME_ENTRY_equal(entry_i, entry_j)) {
entry_found = TRUE;
break;
}
}
if (!entry_found)
return FALSE;
}
return TRUE;
}
/* Checks whether the subject of @cert is a IBM signing key subject. For this we
* must check that the subject is equal to: 'C = US, ST = New York, L =
* Poughkeepsie, O = International Business Machines Corporation, CN =
* Poughkeepsie or Armonk, O = International Business Machines Corporation, CN =
* International Business Machines Corporation' and the organization unit (OUT)
* must end with the suffix ' Key Signing Service'.
*/
@@ -743,8 +690,10 @@ static gboolean has_ibm_signing_subject(X509 *cert)
PV_IBM_Z_SUBJECT_STATE))
return FALSE;
if (!x509_name_data_by_nid_equal(subject, NID_localityName,
PV_IBM_Z_SUBJECT_LOCALITY_NAME))
if (!(x509_name_data_by_nid_equal(subject, NID_localityName,
PV_IBM_Z_SUBJECT_LOCALITY_NAME_POUGHKEEPSIE) ||
x509_name_data_by_nid_equal(subject, NID_localityName,
PV_IBM_Z_SUBJECT_LOCALITY_NAME_ARMONK)))
return FALSE;
if (!x509_name_data_by_nid_equal(subject, NID_organizationName,
@@ -806,6 +755,39 @@ static X509_NAME *x509_name_reorder_attributes(const X509_NAME *name, const gint
return g_steal_pointer(&ret);
}
/** Replace locality 'Armonk' with 'Pougkeepsie'. If Armonk was not set return
* `NULL`.
*/
static X509_NAME *x509_armonk_locality_fixup(const X509_NAME *name)
{
g_autoptr(X509_NAME) ret = NULL;
int pos;
/* Check if ``L=Armonk`` */
if (!x509_name_data_by_nid_equal((X509_NAME *)name, NID_localityName,
PV_IBM_Z_SUBJECT_LOCALITY_NAME_ARMONK))
return NULL;
ret = X509_NAME_dup((X509_NAME *)name);
if (!ret)
g_abort();
pos = X509_NAME_get_index_by_NID(ret, NID_localityName, -1);
if (pos == -1)
return NULL;
X509_NAME_ENTRY_free(X509_NAME_delete_entry(ret, pos));
/* Create a new name entry at the same position as before */
if (X509_NAME_add_entry_by_NID(
ret, NID_localityName, MBSTRING_UTF8,
(const unsigned char *)&PV_IBM_Z_SUBJECT_LOCALITY_NAME_POUGHKEEPSIE,
sizeof(PV_IBM_Z_SUBJECT_LOCALITY_NAME_POUGHKEEPSIE) - 1, pos, 0) != 1)
return NULL;
return g_steal_pointer(&ret);
}
/* In RFC 5280 the attributes of a (subject/issuer) name is not mandatory
* ordered. The problem is that our certificates are not consistent in the order
* (see https://tools.ietf.org/html/rfc5280#section-4.1.2.4 for details).
@@ -828,24 +810,10 @@ X509_NAME *c2b_name(const X509_NAME *name)
return X509_NAME_dup((X509_NAME *)name);
}
/* Verify that: subject(issuer) == issuer(crl) and SKID(issuer) == AKID(crl) */
/* Verify that SKID(issuer) == AKID(crl) if available */
static gint check_crl_issuer(X509_CRL *crl, X509 *issuer, GError **err)
{
const X509_NAME *crl_issuer = X509_CRL_get_issuer(crl);
const X509_NAME *issuer_subject = X509_get_subject_name(issuer);
AUTHORITY_KEYID *akid = NULL;
if (!own_X509_NAME_equal(issuer_subject, crl_issuer)) {
g_autofree char *issuer_subject_str = X509_NAME_oneline(issuer_subject,
NULL, 0);
g_autofree char *crl_issuer_str = X509_NAME_oneline(crl_issuer, NULL, 0);
g_set_error(err, PV_CRYPTO_ERROR,
PV_CRYPTO_ERROR_CRL_SUBJECT_ISSUER_MISMATCH,
_("issuer mismatch:\n%s\n%s"),
issuer_subject_str, crl_issuer_str);
return -1;
}
g_autoptr(AUTHORITY_KEYID) akid = NULL;
/* If AKID(@crl) is specified it must match with SKID(@issuer) */
akid = X509_CRL_get_ext_d2i(crl, NID_authority_key_identifier, NULL, NULL);
@@ -881,7 +849,6 @@ gint check_crl_valid_for_cert(X509_CRL *crl, X509 *cert,
return -1;
}
/* check that the @crl issuer matches with the subject name of @cert*/
if (check_crl_issuer(crl, cert, err) < 0)
return -1;
@@ -910,6 +877,60 @@ gint check_crl_valid_for_cert(X509_CRL *crl, X509 *cert,
return 0;
}
/* This function contains work-arounds for some known subject(CRT)<->issuer(CRL)
* issues.
*/
static STACK_OF_X509_CRL *quirk_X509_STORE_ctx_get1_crls(X509_STORE_CTX *ctx,
const X509_NAME *subject, GError **err)
{
g_autoptr(X509_NAME) fixed_subject = NULL;
g_autoptr(STACK_OF_X509_CRL) ret = NULL;
ret = Pv_X509_STORE_CTX_get1_crls(ctx, subject);
if (ret && sk_X509_CRL_num(ret) > 0)
return g_steal_pointer(&ret);
/* Workaround to fix the mismatch between issuer name of the * IBM
* signing CRLs and the IBM signing key subject name. Locality name has
* changed from Poughkeepsie to Armonk.
*/
fixed_subject = x509_armonk_locality_fixup(subject);
/* Was the locality replaced? */
if (fixed_subject) {
X509_NAME *tmp;
sk_X509_CRL_free(ret);
ret = Pv_X509_STORE_CTX_get1_crls(ctx, fixed_subject);
if (ret && sk_X509_CRL_num(ret) > 0)
return g_steal_pointer(&ret);
/* Workaround to fix the ordering mismatch between issuer name
* of the IBM signing CRLs and the IBM signing key subject name.
*/
tmp = fixed_subject;
fixed_subject = c2b_name(fixed_subject);
X509_NAME_free(tmp);
sk_X509_CRL_free(ret);
ret = Pv_X509_STORE_CTX_get1_crls(ctx, fixed_subject);
if (ret && sk_X509_CRL_num(ret) > 0)
return g_steal_pointer(&ret);
X509_NAME_free(fixed_subject);
fixed_subject = NULL;
}
/* Workaround to fix the ordering mismatch between issuer name of the
* IBM signing CRLs and the IBM signing key subject name.
*/
fixed_subject = c2b_name(subject);
sk_X509_CRL_free(ret);
ret = Pv_X509_STORE_CTX_get1_crls(ctx, fixed_subject);
if (ret && sk_X509_CRL_num(ret) > 0)
return g_steal_pointer(&ret);
g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_NO_CRL, _("no CRL found"));
return NULL;
}
/* Given a certificate @cert try to find valid revocation lists in @ctx. If no
* valid CRL was found NULL is returned.
*/
@@ -927,20 +948,9 @@ STACK_OF_X509_CRL *store_ctx_find_valid_crls(X509_STORE_CTX *ctx, X509 *cert,
return NULL;
}
ret = X509_STORE_CTX_get1_crls(ctx, subject);
if (!ret) {
/* Workaround to fix the mismatch between issuer name of the
* IBM Z signing CRLs and the IBM Z signing key subject name.
*/
g_autoptr(X509_NAME) broken_subject = c2b_name(subject);
ret = X509_STORE_CTX_get1_crls(ctx, broken_subject);
if (!ret) {
g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_NO_CRL,
_("no CRL found"));
return NULL;
}
}
ret = quirk_X509_STORE_ctx_get1_crls(ctx, subject, err);
if (!ret)
return NULL;
/* Filter out non-valid CRLs for @cert */
for (gint i = 0; i < sk_X509_CRL_num(ret); i++) {
@@ -1328,32 +1338,14 @@ gint check_chain_parameters(const STACK_OF_X509 *chain,
/* It's almost the same as X509_check_issed from OpenSSL does except that we
* don't check the key usage of the potential issuer. This means we check:
* 1. issuer_name(cert) == subject_name(issuer)
* 2. Check whether the akid(cert) (if available) matches the issuer skid
* 3. Check that the cert algrithm matches the subject algorithm
* 4. Verify the signature of certificate @cert is using the public key of
* 1. Check whether the akid(cert) (if available) matches the issuer skid
* 2. Check that the cert algrithm matches the subject algorithm
* 3. Verify the signature of certificate @cert is using the public key of
* @issuer.
*/
static gint check_host_key_issued(X509 *cert, X509 *issuer, GError **err)
{
const X509_NAME *issuer_subject = X509_get_subject_name(issuer);
const X509_NAME *cert_issuer = X509_get_issuer_name(cert);
AUTHORITY_KEYID *akid = NULL;
/* We cannot use X509_NAME_cmp() because it considers the order of the
* X509_NAME_Entries.
*/
if (!own_X509_NAME_equal(issuer_subject, cert_issuer)) {
g_autofree char *issuer_subject_str =
X509_NAME_oneline(issuer_subject, NULL, 0);
g_autofree char *cert_issuer_str =
X509_NAME_oneline(cert_issuer, NULL, 0);
g_set_error(err, PV_CRYPTO_ERROR,
PV_CRYPTO_ERROR_CERT_SUBJECT_ISSUER_MISMATCH,
_("Subject issuer mismatch:\n'%s'\n'%s'"),
issuer_subject_str, cert_issuer_str);
return -1;
}
g_autoptr(AUTHORITY_KEYID) akid = NULL;
akid = X509_get_ext_d2i(cert, NID_authority_key_identifier, NULL, NULL);
if (akid && X509_check_akid(issuer, akid) != X509_V_OK) {
@@ -1834,14 +1826,12 @@ static gint __encrypt_decrypt_bio(const struct cipher_parms *parms, BIO *b_in,
g_assert(out_len >= 0);
num_bytes_written = BIO_write(b_out, out_buf, out_len);
if (num_bytes_written < 0) {
if (num_bytes_written != out_len) {
g_set_error(err, PV_CRYPTO_ERROR,
PV_CRYPTO_ERROR_INTERNAL,
_("Failed to write"));
return -1;
}
g_assert(num_bytes_written == out_len);
tmp_size_out += (guint)num_bytes_written;
/* Set new tweak value. Please keep in mind that the

View File

@@ -75,6 +75,7 @@ void x509_pair_free(x509_pair *pair);
/* Register auto cleanup functions */
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(ASN1_INTEGER, ASN1_INTEGER_free)
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(ASN1_OCTET_STRING, ASN1_OCTET_STRING_free)
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(AUTHORITY_KEYID, AUTHORITY_KEYID_free)
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(BIGNUM, BN_free)
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(BIO, BIO_free_all)
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(BN_CTX, BN_CTX_free)

View File

@@ -26,6 +26,17 @@
#define DF_S390_EM_STR "DUMP_END"
#define DF_S390_CPU_MAX 512
#define DF_S390_MAGIC_BLK_ECKD 3
#define DF_S390_DUMPER_MAGIC_SIZE 7
#define DF_S390_DUMPER_MAGIC32 "ZECKD31"
#define DF_S390_DUMPER_MAGIC64 "ZECKD64"
#define DF_S390_DUMPER_MAGIC_EXT "XECKD64"
#define DF_S390_DUMPER_MAGIC32_FBA "ZDFBA31"
#define DF_S390_DUMPER_MAGIC64_FBA "ZDFBA64"
#define DF_S390_DUMPER_MAGIC_FBA_EXT "XDFBA64"
#define DF_S390_DUMPER_MAGIC_MV "ZMULT64"
#define DF_S390_DUMPER_MAGIC_MV_EXT "XMULT64"
#define OLD_DUMPER_HEX_INSTR1 "\x0d\x10\x47\xf0" /* BASR + 1st halfword of BC */
#define OLD_DUMPER_HEX_INSTR2 "\x0d\xd0" /* BASR 13,0 */
/*
* Architecture of dumped system

View File

@@ -27,6 +27,7 @@ enum util_arch_machine_type {
UTIL_ARCH_MACHINE_TYPE_Z15 = 8561,
UTIL_ARCH_MACHINE_TYPE_Z15_T02 = 8562,
UTIL_ARCH_MACHINE_TYPE_Z16 = 3931,
UTIL_ARCH_MACHINE_TYPE_Z16_A02 = 3932,
};
int util_arch_machine_type(void);

View File

@@ -40,6 +40,7 @@
#define LV_COMPAT_CYL 0xFFFE
#define VTOC_ERROR "VTOC error:"
#define MAX_VTOC_ENTRIES 9 /* max number of VTOC labels for cdl formatted DASD */
typedef struct ttr
{

View File

@@ -16,7 +16,8 @@
#define PV_IBM_Z_SUBJECT_COMMON_NAME "International Business Machines Corporation"
#define PV_IBM_Z_SUBJECT_COUNTRY_NAME "US"
#define PV_IBM_Z_SUBJECT_LOCALITY_NAME "Poughkeepsie"
#define PV_IBM_Z_SUBJECT_LOCALITY_NAME_POUGHKEEPSIE "Poughkeepsie"
#define PV_IBM_Z_SUBJECT_LOCALITY_NAME_ARMONK "Armonk"
#define PV_IBM_Z_SUBJECT_ORGANIZATIONAL_UNIT_NAME_SUFFIX "Key Signing Service"
#define PV_IBM_Z_SUBJECT_ORGANIZATION_NAME "International Business Machines Corporation"
#define PV_IBM_Z_SUBJECT_STATE "New York"

View File

@@ -16,6 +16,7 @@
#include <openssl/ssl.h>
#include <json-c/json.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <curl/curl.h>

View File

@@ -21,8 +21,7 @@ WARNINGS := -Wall -Wextra -Wshadow \
-Wno-unused-function -Wno-unused-parameter -Wno-unused-variable \
$(NULL)
ALL_CFLAGS += -std=gnu11 \
-DOPENSSL_API_COMPAT=0x10101000L \
ALL_CFLAGS += -DOPENSSL_API_COMPAT=0x10101000L \
$(GLIB2_CFLAGS) \
$(LIBCRYPTO_CFLAGS) \
$(LIBCURL_CFLAGS) \

View File

@@ -857,7 +857,7 @@ static gboolean x509_name_data_by_nid_equal(X509_NAME *name, int nid, const char
/* Checks whether the subject of @cert is a IBM signing key subject. For this we
* must check that the subject is equal to: 'C = US, ST = New York, L =
* Poughkeepsie, O = International Business Machines Corporation, CN =
* Poughkeepsie or Armonk, O = International Business Machines Corporation, CN =
* International Business Machines Corporation' and the organization unit (OUT)
* must end with the suffix ' Key Signing Service'.
*/
@@ -879,7 +879,10 @@ static gboolean has_ibm_signing_subject(X509 *cert)
if (!x509_name_data_by_nid_equal(subject, NID_stateOrProvinceName, PV_IBM_Z_SUBJECT_STATE))
return FALSE;
if (!x509_name_data_by_nid_equal(subject, NID_localityName, PV_IBM_Z_SUBJECT_LOCALITY_NAME))
if (!(x509_name_data_by_nid_equal(subject, NID_localityName,
PV_IBM_Z_SUBJECT_LOCALITY_NAME_POUGHKEEPSIE) ||
x509_name_data_by_nid_equal(subject, NID_localityName,
PV_IBM_Z_SUBJECT_LOCALITY_NAME_ARMONK)))
return FALSE;
if (!x509_name_data_by_nid_equal(subject, NID_organizationName,
@@ -1085,10 +1088,9 @@ static int check_signature_algo_match(const EVP_PKEY *pkey, const X509 *subject,
/* It's almost the same as X509_check_issed from OpenSSL does except that we
* don't check the key usage of the potential issuer. This means we check:
* 1. issuer_name(cert) == subject_name(issuer)
* 2. Check whether the akid(cert) (if available) matches the issuer skid
* 3. Check that the cert algrithm matches the subject algorithm
* 4. Verify the signature of certificate @cert is using the public key of
* 1. Check whether the akid(cert) (if available) matches the issuer skid
* 2. Check that the cert algrithm matches the subject algorithm
* 3. Verify the signature of certificate @cert is using the public key of
* @issuer.
*/
static int check_host_key_issued(X509 *cert, X509 *issuer, GError **error)
@@ -1097,19 +1099,6 @@ static int check_host_key_issued(X509 *cert, X509 *issuer, GError **error)
const X509_NAME *cert_issuer = X509_get_issuer_name(cert);
g_autoptr(AUTHORITY_KEYID) akid = NULL;
/* We cannot use X509_NAME_cmp() because it considers the order of the
* X509_NAME_Entries.
*/
if (!own_X509_NAME_equal(issuer_subject, cert_issuer)) {
g_autofree char *issuer_subject_str = pv_X509_NAME_oneline(issuer_subject);
g_autofree char *cert_issuer_str = pv_X509_NAME_oneline(cert_issuer);
g_set_error(error, PV_CERT_ERROR, PV_CERT_ERROR_CERT_SUBJECT_ISSUER_MISMATCH,
_("Subject issuer mismatch:\n'%s'\n'%s'"), issuer_subject_str,
cert_issuer_str);
return -1;
}
akid = X509_get_ext_d2i(cert, NID_authority_key_identifier, NULL, NULL);
if (akid && X509_check_akid(issuer, akid) != X509_V_OK) {
g_set_error(error, PV_CERT_ERROR, PV_CERT_ERROR_SKID_AKID_MISMATCH,
@@ -1286,21 +1275,10 @@ int pv_verify_cert(X509_STORE_CTX *ctx, X509 *cert, GError **error)
return 0;
}
/* Verify that: subject(issuer) == issuer(crl) and SKID(issuer) == AKID(crl) */
/* Verify that SKID(issuer) == AKID(crl) */
static int check_crl_issuer(X509_CRL *crl, X509 *issuer, GError **error)
{
const X509_NAME *crl_issuer = X509_CRL_get_issuer(crl);
const X509_NAME *issuer_subject = X509_get_subject_name(issuer);
AUTHORITY_KEYID *akid = NULL;
if (!own_X509_NAME_equal(issuer_subject, crl_issuer)) {
g_autofree char *issuer_subject_str = pv_X509_NAME_oneline(issuer_subject);
g_autofree char *crl_issuer_str = pv_X509_NAME_oneline(crl_issuer);
g_set_error(error, PV_CERT_ERROR, PV_CERT_ERROR_CRL_SUBJECT_ISSUER_MISMATCH,
_("issuer mismatch:\n%s\n%s"), issuer_subject_str, crl_issuer_str);
return -1;
}
g_autoptr(AUTHORITY_KEYID) akid = NULL;
/* If AKID(@crl) is specified it must match with SKID(@issuer) */
akid = X509_CRL_get_ext_d2i(crl, NID_authority_key_identifier, NULL, NULL);
@@ -1325,7 +1303,6 @@ int pv_verify_crl(X509_CRL *crl, X509 *cert, int verify_flags, GError **error)
return -1;
}
/* check that the @crl issuer matches with the subject name of @cert*/
if (check_crl_issuer(crl, cert, error) < 0)
return -1;
@@ -1393,6 +1370,93 @@ int pv_check_chain_parameters(const STACK_OF_X509 *chain, GError **error)
return 0;
}
/** Replace locality 'Armonk' with 'Pougkeepsie'. If Armonk was not set return
* `NULL`.
*/
static X509_NAME *x509_armonk_locality_fixup(const X509_NAME *name)
{
g_autoptr(X509_NAME) ret = NULL;
int pos;
/* Check if ``L=Armonk`` */
if (!x509_name_data_by_nid_equal((X509_NAME *)name, NID_localityName,
PV_IBM_Z_SUBJECT_LOCALITY_NAME_ARMONK))
return NULL;
ret = X509_NAME_dup((X509_NAME *)name);
if (!ret)
g_abort();
pos = X509_NAME_get_index_by_NID(ret, NID_localityName, -1);
if (pos == -1)
return NULL;
X509_NAME_ENTRY_free(X509_NAME_delete_entry(ret, pos));
/* Create a new name entry at the same position as before */
if (X509_NAME_add_entry_by_NID(
ret, NID_localityName, MBSTRING_UTF8,
(const unsigned char *)&PV_IBM_Z_SUBJECT_LOCALITY_NAME_POUGHKEEPSIE,
sizeof(PV_IBM_Z_SUBJECT_LOCALITY_NAME_POUGHKEEPSIE) - 1, pos, 0) != 1)
return NULL;
return g_steal_pointer(&ret);
}
/* This function contains work-arounds for some known subject(CRT)<->issuer(CRL)
* issues.
*/
static STACK_OF_X509_CRL *quirk_X509_STORE_ctx_get1_crls(X509_STORE_CTX *ctx,
const X509_NAME *subject, GError **err)
{
g_autoptr(X509_NAME) fixed_subject = NULL;
g_autoptr(STACK_OF_X509_CRL) ret = NULL;
ret = pv_X509_STORE_CTX_get1_crls(ctx, subject);
if (ret && sk_X509_CRL_num(ret) > 0)
return g_steal_pointer(&ret);
/* Workaround to fix the mismatch between issuer name of the * IBM
* signing CRLs and the IBM signing key subject name. Locality name has
* changed from Poughkeepsie to Armonk.
*/
fixed_subject = x509_armonk_locality_fixup(subject);
/* Was the locality replaced? */
if (fixed_subject) {
X509_NAME *tmp;
sk_X509_CRL_free(ret);
ret = pv_X509_STORE_CTX_get1_crls(ctx, fixed_subject);
if (ret && sk_X509_CRL_num(ret) > 0)
return g_steal_pointer(&ret);
/* Workaround to fix the ordering mismatch between issuer name
* of the IBM signing CRLs and the IBM signing key subject name.
*/
tmp = fixed_subject;
fixed_subject = pv_c2b_name(fixed_subject);
X509_NAME_free(tmp);
sk_X509_CRL_free(ret);
ret = pv_X509_STORE_CTX_get1_crls(ctx, fixed_subject);
if (ret && sk_X509_CRL_num(ret) > 0)
return g_steal_pointer(&ret);
X509_NAME_free(fixed_subject);
fixed_subject = NULL;
}
/* Workaround to fix the ordering mismatch between issuer name of the
* IBM signing CRLs and the IBM signing key subject name.
*/
fixed_subject = pv_c2b_name(subject);
sk_X509_CRL_free(ret);
ret = pv_X509_STORE_CTX_get1_crls(ctx, fixed_subject);
if (ret && sk_X509_CRL_num(ret) > 0)
return g_steal_pointer(&ret);
g_set_error(err, PV_CERT_ERROR, PV_CERT_ERROR_NO_CRL, _("no CRL found"));
return NULL;
}
/* Given a certificate @cert try to find valid revocation lists in @ctx. If no
* valid CRL was found NULL is returned.
*/
@@ -1412,21 +1476,9 @@ STACK_OF_X509_CRL *pv_store_ctx_find_valid_crls(X509_STORE_CTX *ctx, X509 *cert,
return NULL;
}
ret = pv_X509_STORE_CTX_get1_crls(ctx, subject);
if (!ret) {
/* Workaround to fix the mismatch between issuer name of the
* IBM Z signing CRLs and the IBM Z signing key subject name.
*/
g_autoptr(X509_NAME) broken_subject = pv_c2b_name(subject);
ret = pv_X509_STORE_CTX_get1_crls(ctx, broken_subject);
if (!ret) {
g_set_error(error, PV_CERT_ERROR, PV_CERT_ERROR_NO_CRL, _("no CRL found"));
g_info("ERROR: %s", (*error)->message);
return NULL;
}
}
ret = quirk_X509_STORE_ctx_get1_crls(ctx, subject, error);
if (!ret)
return NULL;
/* Filter out non-valid CRLs for @cert */
for (int i = 0; i < sk_X509_CRL_num(ret); i++) {
X509_CRL *crl = sk_X509_CRL_value(ret, i);

View File

@@ -90,10 +90,10 @@ const char *util_arch_machine_type_to_str(int type)
case UTIL_ARCH_MACHINE_TYPE_Z14_ZR1:
return "IBM z14 ZR1";
case UTIL_ARCH_MACHINE_TYPE_Z15:
return "IBM z15";
case UTIL_ARCH_MACHINE_TYPE_Z15_T02:
return "IBM z15 Model T02";
return "IBM z15";
case UTIL_ARCH_MACHINE_TYPE_Z16:
case UTIL_ARCH_MACHINE_TYPE_Z16_A02:
return "IBM z16";
default:
return "Unknown machine type";
@@ -111,6 +111,7 @@ unsigned long util_arch_hsa_maxsize(void)
case UTIL_ARCH_MACHINE_TYPE_Z15:
case UTIL_ARCH_MACHINE_TYPE_Z15_T02:
case UTIL_ARCH_MACHINE_TYPE_Z16:
case UTIL_ARCH_MACHINE_TYPE_Z16_A02:
return HSA_SIZE_512M;
default:
return HSA_SIZE_32M;

View File

@@ -45,7 +45,7 @@ vmcmd: Trigger CP command according to the 'VMCMD_X' configuration in
.TP
\fB - DUMP_TYPE:\fR
Type of dump device. Possible values are 'ccw', 'fcp' and 'nvme'.
Type of dump device. Possible values are 'ccw', 'eckd', 'fcp' and 'nvme'.
.TP
\fB - DEVICE:\fR
@@ -71,6 +71,11 @@ Namespace ID for NVMe dump device.
\fB - BOOTPROG:\fR
Boot program selector.
.TP
\fB - BR_CHR:\fR
Boot record location in "C,H,R" format (comma separated values for
Cylinder, Head and Record) or "auto".
.TP
\fB - BR_LBA:\fR
Boot record logical block address.
@@ -146,6 +151,23 @@ DEVICE=0.0.1234
DELAY_MINUTES=5
.br
#
.br
# Example configuration for an ECKD dump device (DASD)
.br
#
.br
ON_PANIC=dump
.br
DUMP_TYPE=eckd
.br
DEVICE=0.0.1004
.br
BOOTPROG=0
.br
BR_CHR=auto
.br
#
.br
# Example configuration for an FCP dump device (SCSI Disk)

View File

@@ -3,7 +3,6 @@ include ../common.mak
.DEFAULT_GOAL := all
PKGDATADIR := "$(DESTDIR)$(TOOLS_DATADIR)/pvattest"
SUBDIRS := src man tools
RECURSIVE_TARGETS := all-recursive clean-recursive install-recursive

View File

@@ -1,10 +1,7 @@
include ../../common.mak
BIN_PROGRAM = pvattest
PKGDATADIR ?= "$(DESTDIR)$(TOOLS_DATADIR)/$(BIN_PROGRAM)"
SRC_DIR := $(dir $(realpath $(firstword $(MAKEFILE_LIST))))
PVATTESTDIR := $(rootdir)/pvattest
INCLUDE_PATHS = "$(SRC_DIR)" "$(rootdir)/include"
INCLUDE_PARMS = $(addprefix -I,$(INCLUDE_PATHS))
@@ -35,9 +32,7 @@ LIBCRYPTO_LIBS := $(shell $(PKG_CONFIG) --silence-errors --libs libcrypto)
LIBCURL_CFLAGS := $(shell $(PKG_CONFIG) --silence-errors --cflags libcurl)
LIBCURL_LIBS := $(shell $(PKG_CONFIG) --silence-errors --libs libcurl)
ALL_CFLAGS += -std=gnu11 \
-DPKGDATADIR=$(PKGDATADIR) \
-DOPENSSL_API_COMPAT=0x10101000L \
ALL_CFLAGS += -DOPENSSL_API_COMPAT=0x10101000L \
$(GLIB2_CFLAGS) \
$(LIBCRYPTO_CFLAGS) \
$(LIBCURL_CFLAGS) \

View File

@@ -192,13 +192,13 @@ static gboolean hex_str_toull(const char *nptr, uint64_t *dst, GError **error)
}
/* NOTE REQUIRED */
#define _entry_root_ca(__arg_data, __indent) \
{ \
.long_name = "root-ca", .short_name = 0, .flags = G_OPTION_FLAG_NONE, \
.arg = G_OPTION_ARG_FILENAME_ARRAY, .arg_data = __arg_data, \
.description = "Use FILE as the trusted root CA instead the\n" __indent \
"root CAs that are installed on the system (optional).\n", \
.arg_description = "FILE", \
#define _entry_root_ca(__arg_data, __indent) \
{ \
.long_name = "root-ca", .short_name = 0, .flags = G_OPTION_FLAG_NONE, \
.arg = G_OPTION_ARG_FILENAME, .arg_data = __arg_data, \
.description = "Use FILE as the trusted root CA instead the\n" __indent \
"root CAs that are installed on the system (optional).\n", \
.arg_description = "FILE", \
}
/* NOTE REQUIRED */

696
rust/Cargo.lock generated
View File

@@ -2,21 +2,6 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "addr2line"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
dependencies = [
"gimli",
]
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "aho-corasick"
version = "1.1.2"
@@ -81,37 +66,12 @@ version = "1.0.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
[[package]]
name = "assert-json-diff"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47e4f2b81832e72834d7518d8487a0396a28cc408186a2e8854c0f98011faf12"
dependencies = [
"serde",
"serde_json",
]
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "backtrace"
version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
dependencies = [
"addr2line",
"cc",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
]
[[package]]
name = "bitflags"
version = "1.3.2"
@@ -130,12 +90,6 @@ version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "bytes"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
[[package]]
name = "cc"
version = "1.0.79"
@@ -182,7 +136,7 @@ dependencies = [
"heck",
"proc-macro2",
"quote",
"syn 2.0.18",
"syn",
]
[[package]]
@@ -208,15 +162,15 @@ dependencies = [
"openssl-probe",
"openssl-sys",
"schannel",
"socket2 0.4.9",
"socket2",
"winapi",
]
[[package]]
name = "curl-sys"
version = "0.4.68+curl-8.4.0"
version = "0.4.72+curl-8.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4a0d18d88360e374b16b2273c832b5e57258ffc1d4aa4f96b108e0738d5752f"
checksum = "29cbdc8314c447d11e8fd156dcdd031d9e02a7a976163e396b548c03153bc9ea"
dependencies = [
"cc",
"libc",
@@ -224,15 +178,9 @@ dependencies = [
"openssl-sys",
"pkg-config",
"vcpkg",
"windows-sys 0.48.0",
"windows-sys 0.52.0",
]
[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "errno"
version = "0.3.1"
@@ -254,12 +202,6 @@ dependencies = [
"libc",
]
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "foreign-types"
version = "0.3.2"
@@ -275,104 +217,6 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "form_urlencoded"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652"
dependencies = [
"percent-encoding",
]
[[package]]
name = "futures"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-channel"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
name = "futures-core"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c"
[[package]]
name = "futures-executor"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa"
[[package]]
name = "futures-macro"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.18",
]
[[package]]
name = "futures-sink"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817"
[[package]]
name = "futures-task"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2"
[[package]]
name = "futures-util"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104"
dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
"pin-project-lite",
"pin-utils",
"slab",
]
[[package]]
name = "getrandom"
version = "0.2.10"
@@ -384,43 +228,12 @@ dependencies = [
"wasi",
]
[[package]]
name = "gimli"
version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
[[package]]
name = "h2"
version = "0.3.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178"
dependencies = [
"bytes",
"fnv",
"futures-core",
"futures-sink",
"futures-util",
"http",
"indexmap 2.1.0",
"slab",
"tokio",
"tokio-util",
"tracing",
]
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "hashbrown"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
[[package]]
name = "heck"
version = "0.4.1"
@@ -433,64 +246,6 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
[[package]]
name = "http"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb"
dependencies = [
"bytes",
"fnv",
"itoa",
]
[[package]]
name = "http-body"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
dependencies = [
"bytes",
"http",
"pin-project-lite",
]
[[package]]
name = "httparse"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
[[package]]
name = "httpdate"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
name = "hyper"
version = "0.14.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468"
dependencies = [
"bytes",
"futures-channel",
"futures-core",
"futures-util",
"h2",
"http",
"http-body",
"httparse",
"httpdate",
"itoa",
"pin-project-lite",
"socket2 0.4.9",
"tokio",
"tower-service",
"tracing",
"want",
]
[[package]]
name = "indexmap"
version = "1.9.3"
@@ -498,17 +253,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
dependencies = [
"autocfg",
"hashbrown 0.12.3",
]
[[package]]
name = "indexmap"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
dependencies = [
"equivalent",
"hashbrown 0.14.3",
"hashbrown",
]
[[package]]
@@ -570,16 +315,6 @@ version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
[[package]]
name = "lock_api"
version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
dependencies = [
"autocfg",
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.19"
@@ -592,68 +327,11 @@ version = "2.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
[[package]]
name = "miniz_oxide"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
dependencies = [
"adler",
]
[[package]]
name = "mio"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"
dependencies = [
"libc",
"wasi",
"windows-sys 0.48.0",
]
[[package]]
name = "mockito"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8d3038e23466858569c2d30a537f691fa0d53b51626630ae08262943e3bbb8b"
dependencies = [
"assert-json-diff",
"futures",
"hyper",
"log",
"rand",
"regex",
"serde_json",
"serde_urlencoded",
"similar",
"tokio",
]
[[package]]
name = "num_cpus"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "object"
version = "0.32.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0"
dependencies = [
"memchr",
]
[[package]]
name = "once_cell"
version = "1.18.0"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "openssl"
@@ -678,7 +356,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.18",
"syn",
]
[[package]]
@@ -710,47 +388,6 @@ dependencies = [
"openssl-sys",
]
[[package]]
name = "parking_lot"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-targets",
]
[[package]]
name = "percent-encoding"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
[[package]]
name = "pin-project-lite"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkg-config"
version = "0.3.27"
@@ -765,33 +402,61 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "proc-macro2"
version = "1.0.60"
version = "1.0.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406"
checksum = "907a61bd0f64c2f29cd1cf1dc34d05176426a3f504a78010f08416ddb7b13708"
dependencies = [
"unicode-ident",
]
[[package]]
name = "pv"
version = "0.9.0"
version = "1.0.0"
dependencies = [
"byteorder",
"cfg-if",
"clap",
"curl",
"lazy_static",
"libc",
"log",
"mockito",
"openssl",
"openssl_extensions",
"pv_core",
"serde",
"serde_test",
"thiserror",
"utils",
"zerocopy",
]
[[package]]
name = "pv_core"
version = "1.0.0"
dependencies = [
"byteorder",
"libc",
"log",
"serde",
"serde_test",
"thiserror",
"utils",
"zerocopy",
]
[[package]]
name = "pvapconfig"
version = "0.9.0"
dependencies = [
"clap",
"lazy_static",
"openssl",
"openssl-sys",
"pv_core",
"rand",
"regex",
"serde",
"serde_yaml",
"utils",
]
[[package]]
name = "pvsecret"
version = "0.9.0"
@@ -806,9 +471,9 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.28"
version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488"
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [
"proc-macro2",
]
@@ -843,15 +508,6 @@ dependencies = [
"getrandom",
]
[[package]]
name = "redox_syscall"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
dependencies = [
"bitflags 1.3.2",
]
[[package]]
name = "regex"
version = "1.10.2"
@@ -881,12 +537,6 @@ version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
[[package]]
name = "rustc-demangle"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]]
name = "rustix"
version = "0.37.27"
@@ -916,12 +566,6 @@ dependencies = [
"windows-sys 0.42.0",
]
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "serde"
version = "1.0.164"
@@ -939,18 +583,7 @@ checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.18",
]
[[package]]
name = "serde_json"
version = "1.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3"
dependencies = [
"itoa",
"ryu",
"serde",
"syn",
]
[[package]]
@@ -962,61 +595,19 @@ dependencies = [
"serde",
]
[[package]]
name = "serde_urlencoded"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
dependencies = [
"form_urlencoded",
"itoa",
"ryu",
"serde",
]
[[package]]
name = "serde_yaml"
version = "0.9.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9d684e3ec7de3bf5466b32bd75303ac16f0736426e5a4e0d6e489559ce1249c"
dependencies = [
"indexmap 1.9.3",
"indexmap",
"itoa",
"ryu",
"serde",
"unsafe-libyaml",
]
[[package]]
name = "signal-hook-registry"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
dependencies = [
"libc",
]
[[package]]
name = "similar"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2aeaf503862c419d66959f5d7ca015337d864e9c49485d771b732e2a20453597"
[[package]]
name = "slab"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
dependencies = [
"autocfg",
]
[[package]]
name = "smallvec"
version = "1.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
[[package]]
name = "socket2"
version = "0.4.9"
@@ -1027,16 +618,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "socket2"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e"
dependencies = [
"libc",
"windows-sys 0.48.0",
]
[[package]]
name = "strsim"
version = "0.10.0"
@@ -1045,20 +626,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.109"
version = "2.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e"
checksum = "1726efe18f42ae774cc644f330953a5e7b3c3003d3edcecf18850fe9d4dd9afb"
dependencies = [
"proc-macro2",
"quote",
@@ -1092,84 +662,9 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.18",
"syn",
]
[[package]]
name = "tokio"
version = "1.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653"
dependencies = [
"backtrace",
"bytes",
"libc",
"mio",
"num_cpus",
"parking_lot",
"pin-project-lite",
"signal-hook-registry",
"socket2 0.5.4",
"tokio-macros",
"windows-sys 0.48.0",
]
[[package]]
name = "tokio-macros"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.18",
]
[[package]]
name = "tokio-util"
version = "0.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15"
dependencies = [
"bytes",
"futures-core",
"futures-sink",
"pin-project-lite",
"tokio",
"tracing",
]
[[package]]
name = "tower-service"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
[[package]]
name = "tracing"
version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
dependencies = [
"pin-project-lite",
"tracing-core",
]
[[package]]
name = "tracing-core"
version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
dependencies = [
"once_cell",
]
[[package]]
name = "try-lock"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
[[package]]
name = "unicode-ident"
version = "1.0.9"
@@ -1198,15 +693,6 @@ version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "want"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
dependencies = [
"try-lock",
]
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
@@ -1256,7 +742,16 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets",
"windows-targets 0.48.0",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets 0.52.4",
]
[[package]]
@@ -1274,6 +769,21 @@ dependencies = [
"windows_x86_64_msvc 0.48.0",
]
[[package]]
name = "windows-targets"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
dependencies = [
"windows_aarch64_gnullvm 0.52.4",
"windows_aarch64_msvc 0.52.4",
"windows_i686_gnu 0.52.4",
"windows_i686_msvc 0.52.4",
"windows_x86_64_gnu 0.52.4",
"windows_x86_64_gnullvm 0.52.4",
"windows_x86_64_msvc 0.52.4",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.2"
@@ -1286,6 +796,12 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.2"
@@ -1298,6 +814,12 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
[[package]]
name = "windows_i686_gnu"
version = "0.42.2"
@@ -1310,6 +832,12 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
[[package]]
name = "windows_i686_gnu"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
[[package]]
name = "windows_i686_msvc"
version = "0.42.2"
@@ -1322,6 +850,12 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
[[package]]
name = "windows_i686_msvc"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.2"
@@ -1334,6 +868,12 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.2"
@@ -1346,6 +886,12 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.2"
@@ -1359,10 +905,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
[[package]]
name = "zerocopy"
version = "0.6.1"
name = "windows_x86_64_msvc"
version = "0.52.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "332f188cc1bcf1fe1064b8c58d150f497e697f49774aa846f2dc949d9a25f236"
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
[[package]]
name = "zerocopy"
version = "0.7.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"
dependencies = [
"byteorder",
"zerocopy-derive",
@@ -1370,11 +922,11 @@ dependencies = [
[[package]]
name = "zerocopy-derive"
version = "0.3.2"
version = "0.7.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6505e6815af7de1746a08f69c69606bb45695a17149517680f3b2149713b19a3"
checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
"syn",
]

View File

@@ -1,6 +1,8 @@
[workspace]
members = [
"pv",
"pv_core",
"pvapconfig",
"pvsecret",
"utils",
]

View File

@@ -19,7 +19,7 @@ ifneq (${HAVE_CARGO},0)
ifneq (${HAVE_OPENSSL},0)
ifneq (${HAVE_LIBCURL},0)
PV_TARGETS := pvsecret
PV_TARGETS := pvsecret pvapconfig
PV_BUILD_TARGETS := $(PV_TARGETS)
CARGO_TEST_TARGETS += $(addsuffix .test,pv $(PV_TARGETS))
@@ -37,8 +37,8 @@ endif
# the cc crate uses these variables to compile c code. It does not open a shell
# to call the compiler, so no echo etc. allowed here, just a path to a program
$(BUILD_TARGETS) rust-test: CC = $(CC_SILENT)
$(BUILD_TARGETS) rust-test: AR = $(AR_SILENT)
$(BUILD_TARGETS) $(TEST_TARGETS) rust-test: CC = $(CC_SILENT)
$(BUILD_TARGETS) $(TEST_TARGETS) rust-test: AR = $(AR_SILENT)
$(PV_TARGETS): .check-dep-pvtools
$(PV_TARGETS) $(CARGO_TARGETS): .check-cargo .no-cross-compile

View File

@@ -25,16 +25,18 @@ Tip: You can use `make version` to get the version string.
## Internal Libraries
* __utils__ _Library for rust tools that bundles common stuff for the 390-tools_
* currently only provides a macro to get the `S390_TOOLS_RELEASE` string
* provides a macro to get the `S390_TOOLS_RELEASE` string
* provides macros for compile time assertions
* __pv_core__ _Library for pv tools, providing uvdevice access and utilities to send, receive and interpret various UV-calls._
* __pv__ _Library for pv tools, providing uvdevice access, encryption utilities, and utilities for generating UV-request_
* requires openssl and libcurl for the feature `request`; use `HAVE_<OPENSSL|CURL>=0` to
disable build that use pv with the request feature.
* requires openssl and libcurl
* reexports ann symbols from __pv_core__
* if no encryption utilities required, use __pv_core__
## Tools
* __pvsecret__ _Manage secrets for IBM Secure Execution guests_
* requires pv with the `request` feature
## Writing new tools
We encourage to use Rust for new tools. However, for some use cases it makes

View File

@@ -1,32 +1,22 @@
[package]
name = "pv"
version = "0.9.0"
version = "1.0.0"
edition.workspace = true
license.workspace = true
[dependencies]
libc = "0.2.49"
byteorder = "1.3"
clap = { version ="4", features = ["derive", "wrap_help"] }
curl = "0.4.7"
log = { version = "0.4.6", features = ["std", "release_max_level_debug"] }
openssl = "0.10.49"
serde = { version = "1.0.139", features = ["derive"] }
thiserror = "1.0.33"
zerocopy = "0.6"
cfg-if = "1.0.0"
utils = {path = "../utils"}
zerocopy = { version="0.7", features = ["derive"] }
# dependencies for request feature
clap = { version ="4", features = ["derive", "wrap_help"], optional = true }
curl = { version ="0.4.7", optional = true }
openssl = {version = "0.10.49", optional = true }
openssl_extensions = { path = "openssl_extensions", optional = true }
serde = { version = "1.0.139", features = ["derive"], optional = true }
# misc optional dependencies
byteorder = {version = "1.3", optional = true }
openssl_extensions = { path = "openssl_extensions" }
pv_core = { path = "../pv_core" }
[dev-dependencies]
mockito = {version = "1", default-features = false }
serde_test = "1"
lazy_static = "1.1"
[features]
default = []
request = ["dep:openssl", "dep:curl", "dep:openssl_extensions", "dep:serde", "dep:clap"]
uvsecret = ["dep:byteorder", "dep:serde"]

View File

@@ -5,15 +5,15 @@
use std::fmt;
use foreign_types::{foreign_type, ForeignType, ForeignTypeRef};
use libc::c_int;
use openssl::x509::{X509CrlRef, X509Ref};
use std::ffi::c_int;
mod ffi {
extern "C" {
pub fn X509_check_akid(
issuer: *const openssl_sys::X509,
akid: *const openssl_sys::AUTHORITY_KEYID,
) -> ::libc::c_int;
) -> super::c_int;
}
}

View File

@@ -30,7 +30,7 @@ mod ffi {
pub fn X509_STORE_add_crl(
xs: *mut openssl_sys::X509_STORE,
x: *mut openssl_sys::X509_CRL,
) -> libc::c_int;
) -> std::ffi::c_int;
}
}

View File

@@ -5,13 +5,13 @@
use std::{marker::PhantomData, ptr};
use foreign_types::{ForeignType, ForeignTypeRef};
use libc::c_int;
use openssl::{
error::ErrorStack,
stack::Stackable,
x509::{X509Crl, X509CrlRef},
};
use openssl_sys::BIO_new_mem_buf;
use std::ffi::c_int;
pub struct StackableX509Crl(*mut openssl_sys::X509_CRL);

View File

@@ -8,11 +8,10 @@ use std::{
};
// (SE) boot request control block aka SE header
use crate::{
assert_size, request::MagicValue, requires_feat, static_assert, Error, Result, PAGESIZE,
};
use crate::{assert_size, static_assert, Error, Result, PAGESIZE};
use log::debug;
use zerocopy::{AsBytes, BigEndian, FromBytes, U32, U64};
use pv_core::request::MagicValue;
use zerocopy::{AsBytes, BigEndian, FromBytes, FromZeroes, U32, U64};
/// Struct containing all SE-header tags.
///
@@ -22,7 +21,6 @@ use zerocopy::{AsBytes, BigEndian, FromBytes, U32, U64};
/// Tweak List Digest (tld)
/// SE Header Tag (seht)
///
#[doc = requires_feat!(request)]
#[repr(C)]
#[derive(Debug, Clone, Copy, AsBytes, PartialEq, Eq)]
pub struct BootHdrTags {
@@ -144,7 +142,7 @@ impl BootHdrTags {
}
#[repr(C)]
#[derive(Debug, Clone, FromBytes)]
#[derive(Debug, Clone, FromBytes, FromZeroes)]
struct BootHdrHead {
magic: U64<BigEndian>,
version: U32<BigEndian>,

View File

@@ -2,14 +2,12 @@
//
// Copyright IBM Corp. 2023
use crate::misc::{create_file, open_file};
use crate::Result;
use crate::{create_buffered_file, open_buffered_file};
use clap::{ArgGroup, Args, ValueHint};
use std::io::{Read, Write};
/// CLI Argument collection for handling certificates.
///
#[doc = requires_feat!(request)]
#[derive(Args, Debug, PartialEq, Eq, Default)]
#[command(
group(ArgGroup::new("pv_verify").required(true).args(["no_verify", "certs"])),
@@ -32,15 +30,15 @@ pub struct CertificateOptions {
/// Disable the host-key document verification.
///
/// Does not require the host-key documents to be valid.
/// Do not use for a production request unless you verified the host-key document before.
/// Do not use for a production request unless you verified the host-key document beforehand.
#[arg(long)]
pub no_verify: bool,
/// Use FILE as a certificate to verify the host-key(s).
/// Use FILE as a certificate to verify the host key or keys.
///
/// The certificates are used to establish a chain of trust for the verification
/// of the host-key documents. Specify this option twice to specify the IBM Z signing key and
/// the intermediate CA certificate (signed by the rootCA).
/// the intermediate CA certificate (signed by the root CA).
#[arg(
short= 'C',
long = "cert",
@@ -54,7 +52,7 @@ pub struct CertificateOptions {
/// Use FILE as a certificate revocation list.
///
/// That list is used to check whether a certificate of the chain of
/// The list is used to check whether a certificate of the chain of
/// trust is revoked. Specify this option multiple times to use multiple CRLs.
#[arg(
long = "crl",
@@ -72,7 +70,7 @@ pub struct CertificateOptions {
/// Use FILE as the root-CA certificate for the verification.
///
/// If omitted, the system wide root CAs installed on the system are used.
/// If omitted, the system wide-root CAs installed on the system are used.
/// Use this only if you trust the specified certificate.
#[arg(long, requires("certs"))]
pub root_ca: Option<String>,
@@ -104,37 +102,25 @@ impl CertificateOptions {
}
/// stdout
#[cfg(feature = "request")]
pub const STDOUT: &str = "-";
/// stdin
#[cfg(feature = "request")]
pub const STDIN: &str = "-";
/// Converts an argument value into a Writer.
///
/// # Errors
/// No Error will occur but function must match a signature
///
#[cfg(feature = "request")]
pub fn get_writer_from_cli_file_arg(path: &str) -> Result<Box<dyn Write>> {
if path == STDOUT {
Ok(Box::new(std::io::stdout()))
} else {
Ok(Box::new(create_buffered_file!(path)))
Ok(Box::new(create_file(path)?))
}
}
/// Converts an argument value into a Reader.
///
/// # Errors
/// No Error will occur but function must match a signature
///
#[cfg(feature = "request")]
pub fn get_reader_from_cli_file_arg(path: &str) -> Result<Box<dyn Read>> {
if path == STDIN {
Ok(Box::new(std::io::stdin()))
} else {
Ok(Box::new(open_buffered_file!(path)))
Ok(Box::new(open_file(path)?))
}
}

View File

@@ -2,29 +2,29 @@
//
// Copyright IBM Corp. 2023
use crate::requires_feat;
use crate::{error::Result, secret::Secret, Error};
use openssl::rand::rand_bytes;
use openssl::{
derive::Deriver,
ec::{EcGroup, EcKey},
hash::{DigestBytes, MessageDigest},
md::MdRef,
nid::Nid,
pkey::{Id, PKey, Private, Public},
pkey::{HasPublic, Id, PKey, PKeyRef, Private, Public},
pkey_ctx::{HkdfMode, PkeyCtx},
symm::{encrypt, encrypt_aead, Cipher},
rand::rand_bytes,
rsa::Padding,
sign::{Signer, Verifier},
symm::{encrypt_aead, Cipher},
};
use std::convert::TryInto;
use std::{convert::TryInto, ops::Range};
/// An AES256-key that will purge itself out of the memory when going out of scope
///
#[doc = requires_feat!(request)]
pub type Aes256Key = Secret<[u8; 32]>;
pub(crate) const AES_256_GCM_TAG_SIZE: usize = 16;
/// Types of symmetric keys, to specify during construction.
///
#[doc = requires_feat!(request)]
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SymKeyType {
@@ -34,7 +34,6 @@ pub enum SymKeyType {
/// Types of symmetric keys
///
#[doc = requires_feat!(request)]
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SymKey {
@@ -88,7 +87,6 @@ impl From<Aes256Key> for SymKey {
/// Performs an hkdf according to RFC 5869.
/// See [`OpenSSL HKDF`]()
///
#[doc = requires_feat!(request)]
/// # Errors
///
/// This function will return an OpenSSL error if the key could not be generated.
@@ -113,7 +111,6 @@ pub fn hkdf_rfc_5869<const COUNT: usize>(
/// Derive a symmetric key from a private and a public key.
///
#[doc = requires_feat!(request)]
/// # Errors
///
/// This function will return an error if something went bad in OpenSSL.
@@ -132,7 +129,6 @@ pub fn derive_key(k1: &PKey<Private>, k2: &PKey<Public>) -> Result<Aes256Key> {
/// Generate a random array.
///
#[doc = requires_feat!(request)]
/// # Errors
///
/// This function will return an error if the entropy source fails or is not available.
@@ -144,7 +140,6 @@ pub fn random_array<const COUNT: usize>() -> Result<[u8; COUNT]> {
/// Generate a new random EC-SECP521R1 key.
///
#[doc = requires_feat!(request)]
/// # Errors
///
/// This function will return an error if the key could not be generated by OpenSSL.
@@ -154,24 +149,6 @@ pub fn gen_ec_key() -> Result<PKey<Private>> {
PKey::from_ec_key(key).map_err(Error::Crypto)
}
/// Encrypt confidential Data with a symmetric key.
///
/// * `key` - symmetric key used for encryption
/// * `iv` - initialisation vector
/// * `conf` - data to be encrypted
///
#[doc = requires_feat!(request)]
/// # Errors
///
/// This function will return an error if the data could not be encrypted by OpenSSL.
pub fn encrypt_aes(key: &SymKey, iv: &[u8], conf: &[u8]) -> Result<Vec<u8>> {
match key {
SymKey::Aes256(key) => {
encrypt(Cipher::aes_256_gcm(), key.value(), Some(iv), conf).map_err(Error::Crypto)
}
}
}
/// Encrypt confidential Data with a symmetric key and provida a gcm tag.
///
/// * `key` - symmetric key used for encryption
@@ -179,7 +156,6 @@ pub fn encrypt_aes(key: &SymKey, iv: &[u8], conf: &[u8]) -> Result<Vec<u8>> {
/// * `aad` - additional authentic data
/// * `conf` - data to be encrypted
///
#[doc = requires_feat!(request)]
/// # Returns
/// [`Vec<u8>`] with the following content:
/// 1. `aad`
@@ -189,8 +165,13 @@ pub fn encrypt_aes(key: &SymKey, iv: &[u8], conf: &[u8]) -> Result<Vec<u8>> {
/// # Errors
///
/// This function will return an error if the data could not be encrypted by OpenSSL.
pub fn encrypt_aes_gcm(key: &SymKey, iv: &[u8], aad: &[u8], conf: &[u8]) -> Result<Vec<u8>> {
let mut tag = vec![0xff; 16];
pub fn encrypt_aes_gcm(
key: &SymKey,
iv: &[u8],
aad: &[u8],
conf: &[u8],
) -> Result<(Vec<u8>, Range<usize>, Range<usize>, Range<usize>)> {
let mut tag = vec![0xff; AES_256_GCM_TAG_SIZE];
let encr = match key {
SymKey::Aes256(key) => encrypt_aead(
Cipher::aes_256_gcm(),
@@ -202,17 +183,28 @@ pub fn encrypt_aes_gcm(key: &SymKey, iv: &[u8], aad: &[u8], conf: &[u8]) -> Resu
)?,
};
let mut res = vec![0; aad.len() + encr.len() + 16];
res[0..aad.len()].copy_from_slice(aad);
res[aad.len()..aad.len() + encr.len()].copy_from_slice(&encr);
res[aad.len() + encr.len()..aad.len() + encr.len() + 16].copy_from_slice(&tag);
let mut res = vec![0; aad.len() + encr.len() + tag.len()];
let aad_range = Range {
start: 0,
end: aad.len(),
};
let encr_range = Range {
start: aad.len(),
end: aad.len() + encr.len(),
};
let tag_range = Range {
start: aad.len() + encr.len(),
end: aad.len() + encr.len() + tag.len(),
};
Ok(res)
res[aad_range.clone()].copy_from_slice(aad);
res[encr_range.clone()].copy_from_slice(&encr);
res[tag_range.clone()].copy_from_slice(&tag);
Ok((res, aad_range, encr_range, tag_range))
}
/// Calculate the hash of a slice.
///
#[doc = requires_feat!(request)]
/// # Errors
///
/// This function will return an error if OpenSSL could not compute the hash.
@@ -220,10 +212,100 @@ pub fn hash(t: MessageDigest, data: &[u8]) -> Result<DigestBytes> {
openssl::hash::hash(t, data).map_err(Error::Crypto)
}
/// Calculate a digital signature scheme.
///
/// Calculates the digital signature of the provided message using the signing key. [`Id::EC`],
/// and [`Id::RSA`] keys are supported. For [`Id::RSA`] [`Padding::PKCS1_PSS`] is used.
///
/// # Errors
///
/// This function will return an error if OpenSSL could not compute the signature.
pub fn sign_msg(skey: &PKeyRef<Private>, dgst: MessageDigest, msg: &[u8]) -> Result<Vec<u8>> {
match skey.id() {
Id::EC => {
let mut sgn = Signer::new(dgst, skey)?;
sgn.sign_oneshot_to_vec(msg).map_err(Error::Crypto)
}
Id::RSA => {
let mut sgn = Signer::new(dgst, skey)?;
sgn.set_rsa_padding(Padding::PKCS1_PSS)?;
sgn.sign_oneshot_to_vec(msg).map_err(Error::Crypto)
}
_ => Err(Error::UnsupportedSigningKey),
}
}
/// Verify the digital signature of a message.
///
/// Verifies the digital signature of the provided message using the signing key.
/// [`Id::EC`] and [`Id::RSA`] keys are supported. For [`Id::RSA`] [`Padding::PKCS1_PSS`] is used.
///
/// # Returns
/// true if signature could be verified, false otherwise
///
/// # Errors
///
/// This function will return an error if OpenSSL could not compute the signature.
pub fn verify_signature<T: HasPublic>(
skey: &PKeyRef<T>,
dgst: MessageDigest,
msg: &[u8],
sign: &[u8],
) -> Result<bool> {
match skey.id() {
Id::EC => {
let mut ctx = Verifier::new(dgst, skey)?;
ctx.update(msg)?;
ctx.verify(sign).map_err(Error::Crypto)
}
Id::RSA => {
let mut ctx = Verifier::new(dgst, skey)?;
ctx.set_rsa_padding(Padding::PKCS1_PSS)?;
ctx.verify_oneshot(sign, msg).map_err(Error::Crypto)
}
_ => Err(Error::UnsupportedVerificationKey),
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test_utils::*;
use crate::{get_test_asset, test_utils::*};
#[test]
fn sign_ec() {
let (ec_key, _) = get_test_keys();
let data = "sample".as_bytes();
let sign = sign_msg(&ec_key, MessageDigest::sha512(), data).unwrap();
assert!(sign.len() <= 139 && sign.len() >= 137);
assert!(verify_signature(&ec_key, MessageDigest::sha512(), data, &sign).unwrap());
}
#[test]
fn sign_rsa_2048() {
let keypair = get_test_asset!("keys/rsa2048key.pem");
let keypair = PKey::private_key_from_pem(keypair).unwrap();
let data = "sample".as_bytes();
let sign = sign_msg(&keypair, MessageDigest::sha512(), data).unwrap();
assert_eq!(256, sign.len());
assert!(verify_signature(&keypair, MessageDigest::sha512(), data, &sign).unwrap());
}
#[test]
fn sign_rsa_3072() {
let keypair = get_test_asset!("keys/rsa3072key.pem");
let keypair = PKey::private_key_from_pem(keypair).unwrap();
let data = "sample".as_bytes();
let sign = sign_msg(&keypair, MessageDigest::sha512(), data).unwrap();
assert_eq!(384, sign.len());
assert!(verify_signature(&keypair, MessageDigest::sha512(), data, &sign).unwrap());
}
#[test]
fn derive_key() {
@@ -285,7 +367,7 @@ mod tests {
0xee, 0x62, 0x98, 0xf7, 0x7e, 0x0c,
];
let res = encrypt_aes_gcm(
let (res, ..) = encrypt_aes_gcm(
&SymKey::Aes256(aes_gcm_key.into()),
&aes_gcm_iv,
&aes_gcm_aad,
@@ -294,32 +376,4 @@ mod tests {
.unwrap();
assert_eq!(res, aes_gcm_res);
}
#[test]
fn encrypt_aes_256() {
let aes_gcm_key = [
0xee, 0xbc, 0x1f, 0x57, 0x48, 0x7f, 0x51, 0x92, 0x1c, 0x04, 0x65, 0x66, 0x5f, 0x8a,
0xe6, 0xd1, 0x65, 0x8b, 0xb2, 0x6d, 0xe6, 0xf8, 0xa0, 0x69, 0xa3, 0x52, 0x02, 0x93,
0xa5, 0x72, 0x07, 0x8f,
];
let aes_gcm_iv = [
0x99, 0xaa, 0x3e, 0x68, 0xed, 0x81, 0x73, 0xa0, 0xee, 0xd0, 0x66, 0x84,
];
let aes_gcm_plain = [
0xf5, 0x6e, 0x87, 0x05, 0x5b, 0xc3, 0x2d, 0x0e, 0xeb, 0x31, 0xb2, 0xea, 0xcc, 0x2b,
0xf2, 0xa5,
];
let aes_gcm_res = vec![
0xf7, 0x26, 0x44, 0x13, 0xa8, 0x4c, 0x0e, 0x7c, 0xd5, 0x36, 0x86, 0x7e, 0xb9, 0xf2,
0x17, 0x36,
];
let res = encrypt_aes(
&SymKey::Aes256(aes_gcm_key.into()),
&aes_gcm_iv,
&aes_gcm_plain,
)
.unwrap();
assert_eq!(res, aes_gcm_res);
}
}

View File

@@ -10,49 +10,19 @@ pub type Result<T, E = Error> = std::result::Result<T, E>;
#[derive(thiserror::Error, Debug)]
#[non_exhaustive]
pub enum Error {
#[cfg_attr(debug_assertions, error("Ultravisor: '{msg}' ({rc:#06x},{rrc:#06x})"))]
#[cfg_attr(not(debug_assertions), error("Ultravisor: '{msg}' ({rc:#06x})"))]
Uv {
rc: u16,
rrc: u16,
msg: &'static str,
},
#[error("Invalid SE header provided")]
#[cfg(feature = "request")]
InvBootHdr,
#[error("{0}")]
Specification(String),
#[error("Cannot {ty} {ctx} at `{path}`")]
FileIo {
ty: FileIoErrorType,
ctx: String,
path: String,
source: std::io::Error,
},
#[error("Cannot {ty} `{path}`")]
FileAccess {
ty: FileAccessErrorType,
path: String,
source: std::io::Error,
},
#[error("Host-key verification failed: {0}")]
#[cfg(feature = "request")]
HkdVerify(HkdVerifyErrorType),
#[error("No host-key provided")]
#[cfg(feature = "request")]
NoHostkey,
#[error("To many host-keys provided")]
#[cfg(feature = "request")]
#[error("Too many host-keys provided")]
ManyHostkeys,
#[error("Cannot load {ty} from {path}")]
#[cfg(feature = "request")]
X509Load {
path: String,
ty: &'static str,
@@ -60,77 +30,67 @@ pub enum Error {
},
#[error("Internal (unexpected) error: {0}, caused by {1}")]
#[cfg(feature = "request")]
InternalSsl(&'static str, #[source] openssl::error::ErrorStack),
#[error("Signing is only supported for EC and RSA keys")]
UnsupportedSigningKey,
#[error("Verifying signatures is only supported for EC and RSA keys")]
UnsupportedVerificationKey,
#[error("Provided binary request is too small")]
BinRequestSmall,
#[error("No Config UID found: {0}")]
NoCuid(String),
// errors from request types
#[cfg(feature = "uvsecret")]
#[error("Customer Communication Key must be 32 bytes long")]
CckSize,
#[cfg(feature = "uvsecret")]
#[error("Cannot encode secrets (Too many secrets)")]
ManySecrets,
#[error("Invalid {0} user-data for signing provided. Max {} bytes allowed", .0.max())]
AsrcbInvSgnUserData(UserDataType),
#[cfg(feature = "uvsecret")]
#[error("Cannot decode secret list")]
InvSecretList(#[source] std::io::Error),
#[error("Unsupported user data signing key provided. Only EC(secp521r1) and RSA(2048 & 3072 bit) are supported")]
BinAsrcbUnsupportedUserDataSgnKey,
#[cfg(feature = "uvsecret")]
#[error("Input does not contain an add-secret request")]
NoAsrcb,
#[error("No user-key for verification provided and user-data is signed")]
BinAsrcbNoUserDataSgnKey,
#[error("Input does not contain an add-secret request version 1")]
BinAsrcbInvVersion,
#[error("Provided user-data key type ({key}) does not match with the user-data ({kind})")]
AsrcbUserDataKeyMismatch { key: String, kind: UserDataType },
#[error(
"The user-defined request signature could not be verified with the provided certificate"
)]
AsrcbUserDataSgnFail,
// errors from other crates
#[error(transparent)]
PvCore(#[from] pv_core::Error),
#[error(transparent)]
Io(#[from] std::io::Error),
#[error(transparent)]
#[cfg(feature = "request")]
Crypto(#[from] openssl::error::ErrorStack),
#[error(transparent)]
ParseInt(#[from] std::num::ParseIntError),
#[cfg(feature = "request")]
#[error(transparent)]
Curl(#[from] curl::Error),
}
// used in macros
#[doc(hidden)]
impl Error {
pub const CRL: &str = "CRL";
pub const CERT: &str = "certificate";
}
/// Error cases for I/O operations
#[allow(missing_docs)]
#[derive(thiserror::Error, Debug)]
#[non_exhaustive]
pub enum FileIoErrorType {
#[error("read")]
Read,
#[error("write")]
Write,
}
/// Error cases for accessing files
#[allow(missing_docs)]
#[derive(thiserror::Error, Debug)]
#[non_exhaustive]
pub enum FileAccessErrorType {
#[error("open")]
Open,
#[error("create")]
Create,
pub const CRL: &'static str = "CRL";
pub const CERT: &'static str = "certificate";
}
/// Error cases for verifying host-key documents
///
#[doc = crate::requires_feat!(request)]
#[allow(missing_docs)]
#[derive(thiserror::Error, Debug, PartialEq, Eq)]
#[non_exhaustive]
#[cfg(feature = "request")]
pub enum HkdVerifyErrorType {
#[error("Signature verification failed")]
Signature,
@@ -160,37 +120,11 @@ pub enum HkdVerifyErrorType {
IbmSignInvalid(#[source] openssl::x509::X509VerifyResult, u32),
}
macro_rules! path_to_str {
($path: expr) => {
$path.as_ref().to_str().unwrap_or("no UTF-8 path")
};
}
pub(crate) use path_to_str;
macro_rules! file_error {
($ty: tt, $ctx: expr, $path:expr, $src: expr) => {
$crate::Error::FileIo {
ty: $crate::FileIoErrorType::$ty,
ctx: $ctx.to_string(),
path: $path.to_string(),
source: $src,
}
};
}
pub(crate) use file_error;
#[cfg(feature = "request")]
macro_rules! bail_hkd_verify {
($var: tt) => {
return Err($crate::Error::HkdVerify($crate::HkdVerifyErrorType::$var))
};
}
#[cfg(feature = "request")]
pub(crate) use bail_hkd_verify;
macro_rules! bail_spec {
($str: expr) => {
return Err($crate::Error::Specification($str.to_string()))
};
}
pub(crate) use bail_spec;
use crate::request::uvsecret::UserDataType;

View File

@@ -2,7 +2,6 @@
//
// Copyright IBM Corp. 2023
#![allow(macro_expanded_macro_exports_accessed_by_absolute_paths)]
#![deny(missing_docs)]
//! pv - library for pv-tools
//!
@@ -11,155 +10,85 @@
//! `pv` provides abstraction layers for encryption, secure memory management,
//! logging, and accessing the uvdevice.
//!
//! ## Feature Flags
//! The following feature flags are available:
//! - `request`
//! - optional
//! - Enables generation of UV requests
//! - `uvsecret`
//! - optional
//! - Enables support for the UV Secret API.
//! If you do not need any OpenSSL features use `pv_core`.
//! This crate reexports all symbols from `pv_core`
mod brcb;
mod cli;
mod crypto;
mod error;
mod log;
mod req;
mod secret;
mod utils;
mod uvdevice;
mod uvsecret;
mod verify;
/// Internal macro to conveninetly document required features on items
// #[macro_export]
/// utility functions for writing TESTS!!!
//hide any test helpers on docs!
#[doc(hidden)]
macro_rules! requires_feat {
(request) => {
" Requires the feature `request`"
};
(uvsecret) => {
" Requires the feature `uvsecret`"
};
(reqsecret) => {
"Requires the features `request` & `uvsecret`"
};
}
#[allow(unused_imports)]
use requires_feat;
//only some features need this
#[allow(dead_code)]
pub mod test_utils;
pub use ::utils::assert_size;
pub use ::utils::static_assert;
const PAGESIZE: usize = 0x1000;
cfg_if::cfg_if! {
if #[cfg(feature = "request")] {
mod brcb;
mod cli;
mod crypto;
mod req;
mod secret;
mod uvsecret;
mod verify;
/// utility functions for writing TESTS!!!
#[allow(dead_code)]
//hide any test helpers on docs!
#[doc(hidden)]
pub mod test_utils;
}
}
/// Definitions and functions for interacting with the Ultravisor
pub mod uv {
pub use crate::uvdevice::{
pub use pv_core::uv::{
uv_ioctl, ConfigUid, UvCmd, UvDevice, UvDeviceInfo, UvFlags, UvcSuccess,
};
#[cfg(feature = "uvsecret")]
pub use crate::uvsecret::{
secret_list::SecretList,
uvc::{AddCmd, ListCmd, LockCmd},
};
pub use pv_core::uv::{AddCmd, ListCmd, LockCmd};
pub use pv_core::uv::{ListableSecretType, SecretEntry, SecretList};
}
/// Miscellaneous functions and definitions
pub mod misc {
#[cfg(feature = "request")]
pub use crate::cli::{
get_reader_from_cli_file_arg, get_writer_from_cli_file_arg, CertificateOptions, STDIN,
STDOUT,
};
pub use crate::log::PvLogger;
pub use crate::utils::{
memeq, parse_hex, pv_guest_bit_set, read, read_exact_file, read_file, to_u16, to_u32,
try_parse_u128, try_parse_u64, write, write_file, Flags, Lsb0Flags64, Msb0Flags64,
};
#[cfg(feature = "request")]
pub use crate::utils::{read_certs, read_crls};
pub use crate::utils::{read_certs, read_crls, read_private_key};
pub use pv_core::misc::*;
pub use pv_core::PvLogger;
}
#[cfg(feature = "request")]
pub use crate::error::HkdVerifyErrorType;
pub use error::{Error, FileAccessErrorType, FileIoErrorType, Result};
pub use error::{Error, Result};
/// Functionalities to build UV requests
#[doc = requires_feat!(request)]
pub mod request {
pub use crate::brcb::{BootHdrMagic, BootHdrTags};
pub use crate::crypto::derive_key;
pub use crate::crypto::random_array;
pub use crate::crypto::{encrypt_aes_gcm, gen_ec_key};
pub use crate::crypto::{hash, hkdf_rfc_5869};
pub use crate::crypto::{sign_msg, verify_signature};
pub use crate::crypto::{Aes256Key, SymKey, SymKeyType};
pub use crate::req::{Aad, BinReqValues, Encrypt, Keyslot, ReqEncrCtx, Request};
pub use crate::secret::{Secret, Zeroize};
pub use crate::verify::{CertVerifier, HkdVerifier, NoVerifyHkd};
cfg_if::cfg_if! {
if #[cfg(feature = "request")] {
pub use crate::brcb::{BootHdrTags, BootHdrMagic};
pub use crate::crypto::{
derive_key, encrypt_aes, encrypt_aes_gcm, gen_ec_key, hash, hkdf_rfc_5869,
random_array, Aes256Key, SymKey, SymKeyType,
};
pub use crate::req::{Aad, Encrypt, Keyslot, ReqEncrCtx, Request};
pub use crate::secret::{Secret, Zeroize};
pub use crate::verify::HkdVerifier;
/// Reexports some useful OpenSSL symbols
///
#[doc = requires_feat!(request)]
pub mod openssl {
pub use openssl::error::ErrorStack;
pub use openssl::hash::MessageDigest;
pub use openssl::md::Md;
pub use openssl::pkey;
}
}
/// Reexports some useful OpenSSL symbols
pub mod openssl {
pub use openssl::error::ErrorStack;
pub use openssl::hash::MessageDigest;
pub use openssl::md::Md;
pub use openssl::pkey;
}
cfg_if::cfg_if! {
if #[cfg(feature = "uvsecret")] {
/// Functionalities for creating add-secret requests
pub mod uvsecret {
#[cfg(feature = "request")]
pub use crate::uvsecret::{
asrcb::{AddSecretFlags, AddSecretRequest, AddSecretVersion,},
ext_secret::ExtSecret,
guest_secret::GuestSecret,
};
pub use crate::uvsecret::AddSecretMagic;
pub use crate::uvsecret::UserDataType;
}
}
}
/// Version number of the request in system-endian
pub type RequestVersion = u32;
/// Request magic value
///
/// The first 8 byte of a request providing an identifier of the request type
/// for programs
pub type RequestMagic = [u8; 8];
/// A `MagicValue` is a bytepattern, that indicates if a byte slice contains the specified
/// (binary) data.
pub trait MagicValue<const N: usize> {
/// Magic value as byte array
const MAGIC: [u8; N];
/// Test whether the given slice starts with the magic value.
fn starts_with_magic(v: &[u8]) -> bool {
if v.len() < Self::MAGIC.len() {
return false;
}
crate::misc::memeq(&v[..Self::MAGIC.len()], &Self::MAGIC)
}
/// Functionalities for creating add-secret requests
pub mod uvsecret {
pub use crate::uvsecret::{
asrcb::{AddSecretFlags, AddSecretRequest, AddSecretVersion},
ext_secret::ExtSecret,
guest_secret::GuestSecret,
user_data::verify_asrcb_and_get_user_data,
};
pub use pv_core::request::uvsecret::AddSecretMagic;
pub use pv_core::request::uvsecret::UserDataType;
}
pub use pv_core::request::RequestMagic;
}
/// Provides cargo version Info about this crate.
@@ -168,39 +97,3 @@ pub mod request {
pub const fn crate_info() -> &'static str {
concat!(env!("CARGO_PKG_NAME"), "-crate ", env!("CARGO_PKG_VERSION"))
}
#[doc(hidden)]
#[macro_export]
macro_rules! file_acc_error {
($ty: tt, $path:expr, $src: expr) => {
$crate::Error::FileAccess {
ty: $crate::FileAccessErrorType::$ty,
path: $path.to_string(),
source: $src,
}
};
}
#[macro_export]
/// Create a file wrapped in a [BufWriter]
///
/// [BufWriter]: std::io#BufWriter
macro_rules! create_buffered_file {
($path: expr) => {
std::io::BufWriter::new(
std::fs::File::create($path).map_err(|e| $crate::file_acc_error!(Create, $path, e))?,
)
};
}
#[macro_export]
/// Open a file wrapped in a [BufReader]
///
/// [BufReader]: std::io#BufReader
macro_rules! open_buffered_file {
($path: expr) => {
std::io::BufReader::new(
std::fs::File::open($path).map_err(|e| $crate::file_acc_error!(Open, $path, e))?,
)
};
}

View File

@@ -2,19 +2,21 @@
//
// Copyright IBM Corp. 2023
use crate::crypto::AES_256_GCM_TAG_SIZE;
use crate::misc::to_u32;
use crate::request::{
derive_key, encrypt_aes, encrypt_aes_gcm, gen_ec_key, random_array, RequestMagic,
RequestVersion, SymKey, SymKeyType,
};
use crate::request::{derive_key, encrypt_aes_gcm, gen_ec_key, random_array, SymKey, SymKeyType};
use crate::{Error, Result};
use openssl::bn::{BigNum, BigNumContext};
use openssl::ec::{EcGroupRef, EcPointRef};
use openssl::error::ErrorStack;
use openssl::hash::{hash, MessageDigest};
use openssl::pkey::{PKey, PKeyRef, Private, Public};
use pv_core::request::{RequestMagic, RequestVersion};
use std::convert::TryInto;
use zerocopy::{AsBytes, BigEndian, FromBytes, U32};
use std::mem::size_of;
use std::ops::Range;
use utils::assert_size;
use zerocopy::{AsBytes, BigEndian, FromBytes, FromZeroes, U32};
/// Encrypt a _secret_ using self and a given private key.
pub trait Encrypt {
@@ -94,7 +96,7 @@ impl Encrypt for Keyslot {
to: &mut Vec<u8>,
) -> Result<()> {
let derived_key = derive_key(priv_key, &self.0)?;
let mut wrpk_and_kst = encrypt_aes_gcm(&derived_key.into(), &[0; 12], &[], prot_key)?;
let (mut wrpk_and_kst, ..) = encrypt_aes_gcm(&derived_key.into(), &[0; 12], &[], prot_key)?;
let phk: EcdhPubkeyCoord = self.0.as_ref().try_into()?;
to.reserve(80);
@@ -215,10 +217,11 @@ impl ReqEncrCtx {
}
}
let rql = to_u32(auth_data.len() + encr_size + 16)
.ok_or_else(|| Error::Specification("Configured request size to large".to_string()))?;
let rql = to_u32(auth_data.len() + encr_size + 16).ok_or_else(|| {
pv_core::Error::Specification("Configured request size to large".to_string())
})?;
let sea = to_u32(encr_size)
.ok_or_else(|| Error::Specification("Encrypted size to large".to_string()))?;
.ok_or_else(|| pv_core::Error::Specification("Encrypted size to large".to_string()))?;
let req_hdr = RequestHdr::new(version, rql, self.iv, nks, sea, magic);
// copy request header to the start of the request
@@ -235,17 +238,6 @@ impl ReqEncrCtx {
self.priv_key.as_ref().try_into().map_err(Error::Crypto)
}
/// Encrypt confidential Data with this encryption context.
///
/// * `conf` - data to be encrypted
///
/// # Errors
///
/// This function will return an error if the data could not be encrypted by OpenSSL.
pub fn encrypt(&self, conf: &[u8]) -> Result<Vec<u8>> {
encrypt_aes(&self.prot_key, &self.iv, conf)
}
/// Encrypt confidential Data with this encryption context and provide a gcm tag.
///
/// * `aad` - additional authentic data
@@ -260,7 +252,11 @@ impl ReqEncrCtx {
/// # Errors
///
/// This function will return an error if the data could not be encrypted by OpenSSL.
pub fn encrypt_aead(&self, aad: &[u8], conf: &[u8]) -> Result<Vec<u8>> {
pub fn encrypt_aead(
&self,
aad: &[u8],
conf: &[u8],
) -> Result<(Vec<u8>, Range<usize>, Range<usize>, Range<usize>)> {
encrypt_aes_gcm(&self.prot_key, &self.iv, aad, conf)
}
}
@@ -309,7 +305,7 @@ ecdh_from!(Public);
/// Representation of the shared parts of the request header.
/// Used by [`ReqEncrCtx`]
#[repr(C)]
#[derive(Debug, Copy, Clone, AsBytes, FromBytes)]
#[derive(Debug, Copy, Clone, AsBytes, FromBytes, FromZeroes)]
struct RequestHdr {
magic: [u8; 8],
rqvn: U32<BigEndian>,
@@ -321,6 +317,7 @@ struct RequestHdr {
reserved28: u32,
sea: U32<BigEndian>,
}
assert_size!(RequestHdr, 48);
impl RequestHdr {
fn new(rqvn: u32, rql: u32, iv: [u8; 12], nks: u8, sea: u32, magic: Option<[u8; 8]>) -> Self {
@@ -379,6 +376,67 @@ pub trait Request {
fn add_hostkey(&mut self, hostkey: PKey<Public>);
}
/// A struct to represent some parts of a binary/encrypted request.
#[derive(Debug)]
#[allow(unused)]
#[allow(clippy::len_without_is_empty)]
pub struct BinReqValues<'a> {
iv: &'a [u8],
aad: &'a [u8],
req_dep_aad: &'a [u8],
encr: &'a [u8],
tag: &'a [u8],
version: u32,
len: usize,
}
impl<'a> BinReqValues<'a> {
pub(crate) const TAG_LEN: usize = AES_256_GCM_TAG_SIZE;
/// Get the locations from this request.
///
/// Does minimal sanity test, just tests to prevent panics.
/// `req` may be larger than the actual request.
pub fn get(req: &'a [u8]) -> Result<Self> {
let hdr = RequestHdr::read_from_prefix(req).ok_or(Error::BinRequestSmall)?;
let rql = hdr.rql.get() as usize;
let sea = hdr.sea.get() as usize;
if rql < req.len() || sea + Self::TAG_LEN > rql {
return Err(Error::BinRequestSmall);
}
let aad_size = rql - sea - Self::TAG_LEN;
if aad_size < size_of::<RequestHdr>() {
return Err(Error::BinRequestSmall);
}
let iv = &req[0x10..0x1c];
let aad = &req[..aad_size];
let req_dep_aad = &req[size_of::<RequestHdr>()..aad_size];
let encr = &req[aad_size..(aad_size + sea)];
let tag = &req[rql - Self::TAG_LEN..];
Ok(Self {
iv,
aad,
req_dep_aad,
encr,
tag,
version: hdr.rqvn.get(),
len: rql,
})
}
/// Returns the version of this [`BinReqValues`].
pub fn version(&self) -> u32 {
self.version
}
/// Returns the length of this [`BinReqValues`].
pub fn len(&self) -> usize {
self.len
}
}
#[cfg(test)]
mod tests {
use super::*;

View File

@@ -1,336 +1,18 @@
// SPDX-License-Identifier: MIT
//
// Copyright IBM Corp. 2023
use crate::{
error::{bail_spec, file_error, path_to_str},
Error, FileIoErrorType, Result,
use crate::{Error, Result};
use openssl::{
pkey::{PKey, Private},
x509::{X509Crl, X509},
};
#[cfg(feature = "request")]
use openssl::x509::X509Crl;
#[cfg(feature = "request")]
use openssl::x509::X509;
use std::io::{Read, Write};
use std::path::Path;
use zerocopy::{AsBytes, BigEndian, FromBytes, U64};
/// Asserts a constant expression evaluates to `true`.
///
/// If the expression is not evaluated to `true` the compilation will fail.
#[macro_export]
macro_rules! static_assert {
($condition:expr) => {
const _: () = core::assert!($condition);
};
}
/// Asserts that a type has a specific size.
///
/// Useful to validate structs that are passed to C code.
/// If the expression is not evaluated to `true` the compilation will fail.
///
/// # Example
/// ```rust
/// # use pv::assert_size;
/// # fn main() {}
/// #[repr(C)]
/// struct c_struct {
/// v: u64,
/// }
/// assert_size!(c_struct, 8);
/// // assert_size!(c_struct, 7);//won't compile
/// ```
#[macro_export]
macro_rules! assert_size {
($t:ty, $sz:expr ) => {
$crate::static_assert!(::std::mem::size_of::<$t>() == $sz);
};
}
/// Trait that describes bitflags, represented by `T`.
pub trait Flags<T>: From<T> + for<'a> From<&'a T> {
/// Set the specified bit to one.
/// # Panics
///Panics if bit is >= 64
fn set_bit(&mut self, bit: u8);
/// Set the specified bit to zero.
/// # Panics
///Panics if bit is >= 64
fn unset_bit(&mut self, bit: u8);
/// Test if the specified bit is set.
/// # Panics
///Panics if bit is >= 64
fn is_set(&self, bit: u8) -> bool;
}
/// Bitflags in MSB0 ordering
///
/// Wraps an u64 to set/get individual bits
#[repr(C)]
#[derive(Debug, Clone, Copy, Default, AsBytes, FromBytes)]
pub struct Msb0Flags64(U64<BigEndian>);
impl Flags<u64> for Msb0Flags64 {
#[track_caller]
fn set_bit(&mut self, bit: u8) {
assert!(bit < 64, "Flag bit set to greater than 63");
let mut v = self.0.get();
v |= 1 << (63 - bit);
self.0.set(v)
}
#[track_caller]
fn unset_bit(&mut self, bit: u8) {
assert!(bit < 64, "Flag bit set to greater than 63");
let mut v = self.0.get();
v &= !(1 << (63 - bit));
self.0.set(v)
}
#[track_caller]
fn is_set(&self, bit: u8) -> bool {
assert!(bit < 64, "Flag bit set to greater than 63");
self.0.get() & (1 << (63 - bit)) > 0
}
}
impl From<u64> for Msb0Flags64 {
fn from(value: u64) -> Self {
Self(value.into())
}
}
impl From<&u64> for Msb0Flags64 {
fn from(value: &u64) -> Self {
(*value).into()
}
}
/// Bitflags in LSB0 ordering
///
/// Wraps an u64 to set/get individual bits
#[repr(C)]
#[derive(Debug, Clone, Copy, Default, AsBytes, FromBytes)]
pub struct Lsb0Flags64(U64<BigEndian>);
impl Flags<u64> for Lsb0Flags64 {
#[track_caller]
fn set_bit(&mut self, bit: u8) {
assert!(bit < 64, "Flag bit set to greater than 63");
let mut v = self.0.get();
v |= 1 << bit;
self.0.set(v)
}
#[track_caller]
fn unset_bit(&mut self, bit: u8) {
assert!(bit < 64, "Flag bit set to greater than 63");
let mut v = self.0.get();
v &= !(1 << bit);
self.0.set(v)
}
#[track_caller]
fn is_set(&self, bit: u8) -> bool {
assert!(bit < 64, "Flag bit set to greater than 63");
self.0.get() & (1 << bit) > 0
}
}
impl From<u64> for Lsb0Flags64 {
fn from(value: u64) -> Self {
Self(value.into())
}
}
impl From<&u64> for Lsb0Flags64 {
fn from(value: &u64) -> Self {
(*value).into()
}
}
/// Tries to convert a BE hex string into a 128 unsigned integer
/// The hexstring must contain 32chars of hexdigits
///
/// * `hex_str` - string to convert can be prepended with "0x"
/// * `ctx` - Error context string in case of an error
/// ```rust
/// # use std::error::Error;
/// # use pv::misc::try_parse_u128;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// let hex = "11223344556677889900aabbccddeeff";
/// try_parse_u128(&hex, "The test")?;
/// # Ok(())
/// # }
/// ```
///
/// # Errors
/// If `hex_string` is not a 32 byte hex string an Error appears
pub fn try_parse_u128(hex_str: &str, ctx: &str) -> Result<[u8; 16]> {
let hex_str = if hex_str.starts_with("0x") {
hex_str.split_at(2).1
} else {
hex_str
};
if hex_str.len() != 32 {
bail_spec!(format!(
"{ctx} hexstring must be 32chars long to cover all 16 bytes"
));
}
parse_hex(hex_str).try_into().map_err(|_| {
Error::Specification(format!(
"{ctx} hexstring must be 32chars long to cover all 16 bytes"
))
})
}
/// Tries to convert a BE hex string into a 64 unsigned integer
/// The hexstring must *NOT* contain 16 chars of hexdigits, but
/// 16 chars at most.
///
/// * `hex_str` - string to convert can be prepended with "0x"
/// * `ctx` - Error context string in case of an error
/// ```rust
/// # use std::error::Error;
/// # use pv::misc::try_parse_u64;
/// # fn main() -> Result<(), Box<dyn Error>> {
/// let hex = "1234567890abcdef";
/// try_parse_u64(&hex, "The test")?;
/// # Ok(())
/// # }
/// ```
///
/// # Errors
/// If `hex_string` is not a 32 byte hex string an Error appears
pub fn try_parse_u64(hex_str: &str, ctx: &str) -> Result<u64> {
let hex_str = if hex_str.starts_with("0x") {
hex_str.split_at(2).1
} else {
hex_str
};
if hex_str.len() > 16 {
bail_spec!(format!(
"{ctx} hexstring {hex_str} must be max 16 chars long"
));
}
Ok(u64::from_str_radix(hex_str, 16)?)
}
/// Read exactly COUNT bytes into the buffer.
///
/// * `path` - Path to file
/// * `ctx` - Error context string in case of an error
///
/// # Errors
/// If this function encounters an "end of file" before completely filling
/// the buffer, it returns an error. The contents of `buf` are unspecified in this case.
///
/// If any other read error is encountered then this function immediately
/// returns. The contents of `buf` are unspecified in this case.
///
/// If this function returns an error, it is unspecified how many bytes it
/// has read, but it will never read more than would be necessary to
/// completely fill the buffer.
pub fn read_exact_file<P: AsRef<Path>, const COUNT: usize>(
path: P,
ctx: &str,
) -> Result<[u8; COUNT]> {
let mut f = std::fs::File::open(&path).map_err(|e| Error::FileAccess {
ty: crate::FileAccessErrorType::Open,
path: path_to_str!(path).to_string(),
source: e,
})?;
if f.metadata()?.len() as usize != COUNT {
bail_spec!(format!("{ctx} must be exactly {COUNT} bytes long"));
}
let mut buf = [0; COUNT];
f.read_exact(&mut buf)
.map_err(|e| file_error!(Read, ctx, path_to_str!(path).to_string(), e))?;
Ok(buf)
}
/// Read content from a file and add context in case of an error
///
/// * `path` - Path to file
/// * `ctx` - Error context string in case of an error
///
///
/// # Errors
/// Passes through any kind of error `std::fs::read` produces
pub fn read_file<P: AsRef<Path>>(path: P, ctx: &str) -> Result<Vec<u8>> {
std::fs::read(&path).map_err(|e| {
file_error!(
Read,
ctx,
path.as_ref().to_str().unwrap_or("no UTF-8 path"),
e
)
})
}
/// Reads all content from a [`std::io::Read`] and add context in case of an error
///
/// * `path` - Path to file
/// * `ctx` - Error context string in case of an error
///
///
/// # Errors
/// Passes through any kind of error `std::fs::write` produces
pub fn read<R: Read>(rd: &mut R, path: &str, ctx: &str) -> Result<Vec<u8>> {
let mut buf = vec![];
rd.read_to_end(&mut buf).map_err(|e| Error::FileIo {
ty: FileIoErrorType::Write,
ctx: ctx.to_string(),
path: path.to_string(),
source: e,
})?;
Ok(buf)
}
/// write content to a file and add context in case of an error
///
/// * `path` - Path to file
/// * `ctx` - Error context string in case of an error
///
///
/// # Errors
/// Passes through any kind of error `std::fs::write` produces
pub fn write_file<D: AsRef<[u8]>>(path: &str, data: D, ctx: &str) -> Result<()> {
std::fs::write(path, data.as_ref()).map_err(|e| Error::FileIo {
ty: FileIoErrorType::Write,
ctx: ctx.to_string(),
path: path.to_string(),
source: e,
})
}
/// Write content to a [`std::io::Write`] and add context in case of an error
///
/// * `path` - Path to file
/// * `ctx` - Error context string in case of an error
///
///
/// # Errors
/// Passes through any kind of error `std::fs::write` produces
pub fn write<D: AsRef<[u8]>, W: Write>(wr: &mut W, data: D, path: &str, ctx: &str) -> Result<()> {
wr.write_all(data.as_ref()).map_err(|e| Error::FileIo {
ty: FileIoErrorType::Write,
ctx: ctx.to_string(),
path: path.to_string(),
source: e,
})
}
/// Read all CRLs from the buffer and parse them into a vector.
///
/// # Errors
///
/// This function will return an error if the underlying openssl implementation cannot parse `buf`
/// This function will return an error if the underlying OpenSSL implementation cannot parse `buf`
/// as `DER` or `PEM`.
///
/// Requires the `request` feature.
#[cfg(feature = "request")]
pub fn read_crls(buf: &[u8]) -> Result<Vec<X509Crl>> {
use openssl_extensions::crl::StackableX509Crl;
X509Crl::from_der(buf)
@@ -343,11 +25,8 @@ pub fn read_crls(buf: &[u8]) -> Result<Vec<X509Crl>> {
///
/// # Errors
///
/// This function will return an error if the underlying openssl implementation cannot parse `buf`
/// as `DER` or `PEM`.
///
/// Requires the `request` feature.
#[cfg(feature = "request")]
/// This function will return an error if the underlying OpenSSL implementation cannot parse `buf`
pub fn read_certs(buf: &[u8]) -> Result<Vec<X509>> {
X509::from_der(buf)
.map(|crt| vec![crt])
@@ -355,191 +34,23 @@ pub fn read_certs(buf: &[u8]) -> Result<Vec<X509>> {
.map_err(Error::Crypto)
}
macro_rules! usize_to_ui {
($(#[$attr:meta])* => $t: ident, $name:ident) => {
///Converts an [`usize`] to an [`
$(#[$attr])*
///`] if possible
pub fn $name(u: usize) -> Option<$t> {
if u > $t::MAX as usize {
None
} else {
Some(u as $t)
}
}
}
}
usize_to_ui! {
#[doc = r"u32"]
=> u32, to_u32}
usize_to_ui! {
#[doc = r"u16"]
=> u16, to_u16}
/// Test if both slices contain the exact same bytes.
/// Read+parse the first key from the buffer.
///
/// Do not use this to compare cryptographic values (i.e. hashes)
pub fn memeq(lhs: &[u8], rhs: &[u8]) -> bool {
let size = lhs.len();
size == rhs.len()
&& unsafe {
let l = lhs as *const _ as _;
let r = rhs as *const _ as _;
(l as usize) == (r as usize) || libc::memcmp(l, r, size) == 0
}
}
/// Converts the hexstring into a byte vector.
/// # Errors
///
/// Stops if the end or until a non hex chat is found
pub fn parse_hex(hex_str: &str) -> Vec<u8> {
let mut hex_bytes = hex_str.as_bytes().iter().map_while(|b| match b {
b'0'..=b'9' => Some(b - b'0'),
b'a'..=b'f' => Some(b - b'a' + 10),
b'A'..=b'F' => Some(b - b'A' + 10),
_ => None,
});
let mut bytes = Vec::new();
while let (Some(h), Some(l)) = (hex_bytes.next(), hex_bytes.next()) {
bytes.push(h << 4 | l)
}
bytes
}
/// Report if the `prot_virt_guest` sysfs entry is one.
///
/// If the entry does not exist returns false.
///
/// for non-s390-architectures:
/// Returns always false
/// A non-s390 system cannot be a secure execution guest.
#[allow(unreachable_code)]
pub fn pv_guest_bit_set() -> bool {
#[cfg(not(target_arch = "s390x"))]
return false;
//s390 branch
let v = std::fs::read("/sys/firmware/uv/prot_virt_guest").unwrap_or_else(|_| vec![0]);
let v: u8 = String::from_utf8_lossy(&v[..1]).parse().unwrap_or(0);
v == 1
/// This function will return an error if the underlying OpenSSL implementation cannot parse `buf`
/// as `DER` or `PEM`.
pub fn read_private_key(buf: &[u8]) -> Result<PKey<Private>> {
PKey::private_key_from_der(buf)
.or_else(|_| PKey::private_key_from_pem(buf))
.map_err(Error::Crypto)
}
#[cfg(test)]
mod tests {
use std::usize;
use super::*;
#[cfg(feature = "request")]
use crate::test_utils::*;
use crate::{get_test_asset, test_utils::*};
#[test]
fn msb_flags() {
let v = 17;
let v_flag: Msb0Flags64 = v.into();
assert_eq!(v, v_flag.0.get());
let mut v: Msb0Flags64 = 4.into();
v.unset_bit(61);
assert_eq!(v.0.get(), 0);
v.set_bit(61);
assert_eq!(4, v.0.get());
let mut v = Msb0Flags64::default();
v.set_bit(0);
assert_eq!(&[0x80, 0, 0, 0, 0, 0, 0, 0], v.as_bytes());
v.set_bit(0);
assert_eq!(&[0x80, 0, 0, 0, 0, 0, 0, 0], v.as_bytes());
v.set_bit(1);
assert_eq!(&[0xc0, 0, 0, 0, 0, 0, 0, 0], v.as_bytes());
v.set_bit(2);
assert_eq!(&[0xe0, 0, 0, 0, 0, 0, 0, 0], v.as_bytes());
v.set_bit(3);
assert_eq!(&[0xf0, 0, 0, 0, 0, 0, 0, 0], v.as_bytes());
v.unset_bit(3);
assert_eq!(&[0xe0, 0, 0, 0, 0, 0, 0, 0], v.as_bytes());
v.unset_bit(3);
assert_eq!(&[0xe0, 0, 0, 0, 0, 0, 0, 0], v.as_bytes());
v.set_bit(16);
assert_eq!(&[0xe0, 0, 0x80, 0, 0, 0, 0, 0], v.as_bytes());
}
#[test]
#[should_panic]
fn msb_flags_set_panic() {
Msb0Flags64::default().set_bit(64)
}
#[test]
#[should_panic]
fn msb_flags_unset_panic() {
Msb0Flags64::default().unset_bit(64)
}
#[test]
fn lsb_flags() {
let v = 17;
let v_flag: Lsb0Flags64 = v.into();
assert_eq!(v, v_flag.0.get());
let mut v: Lsb0Flags64 = 4.into();
v.unset_bit(2);
assert_eq!(v.0.get(), 0);
v.set_bit(2);
assert_eq!(4, v.0.get());
let mut v = Lsb0Flags64::default();
v.set_bit(0);
assert_eq!(&[0, 0, 0, 0, 0, 0, 0, 1], v.as_bytes());
v.set_bit(0);
assert_eq!(&[0, 0, 0, 0, 0, 0, 0, 1], v.as_bytes());
v.set_bit(1);
assert_eq!(&[0, 0, 0, 0, 0, 0, 0, 3], v.as_bytes());
v.set_bit(2);
assert_eq!(&[0, 0, 0, 0, 0, 0, 0, 7], v.as_bytes());
v.set_bit(3);
assert_eq!(&[0, 0, 0, 0, 0, 0, 0, 0xf], v.as_bytes());
v.unset_bit(3);
assert_eq!(&[0, 0, 0, 0, 0, 0, 0, 7], v.as_bytes());
v.unset_bit(3);
assert_eq!(&[0, 0, 0, 0, 0, 0, 0, 7], v.as_bytes());
v.set_bit(16);
assert_eq!(&[0, 0, 0, 0, 0, 1, 0, 7], v.as_bytes());
}
#[test]
#[should_panic]
fn lsb_flags_set_panic() {
Lsb0Flags64::default().set_bit(64)
}
#[test]
#[should_panic]
fn lsb_flags_unset_panic() {
Lsb0Flags64::default().unset_bit(64)
}
#[test]
fn parse_hex() {
let s = "123456acbef0";
let exp = vec![0x12, 0x34, 0x56, 0xac, 0xbe, 0xf0];
assert_eq!(super::parse_hex(s), exp);
let s = "00123456acbef0";
let exp = vec![0, 0x12, 0x34, 0x56, 0xac, 0xbe, 0xf0];
assert_eq!(super::parse_hex(s), exp);
let s = "00123456acbef0ii90";
let exp = vec![0, 0x12, 0x34, 0x56, 0xac, 0xbe, 0xf0];
assert_eq!(super::parse_hex(s), exp);
}
#[test]
#[cfg(feature = "request")]
fn read_crls() {
let crl = get_cert_asset("ibm.crl");
let crl_der = get_cert_asset("der.crl");
@@ -550,7 +61,6 @@ mod tests {
}
#[test]
#[cfg(feature = "request")]
fn read_certs() {
let crt = get_cert_asset("ibm.crt");
let crt_der = get_cert_asset("der.crt");
@@ -561,98 +71,16 @@ mod tests {
}
#[test]
fn to_u32() {
assert_eq!(Some(17), super::to_u32(17));
assert_eq!(Some(0), super::to_u32(0));
assert_eq!(Some(u32::MAX), super::to_u32(u32::MAX as usize));
assert_eq!(None, super::to_u32(u32::MAX as usize + 1));
assert_eq!(None, super::to_u32(usize::MAX));
fn read_private_key() {
let key = get_test_asset!("keys/rsa3072key.pem");
let key = super::read_private_key(key).unwrap();
assert_eq!(key.rsa().unwrap().size(), 384);
}
#[test]
fn parse_u128() {
assert!(matches!(
try_parse_u128("123456", ""),
Err(Error::Specification(_))
));
assert!(matches!(
try_parse_u128("-1234", ""),
Err(Error::Specification(_))
));
assert!(matches!(
try_parse_u128("0011223344556677889900aabbccddeeff", ""),
Err(Error::Specification(_))
));
assert!(matches!(
try_parse_u128("dd11223344556677889900aabbccddeeff", ""),
Err(Error::Specification(_))
));
assert!(matches!(
try_parse_u128("-1223344556677889900aabbccddeeff", ""),
Err(Error::Specification(_))
));
assert!(matches!(
try_parse_u128("0x123456", ""),
Err(Error::Specification(_))
));
assert!(matches!(
try_parse_u128("-0x1234", ""),
Err(Error::Specification(_))
));
assert!(matches!(
try_parse_u128("0x0011223344556677889900aabbccddeeff", ""),
Err(Error::Specification(_))
));
assert!(matches!(
try_parse_u128("0xdd11223344556677889900aabbccddeeff", ""),
Err(Error::Specification(_))
));
assert!(matches!(
try_parse_u128("0x-1223344556677889900aabbccddeeff", ""),
Err(Error::Specification(_))
));
assert_eq!(
[
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00, 0xaa, 0xbb, 0xcc, 0xdd,
0xee, 0xff
],
try_parse_u128("11223344556677889900aabbccddeeff", "").unwrap()
);
assert_eq!(
[
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00, 0xaa, 0xbb, 0xcc, 0xdd,
0xee, 0xff
],
try_parse_u128("0x11223344556677889900aabbccddeeff", "").unwrap()
);
assert_eq!(
[
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd,
0xee, 0xff
],
try_parse_u128("00112233445566778899aabbccddeeff", "").unwrap()
);
assert_eq!(
[
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd,
0xee, 0xff
],
try_parse_u128("00112233445566778899aabbccddeeff", "").unwrap()
);
}
#[test]
fn memeq() {
let a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
let b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 1];
let c = [0, 0, 1, 2, 3, 4];
assert!(super::memeq(&a, &a));
assert!(super::memeq(&a, &a.clone()));
assert!(!super::memeq(&b, &a));
assert!(!super::memeq(&b, &c));
assert!(!super::memeq(&b, &[]));
fn read_private_key_fail() {
let key = get_test_asset!("exp/secure_guest.hdr");
let key = super::read_private_key(key);
assert!(key.is_err());
}
}

View File

@@ -2,79 +2,12 @@
//
// Copyright IBM Corp. 2023
#![cfg(feature = "uvsecret")]
//! Provides functionality to manage the UV secret store.
//!
//! Provides functionality to build `add-secret` requests.
//! Also provides interfaces, to dispatch `Add Secret`, `Lock Secret Store`,
//! and `List Secrets` requests,
#[cfg(feature = "request")]
pub mod asrcb;
#[cfg(feature = "request")]
pub mod ext_secret;
#[cfg(feature = "request")]
pub mod guest_secret;
pub mod secret_list;
pub mod uvc;
use crate::request::MagicValue;
use crate::requires_feat;
#[allow(unused_imports)] //used for more convenient docstring
use asrcb::AddSecretRequest;
/// Types of (non architectured) user data for [`AddSecretRequest`]
///
#[doc = requires_feat!(uvsecret)]
#[repr(u16)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, zerocopy::AsBytes)]
pub enum UserDataType {
/// Marker that the request does not contain any user data
Null = 0x0000,
}
/// The magic value used to identify an [`AddSecretRequest`]
///
/// The magic value is ASCII:
/// ```rust
/// # use pv::request::uvsecret::AddSecretMagic;
/// # use pv::request::MagicValue;
/// # fn main() {
/// # let magic =
/// # b"asrcbM"
/// # ;
/// # assert!(AddSecretMagic::starts_with_magic(magic));
/// # }
///```
///
#[doc = requires_feat!(uvsecret)]
#[repr(C)]
#[derive(Debug, Clone, Copy, zerocopy::AsBytes)]
pub struct AddSecretMagic {
magic: [u8; 6], // [0x61, 0x73, 0x72, 0x63, 0x62, 0x4D]
tp: UserDataType,
}
impl MagicValue<6> for AddSecretMagic {
// "asrcbM"
const MAGIC: [u8; 6] = [0x61, 0x73, 0x72, 0x63, 0x62, 0x4D];
}
impl From<UserDataType> for AddSecretMagic {
fn from(tp: UserDataType) -> Self {
Self {
magic: Self::MAGIC,
tp,
}
}
}
const SECRET_ID_SIZE: usize = 32;
fn ser_gsid<S>(id: &[u8; SECRET_ID_SIZE], ser: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let mut s = String::with_capacity(32 * 2 + 2);
s.push_str("0x");
let s = id.iter().fold(s, |acc, e| acc + &format!("{e:02x}"));
ser.serialize_str(&s)
}
pub mod user_data;

View File

@@ -2,23 +2,23 @@
//
// Copyright IBM Corp. 2023
use super::{AddSecretMagic, UserDataType};
use crate::requires_feat;
use super::user_data::UserData;
use crate::{
assert_size,
misc::Flags,
request::{
hkdf_rfc_5869,
openssl::{
pkey::{PKey, Public},
pkey::{PKey, Private, Public},
Md,
},
uvsecret::{ExtSecret, GuestSecret},
Aad, BootHdrTags, Keyslot, ReqEncrCtx, Request, RequestVersion, Secret,
Aad, BootHdrTags, Keyslot, ReqEncrCtx, Request, Secret,
},
uv::{ConfigUid, UvFlags},
Result,
};
use pv_core::request::RequestVersion;
use zerocopy::AsBytes;
/// Internal wrapper for Guest Secret, so that we can dump it in the form the UV wants it to be
@@ -52,6 +52,7 @@ impl From<GuestSecret> for BinGuestSecret {
}
}
/// Authenticated data w/o user data
#[repr(C)]
#[derive(Debug, Clone, Copy, AsBytes)]
struct ReqAuthData {
@@ -59,9 +60,8 @@ struct ReqAuthData {
boot_tags: BootHdrTags,
cuid: ConfigUid,
reserved90: [u8; 0x100],
prog_res190: [u8; 0x200],
}
assert_size!(ReqAuthData, 0x3e8);
assert_size!(ReqAuthData, 0x1e8);
impl ReqAuthData {
fn new<F: Into<UvFlags>>(boot_tags: BootHdrTags, flags: F) -> Self {
@@ -70,7 +70,6 @@ impl ReqAuthData {
boot_tags,
cuid: [0; 0x10],
reserved90: [0; 0x100],
prog_res190: [0; 0x200],
}
}
}
@@ -96,8 +95,6 @@ impl ReqConfData {
}
/// Flags for [`AddSecretRequest`]
///
#[doc = requires_feat!(reqsecret)]
#[derive(Default, Clone, Copy, Debug)]
pub struct AddSecretFlags(UvFlags);
impl AddSecretFlags {
@@ -123,8 +120,6 @@ impl From<AddSecretFlags> for UvFlags {
}
/// Versions for [`AddSecretRequest`]
///
#[doc = requires_feat!(reqsecret)]
#[repr(u32)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AddSecretVersion {
@@ -143,12 +138,6 @@ impl From<AddSecretVersion> for RequestVersion {
}
}
impl AddSecretMagic {
fn get(&self) -> crate::request::RequestMagic {
self.as_bytes().try_into().unwrap()
}
}
/// Add-secret request Control Block
///
/// An ASRCB wraps a secret to transport it securely to the Ultravisor.
@@ -158,6 +147,7 @@ impl AddSecretMagic {
/// _______________________________________________________________
/// | generic header (48)
/// | --------------------------------------------------- |
/// | Plaintext Add-Secret flags (8) |
/// | SE header tags: PLD(64) ALD(64) TLD(64) HeaderTag(16) |
/// | Configuration unique ID(16) (Attestation) |
/// | Optional, defaults to 0 |
@@ -173,18 +163,19 @@ impl AddSecretMagic {
/// | AES GCM Tag (16) |
/// |_____________________________________________________________|
///```
///
#[doc = requires_feat!(reqsecret)]
#[derive(Clone, Debug)]
pub struct AddSecretRequest {
magic: AddSecretMagic,
version: AddSecretVersion,
aad: ReqAuthData,
keyslots: Vec<Keyslot>,
conf: ReqConfData,
user_data: UserData,
}
impl AddSecretRequest {
/// Offset of the user-data in the add-secret request in bytes
pub(super) const V1_USER_DATA_OFFS: usize = 0x218;
/// Create a new add-secret request.
///
/// The request has no extension secret, no configuration UID, no host-keys,
@@ -204,7 +195,7 @@ impl AddSecretRequest {
aad: ReqAuthData::new(boot_tags, flags),
keyslots: vec![],
version,
magic: UserDataType::Null.into(),
user_data: UserData::Null,
}
}
@@ -238,18 +229,41 @@ impl AddSecretRequest {
&self.conf.secret.0
}
/// Add user-data to the Add-Secret request
///
/// (Signed) user-data is a non-architectual feature. It allows to add arbitrary
/// data (message) to the request, that is signed optionally with an user defined key.
/// Allowed keys are:
/// - no key (up to 512 bytes of message)
/// - EC SECP521R1 (up to 256 byte message)
/// - RSA 2048 bit (up to 256 byte message)
/// - RSA 3072 bit (up to 128 byte message)
///
/// The signature can be verified during the verification of the secret-request on the target machine.
pub fn set_user_data(&mut self, msg: Vec<u8>, skey: Option<PKey<Private>>) -> Result<()> {
self.user_data = UserData::new(skey, msg)?;
Ok(())
}
/// compiles the authenticated area of this request
fn aad(&self, ctx: &ReqEncrCtx, conf_len: usize) -> Result<Vec<u8>> {
let cust_pub_key = ctx.key_coords()?;
let secr_auth = self.conf.secret.dump_auth();
let user_data = self.user_data.data();
let mut aad: Vec<Aad> = Vec::with_capacity(3 + self.keyslots.len());
let mut aad: Vec<Aad> = Vec::with_capacity(5 + self.keyslots.len());
aad.push(Aad::Plain(self.aad.as_bytes()));
if let Some(data) = user_data.0 {
aad.push(Aad::Plain(data));
}
if let Some(data) = &user_data.1 {
aad.push(Aad::Plain(data));
}
aad.push(Aad::Plain(cust_pub_key.as_ref()));
self.keyslots.iter().for_each(|k| aad.push(Aad::Ks(k)));
aad.push(Aad::Plain(&secr_auth));
ctx.build_aad(self.version.into(), &aad, conf_len, self.magic.get())
ctx.build_aad(self.version.into(), &aad, conf_len, self.user_data.magic())
}
#[doc(hidden)]
@@ -268,13 +282,41 @@ impl AddSecretRequest {
res.append(&mut vec![0x24; 32]);
Ok(res)
}
/// encrypt data, sign request with user-provided signing key, insert signature into aad,
/// calculate request tag
fn encrypt_with_signed_user_data(&self, ctx: &ReqEncrCtx) -> Result<Vec<u8>> {
//encrypt data w/o aead
let conf = self.conf.to_bytes();
let aad = self.aad(ctx, conf.value().len())?;
let (mut buf, aad_range, encr_range, _) = ctx.encrypt_aead(&aad, conf.value())?;
drop(aad);
// sign aad+encrypted data (w/o tag) with user signning key
// add signature to authenticated data starting with USER_DATA_OFFS
self.user_data.sign(
&mut buf[aad_range.start..encr_range.end],
Self::V1_USER_DATA_OFFS,
)?;
// encrypt again with signed data
buf[encr_range.clone()].copy_from_slice(conf.value());
ctx.encrypt_aead(&buf[aad_range], &buf[encr_range])
.map(|(buf, ..)| buf)
}
}
impl Request for AddSecretRequest {
fn encrypt(&self, ctx: &ReqEncrCtx) -> Result<Vec<u8>> {
let conf = self.conf.to_bytes();
let aad = self.aad(ctx, conf.value().len())?;
ctx.encrypt_aead(&aad, conf.value())
match self.user_data {
UserData::Null | UserData::Unsigned(_) => {
let conf = self.conf.to_bytes();
let aad = self.aad(ctx, conf.value().len())?;
ctx.encrypt_aead(&aad, conf.value()).map(|(buf, ..)| buf)
}
_ => self.encrypt_with_signed_user_data(ctx),
}
}
fn add_hostkey(&mut self, hostkey: PKey<Public>) {

View File

@@ -2,11 +2,9 @@
//
// Copyright IBM Corp. 2023
use crate::{request::Secret, requires_feat};
use crate::request::Secret;
/// Extension Secret for [`crate::request::uvsecret::AddSecretRequest`]
///
#[doc = requires_feat!(reqsecret)]
#[derive(Debug, Clone)]
pub enum ExtSecret {
/// A bytepattern that must be equal for each request targeting the same SE-guest instance

View File

@@ -4,18 +4,16 @@
#[allow(unused_imports)] //used for more convenient docstring
use super::asrcb::AddSecretRequest;
use super::{ser_gsid, SECRET_ID_SIZE};
use crate::{
request::{hash, openssl::MessageDigest, random_array, Secret},
requires_feat, Result,
Result,
};
use pv_core::for_pv::{ser_gsid, SECRET_ID_SIZE};
use serde::{Deserialize, Serialize};
use std::convert::TryInto;
const SECRET_SIZE: usize = 32;
/// A Secret to be added in [`AddSecretRequest`]
///
#[doc = requires_feat!(reqsecret)]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum GuestSecret {
/// No guest secret

View File

@@ -1,224 +0,0 @@
// SPDX-License-Identifier: MIT
//
// Copyright IBM Corp. 2023
use crate::{misc::to_u16, uv::ListCmd, uvdevice::UvCmd, Error, Result};
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use serde::{Serialize, Serializer};
use std::usize;
use std::{
fmt::Display,
io::{Cursor, Read, Seek, Write},
};
use zerocopy::{AsBytes, FromBytes, U16, U32};
use super::ser_gsid;
/// List of secrets used to parse the [`crate::uv::ListCmd`] result
///
/// Requires the `uvsecret` feature.
#[derive(Debug, PartialEq, Eq, Serialize)]
pub struct SecretList {
total_num_secrets: u16,
secrets: Vec<SecretEntry>,
}
impl SecretList {
/// Encodes the list in the same binary format the UV would do
pub fn encode<T: Write>(&self, w: &mut T) -> Result<()> {
let num_s = to_u16(self.secrets.len()).ok_or(Error::ManySecrets)?;
w.write_u16::<BigEndian>(num_s)?;
w.write_u16::<BigEndian>(self.total_num_secrets)?;
w.write_all(&[0u8; 12])?;
for secret in &self.secrets {
w.write_all(secret.as_bytes())?;
}
w.flush().map_err(Error::Io)
}
/// Decodes the list from the binary format of the UV into this internal representation
pub fn decode<R: Read + Seek>(r: &mut R) -> std::io::Result<Self> {
let num_s = r.read_u16::<BigEndian>()?;
let total_num_secrets = r.read_u16::<BigEndian>()?;
let mut v: Vec<SecretEntry> = Vec::with_capacity(num_s as usize);
r.seek(std::io::SeekFrom::Current(12))?; //skip reserved bytes
let mut buf = [0u8; SECRET_ENTRY_SIZE];
for _ in 0..num_s {
r.read_exact(&mut buf)?;
//cannot fail. buffer has the same size as the secret entry
let secr = SecretEntry::read_from(buf.as_slice()).unwrap();
v.push(secr);
}
Ok(Self {
total_num_secrets,
secrets: v,
})
}
}
impl TryFrom<ListCmd> for SecretList {
type Error = Error;
fn try_from(mut list: ListCmd) -> Result<SecretList> {
SecretList::decode(&mut Cursor::new(list.data().unwrap())).map_err(Error::InvSecretList)
}
}
impl Display for SecretList {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "Total number of secrets: {}", self.total_num_secrets)?;
if !self.secrets.is_empty() {
writeln!(f)?;
}
for s in &self.secrets {
writeln!(f, "{s}")?;
}
Ok(())
}
}
fn ser_u32<S: Serializer>(v: &U32<BigEndian>, ser: S) -> Result<S::Ok, S::Error> {
ser.serialize_u32(v.get())
}
fn ser_u16<S: Serializer>(v: &U16<BigEndian>, ser: S) -> Result<S::Ok, S::Error> {
ser.serialize_u16(v.get())
}
/// A secret in a [`SecretList`]
///
/// Fields are in big endian
#[repr(C)]
#[derive(Debug, PartialEq, Eq, AsBytes, FromBytes, Serialize)]
pub struct SecretEntry {
#[serde(serialize_with = "ser_u16")]
index: U16<BigEndian>,
#[serde(serialize_with = "ser_u16")]
stype: U16<BigEndian>,
#[serde(serialize_with = "ser_u32")]
len: U32<BigEndian>,
#[serde(skip)]
res_8: u64,
#[serde(serialize_with = "ser_gsid")]
id: [u8; 32],
}
const SECRET_ENTRY_SIZE: usize = 0x30;
fn stype_str(stype: u16) -> String {
match stype {
// should never match (not incl in list), but here for completeness
1 => "Null".to_string(),
2 => "Association".to_string(),
n => format!("Unknown {n}"),
}
}
impl Display for SecretEntry {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "{} {}:", self.index, stype_str(self.stype.get()))?;
write!(f, " ")?;
for b in self.id {
write!(f, "{b:02x}")?;
}
Ok(())
}
}
#[cfg(test)]
mod test {
use super::*;
use std::io::{BufReader, BufWriter, Cursor};
#[test]
fn secret_entry_size() {
assert_eq!(::std::mem::size_of::<SecretEntry>(), SECRET_ENTRY_SIZE);
}
#[test]
fn dump_secret_entry() {
const EXP: &[u8] = &[
0x00, 0x01, 0x00, 0x02, //idx + type
0x00, 0x00, 0x00, 0x20, //len
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved
// id
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
];
let s = SecretEntry {
index: 1.into(),
stype: 2.into(),
len: 32.into(),
res_8: 0,
id: [0; 32],
};
assert_eq!(s.as_bytes(), EXP);
}
#[test]
fn secret_list_dec() {
let buf = [
0x00u8, 0x01, // num secr stored
0x01, 0x12, // total num secrets
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //reserved
// secret
0x00, 0x01, 0x00, 0x02, //idx + type
0x00, 0x00, 0x00, 0x20, //len
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved
// id
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
];
let exp = SecretList {
total_num_secrets: 0x112,
secrets: vec![SecretEntry {
index: 1.into(),
stype: 2.into(),
len: 32.into(),
res_8: 0,
id: [0; 32],
}],
};
let mut br = BufReader::new(Cursor::new(buf));
let sl = SecretList::decode(&mut br).unwrap();
assert_eq!(sl, exp);
}
#[test]
fn secret_list_enc() {
const EXP: &[u8] = &[
0x00, 0x01, // num secr stored
0x01, 0x12, // total num secrets
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //reserved
// secret
0x00, 0x01, 0x00, 0x02, //idx + type
0x00, 0x00, 0x00, 0x20, //len
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved
// id
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
];
let sl = SecretList {
total_num_secrets: 0x112,
secrets: vec![SecretEntry {
index: 1.into(),
stype: 2.into(),
len: 32.into(),
res_8: 0,
id: [0; 32],
}],
};
let mut buf = [0u8; 0x40];
{
let mut bw = BufWriter::new(&mut buf[..]);
sl.encode(&mut bw).unwrap();
}
println!("list: {sl:?}");
assert_eq!(buf, EXP);
}
}

View File

@@ -0,0 +1,611 @@
use crate::{
crypto::{sign_msg, verify_signature},
req::BinReqValues,
request::{
openssl::{
pkey::{PKey, Private},
MessageDigest,
},
uvsecret::{AddSecretRequest, AddSecretVersion},
RequestMagic,
},
Error, Result,
};
use openssl::{
nid::Nid,
pkey::{HasParams, HasPublic, Id, PKeyRef, Public},
};
use pv_core::request::uvsecret::AddSecretMagic;
use pv_core::request::uvsecret::UserDataType;
use utils::assert_size;
use zerocopy::{AsBytes, BigEndian, FromBytes, FromZeroes, U16};
/// User data.
///
/// User defined data can be:
/// - 512 bytes arbitrary data
/// - 256 bytes arbitrary data + EC(secp521r1) signature
/// ```none
/// LAYOUT
/// |------------------------|
/// | user-data (256) |
/// | ec signature (139) |
/// | reserved (5) |
/// | signature size (2) (BE)|
/// | reserved (110) |
/// |------------------------|
/// ```
/// - 256 bytes arbitrary data + RSA2048 signature
/// ```none
/// LAYOUT
/// |---------------------|
/// | user-data (256) |
/// | rsa signature (256) |
/// |---------------------|
/// ```
/// - 128 bytes arbitrary data + RSA3072 signature
/// ```none
/// LAYOUT
/// |---------------------|
/// | user-data (128) |
/// | rsa signature (384) |
/// |---------------------|
/// ```
///
/// Ensures that the data+signature fits into 512 bytes
/// must be created via functions!
#[derive(Debug, Clone)]
pub(super) enum UserData {
Null,
Unsigned(Vec<u8>),
Signed(SignedUserData),
}
#[repr(C)]
#[derive(Debug, AsBytes, FromBytes, FromZeroes)]
struct EcUserData {
data: [u8; 256],
signature: [u8; EC_SIGN_MAX_SIZE],
res_18b: [u8; 5],
sgn_size: U16<BigEndian>,
res_192: [u8; 110],
}
assert_size!(EcUserData, USER_DATA_SIZE);
const USER_DATA_SIZE: usize = 0x200;
const EC_SIGN_MAX_SIZE: usize = 139;
impl EcUserData {
// Sets the signature to this data.
//
//# Panic
// Panics if `sgn` is longer than 139 bytes
fn set_signature(&mut self, sgn: &[u8]) {
debug_assert!(sgn.len() <= EC_SIGN_MAX_SIZE);
self.signature.fill(0);
self.signature[..sgn.len()].copy_from_slice(sgn);
self.res_18b.fill(0);
self.sgn_size = (sgn.len() as u16).into();
self.res_192.fill(0);
}
}
#[derive(Debug, Clone)]
pub(super) struct SignedUserData {
sign_key: PKey<Private>,
data: Vec<u8>,
}
impl UserData {
const USER_DATA_SIZE: usize = 0x200;
fn user_data_type<P: HasPublic>(sign_key: &PKeyRef<P>) -> Result<UserDataType> {
fn check_curve<P: HasParams>(pkey: &PKeyRef<P>) -> Result<bool> {
let nid = pkey.ec_key()?.group().curve_name();
match nid {
Some(nid) => Ok(nid == Nid::SECP521R1),
None => Ok(false),
}
}
match sign_key.id() {
Id::EC if check_curve(sign_key)? => Ok(UserDataType::SgnEcSECP521R1),
Id::RSA if sign_key.rsa()?.size() == 2048 / 8 => Ok(UserDataType::SgnRsa2048),
Id::RSA if sign_key.rsa()?.size() == 3072 / 8 => Ok(UserDataType::SgnRsa3072),
_ => Err(Error::BinAsrcbUnsupportedUserDataSgnKey),
}
}
pub(super) fn magic(&self) -> RequestMagic {
let magic: AddSecretMagic = self.data_type().into();
magic.get()
}
/// Creates new user data
///
/// Verifies that the provided data + signature fits into 512 bytes
///
/// #Error
/// An error is reported if the provided data and the signature would not fit into 512 bytes
/// An error is reported if the key is not of type RSA (2048|3072) or EC(specp521r1)
pub(super) fn new(sign_key: Option<PKey<Private>>, data: Vec<u8>) -> Result<Self> {
let sign_key = match sign_key {
None => {
return match data.len() > UserDataType::Unsigned.max() {
true => Err(Error::AsrcbInvSgnUserData(UserDataType::Unsigned)),
false => Ok(Self::Unsigned(data)),
};
}
Some(skey) => skey,
};
let kind = Self::user_data_type(&sign_key)?;
// does the data fit into the arbitrary buffer?
if data.len() > kind.max() {
return Err(Error::AsrcbInvSgnUserData(kind));
}
Ok(Self::Signed(SignedUserData { sign_key, data }))
}
/// Signs data in buf, writes signature to buf+user_data_offset+sign_offset if applicable.
///
/// Uses [`MessageDigest::sha512`] as digest. Does not modify the abritary user data buffer.
///
/// * buf: user data buffer, must be at least 512 bytes long
///
/// # Panic
/// panics if `buf` is smaller than 512 bytes
///
/// # Errors
/// Returns an error if signature could not be calculated.
/// It is considered no error if no signature is required by user data type
pub(super) fn sign(&self, buf: &mut [u8], user_data_offset: usize) -> Result<()> {
// get signing info or return if no signature is required
let signed_data = match self {
UserData::Null | UserData::Unsigned(_) => return Ok(()),
UserData::Signed(s) => s,
};
debug_assert!(buf.len() >= USER_DATA_SIZE);
// clear the signature area
let sgn_offset = user_data_offset + self.data_type().max();
buf[sgn_offset..user_data_offset + USER_DATA_SIZE].fill(0);
// calculate signature
let sgn = sign_msg(&signed_data.sign_key, MessageDigest::sha512(), buf)?;
// insert signature
if let UserDataType::SgnEcSECP521R1 = self.data_type() {
// Panic: will not panic buffer is 512+ bytes long
let buf_ec = EcUserData::mut_from_prefix(&mut buf[user_data_offset..]).unwrap();
buf_ec.set_signature(&sgn);
} else {
// Panic: will not panic buffer is 512+ bytes long
buf[sgn_offset..sgn_offset + sgn.len()].copy_from_slice(&sgn);
}
Ok(())
}
fn data_type(&self) -> UserDataType {
match self {
Self::Null => UserDataType::Null,
Self::Unsigned(_) => UserDataType::Unsigned,
Self::Signed(data) => Self::user_data_type(&data.sign_key).unwrap(),
}
}
/// returns a slice for the abitraty user data as first tuple part if User data is available
/// the second part contains a vector, created on the fly, which contains enough zeros to fill
/// the missing bytes to fill 512 bytes of space or None if the first slice already contains
/// 512 bytes
pub(super) fn data(&self) -> (Option<&[u8]>, Option<Vec<u8>>) {
let buf = match self {
UserData::Null => None,
UserData::Unsigned(d) => Some(d),
UserData::Signed(SignedUserData { data, .. }) => Some(data),
};
let remaining_size = Self::USER_DATA_SIZE - buf.map(|b| b.len()).unwrap_or(0);
let remaining = match remaining_size > 0 {
true => Some(vec![0; remaining_size]),
false => None,
};
(buf.map(|b| b.as_ref()), remaining)
}
}
fn format_vrfy_key(key: &PKeyRef<Public>) -> String {
let id = key.id();
match key.rsa() {
Ok(key) => format!("RSA {}", key.size() * 8),
Err(_) if id == Id::EC => "EC".to_string(),
Err(_) => "Unknown".to_string(),
}
}
fn check_key_format(kind: UserDataType, key: &PKeyRef<Public>) -> Result<()> {
let other_kind =
UserData::user_data_type(key).map_err(|_| Error::AsrcbUserDataKeyMismatch {
key: format_vrfy_key(key),
kind,
})?;
if other_kind == kind {
Ok(())
} else {
Err(Error::AsrcbUserDataKeyMismatch {
key: format_vrfy_key(key),
kind,
})
}
}
/// Verify the user data contained in the add-secret request.
///
/// First checks that the provided data contains a sound add-secret request.
/// Then performs the inverse action that happened during the add-secret generation with user-data
/// signature:
/// - extract and replace the signature with zeros
/// - verify the signature of the request until, but not including the request tag
///
/// # Returns
///
/// Extracrted user-data if available
///
/// #Errors
///
/// returns an error if
/// - No sound add-secret request presented
/// - Sinned user-data indicated, but no key provided
/// - Another keytype provided than indicated in the request
/// - Signature could not be verified by the provided key
/// - any OpenSSL error that might happen during the verification process
pub fn verify_asrcb_and_get_user_data(
mut asrcb: Vec<u8>,
key: Option<PKey<Public>>,
) -> Result<Option<Vec<u8>>> {
// check that the provided buffer contains an Add Secret request
let magic = AddSecretMagic::try_from_bytes(&asrcb)?;
let req = BinReqValues::get(&asrcb)?;
if req.version() != AddSecretVersion::One as u32 {
return Err(Error::BinAsrcbInvVersion);
}
//preventing the two lines after the truncate from panicking
let req_len = req.len();
if asrcb.len() < req_len
|| req_len < AddSecretRequest::V1_USER_DATA_OFFS + UserData::USER_DATA_SIZE
{
return Err(pv_core::Error::NoAsrcb.into());
}
// forget the tag (and all additional data that might be behind the tag)
asrcb.truncate(req_len - BinReqValues::TAG_LEN);
// get a mutable refrenence on the 512 bytes of user data
let (_, user_data) = asrcb.split_at_mut(AddSecretRequest::V1_USER_DATA_OFFS);
let user_data = &mut user_data[..UserData::USER_DATA_SIZE];
// depending on the user_data_type do:
// Null -> exit w/o user data
// Unsigned -> exit return all user data
// Signed ->
// - check that provided key matches user data keytype
// - extract user data& signature
let (key, user_data) = match (key, magic.kind()) {
(_, UserDataType::Null) => return Ok(None),
(None, UserDataType::Unsigned) => return Ok(Some(user_data.to_vec())),
(Some(key), UserDataType::Unsigned) => {
return Err(Error::AsrcbUserDataKeyMismatch {
key: format_vrfy_key(&key),
kind: UserDataType::Unsigned,
})
}
(Some(key), _) => {
check_key_format(magic.kind(), &key)?;
(key, VerifiedUserData::new(user_data, magic.kind()))
}
(None, _) => return Err(Error::BinAsrcbNoUserDataSgnKey),
};
match verify_signature(&key, MessageDigest::sha512(), &asrcb, user_data.signature())? {
false => Err(Error::AsrcbUserDataSgnFail),
true => Ok(Some(user_data.into())),
}
}
// Internal representation of the 512 bytes of user-data, signing-algorithm agnostic
struct VerifiedUserData {
data: Vec<u8>,
signature: Vec<u8>,
}
impl VerifiedUserData {
/// Reads user-data from buf depending on the indicated user data type.
/// Overwrites the signature in the buf with zeros.
///
/// #Panics
/// Panics it provided buffer is smaller that 512 bytes or kind is Null or Unsigned
fn new(buf: &mut [u8], kind: UserDataType) -> Self {
assert!(buf.len() >= 0x200);
let (ret, sgn) = match kind {
UserDataType::SgnEcSECP521R1 => {
let EcUserData {
data,
signature,
sgn_size,
..
} = EcUserData::mut_from_prefix(buf).unwrap();
let data_len: usize = data.len();
let data = data.to_vec();
let mut signature = signature.to_vec();
signature.truncate(sgn_size.get() as usize);
(Self { data, signature }, &mut buf[data_len..])
}
UserDataType::SgnRsa2048 => (
Self {
data: buf[..0x100].to_vec(),
signature: buf[0x100..].to_vec(),
},
&mut buf[0x100..],
),
UserDataType::SgnRsa3072 => (
Self {
data: buf[..0x80].to_vec(),
signature: buf[0x80..].to_vec(),
},
&mut buf[0x80..],
),
UserDataType::Null => unreachable!(),
UserDataType::Unsigned => unreachable!(),
};
//overwrite signature field with zeros
sgn.fill(0);
ret
}
fn signature(&self) -> &[u8] {
self.signature.as_ref()
}
}
impl From<VerifiedUserData> for Vec<u8> {
fn from(value: VerifiedUserData) -> Self {
value.data
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::{get_test_asset, test_utils::get_test_keys};
#[test]
fn sign_null() {
let mut buf = vec![17; 0x200];
let user_data = UserData::Null;
let (data, _) = user_data.data();
assert!(data.is_none());
user_data.sign(&mut buf, 0).unwrap();
// sign should not touch the buffer
assert_eq!(buf, vec![17; 0x200]);
}
#[test]
fn sign_unsigned() {
let user_data = UserData::Unsigned(vec![0x11; 0x200]);
let (data, _) = user_data.data();
assert_eq!(data.unwrap(), &[0x11; 0x200]);
let mut buf = vec![17; 0x200];
user_data.sign(&mut buf, 0).unwrap();
// sign should not touch the buffer
assert_eq!(buf, vec![17; 0x200]);
}
#[test]
fn sign_rsa2048() {
let rsa = get_test_asset!("keys/rsa2048key.pem");
let rsa = PKey::private_key_from_pem(rsa).unwrap();
let mut buf = vec![0x17; 0x200];
let user_data = UserData::new(Some(rsa.clone()), vec![0x11; 0x100]).unwrap();
let (data, _) = user_data.data();
let data = data.unwrap();
buf[..0x100].copy_from_slice(data);
user_data.sign(&mut buf, 0).unwrap();
let vrf_user_data = VerifiedUserData::new(&mut buf, UserDataType::SgnRsa2048);
let res = verify_signature(
&rsa,
MessageDigest::sha512(),
&buf,
vrf_user_data.signature(),
)
.unwrap();
assert!(res);
}
#[test]
fn sign_rsa3072() {
let rsa = get_test_asset!("keys/rsa3072key.pem");
let rsa = PKey::private_key_from_pem(rsa).unwrap();
let mut buf = vec![0x17; 0x200];
let user_data = UserData::new(Some(rsa.clone()), vec![0x11; 0x80]).unwrap();
let (data, _) = user_data.data();
let data = data.unwrap();
buf[..0x80].copy_from_slice(data);
user_data.sign(&mut buf, 0).unwrap();
let vrf_user_data = VerifiedUserData::new(&mut buf, UserDataType::SgnRsa3072);
let res = verify_signature(
&rsa,
MessageDigest::sha512(),
&buf,
vrf_user_data.signature(),
)
.unwrap();
assert!(res);
}
#[test]
fn sign_rsa4096_fail() {
let rsa = get_test_asset!("keys/rsa4096key.pem");
let rsa = PKey::private_key_from_pem(rsa).unwrap();
let user_data = UserData::new(Some(rsa.clone()), vec![]);
assert!(matches!(
user_data.unwrap_err(),
Error::BinAsrcbUnsupportedUserDataSgnKey
));
}
#[test]
fn sign_ec() {
let (ec, _) = get_test_keys();
let mut buf = vec![0x11; 0x200];
let user_data = UserData::new(Some(ec.clone()), vec![0x11; 0x80]).unwrap();
let (data, _) = user_data.data();
let data = data.unwrap();
buf[..0x80].copy_from_slice(data);
user_data.sign(&mut buf, 0).unwrap();
let buf_ec = EcUserData::mut_from(&mut buf).unwrap();
let EcUserData {
data,
signature,
res_18b,
sgn_size,
res_192,
} = buf_ec;
assert_eq!(data, &[0x11u8; 256]);
assert_ne!(signature, &[0x11u8; 139]);
assert_eq!(res_18b, &[0u8; 5]);
assert!(sgn_size.get() <= 139);
assert_eq!(res_192, &[0u8; 110]);
let vrf_user_data = VerifiedUserData::new(&mut buf, UserDataType::SgnEcSECP521R1);
let res = verify_signature(
&ec,
MessageDigest::sha512(),
&buf,
vrf_user_data.signature(),
)
.unwrap();
assert!(res);
}
#[test]
fn sign_ec_fail() {
let ec = get_test_asset!("keys/ecsecp256k1.pem");
let ec = PKey::private_key_from_pem(ec).unwrap();
let user_data = UserData::new(Some(ec.clone()), vec![]);
assert!(matches!(
user_data.unwrap_err(),
Error::BinAsrcbUnsupportedUserDataSgnKey
));
}
#[test]
fn check_format() {
let (_, ec) = get_test_keys();
check_key_format(UserDataType::SgnEcSECP521R1, &ec).unwrap();
let res = check_key_format(UserDataType::SgnRsa2048, &ec);
assert!(matches!(res, Err(Error::AsrcbUserDataKeyMismatch { .. })));
let rsa = get_test_asset!("keys/rsa2048key.pub.pem");
let rsa = PKey::public_key_from_pem(rsa).unwrap();
check_key_format(UserDataType::SgnRsa2048, &rsa).unwrap();
let rsa = get_test_asset!("keys/rsa3072key.pub.pem");
let rsa = PKey::public_key_from_pem(rsa).unwrap();
check_key_format(UserDataType::SgnRsa3072, &rsa).unwrap();
let res = check_key_format(UserDataType::SgnRsa2048, &rsa);
assert!(matches!(res, Err(Error::AsrcbUserDataKeyMismatch { .. })));
let rsa = get_test_asset!("keys/rsa4096key.pem");
let rsa = PKey::private_key_from_pem(rsa).unwrap();
let rsa = PKey::public_key_from_pem(&rsa.public_key_to_pem().unwrap()).unwrap();
let res = check_key_format(UserDataType::SgnRsa2048, &rsa);
assert!(matches!(res, Err(Error::AsrcbUserDataKeyMismatch { .. })));
}
#[test]
fn kind() {
let (ec, _) = get_test_keys();
let kind = UserData::user_data_type(&ec).unwrap();
assert_eq!(kind, UserDataType::SgnEcSECP521R1);
let rsa = get_test_asset!("keys/rsa2048key.pem");
let rsa = PKey::private_key_from_pem(rsa).unwrap();
let kind = UserData::user_data_type(&rsa).unwrap();
assert_eq!(kind, UserDataType::SgnRsa2048);
let rsa = get_test_asset!("keys/rsa3072key.pem");
let rsa = PKey::private_key_from_pem(rsa).unwrap();
let kind = UserData::user_data_type(&rsa).unwrap();
assert_eq!(kind, UserDataType::SgnRsa3072);
let rsa = get_test_asset!("keys/rsa4096key.pem");
let rsa = PKey::private_key_from_pem(rsa).unwrap();
let kind = UserData::user_data_type(&rsa).unwrap_err();
assert!(matches!(kind, Error::BinAsrcbUnsupportedUserDataSgnKey));
}
#[test]
fn new() {
let (ec, _) = get_test_keys();
let user_data = UserData::new(
Some(ec.clone()),
vec![1; UserDataType::SgnEcSECP521R1.max()],
)
.unwrap();
assert!(matches!(user_data, UserData::Signed(_)));
let user_data = UserData::new(Some(ec), vec![1; UserDataType::SgnEcSECP521R1.max() + 1]);
assert!(matches!(
user_data,
Err(Error::AsrcbInvSgnUserData(UserDataType::SgnEcSECP521R1))
));
let user_data = UserData::new(None, vec![1; UserDataType::Unsigned.max()]).unwrap();
assert!(matches!(user_data, UserData::Unsigned(_)));
let user_data = UserData::new(None, vec![1; UserDataType::Unsigned.max() + 1]);
assert!(matches!(
user_data,
Err(Error::AsrcbInvSgnUserData(UserDataType::Unsigned))
));
}
#[test]
fn data() {
let (ec, _) = get_test_keys();
let data_in = vec![1; UserDataType::SgnEcSECP521R1.max()];
let user_data = UserData::new(Some(ec.clone()), data_in.clone()).unwrap();
let exp_pad = Some(vec![0; UserData::USER_DATA_SIZE - data_in.len()]);
let (data_out, pad) = user_data.data();
assert_eq!(data_out, Some(data_in.as_ref()));
assert_eq!(pad, exp_pad);
let data_in = vec![1; UserDataType::SgnEcSECP521R1.max() - 1];
let user_data = UserData::new(Some(ec.clone()), data_in.clone()).unwrap();
let exp_pad = Some(vec![0; UserData::USER_DATA_SIZE - data_in.len()]);
let (data_out, pad) = user_data.data();
assert_eq!(data_out, Some(data_in.as_ref()));
assert_eq!(pad, exp_pad);
}
}

View File

@@ -2,13 +2,12 @@
//
// Copyright IBM Corp. 2023
use super::AddSecretMagic;
use crate::{
request::MagicValue,
requires_feat,
uv::{uv_ioctl, UvCmd, UvDevice},
Error, Result, PAGESIZE,
};
use pv_core::request::{uvsecret::AddSecretMagic, MagicValue};
use std::io::Read;
use std::usize;
@@ -64,7 +63,7 @@ impl AddCmd {
let mut data = Vec::with_capacity(PAGESIZE);
bin_add_secret_req.read_to_end(&mut data)?;
if !AddSecretMagic::starts_with_magic(&data[..6]) {
if !AddSecretMagic::starts_with_magic(&data) {
return Err(Error::NoAsrcb);
}
Ok(Self(data))

View File

@@ -3,12 +3,17 @@
// Copyright IBM Corp. 2023
use core::slice;
use log::debug;
use log::{debug, trace};
use openssl::error::ErrorStack;
use openssl::stack::Stack;
use openssl::x509::store::X509Store;
use openssl::x509::{CrlStatus, X509Ref, X509StoreContext, X509};
use openssl_extensions::crl::StackableX509Crl;
use openssl_extensions::crl::X509StoreContextExtension;
use openssl::x509::{CrlStatus, X509NameRef, X509Ref, X509StoreContext, X509StoreContextRef, X509};
use openssl_extensions::crl::{StackableX509Crl, X509StoreContextExtension, X509StoreExtension};
#[cfg(not(test))]
use helper::download_first_crl_from_x509;
#[cfg(test)]
use test::download_first_crl_from_x509;
use crate::error::bail_hkd_verify;
use crate::misc::{read_certs, read_file};
@@ -45,6 +50,12 @@ pub struct CertVerifier {
offline: bool,
}
impl std::fmt::Debug for CertVerifier {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("CertVerifier")
}
}
impl HkdVerifier for CertVerifier {
/// This function verifies a host-key
/// document. To do so multiple steps are required:
@@ -76,8 +87,8 @@ impl HkdVerifier for CertVerifier {
if verified_crls.is_empty() {
bail_hkd_verify!(NoCrl);
}
for crl in &verified_crls {
match crl.get_by_cert(&hkd.to_owned()) {
for crl in verified_crls {
match crl.get_by_serial(hkd.serial_number()) {
CrlStatus::NotRevoked => (),
_ => bail_hkd_verify!(HdkRevoked),
}
@@ -88,26 +99,59 @@ impl HkdVerifier for CertVerifier {
}
impl CertVerifier {
fn quirk_crls(
ctx: &mut X509StoreContextRef,
subject: &X509NameRef,
) -> Result<Stack<StackableX509Crl>, ErrorStack> {
match ctx.crls(subject) {
Ok(ret) if !ret.is_empty() => return Ok(ret),
_ => (),
}
// Armonk/Poughkeepsie fixup
trace!("quirk_crls: Try Locality");
if let Some(locality_subject) = helper::armonk_locality_fixup(subject) {
match ctx.crls(&locality_subject) {
Ok(ret) if !ret.is_empty() => return Ok(ret),
_ => (),
}
// reorder
trace!("quirk_crls: Try Locality+Reorder");
if let Ok(locality_ordered_subject) = helper::reorder_x509_names(&locality_subject) {
match ctx.crls(&locality_ordered_subject) {
Ok(ret) if !ret.is_empty() => return Ok(ret),
_ => (),
}
}
}
// reorder unchanged loaciliy subject
trace!("quirk_crls: Try Reorder");
if let Ok(ordered_subject) = helper::reorder_x509_names(subject) {
match ctx.crls(&ordered_subject) {
Ok(ret) if !ret.is_empty() => return Ok(ret),
_ => (),
}
}
// nothing found, return empty stack
Stack::new()
}
///Download the CLRs that a HKD refers to.
pub fn hkd_crls(&self, hkd: &X509Ref) -> Result<Stack<StackableX509Crl>> {
let mut ctx = X509StoreContext::new()?;
// Unfortunately we cannot use a dedicated function here and have to use a closure (E0434)
// Otherwise, we cannot refer to self
// Search for local CRLs
let mut crls = ctx.init_opt(&self.store, None, None, |ctx| {
let subject = self.ibm_z_sign_key.subject_name();
match ctx.crls(subject) {
Ok(crls) => Ok(crls),
_ => {
// reorder the name and try again
let broken_subj = helper::reorder_x509_names(subject)?;
ctx.crls(&broken_subj).or_else(helper::stack_err_hlp)
}
}
Self::quirk_crls(ctx, subject)
})?;
if !self.offline {
// Try to download a CRL if defined in the HKD
if let Some(crl) = helper::download_first_crl_from_x509(hkd)? {
if let Some(crl) = download_first_crl_from_x509(hkd)? {
crl.into_iter().try_for_each(|c| crls.push(c.into()))?;
}
}
@@ -137,7 +181,11 @@ impl CertVerifier {
for path in cert_paths {
let mut crt = read_certs(&read_file(path, "certificate")?)?;
if !offline {
helper::download_crls_into_store(&mut store, &crt)?;
for c in &crt {
if let Some(crl) = download_first_crl_from_x509(c)? {
crl.iter().try_for_each(|c| store.add_crl(c))?;
}
}
}
untr_certs.append(&mut crt);
}

View File

@@ -3,32 +3,25 @@
// Copyright IBM Corp. 2023
use crate::error::bail_hkd_verify;
use crate::misc::{memeq, read_crls};
use crate::HkdVerifyErrorType::*;
use crate::{Error, Result};
use curl::easy::{Easy2, Handler, WriteError};
use libc::c_int;
use log::debug;
use openssl::{
asn1::{Asn1Time, Asn1TimeRef},
error::ErrorStack,
nid::Nid,
ssl::SslFiletype,
stack::{Stack, Stackable},
stack::Stack,
x509::{
store::{File, X509Lookup, X509StoreBuilder, X509StoreBuilderRef, X509StoreRef},
store::{File, X509Lookup, X509StoreBuilder, X509StoreRef},
verify::{X509VerifyFlags, X509VerifyParam},
X509Crl, X509CrlRef, X509Name, X509NameRef, X509PurposeId, X509Ref, X509StoreContext,
X509CrlRef, X509Name, X509NameRef, X509PurposeId, X509Ref, X509StoreContext,
X509StoreContextRef, X509VerifyResult, X509,
},
};
use openssl_extensions::{
akid::{AkidCheckResult, AkidExtension},
crl::X509StoreExtension,
};
use std::cmp::Ordering;
use std::time::Duration;
use std::usize;
use openssl_extensions::akid::{AkidCheckResult, AkidExtension};
use std::str::from_utf8;
use std::{cmp::Ordering, ffi::c_int, usize};
/// Minimum security level for the keys/certificates used to establish a chain of
/// trust (see https://www.openssl.org/docs/man1.1.1/man3/X509_VERIFY_PARAM_set_auth_level.html
@@ -42,7 +35,6 @@ const SECURITY_CHAIN_MAX_LEN: c_int = 2;
/// verifies that the HKD
/// * has enough security bits
/// * is inside its validity period
/// * issuer name is the subject name of the [`sign_key`]
/// * the Authority Key ID matches the Signing Key ID of the [`sign_key`]
pub fn verify_hkd_options(hkd: &X509Ref, sign_key: &X509Ref) -> Result<()> {
let hk_pkey = hkd.public_key()?;
@@ -56,9 +48,6 @@ pub fn verify_hkd_options(hkd: &X509Ref, sign_key: &X509Ref) -> Result<()> {
// verify that the hkd is still valid
check_validity_period(hkd.not_before(), hkd.not_after())?;
// check if hkd.issuer_name == issuer.subject
check_x509_name_equal(sign_key.subject_name(), hkd.issuer_name())?;
// verify that the AKID of the hkd matches the SKID of the issuer
if let Some(akid) = hkd.akid() {
if akid.check(sign_key) != AkidCheckResult::OK {
@@ -78,9 +67,6 @@ pub fn verify_crl(crl: &X509CrlRef, issuer: &X509Ref) -> Option<()> {
return None;
}
}
check_x509_name_equal(crl.issuer_name(), issuer.subject_name()).ok()?;
match crl.verify(issuer.public_key().ok()?.as_ref()).ok()? {
true => Some(()),
false => None,
@@ -195,22 +181,12 @@ pub fn extract_ibm_sign_key(certs: Vec<X509>) -> Result<(X509, Stack<X509>)> {
Ok((ibm_z_sign_key, chain))
}
/// for all certs load the first CRL specified into our store
pub fn download_crls_into_store(store: &mut X509StoreBuilderRef, crts: &[X509]) -> Result<()> {
for crt in crts {
debug!("Download crls for {crt:?}");
if let Some(crl) = download_first_crl_from_x509(crt)? {
crl.iter().try_for_each(|c| store.add_crl(c))?;
}
}
Ok(())
}
// Name Entry values of an IBM Z key signing cert
//Asn1StringRef::as_slice aka ASN1_STRING_get0_data gives a string without \0 delimiter
const IBM_Z_COMMON_NAME: &[u8; 43usize] = b"International Business Machines Corporation";
const IBM_Z_COUNTRY_NAME: &[u8; 2usize] = b"US";
const IBM_Z_LOCALITY_NAME: &[u8; 12usize] = b"Poughkeepsie";
const IBM_Z_LOCALITY_NAME_POUGHKEEPSIE: &[u8; 12usize] = b"Poughkeepsie";
const IBM_Z_LOCALITY_NAME_ARMONK: &[u8; 6usize] = b"Armonk";
const IBM_Z_ORGANIZATIONAL_UNIT_NAME_SUFFIX: &str = "Key Signing Service";
const IBM_Z_ORGANIZATION_NAME: &[u8; 43usize] = b"International Business Machines Corporation";
const IBM_Z_STATE: &[u8; 8usize] = b"New York";
@@ -219,7 +195,7 @@ fn name_data_eq(entries: &X509NameRef, nid: Nid, rhs: &[u8]) -> bool {
let mut it = entries.entries_by_nid(nid);
match it.next() {
None => false,
Some(entry) => memeq(entry.data().as_slice(), rhs),
Some(entry) => entry.data().as_slice() == rhs,
}
}
@@ -229,7 +205,8 @@ fn is_ibm_signing_cert(cert: &X509) -> bool {
if subj.entries().count() != IMB_Z_ENTRY_COUNT
|| !name_data_eq(subj, Nid::COUNTRYNAME, IBM_Z_COUNTRY_NAME)
|| !name_data_eq(subj, Nid::STATEORPROVINCENAME, IBM_Z_STATE)
|| !name_data_eq(subj, Nid::LOCALITYNAME, IBM_Z_LOCALITY_NAME)
|| !(name_data_eq(subj, Nid::LOCALITYNAME, IBM_Z_LOCALITY_NAME_POUGHKEEPSIE)
|| name_data_eq(subj, Nid::LOCALITYNAME, IBM_Z_LOCALITY_NAME_ARMONK))
|| !name_data_eq(subj, Nid::ORGANIZATIONNAME, IBM_Z_ORGANIZATION_NAME)
|| !name_data_eq(subj, Nid::COMMONNAME, IBM_Z_COMMON_NAME)
{
@@ -322,14 +299,17 @@ pub fn x509_dist_points(cert: &X509Ref) -> Vec<String> {
res
}
const CRL_TIMEOUT_MAX: Duration = Duration::from_secs(3);
/// Searches for CRL Distribution points and downloads the CRL. Stops after the first successful
/// download.
///
/// Error if sth bad(=unexpected) happens (not bad: crl not available at link, unexpected format)
/// Other issues are mapped to Ok(None)
pub fn download_first_crl_from_x509(cert: &X509Ref) -> Result<Option<Vec<X509Crl>>> {
#[cfg(not(test))]
pub fn download_first_crl_from_x509(cert: &X509Ref) -> Result<Option<Vec<openssl::x509::X509Crl>>> {
use crate::misc::read_crls;
use curl::easy::{Easy2, Handler, WriteError};
use std::time::Duration;
const CRL_TIMEOUT_MAX: Duration = Duration::from_secs(3);
struct Buf(Vec<u8>);
impl Handler for Buf {
@@ -370,23 +350,6 @@ fn check_validity_period(not_before: &Asn1TimeRef, not_after: &Asn1TimeRef) -> R
}
}
fn check_x509_name_equal(lhs: &X509NameRef, rhs: &X509NameRef) -> Result<()> {
if lhs.entries().count() != rhs.entries().count() {
bail_hkd_verify!(IssuerMismatch);
}
for l in lhs.entries() {
let ldata = l.data().as_slice();
// search for the matching value in the rhs names
// found none? -> names are not equal
if !rhs.entries().any(|r| memeq(ldata, r.data().as_slice())) {
bail_hkd_verify!(IssuerMismatch);
}
}
Ok(())
}
const NIDS_CORRECT_ORDER: [Nid; 6] = [
Nid::COUNTRYNAME,
Nid::ORGANIZATIONNAME,
@@ -409,21 +372,34 @@ pub fn reorder_x509_names(subject: &X509NameRef) -> std::result::Result<X509Name
Ok(correct_subj.build())
}
pub fn stack_err_hlp<T: Stackable>(
e: ErrorStack,
) -> std::result::Result<Stack<T>, openssl::error::ErrorStack> {
match e.errors().len() {
0 => Stack::<T>::new(),
_ => Err(e),
/**
* Workaround for potential locality mismatches between CRLs and Certs
* # Return
* fixed subject or none if locality was not Armonk or any OpenSSL error
*/
pub fn armonk_locality_fixup(subject: &X509NameRef) -> Option<X509Name> {
if !name_data_eq(subject, Nid::LOCALITYNAME, IBM_Z_LOCALITY_NAME_ARMONK) {
return None;
}
let mut ret = X509Name::builder().ok()?;
for entry in subject.entries() {
match entry.object().nid() {
nid @ Nid::LOCALITYNAME => ret
.append_entry_by_nid(nid, from_utf8(IBM_Z_LOCALITY_NAME_POUGHKEEPSIE).ok()?)
.ok()?,
_ => {
ret.append_entry(entry).ok()?;
}
}
}
Some(ret.build())
}
#[cfg(test)]
/// tests for some private functions
mod test {
use openssl_extensions::x509_crl_eq;
use super::*;
use crate::test_utils::*;
use std::time::{Duration, SystemTime};
@@ -453,20 +429,6 @@ mod test {
));
}
#[test]
fn x509_name_equal() {
let sign_crt = load_gen_cert("ibm.crt");
let hkd = load_gen_cert("host.crt");
let other = load_gen_cert("inter_ca.crt");
assert!(super::check_x509_name_equal(sign_crt.subject_name(), hkd.issuer_name()).is_ok(),);
assert!(matches!(
super::check_x509_name_equal(other.subject_name(), hkd.subject_name()),
Err(Error::HkdVerify(IssuerMismatch))
));
}
#[test]
fn is_ibm_z_sign_key() {
let ibm_crt = load_gen_cert("ibm.crt");
@@ -499,20 +461,4 @@ mod test {
));
assert!(super::get_ibm_z_sign_key(&[ibm_crt, no_sign_crt]).is_ok(),);
}
#[test]
fn download_first_crl_from_x509() {
let ibm_crt = load_gen_cert("ibm.crt");
let inter_crl = load_gen_crl("inter_ca.crl");
let _m_inter = super::super::test::mock_endpt("inter_ca.crl");
let crl_d = super::download_first_crl_from_x509(&ibm_crt)
.unwrap()
.unwrap();
assert_eq!(crl_d.len(), 1);
assert!(x509_crl_eq(
crl_d.first().unwrap().as_ref(),
inter_crl.as_ref()
));
}
}

View File

@@ -5,47 +5,30 @@
#![cfg(test)]
use super::{helper, helper::*, *};
use crate::{Error, HkdVerifyErrorType::*};
use core::slice;
use openssl::stack::Stack;
use crate::{misc::read_crls, Error, HkdVerifyErrorType::*};
use openssl::{stack::Stack, x509::X509Crl};
use std::path::Path;
use crate::test_utils::*;
pub fn mock_endpt(res: &str) -> mockito::Mock {
let res_path = get_cert_asset_path(res);
let mut server = mockito::Server::new();
server
.mock("GET", format!("/crl/{res}").as_str())
.with_header("content-type", "application/pkix-crl")
.with_body_from_file(res_path)
.create()
}
#[track_caller]
fn verify_sign_error(exp_raw: libc::c_int, obs: Error) {
verify_sign_error_slice(&[exp_raw], obs)
}
fn verify_sign_error_slice(exp_raw: &[libc::c_int], obs: Error) {
if exp_raw
.iter()
.filter(|e| match &obs {
Error::HkdVerify(ty) => match ty {
IbmSignInvalid(err, _d) => &&err.as_raw() == e,
_ => false,
},
e => panic!("Unexpected error type: {e:?}"),
})
.count()
== 0
{
panic!("Error {obs:?} did not match one of the expected {exp_raw:?}");
//mock function
pub fn download_first_crl_from_x509(cert: &X509Ref) -> Result<Option<Vec<X509Crl>>> {
fn mock_download<P: AsRef<Path>>(path: P) -> Result<Vec<X509Crl>> {
read_crls(&std::fs::read(path)?)
}
}
impl std::fmt::Debug for CertVerifier {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("CertVerifier")
for dist_point in x509_dist_points(cert) {
{
let path = get_cert_asset_path(&dist_point);
let crls = if let Ok(buf) = mock_download(&path) {
buf
} else {
continue;
};
return Ok(Some(crls));
}
}
Ok(None)
}
#[test]
@@ -59,22 +42,12 @@ fn store_setup() {
#[test]
fn verify_chain_online() {
let ibm_crt = load_gen_cert("ibm.crt");
let inter_crt = load_gen_cert("inter_ca.crt");
let ibm_crt = get_cert_asset_path_string("ibm.crt");
let inter_crt = get_cert_asset_path_string("inter_ca.crt");
let root_crt = get_cert_asset_path_string("root_ca.chained.crt");
let mock_inter = mock_endpt("inter_ca.crl");
let mut store = helper::store_setup(&Some(root_crt), &[], &[]).unwrap();
download_crls_into_store(&mut store, slice::from_ref(&ibm_crt)).unwrap();
let store = store.build();
mock_inter.assert();
let mut sk = Stack::<X509>::new().unwrap();
sk.push(inter_crt).unwrap();
verify_chain(&store, &sk, &[ibm_crt.clone()]).unwrap();
assert!(verify_chain(&store, &sk, &[ibm_crt]).is_ok());
let ret = CertVerifier::new(&[ibm_crt, inter_crt], &[], &root_crt.into(), false);
assert!(ret.is_ok(), "CertVerifier::new failed: {ret:?}");
}
#[test]
@@ -94,181 +67,82 @@ fn verify_chain_offline() {
}
#[test]
fn verify_online() {
fn dist_points() {
let crt = load_gen_cert("ibm.crt");
let res = x509_dist_points(&crt);
let exp = vec!["inter_ca.crl"];
assert_eq!(res, exp);
}
fn verify(offline: bool, ibm_crt: &'static str, ibm_crl: &'static str, hkd: &'static str) {
let root_crt = get_cert_asset_path_string("root_ca.chained.crt");
let inter_crt = get_cert_asset_path_string("inter_ca.crt");
let ibm_crt = get_cert_asset_path_string("ibm.crt");
let hkd_revoked = load_gen_cert("host_rev.crt");
let hkd_inv = load_gen_cert("host_invalid_signing_key.crt");
let hkd_exp = load_gen_cert("host_crt_expired.crt");
let hkd = load_gen_cert("host.crt");
let mock_inter = mock_endpt("inter_ca.crl");
let mock_ibm = mock_endpt("ibm.crl");
let inter_crl = get_cert_asset_path_string("inter_ca.crl");
let ibm_crl = get_cert_asset_path_string("ibm.crl");
let ibm_crt = get_cert_asset_path_string(ibm_crt);
let ibm_crl = get_cert_asset_path_string(ibm_crl);
let hkd_revoked = load_gen_cert("host_rev.crt");
let hkd_exp = load_gen_cert("host_crt_expired.crt");
let hkd = load_gen_cert(hkd);
let crls = &[ibm_crl, inter_crl];
let verifier = CertVerifier::new(
&[ibm_crt, inter_crt],
&[ibm_crl, inter_crl],
if offline { crls } else { &[] },
&Some(root_crt),
false,
offline,
)
.unwrap();
mock_inter.assert();
let res = verifier.verify(&hkd);
assert!(res.is_ok(), "Verify failed: res: {res:?}");
verifier.verify(&hkd).unwrap();
mock_ibm.assert();
assert!(matches!(
verifier.verify(&hkd_revoked),
Err(Error::HkdVerify(HdkRevoked))
));
assert!(matches!(
verifier.verify(&hkd_inv),
Err(Error::HkdVerify(IssuerMismatch))
));
assert!(matches!(
verifier.verify(&hkd_exp),
Err(Error::HkdVerify(AfterValidity))
));
}
#[test]
fn verify_online() {
verify(false, "ibm.crt", "ibm.crl", "host.crt")
}
#[test]
fn verify_offline() {
let root_crt = get_cert_asset_path_string("root_ca.chained.crt");
let inter_crt = get_cert_asset_path_string("inter_ca.crt");
let inter_crl = get_cert_asset_path_string("inter_ca.crl");
let ibm_crt = get_cert_asset_path_string("ibm.crt");
let ibm_crl = get_cert_asset_path_string("ibm.crl");
let hkd_revoked = load_gen_cert("host_rev.crt");
let hkd_inv = load_gen_cert("host_invalid_signing_key.crt");
let hkd_exp = load_gen_cert("host_crt_expired.crt");
let hkd = load_gen_cert("host.crt");
let verifier = CertVerifier::new(
&[ibm_crt, inter_crt],
&[ibm_crl, inter_crl],
&Some(root_crt),
true,
)
.unwrap();
verifier.verify(&hkd).unwrap();
assert!(matches!(
verifier.verify(&hkd_revoked),
Err(Error::HkdVerify(HdkRevoked))
));
assert!(matches!(
verifier.verify(&hkd_inv),
Err(Error::HkdVerify(IssuerMismatch))
));
assert!(matches!(
verifier.verify(&hkd_exp),
Err(Error::HkdVerify(AfterValidity))
));
verify(true, "ibm.crt", "ibm.crl", "host.crt")
}
#[test]
fn verifier_new() {
let root_chn_crt = get_cert_asset_path_string("root_ca.chained.crt");
let root_crt = get_cert_asset_path_string("root_ca.crt");
let inter_crt = get_cert_asset_path_string("inter_ca.crt");
let inter_fake_crt = get_cert_asset_path_string("fake_inter_ca.crt");
let inter_fake_crl = get_cert_asset_path_string("fake_inter_ca.crl");
let inter_crl = get_cert_asset_path_string("inter_ca.crl");
let ibm_crt = get_cert_asset_path_string("ibm.crt");
let ibm_early_crt = get_cert_asset_path_string("ibm_outdated_early.crl");
let ibm_late_crt = get_cert_asset_path_string("ibm_outdated_late.crl");
let ibm_rev_crt = get_cert_asset_path_string("ibm_rev.crt");
// To many signing keys
let verifier = CertVerifier::new(&[ibm_crt.clone(), ibm_rev_crt.clone()], &[], &None, true);
assert!(matches!(verifier, Err(Error::HkdVerify(ManyIbmSignKeys))));
// no CRL for each X509
let verifier = CertVerifier::new(
&[inter_crt.clone(), ibm_crt.clone()],
&[inter_crl.clone()],
&Some(root_crt),
false,
);
verify_sign_error(3, verifier.unwrap_err());
let verifier = CertVerifier::new(
&[inter_crt.clone(), ibm_crt.clone()],
&[],
&Some(root_chn_crt.clone()),
false,
);
verify_sign_error(3, verifier.unwrap_err());
// wrong intermediate (or ibm key)
let verifier = CertVerifier::new(
&[inter_fake_crt, ibm_crt.clone()],
&[inter_fake_crl],
&Some(root_chn_crt.clone()),
true,
);
//Depending on the OpenSSL version different error codes can appear
verify_sign_error_slice(&[20, 30], verifier.unwrap_err());
//wrong root ca
let verifier = CertVerifier::new(
&[inter_crt.clone(), ibm_crt.clone()],
&[inter_crl.clone()],
&None,
true,
);
verify_sign_error(20, verifier.unwrap_err());
//correct signing key + intermediate cert
let _verifier = CertVerifier::new(
&[inter_crt.clone(), ibm_crt.clone()],
&[inter_crl.clone()],
&Some(root_chn_crt.clone()),
false,
)
.unwrap();
// no intermediate key
let verifier = CertVerifier::new(&[ibm_crt], &[], &Some(root_chn_crt.clone()), false);
verify_sign_error(20, verifier.unwrap_err());
//Ibm Sign outdated
let verifier = CertVerifier::new(
&[inter_crt.clone(), ibm_early_crt],
&[inter_crl.clone()],
&Some(root_chn_crt.clone()),
false,
);
assert!(matches!(verifier, Err(Error::HkdVerify(NoIbmSignKey))));
let verifier = CertVerifier::new(
&[inter_crt.clone(), ibm_late_crt],
&[inter_crl.clone()],
&Some(root_chn_crt.clone()),
false,
);
assert!(matches!(verifier, Err(Error::HkdVerify(NoIbmSignKey))));
// revoked
let verifier = CertVerifier::new(
&[inter_crt, ibm_rev_crt],
&[inter_crl],
&Some(root_chn_crt),
false,
);
verify_sign_error(23, verifier.unwrap_err());
fn verify_armonk_crt_online() {
verify(false, "ibm_armonk.crt", "ibm.crl", "host.crt")
}
#[test]
fn dist_points() {
let crt = load_gen_cert("ibm.crt");
let res = x509_dist_points(&crt);
let exp = vec!["http://127.0.0.1:1234/crl/inter_ca.crl"];
assert_eq!(res, exp);
fn verify_armonk_crt_offline() {
verify(true, "ibm_armonk.crt", "ibm.crl", "host.crt")
}
#[test]
fn verify_armonk_crl_online() {
verify(false, "ibm_armonk.crt", "ibm_armonk.crl", "host.crt")
}
#[test]
fn verify_armonk_crl_offline() {
verify(true, "ibm_armonk.crt", "ibm_armonk.crl", "host.crt")
}
#[test]
fn verify_armonk_hkd_online() {
verify(false, "ibm_armonk.crt", "ibm_armonk.crl", "host_armonk.crt")
}
#[test]
fn verify_armonk_hkd_offline() {
verify(true, "ibm_armonk.crt", "ibm_armonk.crl", "host_armonk.crt")
}

View File

@@ -1,13 +1,19 @@
// SPDX-License-Identifier: MIT
//
// Copyright IBM Corp. 2023
#![cfg(all(feature = "request", feature = "uvsecret"))]
use openssl::{
ec::{EcGroup, EcKey},
nid::Nid,
pkey::Private,
};
use pv::{
get_test_asset,
request::{
openssl::pkey::{PKey, Public},
uvsecret::{AddSecretFlags, AddSecretRequest, AddSecretVersion, ExtSecret, GuestSecret},
uvsecret::{
verify_asrcb_and_get_user_data, AddSecretFlags, AddSecretRequest, AddSecretVersion,
ExtSecret, GuestSecret,
},
BootHdrTags, ReqEncrCtx, Request, SymKey,
},
test_utils::get_test_keys,
@@ -85,6 +91,93 @@ fn no_flag() -> AddSecretFlags {
AddSecretFlags::default()
}
fn create_signed_asrcb(skey: PKey<Private>, user_data: Vec<u8>) -> Vec<u8> {
let (host_key, ctx) = get_crypto();
let mut asrcb =
AddSecretRequest::new(AddSecretVersion::One, GuestSecret::Null, TAGS, no_flag());
asrcb.add_hostkey(host_key);
asrcb.set_user_data(user_data, Some(skey)).unwrap();
asrcb.encrypt(&ctx).unwrap()
}
#[test]
fn null_none_default_ncuid_one_user_unsgn() {
let user_data_orig = vec![0x56; 0x183];
let (host_key, ctx) = get_crypto();
let mut asrcb =
AddSecretRequest::new(AddSecretVersion::One, GuestSecret::Null, TAGS, no_flag());
asrcb.add_hostkey(host_key);
asrcb.set_user_data(user_data_orig.clone(), None).unwrap();
let asrcb = asrcb.encrypt(&ctx).unwrap();
let user_data = verify_asrcb_and_get_user_data(asrcb, None).unwrap();
assert_eq!(
user_data_orig.as_slice(),
&user_data.as_ref().unwrap()[..user_data_orig.len()]
);
}
#[test]
fn null_none_default_ncuid_one_user_ec() {
let (usr_sgn_key, _) = get_test_keys();
let usr_vrfy_key = usr_sgn_key.ec_key().unwrap();
let usr_vrfy_key = usr_vrfy_key.public_key();
let usr_vrfy_key = PKey::from_ec_key(
EcKey::from_public_key(
&EcGroup::from_curve_name(Nid::SECP521R1).unwrap(),
usr_vrfy_key,
)
.unwrap(),
)
.unwrap();
let user_data_orig = vec![0x56; 0x100];
let asrcb = create_signed_asrcb(usr_sgn_key, user_data_orig.clone());
let user_data = verify_asrcb_and_get_user_data(asrcb, Some(usr_vrfy_key)).unwrap();
assert_eq!(
user_data_orig.as_slice(),
&user_data.as_ref().unwrap()[..user_data_orig.len()]
);
}
#[test]
fn null_none_default_ncuid_one_user_rsa2048() {
let usr_sgn_key = get_test_asset!("keys/rsa2048key.pem");
let usr_sgn_key = PKey::private_key_from_pem(usr_sgn_key).unwrap();
let user_data_orig = vec![0x56; 0x100];
let asrcb = create_signed_asrcb(usr_sgn_key, user_data_orig.clone());
let usr_vrfy_key = get_test_asset!("keys/rsa2048key.pub.pem");
let usr_vrfy_key = PKey::public_key_from_pem(usr_vrfy_key).unwrap();
let user_data = verify_asrcb_and_get_user_data(asrcb, Some(usr_vrfy_key)).unwrap();
assert_eq!(
user_data_orig.as_slice(),
&user_data.as_ref().unwrap()[..user_data_orig.len()]
);
}
#[test]
fn null_none_default_ncuid_one_user_rsa3072() {
let usr_sgn_key = get_test_asset!("keys/rsa3072key.pem");
let usr_sgn_key = PKey::private_key_from_pem(usr_sgn_key).unwrap();
let user_data_orig = vec![0x56; 0x80];
let asrcb = create_signed_asrcb(usr_sgn_key, user_data_orig.clone());
let usr_vrfy_key = get_test_asset!("keys/rsa3072key.pub.pem");
let usr_vrfy_key = PKey::public_key_from_pem(usr_vrfy_key).unwrap();
let user_data = verify_asrcb_and_get_user_data(asrcb, Some(usr_vrfy_key)).unwrap();
assert_eq!(
user_data_orig.as_slice(),
&user_data.as_ref().unwrap()[..user_data_orig.len()]
);
}
#[test]
fn null_none_default_cuid_one() {
let asrcb = gen_asrcb(GuestSecret::Null, None, no_flag(), true).unwrap();
@@ -155,3 +248,12 @@ fn null_none_default_cuid_seven() {
let exp = get_test_asset!("exp/asrcb/null_none_default_cuid_seven");
assert_eq!(asrcb, exp);
}
#[test]
fn verify_no_user_data() {
let req = get_test_asset!("exp/asrcb/null_none_default_ncuid_one");
assert!(matches!(
verify_asrcb_and_get_user_data(req.to_vec(), None),
Ok(None)
))
}

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,29 @@
-----BEGIN CERTIFICATE-----
MIIE/TCCAuWgAwIBAgIUWT/F3gP9fOTTq3yOMVskcXM8vOAwDQYJKoZIhvcNAQEN
BQAwgcwxCzAJBgNVBAYTAlVTMTQwMgYDVQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2lu
ZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFs
IEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMREwDwYDVQQIDAhOZXcgWW9y
azEVMBMGA1UEBwwMUG91Z2hrZWVwc2llMScwJQYDVQQLDB5JQk0gWiBIb3N0IEtl
eSBTaWduaW5nIFNlcnZpY2UwIBcNMjQwMzIxMTQ1MjM5WhgPMjM4ODEyMjMxNDUy
MzlaMIG2MQswCQYDVQQGEwJVUzE0MDIGA1UECgwrSW50ZXJuYXRpb25hbCBCdXNp
bmVzcyBNYWNoaW5lcyBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrSW50ZXJuYXRpb25h
bCBCdXNpbmVzcyBNYWNoaW5lcyBDb3Jwb3JhdGlvbjERMA8GA1UECAwITmV3IFlv
cmsxDzANBgNVBAcMBkFybW9uazEXMBUGA1UECwwOSUJNIFogSG9zdCBLZXkwgZsw
EAYHKoZIzj0CAQYFK4EEACMDgYYABAAT1zpBNemPCT0tEx2S9qnlPxyBgxKl6BSX
ghqf3MfOqQKIUdKEbxP0nr2QtIR/MwvBp4YhjxZ9AZtzVtXbQrULTAGlKK4qcf1I
W1rYZ5S0b4dmvh2HbIv9wZLWKaZ/ovnvAJk949WDCbBzC3Dy1E3zCaYPefLHHNve
dWX8RtFUhnTqm6NxMG8wHQYDVR0fBBYwFDASoBCgDoYMZmFrZV9pYm0uY3J0MA4G
A1UdDwEB/wQEAwIDCDAfBgNVHSMEGDAWgBSQCOxEmGwiupA2ER7srMBydGO1aTAd
BgNVHQ4EFgQUUl5SPIEseFNeneyuOidsw06L7gQwDQYJKoZIhvcNAQENBQADggIB
AFAg/hFlaBT+WNlUmVJlAd6FYr6vvRjJiKxcNBZ5wElzxA5OjuGX6pLYiNkzXSy2
N/4nQ3a8fr04IB9Uhx5ncMzSKVkG+4mbN3xmR7f6zZuFWV/T9Aom3LIbQ5KYR2wW
EvX8b2xbvd74rKAgavq/iuFRn8skQJGgQk9J2YEApOW9wkoFQRgziuu55Cw5GT+f
w9rKgAFTN33ZwfWs86ELJlDOY0aX5373WGccuEKm8y+l2UVLlly125eezz84RSh7
5j0VUTjK4ZqpSD8yiPxN+vocV+nY52cgWxrVf7g7wlPunxXWX4rxR0z/mEVDDBAC
y7cAxsa4HtmJexuZbjEh8TEgDZXDA24BuFXqtkwqnUpv8KghyKb0KgTQecP9rRhL
b2iHdQrALnddMzJzp7Tn+jsR2A2G0lLLsIuIRFR/1eAxecgTMoxXV8N0SJHn6emH
Uwif1Qr5JVw4UOFSLW3MT3f70hY5hMzrxowOapcYhyR0vbhGFrF1YI8YmAuk2m4P
Dfd5Za5cnfVJiAdNBnNPtV/5wiViX1VJGCrIxgDN6B2VE0VQLp2gKwpsSmhqN4CA
qHzAi3Yj3F8vQ2mWQeuABWLAJrIoxXpVYQvTf4uij0ARZRbajQXx+LZnAUsCi5eZ
LaYrTVn8NzHlGQocUWljG06GaLY8GNqKPQrZD/+6hIYK
-----END CERTIFICATE-----

View File

@@ -0,0 +1,8 @@
-----BEGIN PRIVATE KEY-----
MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIAXR6FCIgd+fjhO/WJ
KwLTP01mBDtYkWbVE71jshjLLpZHunRpsYKbQKCwaDmMYLRrQnTxPgZH1PVKzguI
7M7n9zyhgYkDgYYABAAT1zpBNemPCT0tEx2S9qnlPxyBgxKl6BSXghqf3MfOqQKI
UdKEbxP0nr2QtIR/MwvBp4YhjxZ9AZtzVtXbQrULTAGlKK4qcf1IW1rYZ5S0b4dm
vh2HbIv9wZLWKaZ/ovnvAJk949WDCbBzC3Dy1E3zCaYPefLHHNvedWX8RtFUhnTq
mw==
-----END PRIVATE KEY-----

View File

@@ -0,0 +1,20 @@
-----BEGIN X509 CRL-----
MIIDVTCCAT0CAQEwDQYJKoZIhvcNAQENBQAwgcwxCzAJBgNVBAYTAlVTMTQwMgYD
VQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9u
MTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBv
cmF0aW9uMREwDwYDVQQIDAhOZXcgWW9yazEVMBMGA1UEBwwMUG91Z2hrZWVwc2ll
MScwJQYDVQQLDB5JQk0gWiBIb3N0IEtleSBTaWduaW5nIFNlcnZpY2UXDTI0MDMx
MTE1NTIzOVoYDzIzODgxMjIzMTU1MjM5WjAVMBMCAgIrFw0yNDAzMjAxNTUyMzla
oCMwITAfBgNVHSMEGDAWgBSQCOxEmGwiupA2ER7srMBydGO1aTANBgkqhkiG9w0B
AQ0FAAOCAgEAsRE3oW/VAx2JPESuWDZVbKIX9n26BZUZ2mdmUocRmn7KQ6CAi0Ac
L5YRUvYt7kmGo6BSA6rUa0TMoMBtFzfIJ6HQZzEoA/LOkIKMfNHsFFzpIJxghPYJ
PfPkXoLpAOBcLDrYWr1bJ3mkvrd6Tuyx02wJEhVmTcF8W/18AFRPuEVg/u3vJmeQ
yMdwQZG42kEslvhCTO688vozYeX+dXO1/AXamzYQZyEWk2cBQ28DIc5eg39Tq77N
89xqWNK/FWKkF4USn9psiBJQpKEjq+P1jTgdpuN3IGv618hlxS455eGyJrbiTxjD
osWGShI+ZVznnqw98aX558hnNWHic+5JVvdJAwNaMMuNNkApFdz328z9dPtcUAZT
7mNcKAuY1NcqdxKTPwkGWfmZm+WndGwKLwpshBhF/ImiAb/UiDrLh0jGbQ/FDE3j
DtWs4k8eXIibtzGhgjfewdXO66jw5Z55FajcOPgja3uw2g2KEhJ+/VP1YtCvCpkm
NX0liKgKLzUGDCbzyrH7QD16T633ebLbak3CtNMMlxZRQO8DQDbDsEKybCG62f/w
OmM+QmL7lRFcXDbtVNxBSQKaDBDlNaEGEjM8phz166g+UMD7M6xJjmwJx/G/QvUd
98YQfMEIt8IlrIbIfHXnAlj4SJwWNfOw+SN0dCqD5CDEYzYVtZgrNXY=
-----END X509 CRL-----

View File

@@ -0,0 +1,38 @@
-----BEGIN CERTIFICATE-----
MIIGrTCCBJWgAwIBAgIUMCRfNPXX7mCzJea1P3mCUDqZdB0wDQYJKoZIhvcNAQEL
BQAwgbUxCzAJBgNVBAYTAlVTMTQwMgYDVQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2lu
ZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFs
IEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMREwDwYDVQQIDAhOZXcgWW9y
azEPMA0GA1UEBwwGQXJtb25rMRYwFAYDVQQLDA1JQk0gWiBSb290IENBMCAXDTI0
MDMyMTE0NTIzOVoYDzIzODgxMjIzMTQ1MjM5WjCBzDELMAkGA1UEBhMCVVMxNDAy
BgNVBAoMK0ludGVybmF0aW9uYWwgQnVzaW5lc3MgTWFjaGluZXMgQ29ycG9yYXRp
b24xNDAyBgNVBAMMK0ludGVybmF0aW9uYWwgQnVzaW5lc3MgTWFjaGluZXMgQ29y
cG9yYXRpb24xETAPBgNVBAgMCE5ldyBZb3JrMRUwEwYDVQQHDAxQb3VnaGtlZXBz
aWUxJzAlBgNVBAsMHklCTSBaIEhvc3QgS2V5IFNpZ25pbmcgU2VydmljZTCCAiIw
DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALIvcLAKt2DM5rTc1nOhyVT2EbNy
CA1Sy+l1mSloBRVqjyk464mvlqq9p/CDO1e6tWiFhdEFChuTYzzDOxHazLjPc2Y5
U+r0QYYY8KK6jLQDj4crChPMJoJ0HZbmlWe/3uMl7lmrVMyHgqqOftQ52etBCGDn
d/RV7U4OC+MJ01ePYUcABxPh3APA+DDV5eZ2b1k74JzLvXa+SGA82MPDQYc70Waf
CcsfCw04Adnc968CEUbNQYxdfXZfL0Uvi44bohuaB5b07KY4cCetdMaBIuowgVsa
d3Zo3pI/vaj8nlAIVmYNbG4aVmItG2q+3K8Zt11A1WXMCfVBfzg4aHAmEPJzVD+s
u0maCTrRwRfKudHU+FFI36x4aqauNj0jAoQtuACYLS+69z6G0MKHd50jQXYiGwKP
LaTI+mWJ2+GBPMZpRFKyFlAXTFBFCIpZopAdfhgCMkbb212cARGD9N55xjx0F5u5
kuXWhyF/0Zq7IdXdBlR9/0uc2I0z2P2RpQ1x1TExjqZoEt6WrpYuWPHtKqeLV1zu
PonIPZFsKXJDtxoJhvhk/Aivv0329faKxqtIlH1W7b2BrrkC1UYh4+w9f/CVG2tD
FRkXDEdgyknFsGarHSIGtrIr4vRGAh2p6a+7lNnb9GgpGshFIaOnXf1SXFLgdBwb
mEPx8pjT7Fnu01HxAgMBAAGjgZkwgZYwIQYDVR0fBBowGDAWoBSgEoYQZmFrZV9y
b290X2NhLmNybDAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUE
DDAKBggrBgEFBQcDAzAfBgNVHSMEGDAWgBQsIzqwsaKXaQyBeov7u8c7q8IEdzAd
BgNVHQ4EFgQUkAjsRJhsIrqQNhEe7KzAcnRjtWkwDQYJKoZIhvcNAQELBQADggIB
AL+JmoykUGjMygjv23qdStop7VI2ekieYBKJANlq1eEoICLW0yIw9B57pxR6iFpS
ClulV5vU4GvXlOAP7mTJJQWeuU5Z+sn9s+nLMkwZQj6QBpYwVru3SWx7H4XojRkk
bVhN7hTrfXfQAkTLuol9PHNrGiTNGKRultBg6votpMSyd2wWgli7nt0QUydhquEL
2kROaUlHRLo9cKttyy6MIypWlneGx9KC3X/UMoZgxCygpCDQycIp1oU53ZlHO4AZ
7WeJ/FjEM2PIy6EiBnhrfmRimDjghPM8c8OIMx7fVjc5yS7KnryZ8HuzIeO6CPL+
/9+bJASuSAHmAZN3qKmiVUVfYhcbU+hKuCS2HRNkRhE/fZidp3K02OqSiRegiPRC
TIcIXJ/SZ8M345yjGekAJ/M7RGIoirbdLYmpOpvHDg0qMlKFsCdpqasivPFjtLpX
M1hvu9Ahz2HteKhm7WV9tOQ2lzMdqFDNTbxhhGzy7NJf+20zooTZCDwlNlo5JmKl
Bg/Tns0rE5ZN2j5iVvv32Bp5CrY8oy8Xq8NJitaEb4JQKSLIya++rot+OTnX7inc
LzsAwru4YgT+jGnHxEQslPcLMjuLdgZZGyXlKit+8KyslwaAb5Yv5e2rP90gYFFG
5ZxgKxI1NfJZXgPXjrnDv/FPJZe+agqlTJ0RYCJeSmCu
-----END CERTIFICATE-----

View File

@@ -0,0 +1,52 @@
-----BEGIN PRIVATE KEY-----
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
vpiaRjhZtk5MLPJs9mTHq1STrzL9
-----END PRIVATE KEY-----

View File

@@ -1,19 +1,20 @@
-----BEGIN X509 CRL-----
MIIDITCCAQkCAQEwDQYJKoZIhvcNAQELBQAwgb0xCzAJBgNVBAYTAlVTMTQwMgYD
MIIDRjCCAS4CAQEwDQYJKoZIhvcNAQENBQAwgb0xCzAJBgNVBAYTAlVTMTQwMgYD
VQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9u
MTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBv
cmF0aW9uMREwDwYDVQQIDAhOZXcgWW9yazEPMA0GA1UEBwwGQXJtb25rMR4wHAYD
VQQLDBVJQk0gWiBJbnRlcm1lZGlhdGUgQ0EXDTIzMDMxOTExMDQ0N1oYDzIzODcx
MjMxMTEwNDQ3WjAVMBMCAgG8Fw0yMzAzMjgxMTA0NDdaMA0GCSqGSIb3DQEBCwUA
A4ICAQA+KQrjx/6nKzPggDpKEAzH6XxhUU4CZmyUKFirUdenQBjYLag2Nono75o8
9DVK3vuK7aeg4tIkUYOBcOEgYx0wEPU6PEE+yOO6KErn7qilN9gRnDHOTrfT0iNY
Rabyeat256gyfrsS84ZB7MnbhecWwC6sP2NiH18VCprH865X6sm5SxAfez1zITV3
YVtudX4UczqbfpDgP4BU5ERMI71tqj4gKjaHFkC0TGizSphiINDKPmUMbd1w7FHg
Ilj+7pNZS377GCX9JzoTaKLuMBiblkwSTUJic7Z2BJZlTgm18hhfT3AZQDVvkq0A
AEPxQzm3be3ZUb+zJvueTeizVHkd3Eufnk69p7w4wNRQMwfj/icm27RZa3bBpF2o
esr2Ptik9ZBN81oMAakONZ4Wxuf0n/KBd6VBjy6WkbalKGVoZn70Nke3+9HGWSIh
bgbuHt7XAlvsgVChtZWsGsyxYw4p2ku4T2ajUfpxqQY1DDCAThweuHl2FND87Kr1
5sblLLhA3QdjQ0EavsCV1646xorvoyw7YdHkqCPjRb1FsPWm/IePbtu+w9/VjDRF
KcHgBZBWmmQHj/9ykSI9pA5J7R7Nij6sX6Iu1g2yKiPnXeRQFiwhgsxslNk8eJfq
cK4c4HhnNtXa/c8jHcbymwqkF8Qltz0cbEW1usxZ2u6153pyPQ==
VQQLDBVJQk0gWiBJbnRlcm1lZGlhdGUgQ0EXDTI0MDMxMTE1NTIzOFoYDzIzODgx
MjIzMTU1MjM4WjAVMBMCAgG8Fw0yNDAzMjAxNTUyMzhaoCMwITAfBgNVHSMEGDAW
gBSMe9JFoed6PvsUVY3z4MU6KhnKCjANBgkqhkiG9w0BAQ0FAAOCAgEATjy3crOb
zDvF2CiBxmDMvOK8E/fhQ1BSUOB2qc/OiqK6zb1Q2MFvni945+Q+TwbHJqWBfU2z
QHuhOQHUQQNnIvMPXgjJuT32eF2Y7J4weaQOHNjrt1dwE6TPC1DLNUzibbjKr5x1
/scmCiXWYxjeLvS7aTACNaD1UmUxyroK6h4oc968ofdPURK54sAiddY+VBA4KW4B
WlAjxGSErZk0DIg5SXakSQbTkz8+pLnrqqtmvwQXk92lyfrwsSiZhHlcfBrJ6+mp
1Mho9H5r97mO/LRRV+2CRShqTElxVORbW3Q2ku6RGJHEUB7AssIeKBtEma8yfUff
S2bX0P82ETUCT3CPZK29QJ8eaxxH+PaRnyiT/W8vWuo+BRw8XqQ2AsM22vVCPP61
mg6VNsPJkJ8UaUF/S41aGMS21HNGk4Ik0iv0wiuu3q2rcFwGuuWB/gRUfSuPfFSO
K5sEf47dBPB5kMZCSEkX1RvHPWAYwd6g8GgVdlQEt/IIX4ChoASES5JNhDFar7tg
6h72VhfTtwEkGqg/z8vI1zP1Qzl2bZ773B/k/TAJ3j6N1JXiHUKioL1hAnA9glrj
3hnZQEQSewPf8opPe/l7UEQNXGlamYic5WRsm8xbN1KL6HARLqxkiC7K8SS6U99s
T7L2jh4egE5kyM4lLOFYfEugj4s6Soq6XuU=
-----END X509 CRL-----

View File

@@ -1,38 +1,37 @@
-----BEGIN CERTIFICATE-----
MIIGpjCCBI6gAwIBAgIUMp+RLATMshrQnbOfPkwKoDNyYhcwDQYJKoZIhvcNAQEL
MIIGjDCCBHSgAwIBAgIUKp3mjstxJ9gXt3S7lpKjri2dEUwwDQYJKoZIhvcNAQEL
BQAwgbUxCzAJBgNVBAYTAlVTMTQwMgYDVQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2lu
ZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFs
IEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMREwDwYDVQQIDAhOZXcgWW9y
azEPMA0GA1UEBwwGQXJtb25rMRYwFAYDVQQLDA1JQk0gWiBSb290IENBMCAXDTIz
MDMyOTA5MDQ0N1oYDzIzODcxMjMxMDkwNDQ3WjCBvTELMAkGA1UEBhMCVVMxNDAy
azEPMA0GA1UEBwwGQXJtb25rMRYwFAYDVQQLDA1JQk0gWiBSb290IENBMCAXDTI0
MDMyMTE0NTIzOFoYDzIzODgxMjIzMTQ1MjM4WjCBvTELMAkGA1UEBhMCVVMxNDAy
BgNVBAoMK0ludGVybmF0aW9uYWwgQnVzaW5lc3MgTWFjaGluZXMgQ29ycG9yYXRp
b24xNDAyBgNVBAMMK0ludGVybmF0aW9uYWwgQnVzaW5lc3MgTWFjaGluZXMgQ29y
cG9yYXRpb24xETAPBgNVBAgMCE5ldyBZb3JrMQ8wDQYDVQQHDAZBcm1vbmsxHjAc
BgNVBAsMFUlCTSBaIEludGVybWVkaWF0ZSBDQTCCAiIwDQYJKoZIhvcNAQEBBQAD
ggIPADCCAgoCggIBAK75zkJO8mpqPrD9vlSsfJgW7hbioQpuphSo1+3q9cAAWKFg
TYUcGBUNR/lUVdYqgzo3AglUwldWfeO9mBCIGNSN/heLFt1KzNutBsnE3YEeGKpM
7nHhMzh41otFdpZEZfrsGXGok07dy2mEV0mx72e9ALWbXFhxYsdWdSSVTlBH8xcd
38rAzfAiTbjgAUnTIdCPjAJKbXSDBXGXZ3+iuhFxNtSWyJr1AsxPzESErCPzUQjr
m8TM24lKq69zimTEkN4uwP5U8s2JPzbKosg2k24RbpDgkjO8iNK7RL9SMRUE8daP
+eru5EwN4BlZfsNpZDFbILxbt/2sxqmdsx/Nupa5ZAfcHRs88p4l1D3QIiZzaSEc
nCotM/kmnHWbgeJbkGbC9fD23dNJ29uqZU0fbRnG4HpSutrYD6lPg7PXnMt5tT+f
0+wQds38woXT9qW/kN/2WtkVYDhyVjxCgD8iHOZpz2LUmvJfi7Gz9B/DeW1dzgbo
cGxz9ee+R+T5KcKg+XvHD6slk82GrSM21b7zJeK92bJtjkqxBtQf+YgcKtOO7QX7
37C1XvSHFnKvyyRJrldJFGEKfK2C66hdASHRdbUhWHFo1AA7VqzKB1fU9M2+ltUZ
zRpYD7X36OtRY1KsHHn+SVvsn404hWwgPblZ04nsMPanj+jsN//6M9r5lMezAgMB
AAGjgaEwgZ4wOwYDVR0fBDQwMjAwoC6gLIYqaHR0cDovLzEyNy4wLjAuMToxMjM0
L2NybC9mYWtlX3Jvb3RfY2EuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/
BAQDAgEGMB8GA1UdIwQYMBaAFNnX872GsEyiVMz7up1p/Nq/K+0VMB0GA1UdDgQW
BBT2zEtzeetYaOXAVw0Z9Pda1V9n1DANBgkqhkiG9w0BAQsFAAOCAgEAb7xPI93b
gqpXi4E/hAl7Vh354kKV+1smd1Omf7mQZbTrKBo6o1s0ZpXCbC9+WzK47R21VPNe
EgZ3uzTkURu4AX+5OnAMiWDFAGRSDt8ZXk6ZukWP7OmHsnLCu2strdhrvC4EhMF5
G9VPIQsTx16CpprrVjzVzJg4i/X+U9dypvnAQeneyz4Ul/kPr6di8bOB3FiBeEDu
dOkVTbnlDa+wMQlCvqlFroFjEHZBKK/+PVIx9cJYj1grmzgqzm2FGUs5Wvcixpgb
uSHCQY9JP8Hy0xl3wx58VaymUK4EMfs612CfzOMClaiooDYuZgzVfhalU6g268nc
PQ9RCRJtJuda4mJ2H3Rag79sIiCVV31tE6tLXjOGebuO0vEB8wOjJc4YW1gtrZFy
GltT+HMdFgjO2c6HynpkmtqS8axQAw2hVaOpdJbDW+R0jHihO98FAgXR27TqTFp9
sjBacfITeYRXGjQTDU1qxuEfoLnTZRIct1TjRTI1HBT8fl1exxgKUyEawH3MUCo7
LsTPSNASKkJH3Rp29be9xTejUx2HUUwOE/DIF0HKaN+aAc8TR31/4HvC3bf5VPyD
wIwazpjVDZlQ2w+Wry1zNezNCPKiWtkfkj+TkT32h4ZfQEX8t0MUpKnL1LOSV/8h
PV357EenQb+f9DeC4BIbmipovLaUWmml10c=
ggIPADCCAgoCggIBAK+kNJHAUL4dcMnjElivyuzkO2UwTUlJcKQCBmWRHYQjRbP5
akJx8SZ+wI0Spo00hG4sV2BxA83J+Yrked53DEzlR+RxojA16vXzlUO8c9KH2dJQ
E17PgZnu7/hECmQcT69ZJAOh78ILEXRYk+2ixSTaZRTtchJdzfXIQ0633O2Mi/7z
z5idQmQeXbitC3QIZeNzwitl2FLXPIw6MUnktOKNjQSNxMr9AU8q1cfOoICJQs0J
wYVpby0dv1z0f2N21JJywaeAImHa2h58sSX6uqwOXtzdwcPlr2+iJ09YwHM8uO0D
rtPx3bLHfkvbpMd5cCKjSeFozP1nVnlKJUmAZ8UXk4MAFKCtuLv2/InA8MkclZmX
1IzBbvYDOw7AnsAN2VQYZSgM8vCmnRCzpTmtvb3ysSo32sTUjGW44giuRtGqh5Ct
LeRpZZVm6zDFY6cjpr34+3Vc4pys81d3Dq+Sos4YVPXhTKW3I1VtFIdCeNyey7hv
epjna6/JvOzQuwK90+t9VmZk7jTY2WOUNXJhzDTeDku/aTMIeXUZrAxg3pOvl/wf
SN5i4Gauhl7URDx3nI0jc4Y2u9NGFi0TYJMCRVVLknAcre5cDKFyf9ts1gDyxTDc
+orszCE3ZQzXZeEY6aiQPihhL1YDk5SkkTI6XHmUqLW3HFlfg2aFH/oI+VGBAgMB
AAGjgYcwgYQwIQYDVR0fBBowGDAWoBSgEoYQZmFrZV9yb290X2NhLmNybDAPBgNV
HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQsIzqwsaKX
aQyBeov7u8c7q8IEdzAdBgNVHQ4EFgQUjHvSRaHnej77FFWN8+DFOioZygowDQYJ
KoZIhvcNAQELBQADggIBAD4GmfmI5R6cy/Sp37buyO53azgw4RvVclIy/2qSPHVX
Os0pPPIIXLsbJMy7M6rDvKx/thZ27BDwms5dNuDynZ494XjqTmwzbBr+qEIzCNpa
QiX0MHf9JqFq5hkcZihfJ8PZL9JWIjiRfMI6AERd1pU1QJI/G8ha1vAkPfcA7GvH
NBBwKBm63iHYhp+zmnEEh85lpj4pEq+hOLK+mJxu55BodbNiBlBGu4EbalZlwXFp
7lGHLPkxuXZndrlrm8Lk+hi558NgNFxqz6qYtUc7txajViU2xFjEkTcQ0FKNiFpV
eHn5TNjwh4QucnWc7wI9hcDoADrekTEr8mUKrJXgxaBLIXEShC0ZDBnJsEwW4xbg
GQD9qXyo0h8cYx2NngvL+9Ee3rzdYAaSfAnZOU0xxrqZt+2dstNqi3pLKdS6RpA/
3Dt3cAnf0mQQSUP6oZQpfdSEJ9uggT9h+kgJz5RGOQfEELKA5RxHtTe7249J3vDv
hoy0Uy6+w3Ji5AQdn3G5uUGxLsBh/uS1dl8hq4gihrpPbKVJHVxqPL0HCx7DyhRw
hx53GXhGIgZN7QSGTrB5iz9YyzejsnysS0Um+figkxtC1atqhVkqzMDZBHUwRPfy
wq8PREXoRITJHfSkg01bInRFMMNWDQuPwSHDX9OYNqpkXzlV8/ao9Rx6JOtiG0a8
-----END CERTIFICATE-----

View File

@@ -0,0 +1,52 @@
-----BEGIN PRIVATE KEY-----
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
M9Wd2js5nPPh0AN3Px1643vFYcAQ
-----END PRIVATE KEY-----

View File

@@ -0,0 +1,20 @@
-----BEGIN X509 CRL-----
MIIDPjCCASYCAQEwDQYJKoZIhvcNAQENBQAwgbUxCzAJBgNVBAYTAlVTMTQwMgYD
VQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9u
MTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBv
cmF0aW9uMREwDwYDVQQIDAhOZXcgWW9yazEPMA0GA1UEBwwGQXJtb25rMRYwFAYD
VQQLDA1JQk0gWiBSb290IENBFw0yNDAzMTExNTUyMzhaGA8yMzg4MTIyMzE1NTIz
OFowFTATAgIBTRcNMjQwMzIwMTU1MjM4WqAjMCEwHwYDVR0jBBgwFoAULCM6sLGi
l2kMgXqL+7vHO6vCBHcwDQYJKoZIhvcNAQENBQADggIBAJB5ERfMQEZ5Pdc3A8+d
gDiY53VEdA0Zd8MDv+j+Mgu1qn7IW2rpE313yVHieclZ65ReEtb825St8UBJtjiZ
9Vd4lK9FUQKKCblCYNrEbu9cvqNeHDGxldQPUkEoz+z5kielcEwD6RUsK5fSYe3Y
6E3jc9mMHw7xWCSiolvNr5y6AUymfu22v41qgfaB0yNe5uz6vRgRoiy+OTP3Z7oc
ls7o73F9O4k6QYdba8us4v0TSwZAAPO16TsHhmyHcBe3w23UIusTU/c+6A++hGdU
TNUW3OZl+hv+4BcnClrVBDfWiExOMNzIhH9hzlXQ2qNPNqz2ymlH8Wgpf1TBYJ8m
xe8EuGGrDFuewa45kA8uxuHCiSLCsBowDEXXkswaSF4E4yzYZqcNDcLOedK7vG9G
+zXYHOpLsZMyfgauxjuWtwR/ma+ub85CHy+eUC2waI+Mk0Uk0Lr5y0Jdp8ztxakp
UlVHYNU/Q+kwHfmKztkOsedomOf1/8IvzE930ZB8rv0G8ok2HXYvA3+r3lcDSG/V
7+yq3HcJezw0XCDtc5mv8dWI6pUv8siWFKok+hlkZpeSXgtqRhF2rzI8yz+lk5Cr
5yCWroPI0T44o2RzjfGZAViRH0nnYF1GoBORSZORppubcjmiTy46OFG/fiWKGKV1
sngAoQ4TCDQzId0zwGLtUCHu
-----END X509 CRL-----

View File

@@ -0,0 +1,37 @@
-----BEGIN CERTIFICATE-----
MIIGXzCCBEegAwIBAgIUC2OH79tloDOfMBeyDBA84epTMKYwDQYJKoZIhvcNAQEL
BQAwgbUxCzAJBgNVBAYTAlVTMTQwMgYDVQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2lu
ZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFs
IEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMREwDwYDVQQIDAhOZXcgWW9y
azEPMA0GA1UEBwwGQXJtb25rMRYwFAYDVQQLDA1JQk0gWiBSb290IENBMCAXDTI0
MDMyMTE0NTIzOFoYDzIzODgxMjIzMTQ1MjM4WjCBtTELMAkGA1UEBhMCVVMxNDAy
BgNVBAoMK0ludGVybmF0aW9uYWwgQnVzaW5lc3MgTWFjaGluZXMgQ29ycG9yYXRp
b24xNDAyBgNVBAMMK0ludGVybmF0aW9uYWwgQnVzaW5lc3MgTWFjaGluZXMgQ29y
cG9yYXRpb24xETAPBgNVBAgMCE5ldyBZb3JrMQ8wDQYDVQQHDAZBcm1vbmsxFjAU
BgNVBAsMDUlCTSBaIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
AoICAQDK+jIoIZVYyEq7ZrxfKv/TQQWCgI5C8BewYkB+/rt8NY0fn/aAZbvJdnDX
cQCLpCeETDi7C2hGujnZQN68otr2GpJVQ/kgKnM8yU/p9yBSUan9Zo/195a9YytF
6Ys/Yc0HApoPtB3t85NHNjAvhzdcBKWMb+/2FiJ61gdnrO/zORnxp/BejxTMyB6r
0mhhVX4wwdl5vfkX/qS3TL0rajEz0V+SwneDiIomoVJCnco40Km1M20qU5L7EpNH
IMEP00hcj40zO0jJ8cGDNoKgTHsZPovYfFmWITVOFvaPcKaloUU67dYEg0fv3ypX
aYHRszcd794VOWQ85r/mlFSSELwoUrVH7G0t6wnzOawW2kk7ZYndbo+Z1ZFb1Ul+
iVwUAHzx/ylmOORJNM4JGiYyC5+1481MLeB+37+V3TJaBe4IoKqVo/OCBsaPt7x1
rMpZLw4gXj3A0Hh8gi0z5HDkKolMSawuU8dpFeI0GN+4hJN9DNQh0OTGLEfzeo+1
lNzsF+jGT9B0tApWhBq/QTyHXvJREVx32hPd/1X6bVbd9mik0bexg6bVpZVNG1sn
7GsVO2wq5OWKe3UtSh8wJcjGdW38fPAB46oIBQ7x0HGdp/KFiBTWxrexLThMFvYL
wPtWedj8ntgOBoH5MJgL1XkVYP+1EQYaBJNfswvF4CrvPRCtCwIDAQABo2MwYTAP
BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQsIzqw
saKXaQyBeov7u8c7q8IEdzAdBgNVHQ4EFgQULCM6sLGil2kMgXqL+7vHO6vCBHcw
DQYJKoZIhvcNAQELBQADggIBALZNLMgm7RqIKY++Blc2qeIDrwlx1U/PPN/PsZsN
cQR48Bq+vQ4cV9hOcZC3jfRbkkDho8jxVTXdEOcpDyU4zNSLG1+b1FNRvqjq2L+d
ow190dYqvfgbdNFo8V6kLdRFe5aCLhHTWGLTbl0vvkc99h1Lt9ZXr6LzhFwbXSGr
Q/qJoLZFVBwJZmfZY3VmL661sBcTmzDDGJxg00fg+1jCIk2Ot3dn+7jQ8g6HYMQv
8GrqGKcFia8fXcTTmcH+Swr8rps1MYypjkpX/zVHsFuENdqZNkqU+OLTaifkrBuO
6evTTjEOcDzMFs5Uipjvq7XOBg5rz9BKRXrjDMdI4CmUzMR272lToNw7lHqqNDKi
nxAzPjPWVwXQTu2LFY3NwubWkPAVsd6FsHKzQHlq97N4sj+vp6vctaEUgFS4pUlL
tbjw6AtQA72z4uIpcAzE2ctTj831QeQSZGKBUpeNPjuK/NjytXQm8MvW7LI2OgaI
H5B9+KE9KjqijpNiiOoidYVwFRrZniIQii06qXwQUgz2gGIzYPER9+3PijrtOY+t
K/vS6NohUYb16PhbbvzFktSGBtvp1kUF4fB2NJh0z6OiZXVEHlCYEDTv78RS36iU
PXijR+rALi20P4Sg6picuvmt2epfSMQ4ynNxPhbSG7wMp+Zp5tOrZcmg4jN0Yt56
tACH
-----END CERTIFICATE-----

View File

@@ -0,0 +1,52 @@
-----BEGIN PRIVATE KEY-----
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
2lXPecP5/ilaLLUhs7SijqHzcKiNL80=
-----END PRIVATE KEY-----

View File

@@ -0,0 +1,20 @@
-----BEGIN X509 CRL-----
MIIDPjCCASYCAQEwDQYJKoZIhvcNAQENBQAwgbUxCzAJBgNVBAYTAlVTMTQwMgYD
VQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9u
MTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBv
cmF0aW9uMREwDwYDVQQIDAhOZXcgWW9yazEPMA0GA1UEBwwGQXJtb25rMRYwFAYD
VQQLDA1JQk0gWiBSb290IENBFw0yNDAzMTExNTUyMzhaGA8yMzg4MTIyMzE1NTIz
OFowFTATAgIBTRcNMjQwMzIwMTU1MjM4WqAjMCEwHwYDVR0jBBgwFoAU1p7a8iaQ
sGamSdR9585yWIW36CowDQYJKoZIhvcNAQENBQADggIBAMcBN8PztJELdCo6fQvw
C9ZU41AmBZsMdIoacgacupt94gHf8SAO1Ric46j3KERpA0mWKAx6RH1s3OX2qN/C
YSrVPIZ076Cn9EMVdK9w9hqt6SYHoot9CwPutF6BBG5O2uN6eAsEM21B5Tr6xTZ/
SUj3fO3+QsePDL84BRfU5vtZcGj1BkULopWwibG82ayEUlbY3J8OPjK5YKuHtxJd
lI4yfkmrEPwHEm8bwI6lhaIxrtTjoVgoolw+FqtVdVdU6O254AUKwxN88bHoA/sk
BOr13AoHXiKEBaEJhocTLJRfvUZVRYGll43ELsy60XEH51W27/uULnC92vBkp4Q1
5hPwSD0RHKfMwsLKqoJaWX1CxfdttapCfriehMXJlv46GPmq6cLIEbbHzJKsyJhN
4mW8Uiwn1aM5EhMauSLuuwNp8QRo4rmQzUstxwn4O/3HzTcjVWbn0XvBXa2S5HtD
2kyWwN/qck1N9aXYk/sf2A2py2ECDuXc/Kvh1kDi6ZSaKA0VSS1FX62HvdqZKQb5
ZmyoQUpg8yv0hholaZd9Jye0pwww/K8CFddsyUMRYDSj0+qiw4pgx6KK3ElKnHeH
uq+iLxDLWTqrWQw6k0I92B9gSlNKR3Z6Zq2UTxo6hB7IYgZv5nxx3BRxnTm6aH6a
pIoxgnFnbNnyUIRAkOCHbFqy
-----END X509 CRL-----

View File

@@ -4,13 +4,10 @@ import os.path
from enum import Enum
from cryptography import x509
from cryptography.x509.oid import NameOID
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import ec, rsa
from cryptography.x509.oid import NameOID
ONE_DAY = datetime.timedelta(1, 0, 0)
@@ -25,7 +22,9 @@ def createRSAKeyPair(size=4096):
)
def createCRL(pkey, issuer, serial_numbers=None, last_update=None, next_update=None):
def createCRL(
pkey, issuer, serial_numbers=None, last_update=None, next_update=None, authid=True
):
serial_numbers = [333] if serial_numbers is None else serial_numbers
builder = x509.CertificateRevocationListBuilder()
builder = builder.issuer_name(issuer)
@@ -43,50 +42,15 @@ def createCRL(pkey, issuer, serial_numbers=None, last_update=None, next_update=N
.build(default_backend())
)
builder = builder.add_revoked_certificate(revoked_cert)
crl = builder.sign(
private_key=pkey, algorithm=hashes.SHA256(), backend=default_backend()
)
return crl
def createRootCA(pkey, subject):
issuer = subject
ca = (
x509.CertificateBuilder()
.subject_name(subject)
.issuer_name(issuer)
.public_key(pkey.public_key())
.serial_number(x509.random_serial_number())
.not_valid_before(datetime.datetime.utcnow())
.not_valid_after(
datetime.datetime.utcnow() + datetime.timedelta(days=365 * 365)
)
.add_extension(
x509.BasicConstraints(ca=True, path_length=None),
critical=True,
# Sign our certificate with our private key
)
.add_extension(
x509.KeyUsage(
digital_signature=False,
key_encipherment=False,
content_commitment=False,
data_encipherment=False,
key_agreement=False,
encipher_only=False,
decipher_only=False,
key_cert_sign=True,
crl_sign=True,
),
critical=True,
)
.add_extension(
x509.SubjectKeyIdentifier.from_public_key(pkey.public_key()),
if authid:
builder = builder.add_extension(
x509.AuthorityKeyIdentifier.from_issuer_public_key(pkey.public_key()),
critical=False,
)
.sign(pkey, hashes.SHA512(), default_backend())
crl = builder.sign(
private_key=pkey, algorithm=hashes.SHA512(), backend=default_backend()
)
return ca
return crl
class CertType(Enum):
@@ -200,9 +164,7 @@ def createCert(
critical=True,
)
.add_extension(
x509.ExtendedKeyUsage(
[x509.oid.ExtendedKeyUsageOID.CODE_SIGNING]
),
x509.ExtendedKeyUsage([x509.oid.ExtendedKeyUsageOID.CODE_SIGNING]),
critical=False,
)
)
@@ -254,8 +216,7 @@ def getPrivKey(path, create_priv_key):
if __name__ == "__main__":
MOCKUP_CRL_DIST = "http://127.0.0.1:1234/crl/"
MOCKUP_CRL_DIST = ""
# create root CA
root_ca_subject = x509.Name(
@@ -310,7 +271,13 @@ if __name__ == "__main__":
t=CertType.ROOT_CA,
)
fake_root_ca_crt = createRootCA(fake_root_ca_pkey, fake_root_ca_subject)
fake_root_ca_crt = createCert(
pkey=fake_root_ca_pkey,
subject=fake_root_ca_subject,
issuer_pkey=fake_root_ca_pkey,
crl_uri=None,
t=CertType.ROOT_CA,
)
# create intermediate CA
inter_ca_pkey = getPrivKey("inter_ca.key", createRSAKeyPair)
@@ -354,7 +321,7 @@ if __name__ == "__main__":
# create ibm certificate
ibm_pkey = getPrivKey("ibm.key", createRSAKeyPair)
ibm_subject = x509.Name(
ibm_subject_poughkeepsie = x509.Name(
[
x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
x509.NameAttribute(
@@ -371,9 +338,35 @@ if __name__ == "__main__":
),
]
)
ibm_crt = createCert(
ibm_pougkeepsie_crt = createCert(
pkey=ibm_pkey,
subject=ibm_subject,
subject=ibm_subject_poughkeepsie,
issuer_crt=inter_ca_crt,
issuer_pkey=inter_ca_pkey,
crl_uri=MOCKUP_CRL_DIST + "inter_ca.crl",
t=CertType.SIGNING_CERT,
)
ibm_subject_armonk = x509.Name(
[
x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
x509.NameAttribute(
NameOID.ORGANIZATION_NAME,
u"International Business Machines Corporation",
),
x509.NameAttribute(
NameOID.COMMON_NAME, u"International Business Machines Corporation"
),
x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"New York"),
x509.NameAttribute(NameOID.LOCALITY_NAME, u"Armonk"),
x509.NameAttribute(
NameOID.ORGANIZATIONAL_UNIT_NAME, u"IBM Z Host Key Signing Service"
),
]
)
ibm_armonk_crt = createCert(
pkey=ibm_pkey,
subject=ibm_subject_armonk,
issuer_crt=inter_ca_crt,
issuer_pkey=inter_ca_pkey,
crl_uri=MOCKUP_CRL_DIST + "inter_ca.crl",
@@ -381,7 +374,7 @@ if __name__ == "__main__":
)
ibm_expired_crt = createCert(
pkey=ibm_pkey,
subject=ibm_subject,
subject=ibm_subject_poughkeepsie,
issuer_crt=inter_ca_crt,
issuer_pkey=inter_ca_pkey,
crl_uri=MOCKUP_CRL_DIST + "inter_ca.crl",
@@ -390,11 +383,11 @@ if __name__ == "__main__":
not_after=datetime.datetime.today() - 1 * 365 * ONE_DAY,
)
#create revoked ibm certificate
# create revoked ibm certificate
ibm_rev_pkey = getPrivKey("ibm.key", createRSAKeyPair)
ibm_rev_crt = createCert(
pkey=ibm_rev_pkey,
subject=ibm_subject,
subject=ibm_subject_poughkeepsie,
issuer_crt=inter_ca_crt,
issuer_pkey=inter_ca_pkey,
crl_uri=MOCKUP_CRL_DIST + "inter_ca.crl",
@@ -402,7 +395,9 @@ if __name__ == "__main__":
)
# create inter CLRs
inter_ca_crl = createCRL(inter_ca_pkey, inter_ca_subject, [444, ibm_rev_crt.serial_number])
inter_ca_crl = createCRL(
inter_ca_pkey, inter_ca_subject, [444, ibm_rev_crt.serial_number]
)
inter_ca_invalid_signer_crl = createCRL(root_ca_pkey, inter_ca_subject, [444])
inter_ca_invalid_date_crl = createCRL(
inter_ca_pkey,
@@ -431,7 +426,9 @@ if __name__ == "__main__":
),
]
)
ibm_wrong_subject_crl = createCRL(ibm_wrong_subject_pkey, ibm_wrong_subject_subject, [555])
ibm_wrong_subject_crl = createCRL(
ibm_wrong_subject_pkey, ibm_wrong_subject_subject, [555]
)
ibm_wrong_subject_crt = createCert(
pkey=ibm_wrong_subject_pkey,
subject=ibm_wrong_subject_subject,
@@ -469,7 +466,6 @@ if __name__ == "__main__":
t=CertType.SIGNING_CERT,
)
def host_subj():
return x509.Name(
[
@@ -487,14 +483,13 @@ if __name__ == "__main__":
]
)
# create host certificate
host_pkey = getPrivKey("host.key", createEcKeyPair)
host_subject = host_subj()
host_crt = createCert(
pkey=host_pkey,
subject=host_subject,
issuer_crt=ibm_crt,
issuer_crt=ibm_pougkeepsie_crt,
issuer_pkey=ibm_pkey,
crl_uri=MOCKUP_CRL_DIST + "ibm.crl",
t=CertType.HOST_CERT,
@@ -502,7 +497,7 @@ if __name__ == "__main__":
host_crt_expired = createCert(
pkey=host_pkey,
subject=host_subject,
issuer_crt=ibm_crt,
issuer_crt=ibm_pougkeepsie_crt,
issuer_pkey=ibm_pkey,
crl_uri=MOCKUP_CRL_DIST + "ibm.crl",
t=CertType.HOST_CERT,
@@ -512,7 +507,7 @@ if __name__ == "__main__":
host_uri_na_crt = createCert(
pkey=host_pkey,
subject=host_subject,
issuer_crt=ibm_crt,
issuer_crt=ibm_pougkeepsie_crt,
issuer_pkey=ibm_pkey,
crl_uri=MOCKUP_CRL_DIST + "notavailable",
t=CertType.HOST_CERT,
@@ -523,7 +518,7 @@ if __name__ == "__main__":
host_crt = createCert(
pkey=host_pkey,
subject=host_subject,
issuer_crt=ibm_crt,
issuer_crt=ibm_pougkeepsie_crt,
issuer_pkey=ibm_pkey,
crl_uri=MOCKUP_CRL_DIST + "ibm.crl",
t=CertType.HOST_CERT,
@@ -534,35 +529,48 @@ if __name__ == "__main__":
host_rev_crt = createCert(
pkey=host_rev_pkey,
subject=host_rev_subject,
issuer_crt=ibm_crt,
issuer_crt=ibm_pougkeepsie_crt,
issuer_pkey=ibm_pkey,
crl_uri=MOCKUP_CRL_DIST + "ibm.crl",
t=CertType.HOST_CERT,
)
# some IBM revocation lists
ibm_crl = createCRL(ibm_pkey, ibm_subject, [555, host_rev_crt.serial_number])
ibm_poughkeepsie_crl = createCRL(
ibm_pkey, ibm_subject_poughkeepsie, [555, host_rev_crt.serial_number]
)
ibm_armonk_crl = createCRL(
ibm_pkey, ibm_subject_armonk, [555, host_rev_crt.serial_number]
)
ibm_outdated_early_crl = createCRL(
ibm_pkey,
ibm_subject,
ibm_subject_poughkeepsie,
[],
last_update=datetime.datetime.today() + 1000 * 365 * ONE_DAY,
next_update=datetime.datetime.today() + 1001 * 365 * ONE_DAY,
)
ibm_outdated_late_crl = createCRL(
ibm_pkey,
ibm_subject,
ibm_subject_poughkeepsie,
[],
last_update=datetime.datetime.today() - 2 * 365 * ONE_DAY,
next_update=datetime.datetime.today() - 1 * 365 * ONE_DAY,
)
ibm_wrong_issuer_crl = createCRL(ibm_pkey, inter_ca_subject, [])
ibm_wrong_issuer_priv_key_crl = createCRL(
ibm_pkey, inter_ca_subject, [], authid=False
)
ibm_invalid_hash_crl = createCRL(
inter_ca_pkey, ibm_subject, [555, host_crt.serial_number]
inter_ca_pkey,
ibm_subject_poughkeepsie,
[555, host_crt.serial_number],
authid=False,
)
# create host certificate issued by a non-valid signing key
host_invalid_signing_key_pkey = getPrivKey("host_invalid_signing_key.key", createEcKeyPair)
host_invalid_signing_key_pkey = getPrivKey(
"host_invalid_signing_key.key", createEcKeyPair
)
host_invalid_signing_key_subject = x509.Name(
[
x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
@@ -606,12 +614,36 @@ if __name__ == "__main__":
host2_crt = createCert(
pkey=host2_pkey,
subject=host2_subject,
issuer_crt=ibm_crt,
issuer_crt=ibm_pougkeepsie_crt,
issuer_pkey=ibm_pkey,
crl_uri=MOCKUP_CRL_DIST + "ibm.crl",
t=CertType.HOST_CERT,
)
host_armonk_pkey = getPrivKey("host.key", createEcKeyPair)
host_armonk_subject = x509.Name(
[
x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
x509.NameAttribute(
NameOID.ORGANIZATION_NAME,
u"International Business Machines Corporation",
),
x509.NameAttribute(
NameOID.COMMON_NAME, u"International Business Machines Corporation"
),
x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"New York"),
x509.NameAttribute(NameOID.LOCALITY_NAME, u"Armonk"),
x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u"IBM Z Host Key"),
]
)
host_armonk_crt = createCert(
pkey=host_armonk_pkey,
subject=host_armonk_subject,
issuer_crt=ibm_armonk_crt,
issuer_pkey=ibm_pkey,
crl_uri=MOCKUP_CRL_DIST + "ibm_armonk.crl",
t=CertType.HOST_CERT,
)
fake_host_pkey = getPrivKey("fake_host.key", createEcKeyPair)
fake_host_subject = x509.Name(
@@ -637,7 +669,7 @@ if __name__ == "__main__":
crl_uri=MOCKUP_CRL_DIST + "fake_ibm.crt",
t=CertType.HOST_CERT,
)
#TODO DER chain
# TODO DER chain
# store CA
with open("root_ca.crt", "wb") as f:
@@ -673,22 +705,26 @@ if __name__ == "__main__":
# store IBM
with open("ibm.crt", "wb") as f:
f.write(ibm_crt.public_bytes(serialization.Encoding.PEM))
f.write(ibm_pougkeepsie_crt.public_bytes(serialization.Encoding.PEM))
with open("ibm_armonk.crt", "wb") as f:
f.write(ibm_armonk_crt.public_bytes(serialization.Encoding.PEM))
with open("ibm_rev.crt", "wb") as f:
f.write(ibm_rev_crt.public_bytes(serialization.Encoding.PEM))
with open("ibm_expired.crt", "wb") as f:
f.write(ibm_expired_crt.public_bytes(serialization.Encoding.PEM))
with open("ibm.crl", "wb") as f:
f.write(ibm_crl.public_bytes(serialization.Encoding.PEM))
f.write(ibm_poughkeepsie_crl.public_bytes(serialization.Encoding.PEM))
with open("ibm_armonk.crl", "wb") as f:
f.write(ibm_armonk_crl.public_bytes(serialization.Encoding.PEM))
with open("ibm.chained.crt", "wb") as f:
f.write(ibm_crl.public_bytes(serialization.Encoding.PEM))
f.write(ibm_crt.public_bytes(serialization.Encoding.PEM))
f.write(ibm_poughkeepsie_crl.public_bytes(serialization.Encoding.PEM))
f.write(ibm_pougkeepsie_crt.public_bytes(serialization.Encoding.PEM))
with open("ibm_outdated_early.crl", "wb") as f:
f.write(ibm_outdated_early_crl.public_bytes(serialization.Encoding.PEM))
with open("ibm_outdated_late.crl", "wb") as f:
f.write(ibm_outdated_late_crl.public_bytes(serialization.Encoding.PEM))
with open("ibm_wrong_issuer.crl", "wb") as f:
f.write(ibm_wrong_issuer_crl.public_bytes(serialization.Encoding.PEM))
f.write(ibm_wrong_issuer_priv_key_crl.public_bytes(serialization.Encoding.PEM))
with open("ibm_invalid_hash.crl", "wb") as f:
f.write(ibm_invalid_hash_crl.public_bytes(serialization.Encoding.PEM))
with open("ibm_wrong_subject.crt", "wb") as f:
@@ -719,6 +755,10 @@ if __name__ == "__main__":
with open("host2.crt", "wb") as f:
f.write(host2_crt.public_bytes(serialization.Encoding.PEM))
# store host_armonk
with open("host_armonk.crt", "wb") as f:
f.write(host_armonk_crt.public_bytes(serialization.Encoding.PEM))
# store fake host
with open("fake_host.crt", "wb") as f:
f.write(fake_host_crt.public_bytes(serialization.Encoding.PEM))
@@ -728,6 +768,6 @@ if __name__ == "__main__":
# store a DER cert and crl
with open("der.crt", "wb") as f:
f.write(ibm_crt.public_bytes(serialization.Encoding.DER))
f.write(ibm_pougkeepsie_crt.public_bytes(serialization.Encoding.DER))
with open("der.crl", "wb") as f:
f.write(ibm_crl.public_bytes(serialization.Encoding.DER))
f.write(ibm_poughkeepsie_crl.public_bytes(serialization.Encoding.DER))

View File

@@ -1,30 +1,29 @@
-----BEGIN CERTIFICATE-----
MIIFFDCCAvygAwIBAgIUO+SNGBgRvkmR/lKiZhiN4l4zS70wDQYJKoZIhvcNAQEN
MIIE+DCCAuCgAwIBAgIUBSLhuGTvxPbggG70ISL2R6DDGZcwDQYJKoZIhvcNAQEN
BQAwgcwxCzAJBgNVBAYTAlVTMTQwMgYDVQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2lu
ZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFs
IEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMREwDwYDVQQIDAhOZXcgWW9y
azEVMBMGA1UEBwwMUG91Z2hrZWVwc2llMScwJQYDVQQLDB5JQk0gWiBIb3N0IEtl
eSBTaWduaW5nIFNlcnZpY2UwIBcNMjMwMzI5MDkwNDQ4WhgPMjM4NzEyMzEwOTA0
NDhaMIG2MQswCQYDVQQGEwJVUzE0MDIGA1UECgwrSW50ZXJuYXRpb25hbCBCdXNp
eSBTaWduaW5nIFNlcnZpY2UwIBcNMjQwMzIxMTQ1MjM5WhgPMjM4ODEyMjMxNDUy
MzlaMIG2MQswCQYDVQQGEwJVUzE0MDIGA1UECgwrSW50ZXJuYXRpb25hbCBCdXNp
bmVzcyBNYWNoaW5lcyBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrSW50ZXJuYXRpb25h
bCBCdXNpbmVzcyBNYWNoaW5lcyBDb3Jwb3JhdGlvbjERMA8GA1UECAwITmV3IFlv
cmsxDzANBgNVBAcMBkFybW9uazEXMBUGA1UECwwOSUJNIFogSG9zdCBLZXkwgZsw
EAYHKoZIzj0CAQYFK4EEACMDgYYABAF2iBzYS4tt5xI8fpAO33jn97aEmZFGsSY7
qLhshEfwirbUacKxKO2eHDUBWAWs09MCM9ORIvfi+KocKxR7eIO0BgDDRVbCXPkv
Kc5mvUQRTWt7PHjhOj+QvbkAQPaHblJi93imGpN9GzSALrJX404Gct1fKjR63aoo
IDUJKnDDXC55c6OBhzCBhDAyBgNVHR8EKzApMCegJaAjhiFodHRwOi8vMTI3LjAu
MC4xOjEyMzQvY3JsL2libS5jcmwwDgYDVR0PAQH/BAQDAgMIMB8GA1UdIwQYMBaA
FN6M1/Do0NgBB3F9b9loWSA+sGd8MB0GA1UdDgQWBBR6ESQ+J+iXQe0a/KZ2+N+Z
8a9SZjANBgkqhkiG9w0BAQ0FAAOCAgEAVWJHoCxxkqh7b+y93PY4KPy4jJC4gN1S
dAPqttD/yteJ/4mbVel1/KNSoQBk5EpJmRqeBwHCgGJaT/TxYXNw/b8mRPxe/xbb
wieZMqlSmH028UjYDku1eM0IgHISgoCesIR95D5iAOWbMMVUwIHIHTfmhK7DmZVe
SPf7RIkctrpYxZh0Gw8KLZO6Mfy/9tq3dps0A7KS6jjdrF+M9LavPGwFvtfvRMTi
rdteByO2saGAKDvrjtievwlWCNBJlKV1arW9krN7eqJY5YO6eRbX6UjuhbPRgjte
eZ4jL121TBJaKZU7Q/lvYHIWfzstwQdiem2Ua1GyiiEvPZrQlmqQ3gDBtwJQGB4Q
2myP7MY7THiKObjaB8qRsVxKM78ktwAtAYSZv7gZlmSJ/uTMzDV5D2TQxqs7zwCj
sV+psUn4nvh58xP+DW+MYbF/Cpmzvul9FjMKBs270vE1q+gMot27rbQHRRJ4lVN5
khiG6Oi6blVkPKExIVIiaZ9diXK6NhtWp15PWljNiDxZO+zpkeuw7cKLn/idzmvP
Gcj6m7DqcdsSIHNKbR5iM2VuDhg/j8uBD3uF2Wlymp31TBQgdYWSihJpwZKHNqJD
uq9SmegwI5gYg64KwABZM9hGbl/krXt/0CeCR5HRc+fthanKx/tO2tbCuVT3FR5J
XpKNUy1D78o=
EAYHKoZIzj0CAQYFK4EEACMDgYYABAHGO0MnpQa6Q2IxgqV7AGwd3OwBnYOJjYJF
hzrwY+wQacmJjWeNyHahBCxu4bM8vDr70SF5vZFrWpcWpc9JTY5AagFCFDqIfSvL
J6lKJuCog5RfMsWJpG2j/MnK7MxG+Ph0R+ItmLFbWFxCV5YOT43olhwYZr/pd9qH
PAD96UEDM8JanKNsMGowGAYDVR0fBBEwDzANoAugCYYHaWJtLmNybDAOBgNVHQ8B
Af8EBAMCAwgwHwYDVR0jBBgwFoAUw4weXbTWAZisD86gZSugZ6V1FNkwHQYDVR0O
BBYEFL4m5UxVbUdEl9yg4sjiWKO/EAxyMA0GCSqGSIb3DQEBDQUAA4ICAQBwaPG5
Mg3iKtxR6ncteH+YmtMHW4/wB/341pTKFsKBYsMNWuCC5AKbNrshCNbFbctqhLrB
LmEpmza3/Pk6izO4AozHNl0tRec/HnQr2gonfI48HBDRiV2f40x0gJG9gGCiJy7o
6iKZDYUnjfnhXVC67RwLMEiIKbeOAWQ9hHqegUjYdaaIlhyiHLMuWMceidvG76nN
2eyJUNEouT4+UvquD2oqSitB3ZLhWRqPOQn57ME1b0QYF240PN8r21YtzPmSI+s/
ej04EcQZrlJId6GtU7YwD1767hVw84v/QjPbMqnYQbxX8n3IvOf541rQ0UdjBFc9
UhbnSn32IGFrRlL1y3MPBF6hLPcpW4P0QrUijc6gZ+x6SNFho8n+dk53F7RvMi1l
SLgJl7x8pUeqBn5QKMcYYsZG39oZmQj4xHjAABx2hRWayDscvROiQpvLHRtLVmk7
+hq4Q/jalc2cNHZSwLX6Tv5P+8waTnXg8YNEHeAAgcw1lD+uw5HgusjGD4USE7Hq
Q6EDGzC+Ny3u2+35XWbNaKWVthtKAIcZ9B4LjdJXeQFGcOMr6yV5rKfOFQwXo8bS
rNy57tiva8KM2weSfRil4f146Rsb3TJzUdlkaN+NVIY0YImiC+rR0qa6Iv6JCio1
F2lu8m/aRHQQF5J5fD7ge6v7F2D6K3qT9tTlrw==
-----END CERTIFICATE-----

View File

@@ -0,0 +1,8 @@
-----BEGIN PRIVATE KEY-----
MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIA8rPNC6rxZR+GxSxb
qWRreFGnWRQGd22nHWKAvQmrA5GlXTtWQMoL8il9Jb1OnrQPPo620nQpzA1GXo4U
BUqgYoShgYkDgYYABAHGO0MnpQa6Q2IxgqV7AGwd3OwBnYOJjYJFhzrwY+wQacmJ
jWeNyHahBCxu4bM8vDr70SF5vZFrWpcWpc9JTY5AagFCFDqIfSvLJ6lKJuCog5Rf
MsWJpG2j/MnK7MxG+Ph0R+ItmLFbWFxCV5YOT43olhwYZr/pd9qHPAD96UEDM8Ja
nA==
-----END PRIVATE KEY-----

View File

@@ -0,0 +1,29 @@
-----BEGIN CERTIFICATE-----
MIIE+DCCAuCgAwIBAgIUC3KzCH9KUb8ZaY6J/97gqebLoIYwDQYJKoZIhvcNAQEN
BQAwgcwxCzAJBgNVBAYTAlVTMTQwMgYDVQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2lu
ZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFs
IEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMREwDwYDVQQIDAhOZXcgWW9y
azEVMBMGA1UEBwwMUG91Z2hrZWVwc2llMScwJQYDVQQLDB5JQk0gWiBIb3N0IEtl
eSBTaWduaW5nIFNlcnZpY2UwIBcNMjQwMzIxMTQ1MjM5WhgPMjM4ODEyMjMxNDUy
MzlaMIG2MQswCQYDVQQGEwJVUzE0MDIGA1UECgwrSW50ZXJuYXRpb25hbCBCdXNp
bmVzcyBNYWNoaW5lcyBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrSW50ZXJuYXRpb25h
bCBCdXNpbmVzcyBNYWNoaW5lcyBDb3Jwb3JhdGlvbjERMA8GA1UECAwITmV3IFlv
cmsxDzANBgNVBAcMBkFybW9uazEXMBUGA1UECwwOSUJNIFogSG9zdCBLZXkwgZsw
EAYHKoZIzj0CAQYFK4EEACMDgYYABAE3KDrdCdVeBV34NicA8AoP7hItcwxgXHOQ
F+V02N6b5AR7w3YDHE/JSzSoZZIYiqdy8SmeD5GtwHLV8tLQ8xnadgHT0BesGS02
w0H5foGzzZOHZW3AfbdH4MpssR4Bf1jqL0jw6eV+oiMStDuZ44zri7PFjvVByt6M
oeSvh5qAXCQG/6NsMGowGAYDVR0fBBEwDzANoAugCYYHaWJtLmNybDAOBgNVHQ8B
Af8EBAMCAwgwHwYDVR0jBBgwFoAUw4weXbTWAZisD86gZSugZ6V1FNkwHQYDVR0O
BBYEFL8FyjCu1iRcjwx4pzfo+VIQ5NdbMA0GCSqGSIb3DQEBDQUAA4ICAQASxSXu
RxNw/kSwqedNq9jOTHb5FATNykBIVSuXS9BB2qkjcTVDXNnlsSBrPL/CumRp/TFD
5VsB2rLhESmUrpghQrODeFvyFE52yVhxvcNCyjz7yIQZvc4qofMQMsg3o0rSqp2s
lu1PUbcrL2aCG1yxB3isObVqiWaiRdnPxL8aX3Qt6BszlwWUgaFoaH0uZxlgVGKV
C+dXrn5WkNRVd2ouHSLQE6fIUYIf/TrV+AKu804IEoFRIvMUCqQRUHsj5toKhfDb
6tl/Xd+EiPCYbnhR2J01I08yxMExvYXfXapY7JJjlWTHKFKaxLoqv++NZRM1bW6s
uyLWP735Qb+0AmhZ6TfeJM7H77LpQK0WCylaNVJWWjXt9UsnNdirCbp/jpKF8bnG
2PkjBHKruvCakqw1bDq8eDv9In1Ki+Um4gp7OfjYvcN8zxvGQofgj++UaCy982iX
WSq14iUyrRDVu8zWghL/F1lUx7ab8UV+OrmZuCALVHZ76YVdwmJXGYll1OBbJbgL
5xze6p77vKzbgNyABWmR6TlHq/nFDhj9kKirpQaI7WHyOtsGpc7sqd0tT+CeOhNf
l3xXyFPb6N58aSC2cY0W0Nq6X/mWIgMqHY9lzYLmoLBFFZlIjqWzwyVcajmjrtaK
rlfs0e9f9DvVV8bMTXFMUBlWrmYDrROKpYLqhg==
-----END CERTIFICATE-----

View File

@@ -0,0 +1,8 @@
-----BEGIN PRIVATE KEY-----
MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIAQNfN5BLLLAdhlwGk
Ve8w2t+9x4LWR9st6CLCYHnTgc2gr4+HqgcMwmNuj3cA8ENBvIShUnHkX2E+9CyP
3W1ZN8OhgYkDgYYABAE3KDrdCdVeBV34NicA8AoP7hItcwxgXHOQF+V02N6b5AR7
w3YDHE/JSzSoZZIYiqdy8SmeD5GtwHLV8tLQ8xnadgHT0BesGS02w0H5foGzzZOH
ZW3AfbdH4MpssR4Bf1jqL0jw6eV+oiMStDuZ44zri7PFjvVByt6MoeSvh5qAXCQG
/w==
-----END PRIVATE KEY-----

View File

@@ -0,0 +1,29 @@
-----BEGIN CERTIFICATE-----
MIIE+TCCAuGgAwIBAgIUWlKUd1HKU8R7cjv5NJdWhHzhT5cwDQYJKoZIhvcNAQEN
BQAwgcYxCzAJBgNVBAYTAlVTMTQwMgYDVQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2lu
ZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFs
IEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMREwDwYDVQQIDAhOZXcgWW9y
azEPMA0GA1UEBwwGQXJtb25rMScwJQYDVQQLDB5JQk0gWiBIb3N0IEtleSBTaWdu
aW5nIFNlcnZpY2UwIBcNMjQwMzIxMTQ1MjM5WhgPMjM4ODEyMjMxNDUyMzlaMIG2
MQswCQYDVQQGEwJVUzE0MDIGA1UECgwrSW50ZXJuYXRpb25hbCBCdXNpbmVzcyBN
YWNoaW5lcyBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrSW50ZXJuYXRpb25hbCBCdXNp
bmVzcyBNYWNoaW5lcyBDb3Jwb3JhdGlvbjERMA8GA1UECAwITmV3IFlvcmsxDzAN
BgNVBAcMBkFybW9uazEXMBUGA1UECwwOSUJNIFogSG9zdCBLZXkwgZswEAYHKoZI
zj0CAQYFK4EEACMDgYYABAHGO0MnpQa6Q2IxgqV7AGwd3OwBnYOJjYJFhzrwY+wQ
acmJjWeNyHahBCxu4bM8vDr70SF5vZFrWpcWpc9JTY5AagFCFDqIfSvLJ6lKJuCo
g5RfMsWJpG2j/MnK7MxG+Ph0R+ItmLFbWFxCV5YOT43olhwYZr/pd9qHPAD96UED
M8JanKNzMHEwHwYDVR0fBBgwFjAUoBKgEIYOaWJtX2FybW9uay5jcmwwDgYDVR0P
AQH/BAQDAgMIMB8GA1UdIwQYMBaAFMOMHl201gGYrA/OoGUroGeldRTZMB0GA1Ud
DgQWBBS+JuVMVW1HRJfcoOLI4lijvxAMcjANBgkqhkiG9w0BAQ0FAAOCAgEACPbD
hFuibNamlcpnVG7mgnO56RB/K5otOCGS0hbR3OFUGY1ZDQ++M44OF/b+eNYHgjsr
ER4r2cne3qBjOArFj/toEDGM2l/DFWDnpOvh1ZItJjpQe07OGn+KpTLf/ZB0Q5D7
jV/ddjJ0GGyxessjfUvmCT4BVWn1bXKJFSgujic7lgMf8WBGwW+WW3eZecYsh/Cn
rHWfQYqtvzB1uM89bwZwN+lvHz/QHTreAShDAiCY9M31cemvUvC58z8jPKngFhuf
C7ZMUXbzu2jYWo3EowzvcRpO1KqlLfNHjGLbaBaZWP2ocK2IUTrsAbr7PTdcAqjX
TRIds4JlbidA8OziEXFTcM2xShS6WISsO+9JXk5Xxc3+xscjSamHTMwRm2LaKjrr
d8mOxMs4/5547CBsBFMqu98tiD18K0yqdJiJJRDDOvqVeCvDE6y/pzKaSHIIyA0P
ATnjQzvgqbcwLrdoJ4WNdTpZieoisUR0oMAKUViPwd0xStzNX6K89PSd5c0Bqbhj
TwCpaT+DfcvlWk4wqEa9rLn+Su1SUfMSD2dITynLW0UexiKPHZ5epOPu5ho6cOk/
fe/N1cX7SyOjhErWLwqr974YM0EPiR6f5lNooYXMPbatq8lcG0gpEg5pggHhsLiY
LGfvu2jQJKGnrBYM3IcRGUsc+VZ6CNTJjaIIbGg=
-----END CERTIFICATE-----

View File

@@ -1,30 +1,29 @@
-----BEGIN CERTIFICATE-----
MIIFEjCCAvqgAwIBAgIUMXh4o6xcPRTKpYDr+YgZnmWeatMwDQYJKoZIhvcNAQEN
MIIE9jCCAt6gAwIBAgIUSpwJMAovpO3Z9SuY7Zw+/pv3bLEwDQYJKoZIhvcNAQEN
BQAwgcwxCzAJBgNVBAYTAlVTMTQwMgYDVQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2lu
ZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFs
IEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMREwDwYDVQQIDAhOZXcgWW9y
azEVMBMGA1UEBwwMUG91Z2hrZWVwc2llMScwJQYDVQQLDB5JQk0gWiBIb3N0IEtl
eSBTaWduaW5nIFNlcnZpY2UwHhcNMjEwMzI5MTEwNDQ4WhcNMjIwMzI5MTEwNDQ4
eSBTaWduaW5nIFNlcnZpY2UwHhcNMjIwMzIyMTU1MjM5WhcNMjMwMzIyMTU1MjM5
WjCBtjELMAkGA1UEBhMCVVMxNDAyBgNVBAoMK0ludGVybmF0aW9uYWwgQnVzaW5l
c3MgTWFjaGluZXMgQ29ycG9yYXRpb24xNDAyBgNVBAMMK0ludGVybmF0aW9uYWwg
QnVzaW5lc3MgTWFjaGluZXMgQ29ycG9yYXRpb24xETAPBgNVBAgMCE5ldyBZb3Jr
MQ8wDQYDVQQHDAZBcm1vbmsxFzAVBgNVBAsMDklCTSBaIEhvc3QgS2V5MIGbMBAG
ByqGSM49AgEGBSuBBAAjA4GGAAQBdogc2EuLbecSPH6QDt945/e2hJmRRrEmO6i4
bIRH8Iq21GnCsSjtnhw1AVgFrNPTAjPTkSL34viqHCsUe3iDtAYAw0VWwlz5LynO
Zr1EEU1rezx44To/kL25AED2h25SYvd4phqTfRs0gC6yV+NOBnLdXyo0et2qKCA1
CSpww1wueXOjgYcwgYQwMgYDVR0fBCswKTAnoCWgI4YhaHR0cDovLzEyNy4wLjAu
MToxMjM0L2NybC9pYm0uY3JsMA4GA1UdDwEB/wQEAwIDCDAfBgNVHSMEGDAWgBTe
jNfw6NDYAQdxfW/ZaFkgPrBnfDAdBgNVHQ4EFgQUehEkPifol0HtGvymdvjfmfGv
UmYwDQYJKoZIhvcNAQENBQADggIBAEsSd5vd7Vk1y1YsE4eWkrBrMElYa3/O6G2Q
oMZFo2mzzDH50NBEwYG4K+SjEmqJbAErtNHsAcJLWlvORiNoBmPcB6FEMifgCvuZ
zbSEiL/tt8XLI1M04DdKjVZ6AIrdhMKPz/AaRycnlHjbq0R0fEJP/SnWxtGnHewB
QGM8TDGCzXrwXsOr50soxQ+cbXFJ6eQyGrtNP0eyJ7kkIrz6+SJ0dQPXxoZpdtfY
XEv1OagX0tAuDUG26do6MjwC1qiDKoLdkxSFRkCvyRHqFapKlLhzBMrLhQ+Hl6E/
kD5ORD2nMvTHcHWbjb7Mr6tcxKG+7CcJO0hYJbdfNCcKYc3EmE49wazSTBKvWfJp
XObVEGeM/11cdcg6Li1jw/JrrexEeQpjgoNuAgGKRmxzJBOCPNkU8jGs5QEqFCyw
fpl7BA+ydW2/zAvcr7mZZgyK4KiRTdK5VTGfXuwTv+Q3hsE0CZ6L+byNCZajyGzs
xq9ydh2G4kIlWFzs+2gSxQWYRiOGt6W7FVdiPYOnAVgzmRJdfR1qVrWZTGbPxJbX
1O3qYBPQE2tU8xsyl/HuikGProda2xwfTjmRhr7DPYyF75nGPvtGm6vwBBcWm+xl
jI0a/dHqE5MR6acOrXYNSFflPcfd04vJ87Ajx/wFr0Glo/8LWtzMp0nFpvif9LDX
3sGEtRA1
ByqGSM49AgEGBSuBBAAjA4GGAAQBxjtDJ6UGukNiMYKlewBsHdzsAZ2DiY2CRYc6
8GPsEGnJiY1njch2oQQsbuGzPLw6+9Eheb2Ra1qXFqXPSU2OQGoBQhQ6iH0ryyep
SibgqIOUXzLFiaRto/zJyuzMRvj4dEfiLZixW1hcQleWDk+N6JYcGGa/6XfahzwA
/elBAzPCWpyjbDBqMBgGA1UdHwQRMA8wDaALoAmGB2libS5jcmwwDgYDVR0PAQH/
BAQDAgMIMB8GA1UdIwQYMBaAFMOMHl201gGYrA/OoGUroGeldRTZMB0GA1UdDgQW
BBS+JuVMVW1HRJfcoOLI4lijvxAMcjANBgkqhkiG9w0BAQ0FAAOCAgEAd9NdTLDK
fWPdOg78c+CaG2XVnIzBy6niur4vM1DPJYbwabTYbpJM2jtevMo3h96jCd6AfHzv
cFZ1BzpYsWtjbDFhiqowmKnlFlOIoIDXCaG7vBvDWc4iWGG9PHMWEouSQWxg77bZ
A8l7+K0VdRWYCqwxxClK8oK3PqGyGqELRDWwlBb0kRi9XRmB+2BjOdZOQvmGka/R
l8hZWHTs+SPHZ+ySiJn55/w7gN/LCJs1XX70jPrzu01lDPTqVIrGKBtWBMKFKR7g
A4r3EThfj85Xq1T45rvD0ozlkyVmdMtSk3z+fKCt5+qEHAu52kq2Ps7xQviAYkIK
f+yNf1a/Ly79QoqEibRXuKMk/oWoqv7f5vT5HqoWEWZFIYbdbYTBIwkw3mHwZRZx
CcyiukHw2W/ZwM6p60gXWZwrQxwVkdhxWnAHrAToL6O8M9Fk4aVWUkFNjqVUjTWS
HLCxv8mCPujXIneqXyiJOpAPKu2kjmoFwfisjevNUmO5EqUHUba98Ne7rdiWweP3
nwcBBKIQ2MVZ/lPqfPtqFOHqBzCbqozVw1HzE2/ImnYsK8SGqwBnSJyTt+WjM/8S
4ulkjVDIwWFwUkOWjM2yorp3u2tFJF2sMv+3AR3mp6aDjF7sCzYpLaZag6oDmwOF
nR+VwEbTC8gnl21swWSjtUC8I0EidfxzCpc=
-----END CERTIFICATE-----

View File

@@ -1,30 +1,29 @@
-----BEGIN CERTIFICATE-----
MIIFHzCCAwegAwIBAgIUBphLhhHJL2K96bK/cfgBk0d+7gkwDQYJKoZIhvcNAQEN
MIIFAzCCAuugAwIBAgIUELm+ubD3lNPrFxtCj86wMh7lYEcwDQYJKoZIhvcNAQEN
BQAwgckxCzAJBgNVBAYTAlVTMTQwMgYDVQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2lu
ZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFs
IEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMREwDwYDVQQIDAhOZXcgWW9y
azEVMBMGA1UEBwwMUG91Z2hrZWVwc2llMSQwIgYDVQQLDBtLZXkgU2lnbmluZyBT
ZXJ2aWNlIEludmFsaWQwIBcNMjMwMzI5MDkwNDQ4WhgPMjM4NzEyMzEwOTA0NDha
ZXJ2aWNlIEludmFsaWQwIBcNMjQwMzIxMTQ1MjM5WhgPMjM4ODEyMjMxNDUyMzla
MIG2MQswCQYDVQQGEwJVUzE0MDIGA1UECgwrSW50ZXJuYXRpb25hbCBCdXNpbmVz
cyBNYWNoaW5lcyBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrSW50ZXJuYXRpb25hbCBC
dXNpbmVzcyBNYWNoaW5lcyBDb3Jwb3JhdGlvbjERMA8GA1UECAwITmV3IFlvcmsx
DzANBgNVBAcMBkFybW9uazEXMBUGA1UECwwOSUJNIFogSG9zdCBLZXkwgZswEAYH
KoZIzj0CAQYFK4EEACMDgYYABAF709fZwb3pGZWfHLcCG2fLNcvNh6IqPHwfjRYp
brM5BEE8XoXxcCAXwxo4EAGOcuZBRKP6Ofahek7ppizV8bkPMQDCIgNq2N8mwPFO
99CbyrZs4ZMeAWWWPJiHXUHbWQq4ko8w4UUT7nUIgdHQwWM6TdZml8ke+LE9Jxtx
h9KkfCPi/aOBlTCBkjBABgNVHR8EOTA3MDWgM6Axhi9odHRwOi8vMTI3LjAuMC4x
OjEyMzQvY3JsL2libV93cm9uZ19zdWJqZWN0LmNybDAOBgNVHQ8BAf8EBAMCAwgw
HwYDVR0jBBgwFoAU+jIyiVonTYe6GuSPiAkxA65qou0wHQYDVR0OBBYEFJdEECIf
7UdEf08saThHZDzSfxjhMA0GCSqGSIb3DQEBDQUAA4ICAQBgvREPqqKvAZM3q9pG
5S6wtUspz1Y1sBD4duPEnMZ7Vf9a1HRPrR4vc5ncFIcyS/U/UusvWgFMYoa6WIZR
l4OqRplKF1pwCaQ2F/8OdGMV37iUqZuN6V/GggbFXgMFK1dH29T6h4VtoKC9yScQ
ToHQLuz4ymkd2BwxYix19M6QwdrqomjJb2/zrc7pvMZ0k8KKYi/wt6tlz7FDvsxF
VSDf29gm98kfDJfzPfAC5D93YruAohsP8SakVdA2/YbTkDfImT8ggSnsE83upSD6
ssjKPPNRunLeCKLb55/Ikcok1iyGhfdmkJvdIHSEvyNp0p7mrohz6l748xdKkKNt
9hOzsfNjThq3zp97ND7M+knqNuzsZIkcV/OUdxNBootIrJXvfeqpaw++5SfWvf+6
1dHJQpDU3cXKAQ0/RvvqLC+aPvklk2efuvBKIKP9X4WqcP+l2P19GMaM1SZtr5S5
OWMxqT6sW5lSX5Smm4rMB3UmLDS0SXxHIIvFEQSABiWb6Y0ibDj8a+YrWVyQNH1K
fCSNvsW1r03D06q6gp9fxL1hFBLUw9ooi7ewPfNmm3doe2R0TQpE0pWkiRhhjDjJ
RcIPp+gfYDtt0LcoYVpNdKtLoRPVtO2K3zeU0ezW4PL9Q0tjxh2K/+1+8UEv7nJD
sFg4nQMeygdSK4w0ZlT8xqXVJw==
KoZIzj0CAQYFK4EEACMDgYYABAB/2mDXj/QP7fcpxLTNfFfuh/X1Y/RS8XK+Y4v+
0nisTQhe3MK8BZ7D0bcB872s8EJCYZ1OYr5O2epQgv2hbk4T1wCGKe+Pjf2QHTts
wXMpPf87R3etF+zWR+CYH+5N5uQhjW9Ueeq7wve3A61e+Atz7IzTKVlM29kT0XvI
sYtazn6usqN6MHgwJgYDVR0fBB8wHTAboBmgF4YVaWJtX3dyb25nX3N1YmplY3Qu
Y3JsMA4GA1UdDwEB/wQEAwIDCDAfBgNVHSMEGDAWgBTXVfLQH2D0KccIHhK6M5MR
TITvtDAdBgNVHQ4EFgQUWdGEEpvjFJ4SNUillC09iBfcTEUwDQYJKoZIhvcNAQEN
BQADggIBACfZ7+KtT0Hl4Y/JBwCtUqCRRt4kCM5rXqORswkJ6RNmx1OtBHPlkUEI
E5HrE0dZlaECfqMkOBxhbBqOSpoL/xjz1gDHILWXEbWchuFnU4EAgYvJS7nLAHHO
swJCEP8VDM3y5lUWni8sXs6ro/H5tAkm260+xbn0BFF99l+M124ZUawB+tDg7E9b
MNG0eWtfeiZzWBBhoxhQoD03gFADWxTU1EK4JgCl7frsj4PjK7TMKTV/Gd/Bd5l0
KreFW5orupd3YBqDeUYI6p1l9+uThottwrA4z/POygxvhqgoqNA/+evMWX3wxNza
ComAmWffB5EJQFEKcpdASwEhyjBMap15GdJVBFGYzXAlksQz7k1fr4h0ebuYtcpb
dvcDyeIxjsg5XiP32494wogLUjHioi5mwIrGn8/9V6JLRGfKBHnmejHBR/cbMpuv
rpl0ZZks3bicmBVTKFyj1ORRGX1cXsbtCbPBJEmBeR5IOFYBeaQHrqTcaEBz4lWe
K2OT6ebcqtsCzDSmjsoeAX/CWRVaIzLzMc9SqE8lZ68ajXjbt/59I7EBeOenttO5
mg9mokwDqoeM0bXyT3qdT4s9fhy0BPgnBqJHKIc9afzV79Iz1uJ/E+TZJ+tzhbAU
n4fFxIHOdbyaOLCLT0+O74FZCQq8FUUnL9QVY5dXTH2458IUiD20
-----END CERTIFICATE-----

View File

@@ -0,0 +1,8 @@
-----BEGIN PRIVATE KEY-----
MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIB48Wl8pvlD/o6F7YG
sFfCXNQRbKbppIrywEBkfNG0VzfXazBOLD41bcdPEBh1111kSYgn46uUVxjabyLp
BgQthf2hgYkDgYYABAB/2mDXj/QP7fcpxLTNfFfuh/X1Y/RS8XK+Y4v+0nisTQhe
3MK8BZ7D0bcB872s8EJCYZ1OYr5O2epQgv2hbk4T1wCGKe+Pjf2QHTtswXMpPf87
R3etF+zWR+CYH+5N5uQhjW9Ueeq7wve3A61e+Atz7IzTKVlM29kT0XvIsYtazn6u
sg==
-----END PRIVATE KEY-----

View File

@@ -1,30 +1,29 @@
-----BEGIN CERTIFICATE-----
MIIFFDCCAvygAwIBAgIUGuqbEx5X1pFQfF4T6kIfdcrUwbMwDQYJKoZIhvcNAQEN
MIIE+DCCAuCgAwIBAgIUMi8utJhRyr5bbvABnCn/Q9/vJ0kwDQYJKoZIhvcNAQEN
BQAwgcwxCzAJBgNVBAYTAlVTMTQwMgYDVQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2lu
ZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFs
IEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMREwDwYDVQQIDAhOZXcgWW9y
azEVMBMGA1UEBwwMUG91Z2hrZWVwc2llMScwJQYDVQQLDB5JQk0gWiBIb3N0IEtl
eSBTaWduaW5nIFNlcnZpY2UwIBcNMjMwMzI5MDkwNDQ4WhgPMjM4NzEyMzEwOTA0
NDhaMIG2MQswCQYDVQQGEwJVUzE0MDIGA1UECgwrSW50ZXJuYXRpb25hbCBCdXNp
eSBTaWduaW5nIFNlcnZpY2UwIBcNMjQwMzIxMTQ1MjM5WhgPMjM4ODEyMjMxNDUy
MzlaMIG2MQswCQYDVQQGEwJVUzE0MDIGA1UECgwrSW50ZXJuYXRpb25hbCBCdXNp
bmVzcyBNYWNoaW5lcyBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrSW50ZXJuYXRpb25h
bCBCdXNpbmVzcyBNYWNoaW5lcyBDb3Jwb3JhdGlvbjERMA8GA1UECAwITmV3IFlv
cmsxDzANBgNVBAcMBkFybW9uazEXMBUGA1UECwwOSUJNIFogSG9zdCBLZXkwgZsw
EAYHKoZIzj0CAQYFK4EEACMDgYYABABphgYAOqZ4uJPUtVIqaU7UsJgz9+xMmGDq
V7nFimGmkbmqPLT96jIyN4CWdLzfbxP0xvIklkEoOm1xV07YR2LHHQATNEPISTDH
7fySZ47QVc5tyECpZVW7JvSvWKA/KiApAbB1ixErfDrqW1nG5IUtEbDYJgtGwPI/
+I7e9cU2wkA5mKOBhzCBhDAyBgNVHR8EKzApMCegJaAjhiFodHRwOi8vMTI3LjAu
MC4xOjEyMzQvY3JsL2libS5jcmwwDgYDVR0PAQH/BAQDAgMIMB8GA1UdIwQYMBaA
FN6M1/Do0NgBB3F9b9loWSA+sGd8MB0GA1UdDgQWBBTECeFXnyfTnFazbR0K9cYk
lS3O0jANBgkqhkiG9w0BAQ0FAAOCAgEAOjEE4/KdvcJZbloSGLue27FSrhExvUJ3
tYS3rs2xg3Ua2daCioI00VrwIN2Fjisqvi10Nv6+NWz5w1220AJyjlmPxvWFcPco
sXLAOWDhi217JaoJ+RzavpOwzhTffEpvPwR6RU4A36vvonc4jm3mWs6F1i5T6YPi
ZaYuk3CRme6WX012rBhIc+heTGh5ZDwwPmGDMLXdpsu+2+3sCPxUW6eQcOWoXkhJ
jn+n6mU18JdN5+wU6Lig5uxXnoP1VN8Xog/mmKV4ThVAS8k9iS5wFK4jl27n6XZy
wfd65WWlm4MMEvKNruj025aSPJp/bcnchBNfnXXPuI5GnYS2cC3TXHd4XT3r3pYn
qgLoNi+AkxnTnxEv5lg+oE+yTMNxDh4iiYkX96ljamGbUPBvbD7bi3Oc/7EOVra1
BmCGmcjToEnm0e0it9yyuYwKQ6nTz906W3XzaFB+awnXZcGEMgwwdvdal8+eki/r
ofT0nO6cuXbbPYc0rSs/2f3WxjDVmQtiVoJ1dPYIrTX/4lbrsYWVS016Y0UcZ/D/
/qWWWZIyYpzPasTEgGqtwb5WhBvz3RAFTePefFlTzBHhSPk0Tsu4+W7zHpapfZ0M
0LXT1lGR5WBmur002vbTm4yt7tzdypMbL2i70WGEp4mpRohmBG1m9hYGcelip3iL
Im6vFBNWpVE=
EAYHKoZIzj0CAQYFK4EEACMDgYYABAHkrwf4hZ7M5ahoYHT0u1Xgl28qxURcdNmW
kYDA5u1Y2mGXQq85BakAOyfxl/FF/cBrLm0eLVFpePumqgPna3El1gAs9p2SFwN7
4MmcLhbwPmGnWmzVrOh9cNS988XYf01E74966r4MKpAGxSNPKDwu4doXFVAYRH/w
tcgbjlk+Qi3c96NsMGowGAYDVR0fBBEwDzANoAugCYYHaWJtLmNybDAOBgNVHQ8B
Af8EBAMCAwgwHwYDVR0jBBgwFoAUw4weXbTWAZisD86gZSugZ6V1FNkwHQYDVR0O
BBYEFG+41urs6GhYzOrJD/MJDWMSrUlvMA0GCSqGSIb3DQEBDQUAA4ICAQAnowYb
R1qgnpH5FLgkj3LndAAfFmJMlTrNcmtafjaLZHUmxxO1tFjb7vvGgu9LggwwSRoN
y0Qsu0mywXd/ntEuWDyD735aGtUE9xnmluoj4ILBnln195VuvUoWYjCy0XsGZg6G
UL8bOaZgbvXQWDcdXfpYnM9C5Uj4mB3LFDdasd7nDv2F9vZlHNkd0uGmZvBco3SX
GNFETOaY5HjU3jLlCmD74p7G9e//+153R2aXEww3SVVJyRowO7SpwH88DNjl2a6A
OLWoA3oRrX4rDQI66LYv0RZMDCTvzY+HxOQHXeswosA8D96GhpClb1X0wLZUp6gR
pLzVzaE8RFnSg52jzjI3ehFIoSK0x9R1KPzKbYDh7Q8Sc5sOSe6r9Q01BdpBOUjp
iTKhgbUEbcIwcaKLIGeSBe0+Yh1uQpqBtOPectUp9bz+hEUDzG6QMS5VFxAGuZWY
2iA97jxHsUBEgMBZha7z/hQ68Pst+KaIV/24By8lKm0rWpLSKOXVAW1lWZrlpIcx
Le8+dmy9/JFJXmmN/pmAEVVsK5dYtVXt6ikVi+LPr/7fCfvt2zk88wiUp8iz5jgQ
pNYT8MPOMf+yzzoqPXjGmrT5znuHnCg0OSh0u8NILWQPQl8M6KNiI8lzcVBy6Djq
fmnQlaxP1Ey+wrznWmBu5zesU8uMyRTxIfnEzg==
-----END CERTIFICATE-----

View File

@@ -0,0 +1,8 @@
-----BEGIN PRIVATE KEY-----
MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIBLz0ExeBJrxd5gA7C
YFJLVuNd4CPNc/jsOLIMnIbLHSegdOtQn9tief97k5rZdz/MQzWp7rCmsLUYw/fM
ktUQjJKhgYkDgYYABAHkrwf4hZ7M5ahoYHT0u1Xgl28qxURcdNmWkYDA5u1Y2mGX
Qq85BakAOyfxl/FF/cBrLm0eLVFpePumqgPna3El1gAs9p2SFwN74MmcLhbwPmGn
WmzVrOh9cNS988XYf01E74966r4MKpAGxSNPKDwu4doXFVAYRH/wtcgbjlk+Qi3c
9w==
-----END PRIVATE KEY-----

View File

@@ -0,0 +1,29 @@
-----BEGIN CERTIFICATE-----
MIIE/TCCAuWgAwIBAgIUPRltRSFZSbucmw20u9TN7WHxG8UwDQYJKoZIhvcNAQEN
BQAwgcwxCzAJBgNVBAYTAlVTMTQwMgYDVQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2lu
ZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFs
IEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMREwDwYDVQQIDAhOZXcgWW9y
azEVMBMGA1UEBwwMUG91Z2hrZWVwc2llMScwJQYDVQQLDB5JQk0gWiBIb3N0IEtl
eSBTaWduaW5nIFNlcnZpY2UwIBcNMjQwMzIxMTQ1MjM5WhgPMjM4ODEyMjMxNDUy
MzlaMIG2MQswCQYDVQQGEwJVUzE0MDIGA1UECgwrSW50ZXJuYXRpb25hbCBCdXNp
bmVzcyBNYWNoaW5lcyBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrSW50ZXJuYXRpb25h
bCBCdXNpbmVzcyBNYWNoaW5lcyBDb3Jwb3JhdGlvbjERMA8GA1UECAwITmV3IFlv
cmsxDzANBgNVBAcMBkFybW9uazEXMBUGA1UECwwOSUJNIFogSG9zdCBLZXkwgZsw
EAYHKoZIzj0CAQYFK4EEACMDgYYABAHGO0MnpQa6Q2IxgqV7AGwd3OwBnYOJjYJF
hzrwY+wQacmJjWeNyHahBCxu4bM8vDr70SF5vZFrWpcWpc9JTY5AagFCFDqIfSvL
J6lKJuCog5RfMsWJpG2j/MnK7MxG+Ph0R+ItmLFbWFxCV5YOT43olhwYZr/pd9qH
PAD96UEDM8JanKNxMG8wHQYDVR0fBBYwFDASoBCgDoYMbm90YXZhaWxhYmxlMA4G
A1UdDwEB/wQEAwIDCDAfBgNVHSMEGDAWgBTDjB5dtNYBmKwPzqBlK6BnpXUU2TAd
BgNVHQ4EFgQUviblTFVtR0SX3KDiyOJYo78QDHIwDQYJKoZIhvcNAQENBQADggIB
AGlM/E6RfiQV8si38/IieHw2TsZDNKluXA/edGN4d9i5ztIB+G57IgvAR9GBeRTB
AxANycBGOWy+VXsUij3UgpoK3NiZJ+XvgFYqx0ZVUX3uPmU6R0Ko5cHGmSEVV6KS
5ToGLqSZdftybGt9NYKg+LGxzIhT15tgUENkOrFVRSlKVn1zAP+sa2vOEtH5aX6S
ins3hHQBuhGKSR/z2I5IzEVhnx0FJxpFO32QBdmXUdgjlHcpiIy1BaQRTca/U4iJ
Q+fnzn5UP5v29ftr/PRh0W9rPVeS8ge+vuPC1eriRL4WWnkMFm0QljERqhg48NWk
zT8mnVn0E3vQ2Y71FKg85ov0Sza8/OpBgAgnoyCDUIp8YD7BrU1viLEoqLtlvsoH
l/+mU/CnCe5749C6OBppKhdrIRSG8bh6mIeco1ALDNIaqGoUtdhib0f+YKeCc0zC
MFjvoSranndvwO+z/qdL7Feay8uAjgq1GPNuj/xaEbzrZz0yF2viMXfK62kgwq+W
ebg2D1FHVuKXQ2q3IXmwcyLOEUScUcEYDsM5eDenoScgIE2FfHvoGOdJVLsQ9U+8
2HTb7ntvbc6ANCTcnt51s5/PfD7UaHeJiSxRpU6rjxnqKZ2mEjbF/Ha8AjImQrrd
jpjNgH6H5p7ZQqc/4DGa/Q2B/rfvmn5bAgOhicEKMzm1
-----END CERTIFICATE-----

View File

@@ -0,0 +1,59 @@
-----BEGIN X509 CRL-----
MIIDfDCCAWQCAQEwDQYJKoZIhvcNAQENBQAwgcwxCzAJBgNVBAYTAlVTMTQwMgYD
VQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9u
MTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBv
cmF0aW9uMREwDwYDVQQIDAhOZXcgWW9yazEVMBMGA1UEBwwMUG91Z2hrZWVwc2ll
MScwJQYDVQQLDB5JQk0gWiBIb3N0IEtleSBTaWduaW5nIFNlcnZpY2UXDTI0MDMx
MTE1NTIzOVoYDzIzODgxMjIzMTU1MjM5WjA8MBMCAgIrFw0yNDAzMjAxNTUyMzla
MCUCFDIvLrSYUcq+W27wAZwp/0Pf7ydJFw0yNDAzMjAxNTUyMzlaoCMwITAfBgNV
HSMEGDAWgBTDjB5dtNYBmKwPzqBlK6BnpXUU2TANBgkqhkiG9w0BAQ0FAAOCAgEA
hMmvyXLOtDG7faP93ZqMh061Qms/at5uYz/eAA9CGfS4E+hq2uQaic6gEMWf5NkH
9xRWB1UM9sLR5Ai/Fn+MqsbeXK+1ommOfYx0KL6J8JihHAlQpGYJXu683dxIB3LL
ijZ+od5pes5ZIRKtMNaO4+meDG6e5guXDeFNyJaNYqFXOJcy8OIL4O3T840qY1aY
YcHZs/sNwC/hSAloTeUQ6S+ga/EplzSDumz5VrRsEhVd3wScM1FNeqwMvA4VPUIa
NOtZJNLJBLhfmetTeO/wb/y3Ekp8sXAf8UJqABczJODSaGc2RwULmxJd2Q5lESpX
RkfvObqTWgpzpyV/1OhZYDUlXJqiADYnyAsQL8WV2uFQ5fRG7baVDiNYn4uE92Of
FN7jXmT+7UcHSO5L0VqHS6Ia6j2NammKlbhsAw7dU3uxEgCJvBYlWSY+z9Fs+O1B
hNU42fL5W7JnoGfqG+LqfDdbG0MG+GMo1rDDcvrEK73F41w7mLmZhfYAZY26xU6Q
XyLcrG4YfR6FCyOs53zwrKKG9x3ETqY3S0DSSOKTnuvIGZBCSOxGpqdb7pQax6IJ
PqsM+IzFC1C0Ol0eX1ee734rCHfNP6XEM7ucjBweNUJRrU0Q5CrGGJzEQz0ym/JN
81f/kQJJosSSc1+j8iDiaKkUgcQ1DWWZLYZgvCkwZcY=
-----END X509 CRL-----
-----BEGIN CERTIFICATE-----
MIIGsTCCBJmgAwIBAgIUMwTHYM3peBjwVRi6iICr6FVn0cMwDQYJKoZIhvcNAQEL
BQAwgb0xCzAJBgNVBAYTAlVTMTQwMgYDVQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2lu
ZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFs
IEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMREwDwYDVQQIDAhOZXcgWW9y
azEPMA0GA1UEBwwGQXJtb25rMR4wHAYDVQQLDBVJQk0gWiBJbnRlcm1lZGlhdGUg
Q0EwIBcNMjQwMzIxMTQ1MjM4WhgPMjM4ODEyMjMxNDUyMzhaMIHMMQswCQYDVQQG
EwJVUzE0MDIGA1UECgwrSW50ZXJuYXRpb25hbCBCdXNpbmVzcyBNYWNoaW5lcyBD
b3Jwb3JhdGlvbjE0MDIGA1UEAwwrSW50ZXJuYXRpb25hbCBCdXNpbmVzcyBNYWNo
aW5lcyBDb3Jwb3JhdGlvbjERMA8GA1UECAwITmV3IFlvcmsxFTATBgNVBAcMDFBv
dWdoa2VlcHNpZTEnMCUGA1UECwweSUJNIFogSG9zdCBLZXkgU2lnbmluZyBTZXJ2
aWNlMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxNqcFB9GSj+nC1PV
OTIAvzTuo3X7bTbohEPrIDDsEcGyVzQtfagI9vkxhhGLhXxIXrkwEI4u75DeLBdq
ZR3KFJ3QD+jHW12EWNpmSYu272CEAJeb/SBJaFbh40WbY1BsTP+3zI5QMwVTmCH5
QqODD+GU0fDSo9Gti0yX4rxOY+54jDC77AhSlU55rYruBoIXVe4CcPUpqzZLgqB2
cTJ5g7lokGqc6w9pveCznVYGPfcdDt+ePGssOvrfBOJnn6N44tTRAG623BrpctXi
t3IAhG60y6CqF29BjV0RKOv09nOBiph2a3lAiKYrpAt92BETFB7KSQManUrrvWOD
mYEcoVkzvrVrB3WnCcHs6lsjQg1FcNrGcDzV9SmX0BIhM+fasxZyHWc08pr3NrRn
Eks7lRqY+TS8DAeZYJt/2M0Jr32d6Bh+WdyGFFUj6sBPtCaC2VnSkxOgKXeWf/c5
EUXIQT2YXEkNK9CP8Kqs8IerEIpfceelQReA5QcvNruaJNktWLKJgYTrdLdfOP0u
s+9JJHWcFH3tv5906CA+Tlm53Dk6SaRc/DB7lu94yTkcSOpxXZnximZi0GcPZYmZ
TaswE7d8HCPLhks/RkZSV2764Kl08xle65APiWZ4dM24uSyu75Izb4hrwgIA4qyM
dDVQnI3cu6utmKUPyHoJtH26dr0CAwEAAaOBlTCBkjAdBgNVHR8EFjAUMBKgEKAO
hgxpbnRlcl9jYS5jcmwwDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCB4AwEwYD
VR0lBAwwCgYIKwYBBQUHAwMwHwYDVR0jBBgwFoAU+f7h8O2ttBHtwI4OZnpD9wU0
9GYwHQYDVR0OBBYEFMOMHl201gGYrA/OoGUroGeldRTZMA0GCSqGSIb3DQEBCwUA
A4ICAQBfBZZ7ZPkRjRgk+0/7CGam2AAv/GSuma8lOnJ6IpBEUL0D01reRe9NO1Y5
iXasGZ80e95oC7WtePt1LS2I5rOOb3No0iHcUTm5lZV2M/ObAOwraQLXePCRVgU/
OQzNhtRoCpqgL80/1Ne+MTHj1yZp2GRKXOdMd39KZoG92JU/h556GQ6reN6WKNs+
wbFG+JKiRnfvPsul6J5lG4QuObCAZXa0fhcQNUHyWjCGIhMa8AuhkDDlIEOBV1Vx
T/ixdoFhDIoz0xExFidR5uqYXKZlgzcMZ4JT7x0Vs/YsOIg9z5PNkyjt8Kjrxvqs
NZ1eYuNNxdXxdJZ2x04y8AzLkLRYntOCks5nEamQtzv0ice1Jg52qNJnMm0Y0U9o
7BjlWy/pp8dBfIA+FyxsIs62hAE6Z/vuJa1VuWJblrT1MFM48Bh64p1m5uDXAZ9w
Oy7n6YDpzWKWqn6XNV6FoDSkkwaOwB6bPaqAP1ZvP3BmVhednyYRYY21M2aOmxos
7rpaW1FHgYV96Dm60rL7XRtOEYZNPSIPDO/Ro1oWs3EFwjLLAWtlK1HdMswlnVDX
6M+LNCRZA3foNi6xvf7CvPkshtQe3FOfiw/OiPBsYsYREC+90Ml/oeTIsyCaOF6n
5+dpjCBeOUaxzfeQI4WCrLG6+iQZNXWgBkW/PHaPZTldRWzvdQ==
-----END CERTIFICATE-----

View File

@@ -1,20 +1,21 @@
-----BEGIN X509 CRL-----
MIIDVzCCAT8CAQEwDQYJKoZIhvcNAQELBQAwgcwxCzAJBgNVBAYTAlVTMTQwMgYD
MIIDfDCCAWQCAQEwDQYJKoZIhvcNAQENBQAwgcwxCzAJBgNVBAYTAlVTMTQwMgYD
VQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9u
MTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBv
cmF0aW9uMREwDwYDVQQIDAhOZXcgWW9yazEVMBMGA1UEBwwMUG91Z2hrZWVwc2ll
MScwJQYDVQQLDB5JQk0gWiBIb3N0IEtleSBTaWduaW5nIFNlcnZpY2UXDTIzMDMx
OTExMDQ0OFoYDzIzODcxMjMxMTEwNDQ4WjA8MBMCAgIrFw0yMzAzMjgxMTA0NDha
MCUCFBrqmxMeV9aRUHxeE+pCH3XK1MGzFw0yMzAzMjgxMTA0NDhaMA0GCSqGSIb3
DQEBCwUAA4ICAQCGdm0ls5MXM6MUI0wR7qOitKh3TIfRnCvhSibVPskjlBZaBT01
F6xaQGyWVR19IzQNn9GxOGMqvRy/oSihznBeA0+e9497IOPXKop/JsypZR101539
ntVt691ncmctxKnb2nT4dw7AuiLTxMVzdJ/ouXovnPcgSv/r8lwBo1fXxOgQlQLE
Pi126WFkkgBK7EANnAXiXVWvdM6p67jl/AQGOVHp8MeXowejDdVqKzoU6yyMRDeE
uEU4QibvH/J8VPLC/A2oh4XTZbJ5rB6u3rz2fFGI03XqSrJJHbNenGVQ2ar5qJeI
6kHNDIuuwXN+7JPFf8JXdk8L0G88rQsnjrcm0GzQPW/nZ5bN3FA1V139rdOhSBLR
QgaKzju8Le/Zem317ykOJbC6nDBORmpBVzXYdXA9RMg4PIs3kRVqp/RMiiClz42z
w8c1khmcH6FO2Q5Z40vq8tmSLhbu6PgGIPIya/OQacgDjDiDGcWGvqzVCWv/6AoL
em7b5Piu4yznVkEUA2h3LvoigYTJCgHFrQnoIcuM8vx8QkDjXxSHeuy3wTd2l67S
pZp+jSJPdqWe2PWALJrYuq736E2rZ013eLybHKYOkoJP6ZLewh4gsomO0bpxTL1U
TjPsJncaAP/gLqHi0QD4+irMlo6Q9YpEIkbp9ScEoVMHRL9A/vBQfUJfZw==
MScwJQYDVQQLDB5JQk0gWiBIb3N0IEtleSBTaWduaW5nIFNlcnZpY2UXDTI0MDMx
MTE1NTIzOVoYDzIzODgxMjIzMTU1MjM5WjA8MBMCAgIrFw0yNDAzMjAxNTUyMzla
MCUCFDIvLrSYUcq+W27wAZwp/0Pf7ydJFw0yNDAzMjAxNTUyMzlaoCMwITAfBgNV
HSMEGDAWgBTDjB5dtNYBmKwPzqBlK6BnpXUU2TANBgkqhkiG9w0BAQ0FAAOCAgEA
hMmvyXLOtDG7faP93ZqMh061Qms/at5uYz/eAA9CGfS4E+hq2uQaic6gEMWf5NkH
9xRWB1UM9sLR5Ai/Fn+MqsbeXK+1ommOfYx0KL6J8JihHAlQpGYJXu683dxIB3LL
ijZ+od5pes5ZIRKtMNaO4+meDG6e5guXDeFNyJaNYqFXOJcy8OIL4O3T840qY1aY
YcHZs/sNwC/hSAloTeUQ6S+ga/EplzSDumz5VrRsEhVd3wScM1FNeqwMvA4VPUIa
NOtZJNLJBLhfmetTeO/wb/y3Ekp8sXAf8UJqABczJODSaGc2RwULmxJd2Q5lESpX
RkfvObqTWgpzpyV/1OhZYDUlXJqiADYnyAsQL8WV2uFQ5fRG7baVDiNYn4uE92Of
FN7jXmT+7UcHSO5L0VqHS6Ia6j2NammKlbhsAw7dU3uxEgCJvBYlWSY+z9Fs+O1B
hNU42fL5W7JnoGfqG+LqfDdbG0MG+GMo1rDDcvrEK73F41w7mLmZhfYAZY26xU6Q
XyLcrG4YfR6FCyOs53zwrKKG9x3ETqY3S0DSSOKTnuvIGZBCSOxGpqdb7pQax6IJ
PqsM+IzFC1C0Ol0eX1ee734rCHfNP6XEM7ucjBweNUJRrU0Q5CrGGJzEQz0ym/JN
81f/kQJJosSSc1+j8iDiaKkUgcQ1DWWZLYZgvCkwZcY=
-----END X509 CRL-----

View File

@@ -1,39 +1,38 @@
-----BEGIN CERTIFICATE-----
MIIGyzCCBLOgAwIBAgIUeGuWhNwpt9CPzFJ5UJAKfkIlLDcwDQYJKoZIhvcNAQEL
MIIGsTCCBJmgAwIBAgIUMwTHYM3peBjwVRi6iICr6FVn0cMwDQYJKoZIhvcNAQEL
BQAwgb0xCzAJBgNVBAYTAlVTMTQwMgYDVQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2lu
ZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFs
IEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMREwDwYDVQQIDAhOZXcgWW9y
azEPMA0GA1UEBwwGQXJtb25rMR4wHAYDVQQLDBVJQk0gWiBJbnRlcm1lZGlhdGUg
Q0EwIBcNMjMwMzI5MDkwNDQ3WhgPMjM4NzEyMzEwOTA0NDdaMIHMMQswCQYDVQQG
Q0EwIBcNMjQwMzIxMTQ1MjM4WhgPMjM4ODEyMjMxNDUyMzhaMIHMMQswCQYDVQQG
EwJVUzE0MDIGA1UECgwrSW50ZXJuYXRpb25hbCBCdXNpbmVzcyBNYWNoaW5lcyBD
b3Jwb3JhdGlvbjE0MDIGA1UEAwwrSW50ZXJuYXRpb25hbCBCdXNpbmVzcyBNYWNo
aW5lcyBDb3Jwb3JhdGlvbjERMA8GA1UECAwITmV3IFlvcmsxFTATBgNVBAcMDFBv
dWdoa2VlcHNpZTEnMCUGA1UECwweSUJNIFogSG9zdCBLZXkgU2lnbmluZyBTZXJ2
aWNlMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsXm4EgSxVmuNsKgo
sfJNxNQFkdbpCxxyMOuyBFyGKxSwiGl20VWB6itsG+b9NOmAI6D6FPvLPuB/gSq0
HR5FuSIkmp9AUx6Xi6lVA2L7qdINo1OA4nJKe5hLSHfjWn36DZFrDyoODlDzLJrS
O4h4QSP1nDSFhk1ilsR1czlvKreXkJw5FsUHRhZGG6idLoK2Ibrne6WsVhPG6WNA
abuvQFv40cQWcyRoePktG8ImnNF5GDewXwtpzARSQj9jTL/gE77DH78a77J8+H+h
d5guiBbPZK8gNkPe0CjD0B7tUx/+sByoaSeQffFG4Cnu5JJDqFq9LXPjtlG2nXSB
Qh6Sc2gzP3jKV+ZcSwQw9AxEQ0ZB/VIPsR8KZKReDDztEpcKxwxlh7bEix/0Y1sv
zT7/I+m5kufdDG6j3hHHzniKXL4b/WyedSfdnVqIJw82FgPFgyIY6F/0ccLdkhAm
fLtQJBHc3UyK13l0qVJxhAFdz1Q0zfScBS6qM/Gnbcdc6MY9/bZdIK7E+4op5iAM
kvQHap7qnArhI8VQ1bcXYlQ6asPj4e10lmzroiBHM4N/Yuxv38tmtUCudSB+EcXi
EgJIOLmLq2ZACRzug9KPyMXOD/Yxz2wPgs6I3gvrB22w/MfC77wMfEMuQQk4cZel
TFKosHgLjvcLG+zx5yh5ZVFcNV0CAwEAAaOBrzCBrDA3BgNVHR8EMDAuMCygKqAo
hiZodHRwOi8vMTI3LjAuMC4xOjEyMzQvY3JsL2ludGVyX2NhLmNybDAMBgNVHRMB
Af8EAjAAMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAfBgNV
HSMEGDAWgBQRqYdWstn6ntusRZ8LjyPFEicL5TAdBgNVHQ4EFgQU3ozX8OjQ2AEH
cX1v2WhZID6wZ3wwDQYJKoZIhvcNAQELBQADggIBAEqkZawT89MngrmMTREjYGKZ
+qrm7uQf9wFiM7H7Xs11OEJ5PkNh4jNnnIsXZxc8rr76x+zLr4F6aI08AQn5QOy9
JXGIbrMHLebtn198aIOYbxZisbXnBlVO3Xz+k8JLdzsu5zxjjaDY3/a63X2ccStJ
U53pSqvgJi6/AvMPA1CPazSjxu6na8rYz6d7c/god7OF0qwQ/ePqd4uJOaImm7HH
CCkwMPYO7UyOWU5CSPMcJ86SGYhvYkoM7wZeJoukK6HlKDI1SRubiTFAx+Hbyk1R
dyVY9vmIOeUlsGEMgsW836g++dg8efRIbIYbSBLQhUL64lLA6wZJ6/oCtC29aX+o
UfxcGUROrpZ5Xi4b4sn0vW4rYq65BzlU17x45XsZMh11hX9aPNE4B62Jl2XLjX3P
Sedu7b/QB6jWpwTAdH96LeLxVepAWiVcFBApBqpu7wxRhCs6M1t3Gh9nvlPE5NRz
zsmx+HVZIgWoP3CgHmiHqajphL0xp6R9qJOyzAVChsmbQYvr+rfaXMv24KBvJYgc
xq5iCP7IccgC6WlhpWyAoTSuhiStTZJtlCKPZqc+HRcuf2fLWXip8YKNHgEtTxNz
7citBXZNoRDFULWwiYDnwhGcZ53p5zPLABYKZdfNHdI+tV92AbzYyQaV0ZwcxL9K
ObAAlDzZKE8vJwT94E3O
aWNlMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxNqcFB9GSj+nC1PV
OTIAvzTuo3X7bTbohEPrIDDsEcGyVzQtfagI9vkxhhGLhXxIXrkwEI4u75DeLBdq
ZR3KFJ3QD+jHW12EWNpmSYu272CEAJeb/SBJaFbh40WbY1BsTP+3zI5QMwVTmCH5
QqODD+GU0fDSo9Gti0yX4rxOY+54jDC77AhSlU55rYruBoIXVe4CcPUpqzZLgqB2
cTJ5g7lokGqc6w9pveCznVYGPfcdDt+ePGssOvrfBOJnn6N44tTRAG623BrpctXi
t3IAhG60y6CqF29BjV0RKOv09nOBiph2a3lAiKYrpAt92BETFB7KSQManUrrvWOD
mYEcoVkzvrVrB3WnCcHs6lsjQg1FcNrGcDzV9SmX0BIhM+fasxZyHWc08pr3NrRn
Eks7lRqY+TS8DAeZYJt/2M0Jr32d6Bh+WdyGFFUj6sBPtCaC2VnSkxOgKXeWf/c5
EUXIQT2YXEkNK9CP8Kqs8IerEIpfceelQReA5QcvNruaJNktWLKJgYTrdLdfOP0u
s+9JJHWcFH3tv5906CA+Tlm53Dk6SaRc/DB7lu94yTkcSOpxXZnximZi0GcPZYmZ
TaswE7d8HCPLhks/RkZSV2764Kl08xle65APiWZ4dM24uSyu75Izb4hrwgIA4qyM
dDVQnI3cu6utmKUPyHoJtH26dr0CAwEAAaOBlTCBkjAdBgNVHR8EFjAUMBKgEKAO
hgxpbnRlcl9jYS5jcmwwDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCB4AwEwYD
VR0lBAwwCgYIKwYBBQUHAwMwHwYDVR0jBBgwFoAU+f7h8O2ttBHtwI4OZnpD9wU0
9GYwHQYDVR0OBBYEFMOMHl201gGYrA/OoGUroGeldRTZMA0GCSqGSIb3DQEBCwUA
A4ICAQBfBZZ7ZPkRjRgk+0/7CGam2AAv/GSuma8lOnJ6IpBEUL0D01reRe9NO1Y5
iXasGZ80e95oC7WtePt1LS2I5rOOb3No0iHcUTm5lZV2M/ObAOwraQLXePCRVgU/
OQzNhtRoCpqgL80/1Ne+MTHj1yZp2GRKXOdMd39KZoG92JU/h556GQ6reN6WKNs+
wbFG+JKiRnfvPsul6J5lG4QuObCAZXa0fhcQNUHyWjCGIhMa8AuhkDDlIEOBV1Vx
T/ixdoFhDIoz0xExFidR5uqYXKZlgzcMZ4JT7x0Vs/YsOIg9z5PNkyjt8Kjrxvqs
NZ1eYuNNxdXxdJZ2x04y8AzLkLRYntOCks5nEamQtzv0ice1Jg52qNJnMm0Y0U9o
7BjlWy/pp8dBfIA+FyxsIs62hAE6Z/vuJa1VuWJblrT1MFM48Bh64p1m5uDXAZ9w
Oy7n6YDpzWKWqn6XNV6FoDSkkwaOwB6bPaqAP1ZvP3BmVhednyYRYY21M2aOmxos
7rpaW1FHgYV96Dm60rL7XRtOEYZNPSIPDO/Ro1oWs3EFwjLLAWtlK1HdMswlnVDX
6M+LNCRZA3foNi6xvf7CvPkshtQe3FOfiw/OiPBsYsYREC+90Ml/oeTIsyCaOF6n
5+dpjCBeOUaxzfeQI4WCrLG6+iQZNXWgBkW/PHaPZTldRWzvdQ==
-----END CERTIFICATE-----

View File

@@ -0,0 +1,52 @@
-----BEGIN PRIVATE KEY-----
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
jLfytXEfbNWBGcgHySC4HUwnpUVxN44=
-----END PRIVATE KEY-----

View File

@@ -0,0 +1,21 @@
-----BEGIN X509 CRL-----
MIIDdjCCAV4CAQEwDQYJKoZIhvcNAQENBQAwgcYxCzAJBgNVBAYTAlVTMTQwMgYD
VQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9u
MTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBv
cmF0aW9uMREwDwYDVQQIDAhOZXcgWW9yazEPMA0GA1UEBwwGQXJtb25rMScwJQYD
VQQLDB5JQk0gWiBIb3N0IEtleSBTaWduaW5nIFNlcnZpY2UXDTI0MDMxMTE1NTIz
OVoYDzIzODgxMjIzMTU1MjM5WjA8MBMCAgIrFw0yNDAzMjAxNTUyMzlaMCUCFDIv
LrSYUcq+W27wAZwp/0Pf7ydJFw0yNDAzMjAxNTUyMzlaoCMwITAfBgNVHSMEGDAW
gBTDjB5dtNYBmKwPzqBlK6BnpXUU2TANBgkqhkiG9w0BAQ0FAAOCAgEAgvfpzZbh
/utz4zq6/KQdFW25wK9tqPkwFut9vdsOAGMkRRcX699Rk3Km1TpgBVGRKAlsQKfS
IMq1FtNwbKMv+ycZHXDewk/i7dd2A0eUNzbDxD/WJ7mBdUHJtzkvIKwBmU7SkwdM
yBRA20H8xKioveDrms+MM3a4oLNRzkZI/FWkSqjCDh9lI6igZNt3J29vkcdIlu+P
Maa7Cpwh1ELrQbwE3NVgbr172D9qzQ+/NiRlM/Hla/lqGELcUgwVgkNMBFEMo7iK
XsWy9WQ+/0RExo7n09jk9D4tCyAizGae72Xai8IJQD4tSVNpv6ZtNHZBBKQhkjGy
PXGM8tHC91Tr8E9CSVVOrtxVit5htxjnTkJLg/9XnoAkxGNbUFbvCm+zIOzkmlJ4
Drvvt9W4tVfkcfILHKmy4PG/0JU/tAygpr2Hk39e/Lcym64O9gz2g0pU4On/qD6e
91Q4822RIYLDK/IO3H30CbO25nBChZ4z6KBMWXHG8mTJ5m1IbwZTPxBlL8t47P9v
2ce2XDkcPzYpk/wqJ4xxQYhuhV9RaJreEnnqCZ9ER7L+heoJcCZcnr56wT4mNd/a
Kfdm0Oxm8CFCMj1djVJQ7+ghsOY3RAehQ75m2Od5BRM+Vv3gYtkzPWTkWjDUn3us
2KwZvR+lNaIVXPlQqBlIWJvehWZexLzTkA0=
-----END X509 CRL-----

View File

@@ -0,0 +1,38 @@
-----BEGIN CERTIFICATE-----
MIIGqzCCBJOgAwIBAgIUWYLchAxfdv8uD28Im9DK+Lo8pokwDQYJKoZIhvcNAQEL
BQAwgb0xCzAJBgNVBAYTAlVTMTQwMgYDVQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2lu
ZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFs
IEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMREwDwYDVQQIDAhOZXcgWW9y
azEPMA0GA1UEBwwGQXJtb25rMR4wHAYDVQQLDBVJQk0gWiBJbnRlcm1lZGlhdGUg
Q0EwIBcNMjQwMzIxMTQ1MjM4WhgPMjM4ODEyMjMxNDUyMzhaMIHGMQswCQYDVQQG
EwJVUzE0MDIGA1UECgwrSW50ZXJuYXRpb25hbCBCdXNpbmVzcyBNYWNoaW5lcyBD
b3Jwb3JhdGlvbjE0MDIGA1UEAwwrSW50ZXJuYXRpb25hbCBCdXNpbmVzcyBNYWNo
aW5lcyBDb3Jwb3JhdGlvbjERMA8GA1UECAwITmV3IFlvcmsxDzANBgNVBAcMBkFy
bW9uazEnMCUGA1UECwweSUJNIFogSG9zdCBLZXkgU2lnbmluZyBTZXJ2aWNlMIIC
IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxNqcFB9GSj+nC1PVOTIAvzTu
o3X7bTbohEPrIDDsEcGyVzQtfagI9vkxhhGLhXxIXrkwEI4u75DeLBdqZR3KFJ3Q
D+jHW12EWNpmSYu272CEAJeb/SBJaFbh40WbY1BsTP+3zI5QMwVTmCH5QqODD+GU
0fDSo9Gti0yX4rxOY+54jDC77AhSlU55rYruBoIXVe4CcPUpqzZLgqB2cTJ5g7lo
kGqc6w9pveCznVYGPfcdDt+ePGssOvrfBOJnn6N44tTRAG623BrpctXit3IAhG60
y6CqF29BjV0RKOv09nOBiph2a3lAiKYrpAt92BETFB7KSQManUrrvWODmYEcoVkz
vrVrB3WnCcHs6lsjQg1FcNrGcDzV9SmX0BIhM+fasxZyHWc08pr3NrRnEks7lRqY
+TS8DAeZYJt/2M0Jr32d6Bh+WdyGFFUj6sBPtCaC2VnSkxOgKXeWf/c5EUXIQT2Y
XEkNK9CP8Kqs8IerEIpfceelQReA5QcvNruaJNktWLKJgYTrdLdfOP0us+9JJHWc
FH3tv5906CA+Tlm53Dk6SaRc/DB7lu94yTkcSOpxXZnximZi0GcPZYmZTaswE7d8
HCPLhks/RkZSV2764Kl08xle65APiWZ4dM24uSyu75Izb4hrwgIA4qyMdDVQnI3c
u6utmKUPyHoJtH26dr0CAwEAAaOBlTCBkjAdBgNVHR8EFjAUMBKgEKAOhgxpbnRl
cl9jYS5jcmwwDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCB4AwEwYDVR0lBAww
CgYIKwYBBQUHAwMwHwYDVR0jBBgwFoAU+f7h8O2ttBHtwI4OZnpD9wU09GYwHQYD
VR0OBBYEFMOMHl201gGYrA/OoGUroGeldRTZMA0GCSqGSIb3DQEBCwUAA4ICAQC5
dH5QKZHynK7vGHOtol3brWgAWKkUVj+uqok/AUyGF5hkcXI2AVmu5nWV16Z6/c0b
rD37YMPCCnZorQQg5g3c3H9In3NzTYWj1q2YT13yQ5PaD56vkwfPQKlmY2kMb/v8
Y5Ho2LFjhKKOpzP77CsYMs9ZdXs6VKGZ5dSmOAOvJ4AcGaRPs3jXVz3EZFgc+ytK
705mWrAgTYI3xcemxBTwILWAVCoqqirWrDNd3jicQo4Ks/H07RtLuVNY8kXUJEN9
UMG7Ggzc/rTlvV/PUsJaQl8lunPDdbUBLsXE1iWaaAxmRTTQaDX8Ygq8NFZgGSrk
E/dnJXcnJyV/5GH22Ho4JVVtADkP1wh3TKcojiDfM2WlzatSOMPdeISsUQ/D+VSm
GuSOxPkS0wj5XUpoJz2bKvXNMH1Mdp9sMfOlkMe47iTmU5gK4PJMoj2NZ7zW9u6p
pYXQz9LhdwoTJZBJXVYSA1q+sIIy8u3vFXEeN88FuoY8yS8t8qjwGEcKP1oojFxV
ibj9cv87Vcd+tgXAqwkjxGQVbDZPBlL6OWCYoEluqWGnbUD1mUp2y8K99ZlzoT44
i2ipEFyZmVPrmwgKRlz1UYDIsQvtvVw91Oi+DRNP1u+9D++Mnz2itGixHh1Hob25
nQl1/SS4PfgMlYscbHYOfLAzOnW02FvrJZgQAQUpgg==
-----END CERTIFICATE-----

View File

@@ -0,0 +1,38 @@
-----BEGIN CERTIFICATE-----
MIIGrzCCBJegAwIBAgIUU5pxAXMrXmWzioXpyoQoipFwsH4wDQYJKoZIhvcNAQEL
BQAwgb0xCzAJBgNVBAYTAlVTMTQwMgYDVQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2lu
ZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFs
IEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMREwDwYDVQQIDAhOZXcgWW9y
azEPMA0GA1UEBwwGQXJtb25rMR4wHAYDVQQLDBVJQk0gWiBJbnRlcm1lZGlhdGUg
Q0EwHhcNMjIwMzIyMTU1MjM4WhcNMjMwMzIyMTU1MjM4WjCBzDELMAkGA1UEBhMC
VVMxNDAyBgNVBAoMK0ludGVybmF0aW9uYWwgQnVzaW5lc3MgTWFjaGluZXMgQ29y
cG9yYXRpb24xNDAyBgNVBAMMK0ludGVybmF0aW9uYWwgQnVzaW5lc3MgTWFjaGlu
ZXMgQ29ycG9yYXRpb24xETAPBgNVBAgMCE5ldyBZb3JrMRUwEwYDVQQHDAxQb3Vn
aGtlZXBzaWUxJzAlBgNVBAsMHklCTSBaIEhvc3QgS2V5IFNpZ25pbmcgU2Vydmlj
ZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMTanBQfRko/pwtT1Tky
AL807qN1+2026IRD6yAw7BHBslc0LX2oCPb5MYYRi4V8SF65MBCOLu+Q3iwXamUd
yhSd0A/ox1tdhFjaZkmLtu9ghACXm/0gSWhW4eNFm2NQbEz/t8yOUDMFU5gh+UKj
gw/hlNHw0qPRrYtMl+K8TmPueIwwu+wIUpVOea2K7gaCF1XuAnD1Kas2S4KgdnEy
eYO5aJBqnOsPab3gs51WBj33HQ7fnjxrLDr63wTiZ5+jeOLU0QButtwa6XLV4rdy
AIRutMugqhdvQY1dESjr9PZzgYqYdmt5QIimK6QLfdgRExQeykkDGp1K671jg5mB
HKFZM761awd1pwnB7OpbI0INRXDaxnA81fUpl9ASITPn2rMWch1nNPKa9za0ZxJL
O5UamPk0vAwHmWCbf9jNCa99negYflnchhRVI+rAT7QmgtlZ0pMToCl3ln/3ORFF
yEE9mFxJDSvQj/CqrPCHqxCKX3HnpUEXgOUHLza7miTZLViyiYGE63S3Xzj9LrPv
SSR1nBR97b+fdOggPk5Zudw5OkmkXPwwe5bveMk5HEjqcV2Z8YpmYtBnD2WJmU2r
MBO3fBwjy4ZLP0ZGUldu+uCpdPMZXuuQD4lmeHTNuLksru+SM2+Ia8ICAOKsjHQ1
UJyN3LurrZilD8h6CbR9una9AgMBAAGjgZUwgZIwHQYDVR0fBBYwFDASoBCgDoYM
aW50ZXJfY2EuY3JsMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeAMBMGA1Ud
JQQMMAoGCCsGAQUFBwMDMB8GA1UdIwQYMBaAFPn+4fDtrbQR7cCODmZ6Q/cFNPRm
MB0GA1UdDgQWBBTDjB5dtNYBmKwPzqBlK6BnpXUU2TANBgkqhkiG9w0BAQsFAAOC
AgEAo+WGpxIz8s0UY8gOlCYeGr6SRYbgH7bcFVaV2fJf2eacv/YSaryc4PNwFnO4
+e/LvE8908xq57Kl0xpCzp4bO941/aJkJuyr59TOe1nhcH0z0Yik9Dt1zRxxy0XO
uVUSYuYEmKlWNgsWAGCmcHAz+wQxn2qjpD8k/GAe8Rr7O7r/EnSt6HvVKt3dl+zx
rv88gKKJKWrbn7zn4/c/E3XG9RxunCsYGtOfUfk8tGeWtemoGNmXlCLCmKR4JKjk
mEEM16veHHdD5k9MPj6YQH/jh1pDOD11o8GlOd/rEQCpFWeg23Z0uEq5j+qr1FI7
Fjk4HvTtwGU7QXn+QV9bSjhE6svdWVbmADwb3Z/UU//UzgEAZDPb/n4cC95vk/Lt
Wwq5MzHBIyeHladxzLE7LuVA9dmkv7dnST7L5ZAqQYcT5c7vxkrTHD53ZTojPMD2
Lmd3ZIcRIdFbPChY/+ajuBaNpi+gBwQaQ0J4b70fKW7oUxOpgSjh12ACNOYmVRWb
sCzSiIaxkD0pvIYLgNXcY2CekuWxO+4DLGNGPPAHeovue0yRgNKTC14AHsLWh04c
aWdomQToTHFxJcoVk2LiE5nwg5Xu8BoNuMag1jl/ZQVsl4LrL4bItwplWdH/bSyi
9VFeSwPGTiNverBtv/aF4q7O6JWB7/zUh2GqYQcILcaIy4E=
-----END CERTIFICATE-----

View File

@@ -0,0 +1,20 @@
-----BEGIN X509 CRL-----
MIIDVzCCAT8CAQEwDQYJKoZIhvcNAQENBQAwgcwxCzAJBgNVBAYTAlVTMTQwMgYD
VQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9u
MTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBv
cmF0aW9uMREwDwYDVQQIDAhOZXcgWW9yazEVMBMGA1UEBwwMUG91Z2hrZWVwc2ll
MScwJQYDVQQLDB5JQk0gWiBIb3N0IEtleSBTaWduaW5nIFNlcnZpY2UXDTI0MDMx
MTE1NTIzOVoYDzIzODgxMjIzMTU1MjM5WjA8MBMCAgIrFw0yNDAzMjAxNTUyMzla
MCUCFAUi4bhk78T24IBu9CEi9kegwxmXFw0yNDAzMjAxNTUyMzlaMA0GCSqGSIb3
DQEBDQUAA4ICAQCH2paQrJTqVzDjBOixREnhV0Ned2SHHwuIxZPeA1LrA1MR8KeY
RCNiBxaOg2fkIe7WbPbiFVmosRq1kMjOJrgajvI6CG4is5F37KhW+Q/8siNcc8y3
oiu+b8O5wp7vfUq9f4bxh78ytS+cHJpxHLoYzlp1f6aha2x2kUqDQzEf3ghIXEAN
y0Jlmn2OqeZ/cCnWG+QF8Yb9OMlnR6rTpwk4ml0TvMa1/LhBUMj7vva0BmXuTunW
eEr/wxmTMyJsRKNXgqRDLil+hnNzIP7HOmofyad9dyHv73gOkmu1GizwSB/AEVoB
J5N/LUeCh4cG3YJYYpw7HaAHUnka2SDiuL3MD7VD5ONXiwcZIplT7I9vJHaBimoz
kUTr3BkzFHas+KiPuGLm25Pxc0G8mVZl0jzoIJe0JS4bi+NCqeQ3C5s4WOZ476Bs
5PSWbkJ8GwUxtXciOxHVKvgnBkc55bng2VEJlRLDfERdcTa1yobvJBRNZ8J/gDu5
aWvRJs+cQ+1Bj4oq3ejV+Be5UFEVEFfQd4wFixvZcr781aDhYg744Ig0n3oZE0pg
ye9V55q5yra6K1eertb63y1WvIrpfvNBM5p7mFbYBc5vnoH44mAhwbsCL5Mkjcxp
0XjPSUsE9OyORtN92YLrZztEXIZmjw7otzQCQmcj/0ri3X+M1RLUTh+BVQ==
-----END X509 CRL-----

View File

@@ -1,19 +1,20 @@
-----BEGIN X509 CRL-----
MIIDGzCCAQMCAQEwDQYJKoZIhvcNAQELBQAwgcwxCzAJBgNVBAYTAlVTMTQwMgYD
MIIDQDCCASgCAQEwDQYJKoZIhvcNAQENBQAwgcwxCzAJBgNVBAYTAlVTMTQwMgYD
VQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9u
MTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBv
cmF0aW9uMREwDwYDVQQIDAhOZXcgWW9yazEVMBMGA1UEBwwMUG91Z2hrZWVwc2ll
MScwJQYDVQQLDB5JQk0gWiBIb3N0IEtleSBTaWduaW5nIFNlcnZpY2UYDzMwMjIw
NzMwMTEwNDQ4WhgPMzAyMzA3MzAxMTA0NDhaMA0GCSqGSIb3DQEBCwUAA4ICAQAa
bg7llgCL+OdmZQEeBKey5Dm/NxJGJljoT/sxFbQ+86lwACh1mbdxVkaPyUC/oE9T
4ppC/eHoaRcdmvN4FlIYrUhqnrTGD4s8VSoYvJ7+f5ZFGjUyflnMwyaal21hDaG4
2SZjPVOQ0ksEA3mrHE1MTRVFqFl4ZFxGhh7NYMoOEkffM1UooChWHTTBMz67nmbh
Ih0MDHhS5J7677K2N05402Z3v3S+Y8QEjIQjDsTC1S9V607eEfG9YEND2KicQKPH
r+CK9/fVaiTz9wgUEyybps4MFoWBuUqqRebQoargFZW8w329LuS6VokbM6BSduOT
qaYFtzp3DGZbvKwUGjiGVgB/PzzB1rv+2+i/EI3D4RJt+k8xvlBIIONxwK/hcjI3
/i6hJueQpeCuasfX8ck/uKzSf0PhCmyLwWxQux66FJq4sXqWoqwf5P/U+tbB8zna
0cX5/f8+rS7ansbxjeiCHUkbdUEoY7k7KMSNUrtqbgQ4VyjTziysTbSEG7jkb4ri
Jaa9mDfWCkdwfB3TqDofWRkOdNpPTkj9TVZJ5FdV1h39D9O7B+VvedIiVod/KhB1
DyOa44YpkEcS51PuNAC/exUd6nOv9Mz+WOUP+RrxHqndRYE0RGaFP9vENyks0Kga
4CLB/IbT2rmpLivK2i6i3NOqzcykHOab3LtwOLDDmg==
MScwJQYDVQQLDB5JQk0gWiBIb3N0IEtleSBTaWduaW5nIFNlcnZpY2UYDzMwMjMw
NzIzMTU1MjM5WhgPMzAyNDA3MjIxNTUyMzlaoCMwITAfBgNVHSMEGDAWgBTDjB5d
tNYBmKwPzqBlK6BnpXUU2TANBgkqhkiG9w0BAQ0FAAOCAgEATxMm63G11oaOvRm9
nb20MXyXaqejudryJLcKSAUNNcvVpfj4zO4iG7Eiipq5svrEHmb8aNELKb7eHVY0
uT5V1hd3xELkQqVS8rxcD2rQfoE8B3kkeuKtgI0yxC4rkrt8recajh8au/FSoknq
Ts1CKsc0ghFo01gIv4fgWC7eWFrfw51T/bZW4AN1QsAT0wEqcYjuDTZpwXU+8JsB
czQ1wWoKJPCAbh6ZOd8R/DEywffWSVjS+8hrmIc6TAwfu7SOBSvDLh7kKZeEgZ6Y
lwp1R9EcRBYLlyclg4E7w/WL2DY426Lo+0aSIWcFwGbU3kWwFNXCKIpYvVQZ4QPT
2lZfuRVMe1ZgRdPRz5wkiEYYIGFoe3cOC16jHGi+Vs9JQX/EgoRiy/YYxZdckuxA
961S5h4bbYyB9aNH1vNn9Kp2r8oDGD6xucXM9cTXDsXvLLSFUxcFqoOdixYqFzX+
EsZM5A33pMq5zKLkRD8JI2lP7nT0wdyaDjuH4ION7y90tJiq1Q1GPfmJ6+mp/3/I
QF1Mh8axL59Rgz/KrzszP4+kn3NuhvKQOjL3QDo5TSXEmsdjERFHsmOuTwB9E4iH
EIBu7bz9GfVMDUL8LSOK8Tq9Gj9Zzy8kYe2BuwNOTTDzQAUnPZK/m6p1wm/K3vjL
2pjdFJmfRBtPNSRXL2hY2MYdZDk=
-----END X509 CRL-----

View File

@@ -1,19 +1,20 @@
-----BEGIN X509 CRL-----
MIIDFjCB/wIBATANBgkqhkiG9w0BAQsFADCBzDELMAkGA1UEBhMCVVMxNDAyBgNV
BAoMK0ludGVybmF0aW9uYWwgQnVzaW5lc3MgTWFjaGluZXMgQ29ycG9yYXRpb24x
NDAyBgNVBAMMK0ludGVybmF0aW9uYWwgQnVzaW5lc3MgTWFjaGluZXMgQ29ycG9y
YXRpb24xETAPBgNVBAgMCE5ldyBZb3JrMRUwEwYDVQQHDAxQb3VnaGtlZXBzaWUx
JzAlBgNVBAsMHklCTSBaIEhvc3QgS2V5IFNpZ25pbmcgU2VydmljZRcNMjEwMzI5
MTEwNDQ4WhcNMjIwMzI5MTEwNDQ4WjANBgkqhkiG9w0BAQsFAAOCAgEAh+81L4ws
rvOC1j7nwxthaIE4m8alnuaq9h9uxYfDZooimvGwhCjfcoWmfSSA8lt3vbMJ2vRe
ZwnXXCyGWmetZ6ObnT0jwL0QuOYEuIdA8QHleBxLYBeFr4k0O9i8i3VUG0YcgZuN
H+lcpGdoIx2WV0cZ4rbzZ1cNx3bieaivqNoLQAy7g9jTizmTfY5ZvlvuG3iqSG+P
08APxmtt1qFEm1LVu4SyUSyoGB1NaxeoziMITQdfFqHoPRsu7Wdyuqi9f5irIPwM
VQNKs/Y+3Q3S8YkTW3yqxhj4HdSKJE4qVBLMYm7muirDFWo25u2sDX1LJHBsQLvV
fi7cGY0YnOJL2Y7A3XKDuqtZ34zpXg3Hhqpa9RF55K2u5dYUaPq8MEQUHK67II1r
YZAwfarhijQQ6t03E0vrzPVYpK8VjNUunYKQdOBS3OkKgXCwEMuqQDrps98BgDQ4
qfbVfxwm9XEHJZaX/qFR0sp8OQd/SD5dnS3DBl0Pp5w+w2xIaSA7QmBpDqWY66Hb
cJq4CLOKTasHTddHKz7O7zIu8QhwJGLabtnx18iaHTNNHaTF6k/51pwvA3HkJgds
HVcUNljsDNSPE258JwR2XoQAUu6VuFwRzgD7lGwdI70CpIBeAP1TRSius5RsZB+u
cw+872CILlIdNJ72lzMPWQNH+IB1RU8U/eA=
MIIDPDCCASQCAQEwDQYJKoZIhvcNAQENBQAwgcwxCzAJBgNVBAYTAlVTMTQwMgYD
VQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9u
MTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBv
cmF0aW9uMREwDwYDVQQIDAhOZXcgWW9yazEVMBMGA1UEBwwMUG91Z2hrZWVwc2ll
MScwJQYDVQQLDB5JQk0gWiBIb3N0IEtleSBTaWduaW5nIFNlcnZpY2UXDTIyMDMy
MjE1NTIzOVoXDTIzMDMyMjE1NTIzOVqgIzAhMB8GA1UdIwQYMBaAFMOMHl201gGY
rA/OoGUroGeldRTZMA0GCSqGSIb3DQEBDQUAA4ICAQAGD8ryV/GUC+s4qfqchMZA
QYYOBcV7lS9i8zFrdB7UJuhCL/gXzrmldFsi6hW95PBNBtADT75UQ4JzNNVKYXWe
wTbEOG54N7Ff4LdbbCRNjqpyOkqQgRWZOgiTeHSeiNLU+P98HZVKFIfiOS6Rs6zB
5UNdYwCGz9kkeiR7xSpp0z86jI8WSxHR6e7CH78Ax/9dpGAyKYYj8LY0l7igxlIL
yRgu0S81VsprcHKuGp5wcnabOWO7lEUCTFbYa7Cgc1+avUl1vaCmMqUsvydurCU+
BCN8Zhc7noOXm0AE+58r9yy30aW9n+NUmP7uX6Eibb5NXtVZRVe83Ltk2Rbi9HRM
hkcO0X37mXu+jcqw714i/r0mUsfGtC54IRMCgyIgWJ3TDdJ9ORo0rkrYRXVzKHdb
0nqXEsrYecaCNcnx8iygC2YEwAN9WH8cvvLTJQcL+j57xcJVqOSbhXTEE5LfiHpa
DO+dc9A+THZNO+o8GEZ3teTxylOVctiO9CkUkICmVZ9VDA73qOzHI8DJxpCAwT0I
whm1QfCROAXYFW9enTuCGDZGPoyTf+tVrAGLmCWLewBV6W3z+7OBfNomktuI4Z0+
opvwIJwYX3emeZ/5gDuYmwnvNYkC0GRQ/994430b/4Rssv32SCjToJ+Ko5pz4x18
YUtbQcKxpJzRDSkccck83A==
-----END X509 CRL-----

View File

@@ -1,39 +1,38 @@
-----BEGIN CERTIFICATE-----
MIIGyzCCBLOgAwIBAgIUTPiBWJn8k37onZ/aYgLxudbD3kgwDQYJKoZIhvcNAQEL
MIIGsTCCBJmgAwIBAgIUXvZ6XWXXrTAFn66B61xZNya2iYMwDQYJKoZIhvcNAQEL
BQAwgb0xCzAJBgNVBAYTAlVTMTQwMgYDVQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2lu
ZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFs
IEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMREwDwYDVQQIDAhOZXcgWW9y
azEPMA0GA1UEBwwGQXJtb25rMR4wHAYDVQQLDBVJQk0gWiBJbnRlcm1lZGlhdGUg
Q0EwIBcNMjMwMzI5MDkwNDQ3WhgPMjM4NzEyMzEwOTA0NDdaMIHMMQswCQYDVQQG
Q0EwIBcNMjQwMzIxMTQ1MjM4WhgPMjM4ODEyMjMxNDUyMzhaMIHMMQswCQYDVQQG
EwJVUzE0MDIGA1UECgwrSW50ZXJuYXRpb25hbCBCdXNpbmVzcyBNYWNoaW5lcyBD
b3Jwb3JhdGlvbjE0MDIGA1UEAwwrSW50ZXJuYXRpb25hbCBCdXNpbmVzcyBNYWNo
aW5lcyBDb3Jwb3JhdGlvbjERMA8GA1UECAwITmV3IFlvcmsxFTATBgNVBAcMDFBv
dWdoa2VlcHNpZTEnMCUGA1UECwweSUJNIFogSG9zdCBLZXkgU2lnbmluZyBTZXJ2
aWNlMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsXm4EgSxVmuNsKgo
sfJNxNQFkdbpCxxyMOuyBFyGKxSwiGl20VWB6itsG+b9NOmAI6D6FPvLPuB/gSq0
HR5FuSIkmp9AUx6Xi6lVA2L7qdINo1OA4nJKe5hLSHfjWn36DZFrDyoODlDzLJrS
O4h4QSP1nDSFhk1ilsR1czlvKreXkJw5FsUHRhZGG6idLoK2Ibrne6WsVhPG6WNA
abuvQFv40cQWcyRoePktG8ImnNF5GDewXwtpzARSQj9jTL/gE77DH78a77J8+H+h
d5guiBbPZK8gNkPe0CjD0B7tUx/+sByoaSeQffFG4Cnu5JJDqFq9LXPjtlG2nXSB
Qh6Sc2gzP3jKV+ZcSwQw9AxEQ0ZB/VIPsR8KZKReDDztEpcKxwxlh7bEix/0Y1sv
zT7/I+m5kufdDG6j3hHHzniKXL4b/WyedSfdnVqIJw82FgPFgyIY6F/0ccLdkhAm
fLtQJBHc3UyK13l0qVJxhAFdz1Q0zfScBS6qM/Gnbcdc6MY9/bZdIK7E+4op5iAM
kvQHap7qnArhI8VQ1bcXYlQ6asPj4e10lmzroiBHM4N/Yuxv38tmtUCudSB+EcXi
EgJIOLmLq2ZACRzug9KPyMXOD/Yxz2wPgs6I3gvrB22w/MfC77wMfEMuQQk4cZel
TFKosHgLjvcLG+zx5yh5ZVFcNV0CAwEAAaOBrzCBrDA3BgNVHR8EMDAuMCygKqAo
hiZodHRwOi8vMTI3LjAuMC4xOjEyMzQvY3JsL2ludGVyX2NhLmNybDAMBgNVHRMB
Af8EAjAAMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAfBgNV
HSMEGDAWgBQRqYdWstn6ntusRZ8LjyPFEicL5TAdBgNVHQ4EFgQU3ozX8OjQ2AEH
cX1v2WhZID6wZ3wwDQYJKoZIhvcNAQELBQADggIBAA1ipq2MIRdRIiUZ6M6AjY91
L5iUpgKGrmhna/gg2b6AlugDOtVDsfeFm389aSplwY+zcJZ2AbUXhXe8RVHOEUwf
O7iEDWsMZ/wxit5ZotJ5kzr49n9RTtomgbQSqxWadLq6Q9hYOWg/cr1FvXwL5tyO
rHyuRXhkUMmuk4aQ1sfybfPp0PJKbzWu001Q4rxbJTlaib9b+CcsyLWHs06JXVKi
755Lg9/ND1bQjW2CMJbZ2rm8V7oh4J0tJuF3DntOjyOk+yosckTF3bFffGPR67WC
RkZebIKx2Rh6OXMrQTLz9ldqWo0cW0O353gSmrMxExWKhgoDrZKc4UeOanweDTqO
4lU0RP/4naDuQl6/FE0rUzUkfAJmsKIuI4G1lQNZhaqUH/BdN1du094RON0T5agK
etoBcPpNpxOn4N86TJaYoDjRSDpKwxXVKZs9lk5GRLxRhqtY3iQYVZrz2gY36Ri4
lnuKZCeFmfjHvvktmb08EmrvGiQAhXzI8yfeVhlwP8lhtumIO877VW++tedK0z0D
6aBz1LsVI3IbinDZPRsWl0EEi+JFmpIktmMTdSn+0vTs7XJjbBZ+VKaPPWOG/Afg
Qav6+1AnnMtieGfrj3tyyfKo0vPSZKbdGzEr79Ukl+cxLdG5O5qZTy4ASm3EOw36
p70HafhN8Vioa+uhQObP
aWNlMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxNqcFB9GSj+nC1PV
OTIAvzTuo3X7bTbohEPrIDDsEcGyVzQtfagI9vkxhhGLhXxIXrkwEI4u75DeLBdq
ZR3KFJ3QD+jHW12EWNpmSYu272CEAJeb/SBJaFbh40WbY1BsTP+3zI5QMwVTmCH5
QqODD+GU0fDSo9Gti0yX4rxOY+54jDC77AhSlU55rYruBoIXVe4CcPUpqzZLgqB2
cTJ5g7lokGqc6w9pveCznVYGPfcdDt+ePGssOvrfBOJnn6N44tTRAG623BrpctXi
t3IAhG60y6CqF29BjV0RKOv09nOBiph2a3lAiKYrpAt92BETFB7KSQManUrrvWOD
mYEcoVkzvrVrB3WnCcHs6lsjQg1FcNrGcDzV9SmX0BIhM+fasxZyHWc08pr3NrRn
Eks7lRqY+TS8DAeZYJt/2M0Jr32d6Bh+WdyGFFUj6sBPtCaC2VnSkxOgKXeWf/c5
EUXIQT2YXEkNK9CP8Kqs8IerEIpfceelQReA5QcvNruaJNktWLKJgYTrdLdfOP0u
s+9JJHWcFH3tv5906CA+Tlm53Dk6SaRc/DB7lu94yTkcSOpxXZnximZi0GcPZYmZ
TaswE7d8HCPLhks/RkZSV2764Kl08xle65APiWZ4dM24uSyu75Izb4hrwgIA4qyM
dDVQnI3cu6utmKUPyHoJtH26dr0CAwEAAaOBlTCBkjAdBgNVHR8EFjAUMBKgEKAO
hgxpbnRlcl9jYS5jcmwwDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCB4AwEwYD
VR0lBAwwCgYIKwYBBQUHAwMwHwYDVR0jBBgwFoAU+f7h8O2ttBHtwI4OZnpD9wU0
9GYwHQYDVR0OBBYEFMOMHl201gGYrA/OoGUroGeldRTZMA0GCSqGSIb3DQEBCwUA
A4ICAQBlx15n00tEAP8moDUehCtLLJx7CCG/V7gcldTZACXpOYkcuRcKW9GlXqQv
N30rTZpIZv3XIQEhhWhMJ3dqJRC0l2CbNlrIcM9t5p7GrYS/I/HGamKIU09jfud2
1/FimjvBOQKr583vTLL0kr3Aosd3S8jHGA7Clal/85SntQN0kDxnceo01aCUhnxg
Lkrd2+N0wPYGW5DZR6jk4Y/GiOO+q/ANO+tm4szT8RNwC5sNectpaI+ZRNlUHCdM
DtZO5HkBADQ7PdZ2x51gliS5l9w7obFY62TG6LgtKFJgqEhqsHMIp+/OwmKbpP/p
urUDJFCZGWD+lBkaxyy+VsPlvddU7gnXSm0wXoCxpXerRwWFb9/Kc5Q+kQB4nCkv
bHm/zAkhjoRSjWYPcLL3F/9P858W9QlkhNdcoq73EIuc3FHUMdQUm+rjxGxfO76h
fXoR2uBGlESO+gKL2iC9E7KKB+o07hdmafEnE8mGTRcGmVPp8e5SS7LfN8lfHez+
3gBo2/lW1+2wBmBNIeBkkBpUI69DmNZvMliGNl/3LAIR/slQ6ZYXR/2dLeyhqwRt
QSj5e6Jw2fg3ekG11R98OGoP3ZC/N1dTTh82O571ZBGxIWA6zPDrWj7tX0oW+JK0
Of23BiH+4sex36HshqiyZ/faq4AtO62uII5mRQzlAwE2QdXI1g==
-----END CERTIFICATE-----

View File

@@ -0,0 +1,19 @@
-----BEGIN X509 CRL-----
MIIDCTCB8gIBATANBgkqhkiG9w0BAQ0FADCBvTELMAkGA1UEBhMCVVMxNDAyBgNV
BAoMK0ludGVybmF0aW9uYWwgQnVzaW5lc3MgTWFjaGluZXMgQ29ycG9yYXRpb24x
NDAyBgNVBAMMK0ludGVybmF0aW9uYWwgQnVzaW5lc3MgTWFjaGluZXMgQ29ycG9y
YXRpb24xETAPBgNVBAgMCE5ldyBZb3JrMQ8wDQYDVQQHDAZBcm1vbmsxHjAcBgNV
BAsMFUlCTSBaIEludGVybWVkaWF0ZSBDQRcNMjQwMzExMTU1MjM5WhgPMjM4ODEy
MjMxNTUyMzlaMA0GCSqGSIb3DQEBDQUAA4ICAQC1oMFXyJ2mAz0el6drt4KtH38d
FfDvsjc6hTgiPbmQW4NmLuSKnNLOyOulsRaV7Kl7hxQpd+Gyimqbtb1ObeqLvnyb
W5kX90k94l8M/laZT1mZm39AGR8xW8HDtuJgwliI7RujX6iWuyrJCxM4qpAHe0Jw
GGQd7ZlzEZ/4xMsZV0lPSsA9CPUn4HyZ2FWj3DJjfXloEOu+krcpmvmL3EROUi/h
F6bsViKRmoQoe5GJFLdG4eVSgc9+ejaM23n8C0tmAhz7FKOYOqU7pS9+hvCyJ2Ul
c8S3V7hzTlz1G4AJAeSJtCnV/hkpt+yj0eQa0Q92I0NZY3UWT8dOMZUxpHO91Th5
4nfaF6FVSO/AQcpr4FPElYObp+RigqWf44v3vrriHTYi9QntKaNZq5XLgx8EkgBx
1dTM7mDJ9W21ZWGEbRtLRaKt71RVsVKVLh5CPQrFEzENOTuy66QD26LNC2BfE3TJ
tsMgjm14Fm1mC91roj7sOsO3MUl4YKh6cdKFtfryWr5Du+7x9/6vjabuay/BopC9
BF/q8ITHh5Shs0h9OpOeunGFbcTnYOSgOpDLwC4++hur8p0BzClJkt2Z4yZGuKe+
lh66PA/UkHtC3E8NDxVRkd+NsejSJUzRR0+1ruEoDEGP4jZKL83UpOFjIWGlIBsM
2gwwqV/LJsywfW1kFg==
-----END X509 CRL-----

View File

@@ -0,0 +1,20 @@
-----BEGIN X509 CRL-----
MIIDUjCCAToCAQEwDQYJKoZIhvcNAQENBQAwgckxCzAJBgNVBAYTAlVTMTQwMgYD
VQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9u
MTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBv
cmF0aW9uMREwDwYDVQQIDAhOZXcgWW9yazEVMBMGA1UEBwwMUG91Z2hrZWVwc2ll
MSQwIgYDVQQLDBtLZXkgU2lnbmluZyBTZXJ2aWNlIEludmFsaWQXDTI0MDMxMTE1
NTIzOVoYDzIzODgxMjIzMTU1MjM5WjAVMBMCAgIrFw0yNDAzMjAxNTUyMzlaoCMw
ITAfBgNVHSMEGDAWgBTXVfLQH2D0KccIHhK6M5MRTITvtDANBgkqhkiG9w0BAQ0F
AAOCAgEAkHC9VxzSFGrY4NWoMLkunjaRQ5qmc4+3PFDiZLaGQua5QMJixMo+QIp4
RfCLAkvI4VzMdoJXhl4+sV0mocn1HWDBxFUwfsvV4h84o8bEUK+bizrFsEoN58R0
J3yfbikgj4P7WFQdU7p7bbAkmoKejt5+gu5etV2royIh2mjckCN7WnYzvhfRUBYz
v+93R1usMMQIVId6l6k4DuBqaFyip8AKXVoXj4KbmwXZ8n+ILd5gWV3WKYo/ffCh
h2g+jaS8JS8CYqtVGEb7F0zQwdPe1tHA/SBFBCNVqzHos+yET1m0Cn1zoYPvkEu9
U2OVK5tqffEyrkN8hRm7LT2NIYji/z4VOIY/sGA1SPO7HNzoheAyHR7u9ortGMYv
2Q69SEqtA7N6kMX3y/dL95sI/E3EJp5Z27jMMP7+aJ53F/5xmIqkZarA0ETuBic/
KlNjG0WJilUMH7D7emTxksTdZOC8OKjg6gPY5GhVmlQ/LRvJQtoXqC84UQV2ul8R
chvU55EUB67247g/WAusCjutISXnKQ4RGPaH9eOu1yN7StiXtJyiZ8R14ZihhC82
ZzxjfDDk6ATR87bkAeDYJvubLJkVtUyUK0vgklNsyA+hwbdr5E5Q7IaRW2Bk/tnt
K9ANhMjaerwcR20aOmA7pVuMGXU2MhFIleQzl+Yfv8N1CDECw3Y=
-----END X509 CRL-----

View File

@@ -1,39 +1,38 @@
-----BEGIN CERTIFICATE-----
MIIGyDCCBLCgAwIBAgIUOgU+VHYEK4Q4dZokfM01Ok2XBtUwDQYJKoZIhvcNAQEL
MIIGrjCCBJagAwIBAgIUOJ2eXoc9SJ1pRCC4x452LX35eNowDQYJKoZIhvcNAQEL
BQAwgb0xCzAJBgNVBAYTAlVTMTQwMgYDVQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2lu
ZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFs
IEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMREwDwYDVQQIDAhOZXcgWW9y
azEPMA0GA1UEBwwGQXJtb25rMR4wHAYDVQQLDBVJQk0gWiBJbnRlcm1lZGlhdGUg
Q0EwIBcNMjMwMzI5MDkwNDQ4WhgPMjM4NzEyMzEwOTA0NDhaMIHJMQswCQYDVQQG
Q0EwIBcNMjQwMzIxMTQ1MjM5WhgPMjM4ODEyMjMxNDUyMzlaMIHJMQswCQYDVQQG
EwJVUzE0MDIGA1UECgwrSW50ZXJuYXRpb25hbCBCdXNpbmVzcyBNYWNoaW5lcyBD
b3Jwb3JhdGlvbjE0MDIGA1UEAwwrSW50ZXJuYXRpb25hbCBCdXNpbmVzcyBNYWNo
aW5lcyBDb3Jwb3JhdGlvbjERMA8GA1UECAwITmV3IFlvcmsxFTATBgNVBAcMDFBv
dWdoa2VlcHNpZTEkMCIGA1UECwwbS2V5IFNpZ25pbmcgU2VydmljZSBJbnZhbGlk
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA61P3Lfow3E6wGpMJmUWp
wsfFZwcuKSf64JXDn1pVJLUcjTwhApshnGaSBb+knlpwvsO1evrR7re9ZRh51730
IintOP5IA3CSGd7fqmTpchx3kdFOndrXS7BwAWuB/eZ1qzKeOYpyAS3VSE4FphYi
LSxGfwSUl89pwYyWyqGl21hv/sBL6cc+Lm55vXbeRwWKW9K/w7BkhtK1zx1xm4i9
4x1aXJ6DGWQpIk1sVDNPtzQVZYvmR1Y10/r75sNgA/WMiZx3/2VyCREnV+UXfvsX
fyMLcbwMWWt6psdhtoGFZ2sLJka5ZNvttQKfbde4TA3I6fpsrMi+oTT9YO3it5zG
ORCUC+j5B+zrzbSv+RgL+SnnAPkHqufb1a/4mFs/uTbjUYHN2/rhObnkLK4Xtfly
FBlivxx5haT9o49YkCv7l57+We4nafBPMw96ac5AGzA0gVwdMTeRZ3joT2Pc/zSf
H5E9wg3MZfg3TN2THB4S//r1/XOaA5F4BGjorbpPhp1/YaeF0rRMlAbZVKXHZJBR
n5qN8hD/V2tXviEkrZRL+iW6ltkslsjIkzrYSS+6goymUjWrkGjmcsTo0SStHE0p
7pOChLwpUtpaElemp1NDzVJqvrglWPkM1ZIIjxpk23zxKj7V2FazqP6PVuyeWdkj
VYN86ULDRG5j1hfn/n0HEC0CAwEAAaOBrzCBrDA3BgNVHR8EMDAuMCygKqAohiZo
dHRwOi8vMTI3LjAuMC4xOjEyMzQvY3JsL2ludGVyX2NhLmNybDAMBgNVHRMBAf8E
AjAAMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAfBgNVHSME
GDAWgBQRqYdWstn6ntusRZ8LjyPFEicL5TAdBgNVHQ4EFgQU+jIyiVonTYe6GuSP
iAkxA65qou0wDQYJKoZIhvcNAQELBQADggIBABcvU42Z/T7hT8ke5viG2x7FJmwA
gkrphOYiooB77sxY+cjxaYsct4yvFXvwuNAcstnlBK0jJRaWzLwswR1t2bXbRwQF
kjDO3br4ALRMHkDPa8iNioogyap8X6r40p7rvfnudKX0+MruLHXN3ZM2ltucYAYU
oR/Wa04KxDuZQHeKrDosAsJCv5MwgF69H3oPbhspFQsP2V5fFsxupnWFzVlwPfcQ
0lgHVC3nZ2Rj7ZariT/px3nfZ6Eg3pRyK32r2SQWVN/oVBEd5cCTONvD7Hr2SrtB
9D58f+vDyVNWM5OED7NqlNDaQw2x9BMjdEVYTGGRW4IXPbXWH08NUcEkT1Tx/vUE
EPlTgwt88Fca03yvAn/8Daw7ezsJNAFwDpPDcQhPi3vg2l32nuRkuQ5641hJiTGw
TEtpJc3dg3FJymG999rOCLLIheNLMehEDMPZHqG7XeEg/42F0580MdkOenMpjhwg
ZhrommB85sZcGBOwc63VMb5PPInYDQi5PXz9Tpann/VliVd4Dpnyn0XVy73VccXu
WWgDt8gJKWUpRiJ6MZzEKkBrXYjPLmrKB64usEJNQ1e2NIKV3bwvH5K3PmibyVBu
9fT5t0VXQpNxxlwngCjvjtt0D/frMCJQXpXpnz25aQDog9bnD1yl02SzxdZaVK05
LZP4wR2beOGlz828
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAw7LcEUPdhr0FKp+muH7w
Bj5Mbktl4e4kpIMqc2OaTxtwM4RDUDpLwy9X4PuEpGYEgOwOQYyd6udfInpjVVTy
JBnwxdfpgHfsdqamkrZDqjGWHeSw4332D8gGMNFLmbCuHEzVmr1XLYQFVYMTuWex
VFvL9ctA4gv5xO9f6oL7fVE7X420qb7IzntrxJHKsQA/IheJkZHYvPpBLs9Xlwje
tb5OwyhdbTIsfR4V3vHdQ3shwD9TFbc+6MTDryWZThlDDUA8f+iO+euAe6QjLDnL
JgLwnXd4EmGyePDhBM8oSex5o3/vzJVmJkpb40pvloOG11qlXGaqJxOLH2jjsNKx
iC4l7oAHP0tXIw5f8hn+pk5vQNIcIHguXIT65ZR0IFRE9tjciLOtxndEn976jmqN
Qu6Ajx5DiImwzp4wHjJOoVWmKCM9BklFRhwJvZ2xTmBGvC20jX0OgEaCeWV+E7UK
2pzfGwwkWdXC7ihIszhGNP/lLlE3IflS0MHSxtie5fUrwuoZ+bVkKYClkLYeKrBT
MLfszTuWg+rJfGmCwvYWGG9gcIRc1T3EuOiNpN4YJ5HZyD4rSI82fSzbrAtAPWPk
6iVdmo9Ban0pQhMzyH2Gu07OnvBpmH2ADLzFpugjWafW157//GCNVgjrKVN/JbuC
0nne/OTbQgCO1mFOy6RI1RcCAwEAAaOBlTCBkjAdBgNVHR8EFjAUMBKgEKAOhgxp
bnRlcl9jYS5jcmwwDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCB4AwEwYDVR0l
BAwwCgYIKwYBBQUHAwMwHwYDVR0jBBgwFoAU+f7h8O2ttBHtwI4OZnpD9wU09GYw
HQYDVR0OBBYEFNdV8tAfYPQpxwgeErozkxFMhO+0MA0GCSqGSIb3DQEBCwUAA4IC
AQATY32D+AMy1/x1WLGbQcvEkcT5+UEGp82FEVamXy4eM+zctzemEufjSszEpRod
N5UgiNGDjuD5ttZSc37XHwtOwqZv2V0tu2jclxQQCswPjLhkecpIwSFJW9Y7IQPo
+4FKry6q+vyo0sLA+pIhTT+OHK8ijy9PQEx9YOHgr0HTTTG8UZ/6oqx70lvx9KcA
x9PhFb5TWaOhOds+v7NEPxslwrMRQ4jOz92bGeBjSXBzxwohoKKWcLWIy5ktJsFS
PhVztHa+on4AXdDJVifU4lYIPTRZBX491EnIpEaZtyEED319SNlj691+5SgDNHRw
Ysk+xcVYy8RmL84qfTNce+t2eEr0vjnkUqVNt6ps3UvkK2jvlehBlfPW/Dy/r/Er
q1KNvc1Uiza3ryf2dAMDWL2VBIKMZb+d88cEuLHIgmCXrxtcyxCBTWCK6t4cnKsQ
J82B4XQ9IRCCJDTjGEQLxsjYt9jwHeUIK0l/sseBeohxMfDptfRQ8hWt7c5SvvNy
xRGJ1adli7LiJ3+gnPcyO+D+3DPtKtgY4y8Aed5P3oDOQGNdUznSP2qexUpT9GO0
fJaRI8Bc3Kj1zLkS+mtYHeOBu5eyLhR0fSBpKr3/3RoKj2/NI3SvlBbJ6dD5jQBs
4qEi8T70wjhDqITPyqZV4auy/0/h89JXDB/qAg162p8EJA==
-----END CERTIFICATE-----

View File

@@ -0,0 +1,52 @@
-----BEGIN PRIVATE KEY-----
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
ZAbU3ynucdvh2dgqN4agS//dmuRo0A==
-----END PRIVATE KEY-----

View File

@@ -0,0 +1,58 @@
-----BEGIN CERTIFICATE-----
MIIGhjCCBG6gAwIBAgIUOkSdvHg4/HXtknNMhIFkuPv/ghMwDQYJKoZIhvcNAQEL
BQAwgbUxCzAJBgNVBAYTAlVTMTQwMgYDVQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2lu
ZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFs
IEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMREwDwYDVQQIDAhOZXcgWW9y
azEPMA0GA1UEBwwGQXJtb25rMRYwFAYDVQQLDA1JQk0gWiBSb290IENBMCAXDTI0
MDMyMTE0NTIzOFoYDzIzODgxMjIzMTQ1MjM4WjCBvTELMAkGA1UEBhMCVVMxNDAy
BgNVBAoMK0ludGVybmF0aW9uYWwgQnVzaW5lc3MgTWFjaGluZXMgQ29ycG9yYXRp
b24xNDAyBgNVBAMMK0ludGVybmF0aW9uYWwgQnVzaW5lc3MgTWFjaGluZXMgQ29y
cG9yYXRpb24xETAPBgNVBAgMCE5ldyBZb3JrMQ8wDQYDVQQHDAZBcm1vbmsxHjAc
BgNVBAsMFUlCTSBaIEludGVybWVkaWF0ZSBDQTCCAiIwDQYJKoZIhvcNAQEBBQAD
ggIPADCCAgoCggIBAMheyYWl/STLJ0iwlrqNRyURatdeC8oDpKFdpglYHAs/jo3s
fWNySCnaw6NCe0vxFLpqcK8VMNFRGu/XhR/kZ1YR3V4mLwF1Wa5v7a7J9swq50Fk
CsLtaU5vq/h6rIpy0NLnmN5KgqChrMh9IwZ+Mc8sqc/0BFFJsuCCGu0TNlGVOhmN
AbdS3s7wEUwT023CKn47G3pVqeaErEB9honz1I71g5/jNKGe5CLCV35ExzsrzU43
atyJ0jgh15PYCXDTdsRccSmEs2S6Xh2o4ZhlqioWB+tKxGsdxq8Ri4soy6yyooOz
T/3X5CHpKxiI2P9z38Pr9egPcNPPVMGDhzwHz7p3iBPg0RcWd5VP2nimLJsdGWK0
bkU7zlQ3R2NelSIW9Hr8MVASihmELvX+AcC6KhTpHHhf3CTPgcAfV2fE9U84Xl2i
shmoEsUQTUx97qKUOKRfY6o+WMBnVkzlqWj+s52ndiT+0KNLTDtvlejEFf1VSF43
IkS9UJK+XxxEnvIBzNKI5EbWlG5Z38/nKv6pjTXFi3aZR4cdmI/0XfAjLTkrTBaW
lkguEjt+/cxPYJOqt50ldI9kle8XTu/HibmcbU2wYIF21CBjE/hLk/KY3FQlnTFL
y7x3bM0CuTfJ8Noy59f3l56fwPOpaQWqhqO+UoFkbFlbROAiVxfb8KlyZPdNAgMB
AAGjgYEwfzAcBgNVHR8EFTATMBGgD6ANhgtyb290X2NhLmNybDAPBgNVHRMBAf8E
BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBTWntryJpCwZqZJ1H3n
znJYhbfoKjAdBgNVHQ4EFgQU+f7h8O2ttBHtwI4OZnpD9wU09GYwDQYJKoZIhvcN
AQELBQADggIBAE8gulfly5+EC8DX3K02qEYPoQwVbVhD0wGrlAhgJiakDvPlX6/K
vSe/1nNRG87jXvXdDiuJ6F4iKZpeJndzvx/8ZEmllyyxDwb3UOmylwW/o3/Uh6fY
kiVBfW6uNNB0BfDKcXDDZgKjTg3kLT5z8m4u8rPoIPFkLFl9AuAq82Ll6NQ+xZFP
lZ3K6HN+ntVnIGP4XkOgEYPxjJO3yTGle8VBqLfo/JKwbZtKfNXxSAMRXiP02SQg
D9yshxkonQYWog2hHz8oDuQQNbzaAFlxnY914av/XwxP8TwEfGNchNtAtrlGRlx8
PjMfp3Mnbz71yp+L2We2/A7njIPbEcn0FIBedpNyyBON5Cd6Xqx18otmMTtUILZ3
SUKeYmLp8soVMEmmnWz6y1a4bCKwo6hA8oSoq5ydIeWy/jI9v7DF0S/qZTz3c2Q1
a3aniuug2FRAxuU/8fSlMrE4672d3505SbHUblhy9XzQ4+sWjkDtYnY89kyY4BTu
W5n6JlVoewZGOjlJ9/6mV6BVLQ74IeiytWtdH5uOQ1wroi5Kq+EroGgFmPSQCIvN
XNDvBCNFN/O1+/eVZd6JNx6NMO7DrWql3GFMtJE8u/SWXA9vit3pfmeDrosZ4SDg
ZPt7+JfzITUh2UMaPsQsPF8G8/tYmxDbELE5LjFcQ24ps362rG+q2rfA
-----END CERTIFICATE-----
-----BEGIN X509 CRL-----
MIIDbTCCAVUCAQEwDQYJKoZIhvcNAQENBQAwgb0xCzAJBgNVBAYTAlVTMTQwMgYD
VQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9u
MTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBv
cmF0aW9uMREwDwYDVQQIDAhOZXcgWW9yazEPMA0GA1UEBwwGQXJtb25rMR4wHAYD
VQQLDBVJQk0gWiBJbnRlcm1lZGlhdGUgQ0EXDTI0MDMxMTE1NTIzOFoYDzIzODgx
MjIzMTU1MjM4WjA8MBMCAgG8Fw0yNDAzMjAxNTUyMzhaMCUCFF72el1l160wBZ+u
getcWTcmtomDFw0yNDAzMjAxNTUyMzhaoCMwITAfBgNVHSMEGDAWgBT5/uHw7a20
Ee3Ajg5mekP3BTT0ZjANBgkqhkiG9w0BAQ0FAAOCAgEAbGRxfJj3wsZ9iUsYTO3W
7+hNbZ+nRaokZT1UgprzDTMmQKWp5HRyvAsTtzxeJZ4NDEqP2mg8imvmSUSnLSmR
pdq7vUdk7lKvdV++fZo4XIRF/pqv7+8Nz8iZvxINGhFaJDUUPPQSFcLm00JIUMzn
9nh5JkCkKFuk34DgHDR3Zn+nM6R+gAuaDsBgv3xnU6PKVW796JPbz3yrN9fma9Pw
P27ICXVyOH2oH7p/E7oNB/J0YxKcD5bjaFkzVHsMExCzeyGTA56qtdN2O1Oxiw2z
L1Yitj1c+2/P29vhCw0IuxKjduL15Qu5Px5BT+B6V3cVUPbn9fYlDjSFAHxyrGno
X3QnVzCChVoHuS+Og/QwEx6AcTSEbl4E47XQK0gr1cG7ayOZoDO3rqGQ+eO6kREM
LpX2lHPofzMBk9lGPfAZX41pXUlshT0irrwFbIt3OTGfvU5x2wAjCap1InzvFS9J
4vEFHcLeHAi5ztlnYNIkB9/kja3ogpSCbcO6WoveJeHCTsXk5K4qIOSvoLYEdRE1
Pn2EJStyULZW9Sv1JH2puyZ2d2Y7cl6DqCZ5D4tFsyFFsMUNlBJQSxKoPDYnGsi8
DOTxrwhdxG/mSwn/NoYjZdC0Y+NJyBs1RvLvBZLdgzWS8I+uvyuwTfn27tP7GT6Z
8hmLPBMvUOyczXdMD6b1mfQ=
-----END X509 CRL-----

View File

@@ -1,20 +1,21 @@
-----BEGIN X509 CRL-----
MIIDSDCCATACAQEwDQYJKoZIhvcNAQELBQAwgb0xCzAJBgNVBAYTAlVTMTQwMgYD
MIIDbTCCAVUCAQEwDQYJKoZIhvcNAQENBQAwgb0xCzAJBgNVBAYTAlVTMTQwMgYD
VQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9u
MTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBv
cmF0aW9uMREwDwYDVQQIDAhOZXcgWW9yazEPMA0GA1UEBwwGQXJtb25rMR4wHAYD
VQQLDBVJQk0gWiBJbnRlcm1lZGlhdGUgQ0EXDTIzMDMxOTExMDQ0N1oYDzIzODcx
MjMxMTEwNDQ3WjA8MBMCAgG8Fw0yMzAzMjgxMTA0NDdaMCUCFEz4gViZ/JN+6J2f
2mIC8bnWw95IFw0yMzAzMjgxMTA0NDdaMA0GCSqGSIb3DQEBCwUAA4ICAQA0FKRq
yESt1SYxVW+BlFjeDWCf1GL471q+603JiRek5iEVt+bZXrII9y9lXsYhZ1d7BxCt
Wyo/497tPMwRKSiPJwrXPODQn3DTl6EM6VB+w9Kipmm3Fq97TSRBuiDkYaS/nUHh
nDfj40qb1tc18SgBXVLSSiu97U0JMAq8AHIfMzlnhIe4fJ7TJU2TFSrkFAOUVqZs
p0/J3aDccYJBnUnEeGD44i80wd3xmuOoBDqRgKcasYsv8QmSFhbD4BTvicxKueDD
kiWTFbgNTDQU9Prp8gYmuSOaQoK6S+8DlO80IRTDwpDq1nQaf5MvwfOqfwQVgAjt
RgrC9BI1RvQu0OyihvcqOh9EEj5O9D/nrgTdsWYJGF/otb8lL6JdXDOAjqWSkZVA
gKDq4NPUskgKzoccD6HY5wgIvSZTV8bXjz2ST2oddfg0/7akNBEmq4TQV9NHb/G0
AihNJgd3HtESn5Fhm51aJZPyuwqzmkmNHTuHZ5qeDB1dN/UVSqfnLXKeKirOtJCq
VdWGZTFEKJSDPgmLOMy0GhrOeM/y5N5MJZBrwBxPJ3No3TOGr13Ir8E1cxCnchZX
PgpyXNU183gMX4k5NVEWYpCzoTxzY7PNvaMft61IkC9DIdnRxRbEqfdLiVy/k4jP
MUjX4ThGwtUVzqVOiH5uRRE1J7Msk/W3EYzIWg==
VQQLDBVJQk0gWiBJbnRlcm1lZGlhdGUgQ0EXDTI0MDMxMTE1NTIzOFoYDzIzODgx
MjIzMTU1MjM4WjA8MBMCAgG8Fw0yNDAzMjAxNTUyMzhaMCUCFF72el1l160wBZ+u
getcWTcmtomDFw0yNDAzMjAxNTUyMzhaoCMwITAfBgNVHSMEGDAWgBT5/uHw7a20
Ee3Ajg5mekP3BTT0ZjANBgkqhkiG9w0BAQ0FAAOCAgEAbGRxfJj3wsZ9iUsYTO3W
7+hNbZ+nRaokZT1UgprzDTMmQKWp5HRyvAsTtzxeJZ4NDEqP2mg8imvmSUSnLSmR
pdq7vUdk7lKvdV++fZo4XIRF/pqv7+8Nz8iZvxINGhFaJDUUPPQSFcLm00JIUMzn
9nh5JkCkKFuk34DgHDR3Zn+nM6R+gAuaDsBgv3xnU6PKVW796JPbz3yrN9fma9Pw
P27ICXVyOH2oH7p/E7oNB/J0YxKcD5bjaFkzVHsMExCzeyGTA56qtdN2O1Oxiw2z
L1Yitj1c+2/P29vhCw0IuxKjduL15Qu5Px5BT+B6V3cVUPbn9fYlDjSFAHxyrGno
X3QnVzCChVoHuS+Og/QwEx6AcTSEbl4E47XQK0gr1cG7ayOZoDO3rqGQ+eO6kREM
LpX2lHPofzMBk9lGPfAZX41pXUlshT0irrwFbIt3OTGfvU5x2wAjCap1InzvFS9J
4vEFHcLeHAi5ztlnYNIkB9/kja3ogpSCbcO6WoveJeHCTsXk5K4qIOSvoLYEdRE1
Pn2EJStyULZW9Sv1JH2puyZ2d2Y7cl6DqCZ5D4tFsyFFsMUNlBJQSxKoPDYnGsi8
DOTxrwhdxG/mSwn/NoYjZdC0Y+NJyBs1RvLvBZLdgzWS8I+uvyuwTfn27tP7GT6Z
8hmLPBMvUOyczXdMD6b1mfQ=
-----END X509 CRL-----

Some files were not shown because too many files have changed in this diff Show More