mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
Compare commits
165 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
03f7566436 | ||
|
|
177d8ae0dd | ||
|
|
08d21b24b4 | ||
|
|
ed74e84862 | ||
|
|
0263637d9f | ||
|
|
1aa1558f91 | ||
|
|
29a1ef0023 | ||
|
|
39eb46763b | ||
|
|
ce1464ad5f | ||
|
|
c6d74eebfb | ||
|
|
ad129057b5 | ||
|
|
5b8fdc2bec | ||
|
|
784cff18c3 | ||
|
|
fb33935c9b | ||
|
|
175b336d32 | ||
|
|
9a5c9cd7f9 | ||
|
|
73c227fa9a | ||
|
|
1078e6d45f | ||
|
|
50808edb7c | ||
|
|
9dca2d3181 | ||
|
|
fc853f3259 | ||
|
|
89577c2f8c | ||
|
|
d6fc4921fb | ||
|
|
cb9c2f993c | ||
|
|
637c8196a6 | ||
|
|
c87d11abfe | ||
|
|
20fffb31d7 | ||
|
|
2d330cd45f | ||
|
|
618e22e38b | ||
|
|
173a055372 | ||
|
|
4670b108a6 | ||
|
|
ebe56592c8 | ||
|
|
1746d2bb6a | ||
|
|
91123e5d45 | ||
|
|
0f0e8cf33b | ||
|
|
7586a1ad59 | ||
|
|
1da328921b | ||
|
|
f96f09a5c9 | ||
|
|
4fd607ae5c | ||
|
|
f1a11a01df | ||
|
|
2eceedeb11 | ||
|
|
a9dbb8a1a2 | ||
|
|
78dd82d129 | ||
|
|
113e9ebfef | ||
|
|
f9ef8a0106 | ||
|
|
2c63c69af4 | ||
|
|
8a4a4e0557 | ||
|
|
e8550a4f8d | ||
|
|
e7bc4a5d31 | ||
|
|
8b38bf37b0 | ||
|
|
3696d6bd08 | ||
|
|
6847b6a8cf | ||
|
|
1f339a9e7e | ||
|
|
905c3921af | ||
|
|
e55e0e470a | ||
|
|
9d9fca6e72 | ||
|
|
2a6657dfd1 | ||
|
|
b3dd05e16d | ||
|
|
f216862052 | ||
|
|
e4aeeef8eb | ||
|
|
c911419121 | ||
|
|
e6de495daa | ||
|
|
419d93bef7 | ||
|
|
2714f1d90e | ||
|
|
10ec3f18fc | ||
|
|
0c771423b4 | ||
|
|
f67fa03581 | ||
|
|
29db9032b3 | ||
|
|
56a55901c1 | ||
|
|
43edafd088 | ||
|
|
b1e3ee255f | ||
|
|
a69a46eafd | ||
|
|
c85b4e54dd | ||
|
|
da4b881eac | ||
|
|
9f03ddf519 | ||
|
|
a05935cca9 | ||
|
|
6f9f846bc0 | ||
|
|
603a2b1762 | ||
|
|
dcece3f980 | ||
|
|
ff19180f03 | ||
|
|
42eba67268 | ||
|
|
3cf95a1d92 | ||
|
|
5e93b53f78 | ||
|
|
360e8d4156 | ||
|
|
a048670bec | ||
|
|
4ca93aa808 | ||
|
|
9a5886c0b3 | ||
|
|
78676df2f0 | ||
|
|
224e35b600 | ||
|
|
bd52e14740 | ||
|
|
dd380942ed | ||
|
|
9ce9ed72a9 | ||
|
|
a8a87779c0 | ||
|
|
cdabf280ac | ||
|
|
33c75584cd | ||
|
|
1f68c1aaf3 | ||
|
|
6c6938d1e2 | ||
|
|
90ad42d814 | ||
|
|
cf7c74b2dc | ||
|
|
4388a6d299 | ||
|
|
44821d0586 | ||
|
|
405b2da3f3 | ||
|
|
d3ac9f3365 | ||
|
|
7535682b1b | ||
|
|
72f1a2e0a9 | ||
|
|
220f51fb98 | ||
|
|
5ab3473442 | ||
|
|
cf51aa1421 | ||
|
|
b1d44876bd | ||
|
|
c006800bd5 | ||
|
|
634095aa24 | ||
|
|
b4f575abc4 | ||
|
|
6c729fba9e | ||
|
|
71503c0e7d | ||
|
|
5c8bd68f6f | ||
|
|
927f901969 | ||
|
|
35cc35894b | ||
|
|
dfaa1791b7 | ||
|
|
52158e73fa | ||
|
|
cc6f1a6d7b | ||
|
|
866324bcd2 | ||
|
|
7fd2421a2c | ||
|
|
66581d57f3 | ||
|
|
de688f350f | ||
|
|
958ccb46c5 | ||
|
|
3ea90a2258 | ||
|
|
7d56dde24a | ||
|
|
c7d0d3c1b9 | ||
|
|
d7648875cc | ||
|
|
5fdeaab3d0 | ||
|
|
f0bf1985c3 | ||
|
|
a3a2d70603 | ||
|
|
226728731c | ||
|
|
94292dac54 | ||
|
|
278f4f6fd5 | ||
|
|
17007ab121 | ||
|
|
4f9e5d7842 | ||
|
|
8a52693acc | ||
|
|
a93146d976 | ||
|
|
187437c6c8 | ||
|
|
cdc787d92d | ||
|
|
5feee12827 | ||
|
|
cf70a27d76 | ||
|
|
5552b476bd | ||
|
|
7510b96238 | ||
|
|
778d9e436a | ||
|
|
692af4058c | ||
|
|
2565a4ca99 | ||
|
|
6d5f4a99de | ||
|
|
a9ed19285a | ||
|
|
4eb18bd6b7 | ||
|
|
cf45a6e108 | ||
|
|
a879036e3f | ||
|
|
5340d11165 | ||
|
|
162a041077 | ||
|
|
b38d5833fa | ||
|
|
ee8897f9db | ||
|
|
4f622325ef | ||
|
|
f2902a1990 | ||
|
|
9882aabe44 | ||
|
|
d06d197522 | ||
|
|
3fd07bb7f2 | ||
|
|
58ede126cc | ||
|
|
e4a03c6f71 | ||
|
|
c66495888d |
8
.gitignore
vendored
8
.gitignore
vendored
@@ -102,9 +102,11 @@ lsstp/_lsstp
|
||||
lsstp/lsstp.bash
|
||||
mon_tools/mon_fsstatd
|
||||
mon_tools/mon_procd
|
||||
opticsmon/opticsmon
|
||||
opticsmon/_opticsmon
|
||||
opticsmon/opticsmon.bash
|
||||
zpcimon/zpcimon
|
||||
zpcimon/zpcimon.bash
|
||||
zpcimon/_zpcimon
|
||||
zpcimon/opticsmon.bash
|
||||
zpcimon/_opticsmon
|
||||
osasnmpd/osasnmpd
|
||||
qetharp/qetharp
|
||||
qethqoat/qethqoat
|
||||
|
||||
58
CHANGELOG.md
58
CHANGELOG.md
@@ -1,6 +1,64 @@
|
||||
Release history for s390-tools (MIT version)
|
||||
--------------------------------------------
|
||||
|
||||
* __v2.44.0 (2026-07-31)__
|
||||
|
||||
For Linux kernel version: 7.2
|
||||
|
||||
Changes of existing tools / libraries:
|
||||
- create-sehdr: Enable quantum safe keys usage
|
||||
- dbginfo.sh: Let zpcimon log both optical module and SMART data
|
||||
- libutil/util_fmt: Add util_fmt_type_to_name()
|
||||
- nvmemon: Skip SCLP on NVMes with non-IBM subsystem vendor ID
|
||||
- opticsmon: zpcimon: Rename opticsmon to zpcimon
|
||||
- pvattest: Enable quantum safe keys usage
|
||||
- pvimg: Add '--flags <...>' and '--disable-flags <...>' option
|
||||
- pvimg: Enable quantum safe keys usage
|
||||
- pvsecret: Enable quantum safe keys usage
|
||||
- pvverify: Enable quantum safe keys usage
|
||||
- zmemtopo: Add CLI option to filter partitions by name
|
||||
- zpcimon: Allow setting output format using --format CLI option
|
||||
- zpcimon: Monitor for hotplug of NVMes to trigger SMART collection
|
||||
|
||||
Bug Fixes:
|
||||
- opticsmon: Fix wrong size check for OPTICS_QSFP28_LOS_IMPLEMENTED_OFFSET
|
||||
- opticsmon: Handle error return of ethtool_nl_connect()
|
||||
- opticsmon: Fix error path free of struct optics in ethtool_nl_get_optics()
|
||||
- opticsmon: Close epoll fd in monitor_wait_loop()
|
||||
- opticsmon: Fix wrong JSON print for tx_fault
|
||||
|
||||
* __v2.43.1 (2026-07-22)__
|
||||
|
||||
For Linux kernel version: 7.1
|
||||
|
||||
Changes of existing tools:
|
||||
- dasdfmt: Check disk type before prompting for blocksize
|
||||
- iucvterm/ts-shell: Introduce config parameter to specify iucvconn binary
|
||||
- iucvterm/ts-shell: Introduce pager config to replace env variable
|
||||
- pv: Add root CA organization pinning to certificate verification
|
||||
- zdump/ngdump: Use OpenSSL's SHA256 to compute digest of dump image
|
||||
|
||||
Bug Fixes:
|
||||
- 95sel-ebc: Add udev-settle dependency
|
||||
- 95sel-ebc: Add umount to boot service
|
||||
- 95sel-ebc: Harden boot mount service
|
||||
- fdasd: Fix memory leak in yes_no() function
|
||||
- iucvterm/iucvtty: Ensure PTY and server fd's are closed at exec
|
||||
- iucvterm/iucvtty: Prevent connection stalls when receiving TERM env
|
||||
- iucvterm/iucvtty: Validate TERM environment name
|
||||
- libkmipclient: Protect from symlink-following attacks
|
||||
- libkmipclient: Various bugfixes
|
||||
- libseckey: Protect from symlink-following attacks
|
||||
- libseckey: Various bugfixes
|
||||
- mon_procd: Fix possible static buffer overflow
|
||||
- osasnmpd: Fix SNMP non-compliance
|
||||
- zdev: Harden against invalid udev, import, firmware, or hypervisor data
|
||||
- zipl-editenv: Check in-bootmap environment block validity
|
||||
- zipl/boot: Check in-bootmap environment block syntax
|
||||
- zipl: Check keyword duplications in BLS entries
|
||||
- zipl: Fix bugs in mirror support
|
||||
- zkey: Protect from symlink-following attacks
|
||||
|
||||
* __v2.43.0 (2026-06-25)__
|
||||
|
||||
For Linux kernel version: 7.1
|
||||
|
||||
2
Makefile
2
Makefile
@@ -15,7 +15,7 @@ TOOL_DIRS = zipl zdump fdasd dasdfmt dasdview tunedasd \
|
||||
vmcp man mon_tools dasdinfo vmur cpuplugd ipl_tools \
|
||||
ziomon iucvterm hyptop cmsfs-fuse qethqoat zfcpdump zdsfs cpumf \
|
||||
systemd hmcdrvfs cpacfstats zdev dump2tar zkey netboot etc zpcictl \
|
||||
lsstp hsci hsavmcore chreipl-fcp-mpath ap_tools rust opticsmon \
|
||||
lsstp hsci hsavmcore chreipl-fcp-mpath ap_tools rust zpcimon \
|
||||
zpwr zmemtopo
|
||||
|
||||
else
|
||||
|
||||
17
README.md
17
README.md
@@ -316,7 +316,7 @@ build options:
|
||||
| glibc-static | `HAVE_LIBC_STATIC` | zfcpdump |
|
||||
| openssl | `HAVE_OPENSSL` | zkey, libekmfweb, libkmipclient, |
|
||||
| | | zgetdump, rust/pvattest, rust/pvimg, |
|
||||
| | | zgetdump/pvsecret, opticsmon |
|
||||
| | | zgetdump/pvsecret, zpcimon |
|
||||
| cryptsetup | `HAVE_CRYPTSETUP2` | zkey-cryptsetup |
|
||||
| json-c | `HAVE_JSONC` | zkey-cryptsetup, libekmfweb, |
|
||||
| | | libkmipclient |
|
||||
@@ -325,8 +325,9 @@ build options:
|
||||
| | | rust/pvattest, rust/pvsecret, |
|
||||
| libxml2 | `HAVE_LIBXML2` | libkmipclient |
|
||||
| systemd | `HAVE_SYSTEMD` | hsavmcore |
|
||||
| libudev | `HAVE_LIBUDEV` | cpacfstatsd |
|
||||
| libnl3 | `HAVE_LIBNL3` | opticsmon |
|
||||
| libudev | `HAVE_LIBUDEV` | cpacfstatsd, zpcimon |
|
||||
| libnl3 | `HAVE_LIBNL3` | zpcimon |
|
||||
| libnvme | `HAVE_LIBNVME` | zpcimon |
|
||||
|
||||
This table lists additional build or install options:
|
||||
|
||||
@@ -374,11 +375,11 @@ the different tools are provided:
|
||||
|
||||
The runtime requirements are: openssl-libs (>= 1.1.1) and libcurl.
|
||||
|
||||
* opticsmon:
|
||||
For building opticsmon OpenSSL and the Netlink Library Suite (libnl3) are
|
||||
required.
|
||||
Tip: you may skip the opticsmon build by adding
|
||||
`HAVE_OPENSSL=0` or `HAVE_LIBNL3=0`
|
||||
* zpcimon:
|
||||
For building zpcimon OpenSSL, the Netlink Library Suite (libnl3),
|
||||
and libnvme are required.
|
||||
Tip: you may skip the zpcimon build by adding
|
||||
`HAVE_OPENSSL=0` or `HAVE_LIBNL3=0` or `HAVE_LIBNVME=0`.
|
||||
|
||||
* osasnmpd:
|
||||
You need at least the NET-SNMP 5.1.x package (net-snmp-devel.rpm)
|
||||
|
||||
@@ -713,7 +713,7 @@ static int readdir_entry(struct fst_entry *fst, off_t addr)
|
||||
*/
|
||||
static inline int strip_right(const char *str, int size)
|
||||
{
|
||||
while (str[size - 1] == 0x20)
|
||||
while (size > 0 && str[size - 1] == 0x20)
|
||||
size--;
|
||||
return size;
|
||||
}
|
||||
|
||||
@@ -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 := 43
|
||||
RELEASE := 44
|
||||
PATCHLEVEL := 0
|
||||
DISTRELEASE := build-$(shell date +%Y%m%d)
|
||||
S390_TOOLS_RELEASE := $(VERSION).$(RELEASE).$(PATCHLEVEL)-$(DISTRELEASE)
|
||||
|
||||
@@ -1566,6 +1566,8 @@ int main(int argc, char *argv[])
|
||||
g.ese = dasd_sys_ese(g.dev_node);
|
||||
eval_format_mode();
|
||||
|
||||
check_disk();
|
||||
|
||||
/* Either let the user specify the blksize or get it from the kernel */
|
||||
if (!g.blksize_specified) {
|
||||
if (!(mode == FULL ||
|
||||
@@ -1587,8 +1589,6 @@ int main(int argc, char *argv[])
|
||||
error("VOLSER not found on device %s", g.dev_path);
|
||||
}
|
||||
|
||||
check_disk();
|
||||
|
||||
if (check_param(str, ERR_LENGTH, &format_params) < 0)
|
||||
error("%s", str);
|
||||
|
||||
|
||||
@@ -387,20 +387,28 @@ static int yes_no(char *question_str)
|
||||
ssize_t bytes_read;
|
||||
char *answer;
|
||||
size_t size;
|
||||
int rc;
|
||||
|
||||
size = 0;
|
||||
answer = NULL;
|
||||
while (1) {
|
||||
printf("%s (y/n): ", question_str);
|
||||
bytes_read = getline(&answer, &size, stdin);
|
||||
if (bytes_read < 0)
|
||||
return -1;
|
||||
if (answer[0] == 'y')
|
||||
return 0;
|
||||
if (answer[0] == 'n')
|
||||
return 1;
|
||||
if (bytes_read < 0) {
|
||||
rc = -1;
|
||||
break;
|
||||
}
|
||||
if (answer[0] == 'y') {
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
if (answer[0] == 'n') {
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(answer);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static char *fdasd_partition_type(char *dsname)
|
||||
|
||||
@@ -514,7 +514,7 @@ static int hmcdrv_path_copy(struct hmcdrv_fuse_file *fp, char *dest)
|
||||
char *src = HMCDRV_FUSE_PATH(fp);
|
||||
int len = 0;
|
||||
|
||||
while ((len < (HMCDRV_FUSE_MAXPATH - 1)) &&
|
||||
while ((len < (HMCDRV_FUSE_MAXPATH - 2)) &&
|
||||
(*src != '\0')) {
|
||||
|
||||
*dest = *src;
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
|
||||
#include "util_list.h"
|
||||
|
||||
#define PCI_BDF_LEN 13 /* DDDD:BB:dd.f\0 */
|
||||
#define PCI_VENDOR_ID_IBM 0x1014
|
||||
|
||||
enum zpci_pft {
|
||||
ZPCI_PFT_UNCLASSIFIED = 0x00,
|
||||
|
||||
@@ -65,6 +68,9 @@ struct zpci_dev {
|
||||
bool uid_is_unique;
|
||||
/* Configuration state 0 - Standby, 1 Configured */
|
||||
bool conf;
|
||||
/* Common PCI attributes */
|
||||
uint16_t subsystem_vendor;
|
||||
uint16_t subsystem_device;
|
||||
|
||||
/* Associated netdevs if any */
|
||||
int num_netdevs;
|
||||
@@ -96,4 +102,6 @@ operstate_t zpci_operstate_from_str(const char *oper_str);
|
||||
struct zpci_dev *zpci_find_by_netdev(struct util_list *zpci_list, char *netdev_name,
|
||||
struct zpci_netdev **netdev);
|
||||
|
||||
char *zpci_get_nvme_device_node(const char *pci_addr);
|
||||
|
||||
#endif /* LIB_ZPCI_PCI_LIST_H */
|
||||
|
||||
@@ -21,9 +21,11 @@
|
||||
#define SCLP_ERRNOTIFY_AQ_DECONF 1
|
||||
#define SCLP_ERRNOTIFY_AQ_REPORT_ERR 2
|
||||
#define SCLP_ERRNOTIFY_AQ_OPTICS_DATA 3
|
||||
#define SCLP_ERRNOTIFY_AQ_NVME_SMART_DATA 4
|
||||
|
||||
#define SCLP_ERRNOTIFY_ID_ZPCICTL 0x4713
|
||||
#define SCLP_ERRNOTIFY_ID_OPTICSMON 0x4714
|
||||
#define SCLP_ERRNOTIFY_ID_NVMEMON 0x4715
|
||||
|
||||
#define SCLP_ERRNOTIFY_DATA_SIZE 4054
|
||||
|
||||
|
||||
@@ -157,6 +157,16 @@ void util_fmt_exit(void);
|
||||
*/
|
||||
bool util_fmt_name_to_type(const char *name, enum util_fmt_t *type);
|
||||
|
||||
/**
|
||||
* util_fmt_type_to_name() - Get name of given format type identifier.
|
||||
* @type: Format type identifier
|
||||
*
|
||||
* Get the name corresponding to the given format type identifier.
|
||||
*
|
||||
* Return: name of the format type
|
||||
*/
|
||||
const char *util_fmt_type_to_name(enum util_fmt_t type);
|
||||
|
||||
/**
|
||||
* util_fmt_set_indent() - Set indentation parameters.
|
||||
* @base : Base indentation level to apply to all output lines (default 0)
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
#define MSEC_PER_SEC 1000L
|
||||
|
||||
#define SEC_PER_DAY (24 * 60 * 60)
|
||||
|
||||
/**
|
||||
* Convert nanoseconds to microseconds
|
||||
*
|
||||
|
||||
@@ -72,6 +72,11 @@
|
||||
#define __section(x) __attribute__((__section__(#x)))
|
||||
#define __noinline __attribute__((__noinline__))
|
||||
#define __big_endian
|
||||
#ifdef __CHECKER__
|
||||
# define __force __attribute__((force))
|
||||
#else
|
||||
# define __force
|
||||
#endif
|
||||
/* The Linux kernel (in stddef.h) and glibc (sys/cdefs.h) define
|
||||
* __always_inline. Therefore undefine it first to allow the headers
|
||||
* to be included first.
|
||||
|
||||
@@ -14,14 +14,19 @@ use strict;
|
||||
use warnings;
|
||||
use File::Basename;
|
||||
use Getopt::Long qw(:config no_ignore_case);
|
||||
use Scalar::Util qw(tainted);
|
||||
use Term::ReadLine;
|
||||
use POSIX;
|
||||
|
||||
$ENV{'PERL5LIB'} = "";
|
||||
$ENV{'PERL5OPT'} = "";
|
||||
$ENV{'PERLLIB'} = "";
|
||||
$ENV{'PERL_USE_UNSAFE_INC'} = "";
|
||||
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
|
||||
|
||||
$ENV{'PERL_RL'} = " o=0"; # use best avail. readline
|
||||
$ENV{'PATH'} = "/bin:/sbin:/usr/bin:/usr/sbin";
|
||||
$ENV{'LESSSECURE'} = 1; # let less run in "secure" mode
|
||||
$ENV{'PAGER'} = $ENV{'PAGER'} || "/usr/bin/less";
|
||||
my $ts_shell = fileparse($0, qr/\.[^.]+/);
|
||||
$SIG{__WARN__} = sub { print STDERR "$ts_shell: $_[0]"; };
|
||||
$SIG{__DIE__} = sub { print STDERR "$ts_shell: $_[0]"; exit 255; };
|
||||
@@ -36,6 +41,7 @@ my %config = (
|
||||
'auditdir' => "@var_path@/log/ts-shell",
|
||||
'iucvconn' => "@iucvconn_path@/iucvconn",
|
||||
'prompt' => getpwuid($>) . '@'."$ts_shell> ",
|
||||
'pager' => "/usr/bin/less",
|
||||
# runtime options
|
||||
'rl' => undef, # terminal readline (rl)
|
||||
'user' => getpwuid($>), # user name
|
||||
@@ -65,6 +71,7 @@ sub cmd_list(\%);
|
||||
sub rl_cmd_completion($$$);
|
||||
sub list_regex_match($);
|
||||
sub updateConfiguration(\%$);
|
||||
sub checkConfiguration(\%);
|
||||
sub loadAuthorization(\%);
|
||||
sub readFile($$);
|
||||
sub log_debug($);
|
||||
@@ -103,6 +110,7 @@ sub main()
|
||||
"$config{conffile} failed: $!";
|
||||
exit 3;
|
||||
}
|
||||
checkConfiguration(%config);
|
||||
|
||||
# load list of systems the ts-shell is allowed to use; and
|
||||
# hash the systems names in uppercase
|
||||
@@ -185,11 +193,50 @@ sub updateConfiguration(\%$)
|
||||
{
|
||||
my ($cfg, $line) = @_;
|
||||
my ($option, $value) = split /\s*=\s*/, $line;
|
||||
|
||||
|
||||
$cfg->{sysfile} = $value if $option =~ /^ts-systems$/;
|
||||
$cfg->{authfile} = $value if $option =~ /^ts-authorization$/;
|
||||
$cfg->{auditdir} = $value if $option =~ /^transcript-directory$/;
|
||||
$cfg->{auditfile} = $value if $option =~ /^transcript-systems$/;
|
||||
$cfg->{pager} = $value if $option =~ /^pager$/;
|
||||
$cfg->{iucvconn} = $value if $option =~ /^iucvconn$/;
|
||||
}
|
||||
|
||||
# checkConfiguration() - Validate and untaint configuration values
|
||||
#
|
||||
# Called once after readFile() has finished populating %cfg from
|
||||
# ts-shell.conf. Validates each security-sensitive path and untaints
|
||||
# it via a regex capture so Perl taint mode permits later filesystem use.
|
||||
#
|
||||
# %cfg: Hash reference to terminal server configuration
|
||||
#
|
||||
sub checkConfiguration(\%)
|
||||
{
|
||||
my $cfg = shift;
|
||||
|
||||
# Validate pager to untaint for later use
|
||||
unless ($cfg->{pager} =~ m#^(/[\w./-]+)$#) {
|
||||
log_error "Invalid pager configuration";
|
||||
exit 6;
|
||||
}
|
||||
$cfg->{pager} = $1;
|
||||
|
||||
# Validate iucvconn path to untaint for later use
|
||||
unless ($cfg->{iucvconn} =~ m#^(/[\w./-]+)$#) {
|
||||
log_error "Invalid iucvconn configuration";
|
||||
exit 7;
|
||||
}
|
||||
$cfg->{iucvconn} = $1;
|
||||
|
||||
# Validate transcript-directory to untaint for later use
|
||||
unless ($cfg->{auditdir} =~ m#^(/[\w./-]+)$#) {
|
||||
log_error "Invalid transcript-directory configuration";
|
||||
exit 8;
|
||||
}
|
||||
$cfg->{auditdir} = $1;
|
||||
|
||||
# Untaint user name (tainted by getpwuid) for use in filesystem paths
|
||||
($cfg->{user}) = ($cfg->{user} =~ /^([\w.-]+)$/);
|
||||
}
|
||||
|
||||
# loadAuthorization() - Load system authorizations from file
|
||||
@@ -205,7 +252,7 @@ sub loadAuthorization(\%)
|
||||
{
|
||||
my $cfg = shift();
|
||||
|
||||
return 0 unless open(AUTH, "<$cfg->{authfile}");
|
||||
return 0 unless open(AUTH, "<", $cfg->{authfile});
|
||||
|
||||
AUTH_ENT: while (<AUTH>) {
|
||||
chomp;
|
||||
@@ -217,13 +264,13 @@ sub loadAuthorization(\%)
|
||||
my ($key, $val) = split /\s*=\s*/;
|
||||
|
||||
# read authorization configuration for user and its groups
|
||||
if ($key =~ /^$cfg->{user}$/) {
|
||||
if ($key =~ /^\Q$cfg->{user}\E$/) {
|
||||
$authorized = 1;
|
||||
log_debug "Found user: $key";
|
||||
|
||||
} elsif ($key =~ /^@(\S+)$/) {
|
||||
my $group = $1;
|
||||
$authorized = 1 if grep {/^${group}$/} @{$cfg->{groups}};
|
||||
$authorized = 1 if grep {/^\Q${group}\E$/} @{$cfg->{groups}};
|
||||
log_debug "Found group: $key" if $authorized;
|
||||
}
|
||||
|
||||
@@ -303,7 +350,7 @@ sub readFile($$)
|
||||
{
|
||||
my ($file, $sub) = @_;
|
||||
|
||||
return 0 unless open(CONF, "<$file");
|
||||
return 0 unless open(CONF, "<", "$file");
|
||||
while (<CONF>) {
|
||||
chomp;
|
||||
next if /^#/; # ignore comments
|
||||
@@ -392,7 +439,15 @@ sub get_auditlog_file($$$)
|
||||
}
|
||||
}
|
||||
|
||||
$$filepath = "$cfg->{auditdir}/$cfg->{user}/" . uc $guest . "_";
|
||||
# validate and sanitize guest directory
|
||||
$guest = uc $guest;
|
||||
unless ($guest =~ /^([A-Z0-9@#\$_-]{1,8})$/) {
|
||||
log_error "Creating session file path failed for guest: $guest";
|
||||
return 0; # return error
|
||||
}
|
||||
|
||||
# construct the file path
|
||||
$$filepath = "$cfg->{auditdir}/$cfg->{user}/" . $guest . "_";
|
||||
$$filepath .= strftime '%F-%H%M%S', localtime;
|
||||
|
||||
log_debug "Session transcript file: $$filepath";
|
||||
@@ -416,7 +471,7 @@ sub cmd_connect($\%)
|
||||
}
|
||||
|
||||
my ($guest, $srv) = split /\s+/, $params;
|
||||
$service = $srv if $srv && $srv =~ /\w{1,8}/;
|
||||
$service = $srv if $srv && $srv =~ /^\w{1,8}$/;
|
||||
|
||||
# check authorization:
|
||||
# The auth_func contract is to return a code, that must be one of:
|
||||
@@ -482,7 +537,7 @@ sub cmd_service($\%)
|
||||
return;
|
||||
}
|
||||
|
||||
if ($new =~ /\w{1,8}/) {
|
||||
if ($new =~ /^\w{1,8}$/) {
|
||||
$cfg->{service} = $new;
|
||||
# push new service for cmd completion
|
||||
unless (grep /$new/, @{$cfg->{services}}) {
|
||||
@@ -545,7 +600,7 @@ sub pager($)
|
||||
{
|
||||
my $eval = shift();
|
||||
|
||||
unless (open(PAGER, "|$ENV{'PAGER'}")) {
|
||||
unless (open(PAGER, '|-', "$config{'pager'}")) {
|
||||
eval &$eval;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
.\" SPDX-License-Identifier: MIT
|
||||
.\"
|
||||
.\" ts-shell.1
|
||||
.\"
|
||||
.\"
|
||||
.\" Copyright IBM Corp. 2008, 2017
|
||||
.\" s390-tools is free software; you can redistribute it and/or modify
|
||||
.\" it under the terms of the MIT license. See LICENSE for details.
|
||||
.\" Copyright IBM Corp.
|
||||
.\" ----------------------------------------------------------------------
|
||||
.TH "ts-shell" "1" "March 2009" "s390-tools" "Terminal Server over IUCV"
|
||||
.
|
||||
@@ -269,6 +268,10 @@ session transcripts are saved.
|
||||
|
||||
See section "Configure terminal session transcripts" for details.
|
||||
.
|
||||
.TP
|
||||
.BR pager " = " \fI/usr/bin/less\fP
|
||||
Specifies the path to a pager program to paginate output of ts-shell commands.
|
||||
.
|
||||
.RE
|
||||
.
|
||||
.
|
||||
@@ -542,14 +545,6 @@ Directory for saving terminal session transcripts.
|
||||
.
|
||||
.SH "ENVIRONMENT"
|
||||
.TP
|
||||
.B PAGER
|
||||
The \fBPAGER\fP environment variable designates a program used as pager for the
|
||||
\fBlist\fP command of the terminal server shell.
|
||||
If \fBPAGER\fP is not set or empty,
|
||||
.BR less (1)
|
||||
is used.
|
||||
.
|
||||
.TP
|
||||
.B LESSSECURE
|
||||
\fBts-shell\fP sets this variable to run
|
||||
.BR less (1)
|
||||
|
||||
@@ -2,6 +2,12 @@
|
||||
#
|
||||
# See ts-shell(1) manual page for file format syntax.
|
||||
|
||||
# Generic settings
|
||||
# ----------------
|
||||
|
||||
# pager
|
||||
# binary to paginate output (default: less)
|
||||
#pager = /usr/bin/less
|
||||
|
||||
# System and authorization settings
|
||||
# ---------------------------------
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
/* Message buffer: message header + 4096 bytes of data */
|
||||
#define MSG_BUFFER_SIZE (MSG_DATA_OFFSET + (4096))
|
||||
|
||||
/* Message data sizes */
|
||||
#define MAX_TERM_SIZE 256
|
||||
|
||||
/* Error macros */
|
||||
#define print_error(s) program_error(PRG_COMPONENT, (s))
|
||||
#define iucvtty_error(m) \
|
||||
@@ -55,13 +58,14 @@ extern int iucvtty_read_data(int, struct iucvtty_msg *, size_t);
|
||||
|
||||
extern int iucvtty_read_msg(int, struct iucvtty_msg *, size_t, size_t *);
|
||||
extern int iucvtty_write_msg(int, struct iucvtty_msg *);
|
||||
extern void iucvtty_skip_msg_residual(int, size_t *);
|
||||
extern void iucvtty_skip_msg_chunk(int, size_t *);
|
||||
|
||||
extern ssize_t __write(int, const void*, size_t);
|
||||
|
||||
extern int strmatch(const char *, const char *);
|
||||
extern int is_regex_valid(const char *);
|
||||
extern int is_client_allowed(const char *, const struct iucvterm_cfg *);
|
||||
extern int is_term_valid(const char *term, size_t len);
|
||||
extern void userid_cpy(char [9], const char [8]);
|
||||
|
||||
extern void iucv_msg_error(const char *, uint32_t);
|
||||
|
||||
@@ -86,7 +86,7 @@ static inline struct iucvtty_msg *msg_alloc(uint8_t type, uint16_t size)
|
||||
{
|
||||
struct iucvtty_msg *m;
|
||||
|
||||
m = malloc(size + MSG_DATA_OFFSET);
|
||||
m = calloc(1, size + MSG_DATA_OFFSET);
|
||||
if (m != NULL) {
|
||||
m->version = MSG_VERSION;
|
||||
m->type = type;
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
* s390-tools is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <regex.h>
|
||||
#include <stdio.h>
|
||||
@@ -36,7 +38,7 @@
|
||||
* @len: Buffer length
|
||||
*
|
||||
* Write @len number of bytes from the buffer @buf to the file
|
||||
* descriptor @fd. The routines handles EINTR and partially writes.
|
||||
* descriptor @fd. The routine handles EINTR and partial writes.
|
||||
* Returns the error code from the underlying write(2) syscall.
|
||||
*/
|
||||
ssize_t __write(int fd, const void *buf, size_t len)
|
||||
@@ -55,6 +57,33 @@ ssize_t __write(int fd, const void *buf, size_t len)
|
||||
return written;
|
||||
}
|
||||
|
||||
/**
|
||||
* __read() - Read data
|
||||
* @fd: File descriptor
|
||||
* @buf: Pointer to data buffer
|
||||
* @len: Buffer size
|
||||
*
|
||||
* Read up to @len number of bytes from file descriptor @fd and stores them
|
||||
* in the buffer to which @buf points.
|
||||
* The routine handles EINTR and partial reads and returns the error code
|
||||
* from the underlying read(2) syscall.
|
||||
*/
|
||||
ssize_t __read(int fd, void *buf, size_t len)
|
||||
{
|
||||
ssize_t rc;
|
||||
size_t count = 0;
|
||||
|
||||
while (count < len) {
|
||||
rc = read(fd, buf + count, len - count);
|
||||
if (rc == -1 && errno == EINTR)
|
||||
continue;
|
||||
if (rc <= 0)
|
||||
return rc;
|
||||
count += rc;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
#ifdef __DEBUG__
|
||||
static void __dump_msg(int fd, const struct iucvtty_msg *m, char dir)
|
||||
{
|
||||
@@ -116,14 +145,16 @@ int iucvtty_tx_termenv(int dest, char *dflt)
|
||||
|
||||
len = 0;
|
||||
if (term != NULL)
|
||||
len = 1 + strlen(term);
|
||||
len = MIN(1 + strlen(term), (size_t)MAX_TERM_SIZE);
|
||||
|
||||
/* Note: The server console tool waits for terminal environment
|
||||
* information: the message is sent even if it is empty */
|
||||
msg = msg_alloc(MSG_TYPE_TERMENV, len);
|
||||
if (msg == NULL)
|
||||
return -1;
|
||||
msg_cpy_from(msg, term, len);
|
||||
msg->datalen = len;
|
||||
if (msg->datalen)
|
||||
snprintf((char *)msg->data, msg->datalen, "%s", term);
|
||||
rc = iucvtty_write_msg(dest, msg);
|
||||
msg_free(msg);
|
||||
|
||||
@@ -146,12 +177,14 @@ int iucvtty_rx_termenv(int fd, void *buf, size_t len)
|
||||
return -1;
|
||||
skip = 0;
|
||||
rc = iucvtty_read_msg(fd, msg, msg_size(msg), &skip);
|
||||
iucvtty_skip_msg_residual(fd, &skip);
|
||||
iucvtty_skip_msg_chunk(fd, &skip);
|
||||
if (!rc) {
|
||||
if (msg->datalen == 0)
|
||||
if (msg->datalen == 0) {
|
||||
memset(buf, 0, MIN(1u, len));
|
||||
else
|
||||
} else {
|
||||
msg_cpy_to(msg, buf, len);
|
||||
memset(buf + MIN(msg->datalen, len - 1), 0, 1);
|
||||
}
|
||||
}
|
||||
msg_free(msg);
|
||||
return rc;
|
||||
@@ -262,93 +295,175 @@ int iucvtty_copy_data(int dest, struct iucvtty_msg *msg)
|
||||
}
|
||||
|
||||
/**
|
||||
* iucvtty_skip_msg_residual() - Skip (receive & forget) count number of bytes
|
||||
* iucvtty_skip_msg_chunk() - Skip (receive & forget) count number of bytes
|
||||
* @fd: File descriptor
|
||||
* @residual: Residual of an iucv tty message received by iucvtty_read_msg()
|
||||
* @chunk: Remaining chunk from a previous iucvtty_read_msg() call
|
||||
*
|
||||
* See iucvtty_read_msg() for an explanation when to use this routine.
|
||||
* Note: The @residual parameter shall not be NULL.
|
||||
* Note: The @chunk parameter must not be NULL.
|
||||
*/
|
||||
void iucvtty_skip_msg_residual(int fd, size_t *residual)
|
||||
void iucvtty_skip_msg_chunk(int fd, size_t *chunk)
|
||||
{
|
||||
char b;
|
||||
size_t i;
|
||||
int r;
|
||||
char buf[256];
|
||||
|
||||
if (*residual <= 0)
|
||||
if (*chunk <= 0)
|
||||
return;
|
||||
for (i = 0; i < *residual; i++)
|
||||
if (read(fd, &b, 1) <= 0)
|
||||
|
||||
while (*chunk) {
|
||||
r = __read(fd, buf, MIN(sizeof(buf), *chunk));
|
||||
if (r <= 0)
|
||||
break;
|
||||
*residual = 0;
|
||||
*chunk -= r;
|
||||
}
|
||||
|
||||
*chunk = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* iucvtty_read_msg_chunk() - Read IUCV message chunk
|
||||
* @fd: File descriptor to read from
|
||||
* @msg: Pointer to IUCV message buffer
|
||||
* @msglen: IUCV message buffer size (including message header)
|
||||
* @chunk: Size of chunk data to read
|
||||
*
|
||||
* Stores new message data and calculates next chunk size if not all data
|
||||
* could be read. Returns zero on success, non-zero otherwise.
|
||||
*/
|
||||
static int iucvtty_read_msg_chunk(int fd, struct iucvtty_msg *msg,
|
||||
size_t msglen, size_t *chunk)
|
||||
{
|
||||
ssize_t r;
|
||||
size_t datalen;
|
||||
|
||||
/* Calculate message data length to read */
|
||||
datalen = MIN(msglen - MSG_DATA_OFFSET, *chunk);
|
||||
|
||||
for (;;) {
|
||||
r = read(fd, msg->data, datalen);
|
||||
if (r == -1 && errno == EINTR)
|
||||
continue;
|
||||
if (r <= 0)
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Update message and re-calculate next chunk */
|
||||
msg->datalen = r;
|
||||
*chunk -= r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* validate_msg() - Perform sanity checks on a received message
|
||||
* @msg: IUCV message buffer
|
||||
*
|
||||
* Returns zero if the message is valid; otherwise non-zero
|
||||
*/
|
||||
static int validate_msg(struct iucvtty_msg *msg)
|
||||
{
|
||||
switch (msg->type) {
|
||||
case MSG_TYPE_DATA:
|
||||
/* The datalen ranges from 0 to its maximum of 0xffff
|
||||
* which is the maximum of the type definition of uint16_t.
|
||||
*
|
||||
* Consider the datalen value as valid.
|
||||
*/
|
||||
break;
|
||||
case MSG_TYPE_ERROR:
|
||||
if (msg->datalen != sizeof(uint32_t))
|
||||
return 1;
|
||||
break;
|
||||
case MSG_TYPE_TERMENV:
|
||||
if (msg->datalen > MAX_TERM_SIZE)
|
||||
return 1;
|
||||
break;
|
||||
case MSG_TYPE_TERMIOS: /* ignored */
|
||||
break;
|
||||
case MSG_TYPE_WINSIZE:
|
||||
if (msg->datalen != sizeof(struct winsize))
|
||||
return 1;
|
||||
break;
|
||||
default:
|
||||
/* Invalid message type */
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* iucvtty_read_msg() - Read/Receive an IUCV message
|
||||
* @fd: File descriptor to read from
|
||||
* @msg: Pointer to IUCV message buffer
|
||||
* @len: IUCV message data len
|
||||
* @residual: Status to be used by next call
|
||||
* @msglen: IUCV message buffer size (MUST BE > MSG_DATA_OFFSET)
|
||||
* @chunk: Size of remaining data; must be passed on next call
|
||||
*
|
||||
* The function reads up to @len bytes from file descriptor @fd.
|
||||
* If the received message is larger than @len bytes, the @residual value
|
||||
* is set to the number of bytes remaining.
|
||||
* The function shall then be re-called to create a new message and receive
|
||||
* the next chunk of size @residual; or the remaining characters must be
|
||||
* skipped using the iucvtty_skip_msg() routine.
|
||||
* Note: The @len parameter shall be greater than MSG_DATA_OFFSET.
|
||||
* The @residual parameter shall not be NULL.
|
||||
* The function reads up to @len bytes from file descriptor @fd. If the
|
||||
* received message is larger than @len bytes, the @chunk value is set to
|
||||
* the number of remaining bytes. The function shall then be re-called to
|
||||
* create a new message and receive the outstanding data. Alternatively,
|
||||
* call iucvtty_skip_msg_chunk() to discard remaining data.
|
||||
*
|
||||
* NOTE: The @len parameter must be greater than MSG_DATA_OFFSET!
|
||||
* The @chunk parameter must not be NULL.
|
||||
*/
|
||||
int iucvtty_read_msg(int fd, struct iucvtty_msg *msg,
|
||||
size_t len, size_t *residual)
|
||||
size_t msglen, size_t *chunk)
|
||||
{
|
||||
int rc;
|
||||
ssize_t r; /* number of bytes read from fd */
|
||||
|
||||
if (*residual)
|
||||
len = MIN(len - MSG_DATA_OFFSET, *residual);
|
||||
/* Ensure message buffer size can hold data and can be processed */
|
||||
assert(msglen > MSG_DATA_OFFSET);
|
||||
assert(chunk != NULL);
|
||||
|
||||
while (1) {
|
||||
if (*residual) {
|
||||
r = read(fd, msg->data, len);
|
||||
if (r > 0)
|
||||
msg->datalen = r;
|
||||
} else
|
||||
r = read(fd, msg, len);
|
||||
/* Read pending message data */
|
||||
if (*chunk)
|
||||
return iucvtty_read_msg_chunk(fd, msg, msglen, chunk);
|
||||
|
||||
if (r == -1 && errno == EINTR)
|
||||
continue;
|
||||
if (r <= 0) {
|
||||
rc = -1;
|
||||
goto out_read_error;
|
||||
}
|
||||
|
||||
break; /* exit loop for a successful read */
|
||||
/* Read message header of new message */
|
||||
r = __read(fd, msg, MSG_DATA_OFFSET);
|
||||
if (r <= 0) {
|
||||
rc = -1;
|
||||
goto out_read_error;
|
||||
}
|
||||
|
||||
#ifdef __DEBUG__
|
||||
if (!*residual)
|
||||
__dump_msg(fd, msg, 'R');
|
||||
__dump_msg(fd, msg, 'R');
|
||||
#endif
|
||||
|
||||
/* (re)calculate next chunk */
|
||||
if (*residual)
|
||||
*residual -= msg->datalen;
|
||||
else
|
||||
if (msg->datalen > (r - MSG_DATA_OFFSET)) {
|
||||
/* calculate pending msg data and update datalen */
|
||||
*residual = msg->datalen - (r - MSG_DATA_OFFSET);
|
||||
msg->datalen = r - MSG_DATA_OFFSET;
|
||||
}
|
||||
|
||||
/* check for a sane message */
|
||||
/* Check message header */
|
||||
if (msg->version != MSG_VERSION) {
|
||||
fprintf(stderr, _("%s: %s\n"),
|
||||
PRG_COMPONENT, _("The version of the received data "
|
||||
"message is not supported\n"));
|
||||
"message is not supported"));
|
||||
fprintf(stderr, "MSG: msg->version=%u msg->type=%u msg->datalen=%u\n",
|
||||
msg->version, msg->type, msg->datalen);
|
||||
rc = -2;
|
||||
goto out_read_error;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
/* Check for an empty message */
|
||||
if (!msg->datalen)
|
||||
return 0;
|
||||
|
||||
/* Check message type and data length */
|
||||
if (validate_msg(msg)) {
|
||||
fprintf(stderr, _("%s: %s\n"),
|
||||
PRG_COMPONENT, _("The received message is invalid"));
|
||||
fprintf(stderr, "MSG: msg->version=%u msg->type=%u msg->datalen=%u\n",
|
||||
msg->version, msg->type, msg->datalen);
|
||||
rc = -3;
|
||||
goto out_read_error;
|
||||
}
|
||||
|
||||
/* Process the new message as a one chunk */
|
||||
*chunk = msg->datalen;
|
||||
msg->datalen = 0;
|
||||
rc = iucvtty_read_msg_chunk(fd, msg, msglen, chunk);
|
||||
|
||||
out_read_error:
|
||||
return rc;
|
||||
}
|
||||
@@ -501,6 +616,31 @@ int is_client_allowed(const char *client, const struct iucvterm_cfg *cfg)
|
||||
return strmatch(client, cfg->client_re);
|
||||
}
|
||||
|
||||
/**
|
||||
* is_term_valid() - Validate TERM environment value
|
||||
* @term: Terminal environment name to validate
|
||||
* @len: Maximum number of characters to validate
|
||||
*/
|
||||
int is_term_valid(const char *term, size_t len)
|
||||
{
|
||||
const char *c;
|
||||
|
||||
if (term == NULL || *term == '\0')
|
||||
return 0;
|
||||
|
||||
for (c = term; *c != '\0'; c++) {
|
||||
if ((size_t)(c - term) >= len)
|
||||
return 0;
|
||||
if (!isalnum((unsigned char)*c) &&
|
||||
*c != '.' &&
|
||||
*c != '_' &&
|
||||
*c != '-')
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* userid_cpy() - Copy z/VM user ID and skip trailing spaces.
|
||||
* @dest: Destination buffer
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <string.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <syslog.h>
|
||||
@@ -32,7 +33,6 @@
|
||||
|
||||
#define SYSLOG_IDENT "iucvtty"
|
||||
#define PRG_COMPONENT SYSLOG_IDENT
|
||||
#define TERM_BUFSIZE 256
|
||||
#define TERM_DEFAULT "linux"
|
||||
|
||||
|
||||
@@ -63,12 +63,46 @@ static int exec_login_prog(char *cmd[])
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* receive_term_env() - receive terminal environment with timeout
|
||||
* @term: Terminal environment variable
|
||||
* @len: Maximum characters for the terminal environment variable
|
||||
*/
|
||||
static void receive_term_env(int client, char *term, size_t len)
|
||||
{
|
||||
struct timeval tv = { .tv_sec = 0, .tv_usec = 0};
|
||||
|
||||
/* Set a temporary timeout of 10s to time out a stalling
|
||||
* client connection. Use SO_RCVTIMEO to set the timeout.
|
||||
* Using those hard coded values directly is safe as
|
||||
* SO_RCVTIMEO is not being used in other parts of iucvtty.
|
||||
*/
|
||||
tv.tv_sec = 10;
|
||||
setsockopt(client, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
|
||||
|
||||
memset(term, 0, len);
|
||||
if (iucvtty_rx_termenv(client, term, len))
|
||||
snprintf(term, len, "%s", TERM_DEFAULT);
|
||||
|
||||
tv.tv_sec = 0;
|
||||
setsockopt(client, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
|
||||
|
||||
if (!is_term_valid(term, len)) {
|
||||
print_error("Ignoring received TERM env due to invalid character(s)");
|
||||
snprintf(term, len, "%s", TERM_DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* iucvtty_worker() - Handle an incoming client connection
|
||||
* @client: Client file descriptor
|
||||
* @master: PTY master file descriptor
|
||||
* @slave: PTY slave file descriptor
|
||||
* @cfg: IUCV TTY configuration structure.
|
||||
*
|
||||
* Unlike the HVC IUCV terminal device driver, iucvtty expects to
|
||||
* receive the TERM environment first. This is necessary to correctly
|
||||
* set up the login program.
|
||||
*/
|
||||
static int iucvtty_worker(int client, int master, int slave,
|
||||
const struct iucvterm_cfg *cfg)
|
||||
@@ -78,15 +112,14 @@ static int iucvtty_worker(int client, int master, int slave,
|
||||
pid_t child;
|
||||
fd_set set;
|
||||
size_t chunk;
|
||||
char term_env[TERM_BUFSIZE];
|
||||
char term_env[MAX_TERM_SIZE];
|
||||
|
||||
|
||||
/* flush pending terminal data */
|
||||
tcflush(master, TCIOFLUSH);
|
||||
|
||||
/* read terminal parameters from client */
|
||||
if (iucvtty_rx_termenv(client, term_env, TERM_BUFSIZE))
|
||||
sprintf(term_env, TERM_DEFAULT);
|
||||
/* read and validate terminal parameters from client */
|
||||
receive_term_env(client, term_env, sizeof(term_env));
|
||||
|
||||
/* start login program */
|
||||
child = fork();
|
||||
@@ -113,6 +146,9 @@ static int iucvtty_worker(int client, int master, int slave,
|
||||
exit(3); /* we only reach here if exec has failed */
|
||||
}
|
||||
|
||||
/* Close slave fd to properly handle SIGHUP for the child process */
|
||||
close(slave);
|
||||
|
||||
/* setup buffers */
|
||||
msg = malloc(MSG_BUFFER_SIZE);
|
||||
if (msg == NULL) {
|
||||
@@ -226,8 +262,13 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
/* set close-on-exec for file descriptors */
|
||||
fcntl(master, F_SETFD, FD_CLOEXEC);
|
||||
fcntl(server, F_SETFD, FD_CLOEXEC);
|
||||
if (fcntl(master, F_SETFD, FD_CLOEXEC) ||
|
||||
fcntl(server, F_SETFD, FD_CLOEXEC)) {
|
||||
print_error("Setting file controls failed");
|
||||
close(server);
|
||||
rc = 1;
|
||||
goto exit_on_error;
|
||||
}
|
||||
|
||||
/* syslog */
|
||||
openlog(SYSLOG_IDENT, LOG_PID, LOG_AUTHPRIV);
|
||||
@@ -240,6 +281,7 @@ int main(int argc, char *argv[])
|
||||
client = accept(server, (struct sockaddr *) &caddr, &len);
|
||||
if (client == -1) {
|
||||
print_error("An incoming connection could not be accepted");
|
||||
close(server);
|
||||
rc = 2;
|
||||
goto exit_on_error;
|
||||
}
|
||||
@@ -256,10 +298,14 @@ int main(int argc, char *argv[])
|
||||
} else { /* client is allowed to connect */
|
||||
syslog(LOG_INFO, "Accepted client connection from %s",
|
||||
client_host);
|
||||
/* set close-on-exec for client socket */
|
||||
fcntl(client, F_SETFD, FD_CLOEXEC);
|
||||
/* close server socket */
|
||||
close(server);
|
||||
/* set close-on-exec for client socket */
|
||||
if (fcntl(client, F_SETFD, FD_CLOEXEC)) {
|
||||
print_error("Setting file controls failed");
|
||||
rc = 4;
|
||||
goto exit_on_error;
|
||||
}
|
||||
|
||||
/* setup signal handler to notify shutdown signal */
|
||||
sigemptyset(&sigact.sa_mask);
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <termio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "iucvterm/functions.h"
|
||||
@@ -114,7 +113,7 @@ static int __testReadWriteMessage_nochunks(int sv[2])
|
||||
if (iucvtty_read_msg(sv[1], msg[1], 6 + MSG_DATA_OFFSET, &residual))
|
||||
return 2;
|
||||
assert(0 == memcmp(msg[1]->data, data, msg[1]->datalen));
|
||||
iucvtty_skip_msg_residual(sv[1], &residual);
|
||||
iucvtty_skip_msg_chunk(sv[1], &residual);
|
||||
assert(0 == residual);
|
||||
/*printf("datalen=%u data='%s'\n",
|
||||
msg[1]->datalen, msg[1]->data);*/
|
||||
@@ -144,7 +143,7 @@ static int __testReadWriteMessage(int sv[2])
|
||||
/* read msg */
|
||||
if (iucvtty_read_msg(sv[1], msg[1], BUF_SIZE, &chunk))
|
||||
return 2;
|
||||
iucvtty_skip_msg_residual(sv[1], &chunk);
|
||||
iucvtty_skip_msg_chunk(sv[1], &chunk);
|
||||
|
||||
/* compare msg */
|
||||
if (__msgcmp(msg[0], msg[1]))
|
||||
|
||||
@@ -233,7 +233,7 @@ static int _ekmf_extract_pubkey(const char *cert, const char *pub_key_pem,
|
||||
goto out;
|
||||
}
|
||||
|
||||
fp = fopen(pub_key_pem, "w");
|
||||
fp = fopen_nofollow(pub_key_pem, "w");
|
||||
if (fp == NULL) {
|
||||
rc = -errno;
|
||||
pr_verbose(verbose, "File '%s': %s", pub_key_pem,
|
||||
@@ -458,7 +458,7 @@ retry:
|
||||
out);
|
||||
|
||||
if (server_cert_pem != NULL) {
|
||||
fp = fopen(server_cert_pem, "w");
|
||||
fp = fopen_nofollow(server_cert_pem, "w");
|
||||
if (fp == NULL) {
|
||||
rc = -errno;
|
||||
pr_verbose(verbose, "File '%s': %s", server_cert_pem,
|
||||
@@ -495,7 +495,7 @@ retry:
|
||||
*/
|
||||
if (ci->num_of_certs > 1 && ca_bundle_pem != NULL &&
|
||||
do_verify == 0) {
|
||||
fp = fopen(ca_bundle_pem, "w");
|
||||
fp = fopen_nofollow(ca_bundle_pem, "w");
|
||||
if (fp == NULL) {
|
||||
rc = -errno;
|
||||
pr_verbose(verbose, "File '%s': %s",
|
||||
@@ -1415,7 +1415,7 @@ int ekmf_login(const struct ekmf_config *config, CURL **curl_handle,
|
||||
while (*tok == ' ')
|
||||
tok++;
|
||||
|
||||
fp = fopen(config->login_token, "w");
|
||||
fp = fopen_nofollow(config->login_token, "w");
|
||||
if (fp == NULL) {
|
||||
rc = -errno;
|
||||
pr_verbose(verbose, "Failed to open file %s: '%s'",
|
||||
@@ -1739,7 +1739,7 @@ int ekmf_get_settings(const struct ekmf_config *config, CURL **curl_handle,
|
||||
if (xts_key2_template != NULL) {
|
||||
*xts_key2_template = _ekmf_find_setting(response_obj,
|
||||
SETTING_ID_XTS_KEY2_TEMPLATE, verbose);
|
||||
if (*identity_template == NULL) {
|
||||
if (*xts_key2_template == NULL) {
|
||||
if (error_msg != NULL) {
|
||||
if (asprintf(error_msg, "The EKMF Web setting "
|
||||
"'XTS Key Template Name (Key 2)' "
|
||||
@@ -1882,8 +1882,9 @@ int ekmf_check_feature(const struct ekmf_config *config, CURL **curl_handle,
|
||||
pr_verbose(verbose, "Feature '%s' is not installed",
|
||||
FEATURE_ID_PERVASIVE_ENCRYPTION);
|
||||
rc = -ENOTSUP;
|
||||
if (asprintf(error_msg, "EKMF Web feature "
|
||||
"'Pervasive Encryption' is not installed.")) {
|
||||
if (error_msg != NULL &&
|
||||
asprintf(error_msg, "EKMF Web feature "
|
||||
"'Pervasive Encryption' is not installed.") < 0) {
|
||||
pr_verbose(verbose, "asprintf failed");
|
||||
rc = -ENOMEM;
|
||||
}
|
||||
@@ -1925,7 +1926,7 @@ static int _ekmf_build_party_info(const char *key_uuid, const char *timestamp,
|
||||
|
||||
if (*party_info_length < (size_t)EVP_MD_size(md)) {
|
||||
pr_verbose(verbose, "Party info buffer is too small");
|
||||
return -ERANGE;
|
||||
rc = -ERANGE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -2219,6 +2220,11 @@ static int _ekmf_import_key(unsigned char *req_sess_key,
|
||||
unsigned char *party_info = NULL;
|
||||
int rc;
|
||||
|
||||
if (resp_party_info_length > SIZE_MAX - req_party_info_length) {
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
party_info_length = req_party_info_length + resp_party_info_length;
|
||||
party_info = malloc(party_info_length);
|
||||
if (party_info == NULL) {
|
||||
@@ -4547,8 +4553,9 @@ out:
|
||||
*/
|
||||
static char *_ekmf_base64_encode(const unsigned char *data, size_t data_size)
|
||||
{
|
||||
int outlen, len;
|
||||
size_t outlen;
|
||||
char *out;
|
||||
int len;
|
||||
|
||||
outlen = (data_size / 3) * 4;
|
||||
if (data_size % 3 > 0)
|
||||
@@ -4559,7 +4566,7 @@ static char *_ekmf_base64_encode(const unsigned char *data, size_t data_size)
|
||||
return NULL;
|
||||
|
||||
len = EVP_EncodeBlock((unsigned char *)out, data, data_size);
|
||||
if (len != outlen) {
|
||||
if (len < 0 || (size_t)len != outlen) {
|
||||
free(out);
|
||||
return NULL;
|
||||
}
|
||||
@@ -4596,7 +4603,7 @@ static int _ekmf_build_key_material(const unsigned char *certificate,
|
||||
"JSON object", verbose, out);
|
||||
|
||||
payload = _ekmf_base64_encode(certificate, certificate_size);
|
||||
JSON_CHECK_ERROR(*keymat_obj == NULL, rc, -EIO,
|
||||
JSON_CHECK_ERROR(payload == NULL, rc, -EIO,
|
||||
"Failed to base64 encode the certificate",
|
||||
verbose, out);
|
||||
|
||||
|
||||
@@ -9,9 +9,11 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/pem.h>
|
||||
@@ -104,7 +106,7 @@ int decode_base64url(unsigned char *output, size_t *outlen,
|
||||
|
||||
len = EVP_DecodeBlock((unsigned char *)padded_output,
|
||||
(unsigned char *)padded_input, padded_inlen);
|
||||
if (len != (int)padded_inlen * 3 / 4) {
|
||||
if ((size_t)len != padded_inlen * 3 / 4) {
|
||||
rc = -EIO;
|
||||
goto out;
|
||||
}
|
||||
@@ -364,9 +366,9 @@ out:
|
||||
*payload_obj = pld;
|
||||
else
|
||||
json_object_put(pld);
|
||||
if (signature != NULL && rc != 0) {
|
||||
free(signature);
|
||||
signature = NULL;
|
||||
if (signature != NULL && *signature != NULL && rc != 0) {
|
||||
free(*signature);
|
||||
*signature = NULL;
|
||||
*signature_len = 0;
|
||||
}
|
||||
if (json != NULL)
|
||||
@@ -1035,7 +1037,7 @@ int clone_tag_def_list(const struct ekmf_tag_def_list *src,
|
||||
if (src->tag_defs[i].description != NULL) {
|
||||
dest->tag_defs[i].description =
|
||||
strdup(src->tag_defs[i].description);
|
||||
if (dest->tag_defs[i].description != NULL) {
|
||||
if (dest->tag_defs[i].description == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
@@ -1931,7 +1933,7 @@ int write_key_blob(const char *filename, unsigned char *key_blob,
|
||||
if (filename == NULL || key_blob == NULL || key_blob_len == 0)
|
||||
return -EINVAL;
|
||||
|
||||
fp = fopen(filename, "w");
|
||||
fp = fopen_nofollow(filename, "w");
|
||||
if (fp == NULL)
|
||||
return -errno;
|
||||
|
||||
@@ -2052,7 +2054,7 @@ int write_x509_certificate(const char *pem_filename, X509 *cert)
|
||||
if (pem_filename == NULL || cert == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
fp = fopen(pem_filename, "w");
|
||||
fp = fopen_nofollow(pem_filename, "w");
|
||||
if (fp == NULL)
|
||||
return -errno;
|
||||
|
||||
@@ -2086,7 +2088,7 @@ int write_x509_request(const char *pem_filename, X509_REQ *req, bool new_hdr)
|
||||
if (pem_filename == NULL || req == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
fp = fopen(pem_filename, "w");
|
||||
fp = fopen_nofollow(pem_filename, "w");
|
||||
if (fp == NULL)
|
||||
return -errno;
|
||||
|
||||
@@ -2154,7 +2156,7 @@ int write_public_key(const char *pem_filename, EVP_PKEY *pkey)
|
||||
if (pem_filename == NULL || pkey == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
fp = fopen(pem_filename, "w");
|
||||
fp = fopen_nofollow(pem_filename, "w");
|
||||
if (fp == NULL)
|
||||
return -errno;
|
||||
|
||||
@@ -2606,3 +2608,33 @@ int json_object_object_add_ex(struct json_object *obj, const char *const key,
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
FILE *fopen_nofollow(const char *path, const char *mode)
|
||||
{
|
||||
int flags = O_NOFOLLOW;
|
||||
int fd;
|
||||
FILE *fp;
|
||||
|
||||
/* Determine flags based on mode */
|
||||
if (mode[0] == 'r')
|
||||
flags |= (mode[1] == '+') ? O_RDWR : O_RDONLY;
|
||||
else if (mode[0] == 'w')
|
||||
flags |= O_CREAT | O_TRUNC |
|
||||
((mode[1] == '+') ? O_RDWR : O_WRONLY);
|
||||
else if (mode[0] == 'a')
|
||||
flags |= O_CREAT | O_APPEND |
|
||||
((mode[1] == '+') ? O_RDWR : O_WRONLY);
|
||||
else
|
||||
return NULL;
|
||||
|
||||
fd = open(path, flags, 0600);
|
||||
if (fd < 0)
|
||||
return NULL;
|
||||
|
||||
fp = fdopen(fd, mode);
|
||||
if (fp == NULL) {
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
@@ -124,4 +124,6 @@ int json_object_object_add_ex(struct json_object *obj, const char *const key,
|
||||
const unsigned int opts);
|
||||
#endif
|
||||
|
||||
FILE *fopen_nofollow(const char *path, const char *mode);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -735,7 +735,8 @@ int kmip_connection_https_perform(struct kmip_connection *conn,
|
||||
switch (conn->config.encoding) {
|
||||
case KMIP_ENCODING_TTLV:
|
||||
rc = kmip_decode_ttlv(write_cb.ttlv.resp_mem_bio, NULL,
|
||||
response, debug);
|
||||
response, KMIP_DECODE_MAX_NESTING_LEVEL,
|
||||
debug);
|
||||
if (rc != 0) {
|
||||
kmip_debug(debug, "kmip_decode_ttlv failed");
|
||||
goto out;
|
||||
@@ -750,7 +751,7 @@ int kmip_connection_https_perform(struct kmip_connection *conn,
|
||||
}
|
||||
|
||||
rc = kmip_decode_json(write_cb.json.resp_obj, NULL, response,
|
||||
debug);
|
||||
KMIP_DECODE_MAX_NESTING_LEVEL, debug);
|
||||
if (rc != 0) {
|
||||
kmip_debug(debug, "kmip_decode_json failed");
|
||||
goto out;
|
||||
@@ -768,7 +769,8 @@ int kmip_connection_https_perform(struct kmip_connection *conn,
|
||||
|
||||
rc = kmip_decode_xml(xmlDocGetRootElement(
|
||||
write_cb.xml.ctx->myDoc),
|
||||
NULL, response, debug);
|
||||
NULL, response,
|
||||
KMIP_DECODE_MAX_NESTING_LEVEL, debug);
|
||||
if (rc != 0) {
|
||||
kmip_debug(debug, "kmip_decode_xml failed");
|
||||
goto out;
|
||||
|
||||
@@ -27,12 +27,16 @@
|
||||
* @param parent the parent node or NULL if no parent exists.
|
||||
* @param node On return: the decoded node. The newly allocated
|
||||
* node has a reference count of 1.
|
||||
* @param max_nesting_level the maximum nesting levels of structures within the
|
||||
* KMIP node. If the nesting level is reached, E2BIG
|
||||
* is returned.
|
||||
* @param debug if true, debug messages are printed
|
||||
*
|
||||
* @returns 0 in case of success, or a negative errno value
|
||||
*/
|
||||
int kmip_decode_json(const json_object *obj, struct kmip_node *parent,
|
||||
struct kmip_node **node, bool debug)
|
||||
struct kmip_node **node, size_t max_nesting_level,
|
||||
bool debug)
|
||||
{
|
||||
json_object *tag_obj, *type_obj, *value_obj, *name_obj;
|
||||
enum kmip_tag tag, v1_attr_tag = 0;
|
||||
@@ -42,6 +46,9 @@ int kmip_decode_json(const json_object *obj, struct kmip_node *parent,
|
||||
int rc, num, i;
|
||||
int64_t int64;
|
||||
|
||||
if (max_nesting_level == 0)
|
||||
return -E2BIG;
|
||||
|
||||
if (obj == NULL || node == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -82,7 +89,7 @@ int kmip_decode_json(const json_object *obj, struct kmip_node *parent,
|
||||
rc = -EBADMSG;
|
||||
goto out;
|
||||
}
|
||||
n->name = strdup(json_object_get_string(tag_obj));
|
||||
n->name = strdup(json_object_get_string(name_obj));
|
||||
}
|
||||
|
||||
type_obj = json_object_object_get(obj, KMIP_JSON_TYPE);
|
||||
@@ -138,7 +145,7 @@ int kmip_decode_json(const json_object *obj, struct kmip_node *parent,
|
||||
for (i = 0; i < num; i++) {
|
||||
rc = kmip_decode_json(
|
||||
json_object_array_get_idx(value_obj, i),
|
||||
n, &e, debug);
|
||||
n, &e, max_nesting_level - 1, debug);
|
||||
if (rc != 0) {
|
||||
kmip_debug(debug, "Failed to parse "
|
||||
"array element %d", i);
|
||||
@@ -614,6 +621,10 @@ int kmip_encode_json(const struct kmip_node *node, json_object **obj,
|
||||
|
||||
case KMIP_TYPE_DATE_TIME:
|
||||
tm = gmtime((time_t *)&node->date_time_value);
|
||||
if (tm == NULL) {
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
strftime(outstr, sizeof(outstr), KMIP_ISO8601_TIMESTAMP_UTC,
|
||||
tm);
|
||||
memb_obj = json_object_new_string(outstr);
|
||||
|
||||
@@ -426,8 +426,14 @@ int kmip_get_key_value(const struct kmip_node *node,
|
||||
/* Must be a KMIP v1.x attribute then */
|
||||
kmip_node_free(attr);
|
||||
|
||||
if (num_attrs != NULL)
|
||||
*num_attrs = kmip_node_get_structure_element_count(node) - 1;
|
||||
if (num_attrs != NULL) {
|
||||
*num_attrs = kmip_node_get_structure_element_count(node);
|
||||
if (*num_attrs == 0) {
|
||||
rc = -EBADMSG;
|
||||
goto error;
|
||||
}
|
||||
(*num_attrs)--;
|
||||
}
|
||||
|
||||
if (v2_attr == NULL)
|
||||
return 0;
|
||||
|
||||
@@ -258,7 +258,7 @@ int kmip_node_add_structure_elements(struct kmip_node *node,
|
||||
*
|
||||
* @param node the KMIP node
|
||||
*
|
||||
* @returns the number of elements, or -1 if the node is not of type structure
|
||||
* @returns the number of elements, or 0 if the node is not of type structure
|
||||
*/
|
||||
unsigned int kmip_node_get_structure_element_count(const struct kmip_node *node)
|
||||
{
|
||||
@@ -266,10 +266,10 @@ unsigned int kmip_node_get_structure_element_count(const struct kmip_node *node)
|
||||
unsigned int i;
|
||||
|
||||
if (node == NULL)
|
||||
return -1;
|
||||
return 0;
|
||||
|
||||
if (node->type != KMIP_TYPE_STRUCTURE)
|
||||
return -1;
|
||||
return 0;
|
||||
|
||||
element = node->structure_value;
|
||||
for (i = 0; element != NULL; i++)
|
||||
@@ -319,7 +319,7 @@ struct kmip_node *kmip_node_get_structure_element_by_index(
|
||||
* @param node the KMIP node
|
||||
* @param tag the tag to find
|
||||
*
|
||||
* @returns the number of elements, or -1 if the node is not of type structure
|
||||
* @returns the number of elements, or 0 if the node is not of type structure
|
||||
*/
|
||||
unsigned int kmip_node_get_structure_element_by_tag_count(
|
||||
const struct kmip_node *node,
|
||||
@@ -329,10 +329,10 @@ unsigned int kmip_node_get_structure_element_by_tag_count(
|
||||
unsigned int i;
|
||||
|
||||
if (node == NULL)
|
||||
return -1;
|
||||
return 0;
|
||||
|
||||
if (node->type != KMIP_TYPE_STRUCTURE)
|
||||
return -1;
|
||||
return 0;
|
||||
|
||||
element = node->structure_value;
|
||||
for (i = 0; element != NULL; element = element->next) {
|
||||
@@ -897,7 +897,7 @@ struct kmip_node *kmip_node_clone(const struct kmip_node *node)
|
||||
case KMIP_TYPE_TEXT_STRING:
|
||||
if (node->text_value != NULL) {
|
||||
clone->text_value = strdup(node->text_value);
|
||||
if (node->text_value == NULL)
|
||||
if (clone->text_value == NULL)
|
||||
goto error;
|
||||
clone->length = strlen(clone->text_value);
|
||||
}
|
||||
@@ -1489,7 +1489,7 @@ retry:
|
||||
}
|
||||
|
||||
if (i == 0 && server_cert_pem != NULL) {
|
||||
fp = fopen(server_cert_pem, "w");
|
||||
fp = fopen_nofollow(server_cert_pem, "w");
|
||||
if (fp == NULL) {
|
||||
rc = -errno;
|
||||
kmip_debug(debug, "Failed to open %s for write",
|
||||
@@ -1507,7 +1507,7 @@ retry:
|
||||
fp = NULL;
|
||||
|
||||
if (server_pubkey_pem != NULL) {
|
||||
fp = fopen(server_pubkey_pem, "w");
|
||||
fp = fopen_nofollow(server_pubkey_pem, "w");
|
||||
if (fp == NULL) {
|
||||
rc = -errno;
|
||||
kmip_debug(debug, "Failed to open %s "
|
||||
@@ -1533,7 +1533,7 @@ retry:
|
||||
|
||||
if (i > 0 && cert_chain_pem != NULL) {
|
||||
if (fp == NULL)
|
||||
fp = fopen(cert_chain_pem, "w");
|
||||
fp = fopen_nofollow(cert_chain_pem, "w");
|
||||
if (fp == NULL) {
|
||||
rc = -errno;
|
||||
kmip_debug(debug, "Failed to open %s for write",
|
||||
|
||||
@@ -94,19 +94,23 @@ int kmip_connection_https_perform(struct kmip_connection *connection,
|
||||
bool debug);
|
||||
void kmip_connection_https_term(struct kmip_connection *connection);
|
||||
|
||||
/* KIMP decoding and encoding internal functions */
|
||||
/* KIMP decoding and encoding internal functions and definitions */
|
||||
#define KMIP_DECODE_MAX_NESTING_LEVEL 32
|
||||
|
||||
int kmip_decode_ttlv(BIO *bio, size_t *size, struct kmip_node **node,
|
||||
bool debug);
|
||||
size_t max_nesting_level, bool debug);
|
||||
int kmip_encode_ttlv(struct kmip_node *node, BIO *bio, size_t *size,
|
||||
bool debug);
|
||||
|
||||
int kmip_decode_json(const json_object *obj, struct kmip_node *parent,
|
||||
struct kmip_node **node, bool debug);
|
||||
struct kmip_node **node, size_t max_nesting_level,
|
||||
bool debug);
|
||||
int kmip_encode_json(const struct kmip_node *node, json_object **obj,
|
||||
bool debug);
|
||||
|
||||
int kmip_decode_xml(const xmlNode *xml, struct kmip_node *parent,
|
||||
struct kmip_node **node, bool debug);
|
||||
struct kmip_node **node, size_t max_nesting_level,
|
||||
bool debug);
|
||||
int kmip_encode_xml(const struct kmip_node *node, xmlNode **xml, bool debug);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -686,14 +686,20 @@ int kmip_get_get_attribute_list_response_payload(const struct kmip_node *node,
|
||||
|
||||
if (kmip_node_get_tag(node) != KMIP_TAG_RESPONSE_PAYLOAD)
|
||||
return -EBADMSG;
|
||||
if (kmip_node_get_type(node) != KMIP_TYPE_STRUCTURE)
|
||||
return -EBADMSG;
|
||||
|
||||
if (unique_id != NULL)
|
||||
*unique_id = kmip_node_get_structure_element_by_tag(node,
|
||||
KMIP_TAG_UNIQUE_IDENTIFIER, 0);
|
||||
|
||||
if (num_attr_refs != NULL)
|
||||
if (num_attr_refs != NULL) {
|
||||
*num_attr_refs =
|
||||
kmip_node_get_structure_element_count(node) - 1;
|
||||
kmip_node_get_structure_element_count(node);
|
||||
if (*num_attr_refs == 0)
|
||||
return -EBADMSG;
|
||||
(*num_attr_refs)--;
|
||||
}
|
||||
|
||||
if (attr_ref == NULL)
|
||||
return 0;
|
||||
@@ -766,6 +772,8 @@ int kmip_get_get_attributes_response_payload(const struct kmip_node *node,
|
||||
|
||||
if (kmip_node_get_tag(node) != KMIP_TAG_RESPONSE_PAYLOAD)
|
||||
return -EBADMSG;
|
||||
if (kmip_node_get_type(node) != KMIP_TYPE_STRUCTURE)
|
||||
return -EBADMSG;
|
||||
|
||||
if (unique_id != NULL)
|
||||
*unique_id = kmip_node_get_structure_element_by_tag(node,
|
||||
@@ -798,8 +806,12 @@ int kmip_get_get_attributes_response_payload(const struct kmip_node *node,
|
||||
/* Must be a KMIP v1.x attribute then */
|
||||
kmip_node_free(attr);
|
||||
|
||||
if (num_attrs != NULL)
|
||||
*num_attrs = kmip_node_get_structure_element_count(node) - 1;
|
||||
if (num_attrs != NULL) {
|
||||
*num_attrs = kmip_node_get_structure_element_count(node);
|
||||
if (*num_attrs == 0)
|
||||
return -EBADMSG;
|
||||
(*num_attrs)--;
|
||||
}
|
||||
|
||||
if (v2_attr == NULL)
|
||||
return 0;
|
||||
|
||||
@@ -493,7 +493,8 @@ int kmip_connection_tls_perform(struct kmip_connection *conn,
|
||||
kmip_debug(debug, "%lu bytes sent", size);
|
||||
|
||||
/* receive the response */
|
||||
rc = kmip_decode_ttlv(conn->plain_tls.bio, NULL, response, debug);
|
||||
rc = kmip_decode_ttlv(conn->plain_tls.bio, NULL, response,
|
||||
KMIP_DECODE_MAX_NESTING_LEVEL, debug);
|
||||
if (rc != 0 || *response == NULL) {
|
||||
kmip_debug(debug, "kmip_decode_ttlv failed");
|
||||
goto out;
|
||||
|
||||
@@ -28,12 +28,15 @@
|
||||
* as many bytes as needed.
|
||||
* @param node On return: the decoded node. The newly allocated
|
||||
* node has a reference count of 1.
|
||||
* @param max_nesting_level the maximum nesting levels of structures within the
|
||||
* KMIP node. If the nesting level is reached, E2BIG
|
||||
* is returned.
|
||||
* @param debug if true, debug messages are printed
|
||||
*
|
||||
* @returns 0 in case of success, or a negative errno value
|
||||
*/
|
||||
int kmip_decode_ttlv(BIO *bio, size_t *size, struct kmip_node **node,
|
||||
bool debug)
|
||||
size_t max_nesting_level, bool debug)
|
||||
{
|
||||
unsigned char padding[KMIP_TTLV_BLOCK_LENGTH];
|
||||
unsigned char ttlv[KMIP_TTLV_HEADER_LENGTH];
|
||||
@@ -44,6 +47,9 @@ int kmip_decode_ttlv(BIO *bio, size_t *size, struct kmip_node **node,
|
||||
uint64_t int64;
|
||||
int rc;
|
||||
|
||||
if (max_nesting_level == 0)
|
||||
return -E2BIG;
|
||||
|
||||
if (bio == NULL || node == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -73,18 +79,18 @@ int kmip_decode_ttlv(BIO *bio, size_t *size, struct kmip_node **node,
|
||||
n->ref_count = 1;
|
||||
|
||||
/* Tag: 3-byte binary unsigned integer, transmitted big endian */
|
||||
n->tag |= (uint32_t)(ttlv[0] << 16);
|
||||
n->tag |= (uint32_t)(ttlv[1] << 8);
|
||||
n->tag |= (uint32_t)(ttlv[2]);
|
||||
n->tag |= (uint32_t)ttlv[0] << 16;
|
||||
n->tag |= (uint32_t)ttlv[1] << 8;
|
||||
n->tag |= (uint32_t)ttlv[2];
|
||||
|
||||
/* Type: 1 byte containing a coded value that indicates the data type */
|
||||
n->type = ttlv[3];
|
||||
|
||||
/* Length: 32-bit binary integer, transmitted big-endian */
|
||||
n->length |= (uint32_t)(ttlv[4] << 24);
|
||||
n->length |= (uint32_t)(ttlv[5] << 16);
|
||||
n->length |= (uint32_t)(ttlv[6] << 8);
|
||||
n->length |= (uint32_t)(ttlv[7]);
|
||||
n->length |= (uint32_t)ttlv[4] << 24;
|
||||
n->length |= (uint32_t)ttlv[5] << 16;
|
||||
n->length |= (uint32_t)ttlv[6] << 8;
|
||||
n->length |= (uint32_t)ttlv[7];
|
||||
|
||||
kmip_debug(debug, "tag: 0x%x type: 0x%x, length: %u", n->tag, n->type,
|
||||
n->length);
|
||||
@@ -98,6 +104,11 @@ int kmip_decode_ttlv(BIO *bio, size_t *size, struct kmip_node **node,
|
||||
case KMIP_TYPE_TEXT_STRING:
|
||||
case KMIP_TYPE_BYTE_STRING:
|
||||
value_len = n->length;
|
||||
if (value_len > INT_MAX) {
|
||||
rc = -EMSGSIZE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
value = calloc(1, value_len + 1);
|
||||
if (value == NULL) {
|
||||
kmip_debug(debug, "calloc failed");
|
||||
@@ -160,14 +171,22 @@ int kmip_decode_ttlv(BIO *bio, size_t *size, struct kmip_node **node,
|
||||
rc = -EIO;
|
||||
goto out;
|
||||
}
|
||||
if (size != NULL)
|
||||
|
||||
if (size != NULL) {
|
||||
if (*size < pad_len) {
|
||||
rc = -EMSGSIZE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
*size -= pad_len;
|
||||
}
|
||||
}
|
||||
|
||||
switch (n->type) {
|
||||
case KMIP_TYPE_STRUCTURE:
|
||||
while (value_len > 0) {
|
||||
rc = kmip_decode_ttlv(bio, &value_len, &e, debug);
|
||||
rc = kmip_decode_ttlv(bio, &value_len, &e,
|
||||
max_nesting_level - 1, debug);
|
||||
if (rc != 0) {
|
||||
kmip_debug(debug, "kmip_decode_ttlv failed: "
|
||||
"rc: %d", rc);
|
||||
@@ -263,7 +282,7 @@ out:
|
||||
static int kmip_node_get_length(struct kmip_node *node, size_t *length)
|
||||
{
|
||||
struct kmip_node *element;
|
||||
size_t len;
|
||||
size_t len, prev_len;
|
||||
int rc;
|
||||
|
||||
if (node == NULL || length == NULL)
|
||||
@@ -278,10 +297,13 @@ static int kmip_node_get_length(struct kmip_node *node, size_t *length)
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
|
||||
prev_len = *length;
|
||||
*length += KMIP_TTLV_HEADER_LENGTH + len;
|
||||
if ((len % KMIP_TTLV_BLOCK_LENGTH) != 0)
|
||||
*length += KMIP_TTLV_BLOCK_LENGTH -
|
||||
(len % KMIP_TTLV_BLOCK_LENGTH);
|
||||
if (*length < prev_len)
|
||||
return -EOVERFLOW;
|
||||
|
||||
element = element->next;
|
||||
}
|
||||
|
||||
@@ -12,9 +12,11 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include <err.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "names.h"
|
||||
@@ -72,6 +74,8 @@ int kmip_parse_decimal_uint(const char *str, uint64_t *val)
|
||||
|
||||
if (str == NULL)
|
||||
return -EINVAL;
|
||||
if (str[0] == '-')
|
||||
return -EBADMSG;
|
||||
|
||||
errno = 0;
|
||||
v = strtoull(str, &endptr, 10);
|
||||
@@ -164,13 +168,16 @@ int kmip_parse_hex(const char *str, bool has_prefix, unsigned char **val,
|
||||
* Format a hex string from the byte array specified in val. The caller must
|
||||
* free the returned str.
|
||||
*/
|
||||
int kmip_format_hex(const unsigned char *val, uint32_t length, bool prefix,
|
||||
int kmip_format_hex(const unsigned char *val, size_t length, bool prefix,
|
||||
char **str)
|
||||
{
|
||||
uint32_t str_len, i;
|
||||
size_t str_len, i;
|
||||
char tmp[4];
|
||||
char *ret;
|
||||
|
||||
if (length > (SIZE_MAX - ((prefix ? 2 : 0) + 1)) / 2)
|
||||
return -EINVAL;
|
||||
|
||||
str_len = length * 2 + (prefix ? 2 : 0) + 1;
|
||||
ret = calloc(1, str_len);
|
||||
if (ret == NULL)
|
||||
@@ -220,14 +227,18 @@ int kmip_parse_bignum(const char *str, bool has_prefix, BIGNUM **bn)
|
||||
int kmip_format_bignum(const BIGNUM *bn, bool prefix, char **str)
|
||||
{
|
||||
unsigned char *buf;
|
||||
uint32_t len;
|
||||
uint32_t len, prev_len;
|
||||
int rc;
|
||||
|
||||
len = kmip_encode_bignum_length(bn);
|
||||
/* BIG INTEGERS must be a multiple of 8 bytes long */
|
||||
if ((len % KMIP_BIG_INTEGER_BLOCK_LENGTH) != 0)
|
||||
if ((len % KMIP_BIG_INTEGER_BLOCK_LENGTH) != 0) {
|
||||
prev_len = len;
|
||||
len += KMIP_BIG_INTEGER_BLOCK_LENGTH -
|
||||
(len % KMIP_BIG_INTEGER_BLOCK_LENGTH);
|
||||
if (len < prev_len)
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
|
||||
buf = malloc(len);
|
||||
if (buf == NULL)
|
||||
@@ -402,10 +413,10 @@ int kmip_parse_mask(enum kmip_tag tag, const char *str, char separator,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int kmip_append_string(char **str, int *str_len, char separator,
|
||||
static int kmip_append_string(char **str, size_t *str_len, char separator,
|
||||
const char *append)
|
||||
{
|
||||
int new_len;
|
||||
size_t new_len;
|
||||
char *tmp;
|
||||
|
||||
if (str == NULL || str_len == NULL)
|
||||
@@ -422,6 +433,9 @@ static int kmip_append_string(char **str, int *str_len, char separator,
|
||||
if (append != NULL)
|
||||
new_len += strlen(append);
|
||||
|
||||
if (new_len < *str_len)
|
||||
return -EOVERFLOW;
|
||||
|
||||
tmp = realloc(*str, new_len);
|
||||
if (tmp == NULL)
|
||||
return -ENOMEM;
|
||||
@@ -446,8 +460,9 @@ int kmip_format_mask(enum kmip_tag tag, int32_t value, char separator,
|
||||
char **str)
|
||||
{
|
||||
const struct kmip_enum *info;
|
||||
int rc = 0, i, s_len = 0;
|
||||
char *s = NULL, *tmp;
|
||||
size_t s_len = 0;
|
||||
int rc = 0, i;
|
||||
|
||||
info = kmip_enum_info_by_tag(tag);
|
||||
if (info == NULL || value == 0)
|
||||
@@ -726,3 +741,32 @@ enum kmip_tag kmip_find_v1_attribute_name_tag(struct kmip_node *parent)
|
||||
return 0;
|
||||
}
|
||||
|
||||
FILE *fopen_nofollow(const char *path, const char *mode)
|
||||
{
|
||||
int flags = O_NOFOLLOW;
|
||||
int fd;
|
||||
FILE *fp;
|
||||
|
||||
/* Determine flags based on mode */
|
||||
if (mode[0] == 'r')
|
||||
flags |= (mode[1] == '+') ? O_RDWR : O_RDONLY;
|
||||
else if (mode[0] == 'w')
|
||||
flags |= O_CREAT | O_TRUNC |
|
||||
((mode[1] == '+') ? O_RDWR : O_WRONLY);
|
||||
else if (mode[0] == 'a')
|
||||
flags |= O_CREAT | O_APPEND |
|
||||
((mode[1] == '+') ? O_RDWR : O_WRONLY);
|
||||
else
|
||||
return NULL;
|
||||
|
||||
fd = open(path, flags, 0600);
|
||||
if (fd < 0)
|
||||
return NULL;
|
||||
|
||||
fp = fdopen(fd, mode);
|
||||
if (fp == NULL) {
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ int kmip_parse_decimal_uint(const char *str, uint64_t *val);
|
||||
int kmip_parse_hex_int(const char *str, int64_t *val);
|
||||
int kmip_parse_hex(const char *str, bool has_prefix, unsigned char **val,
|
||||
uint32_t *length);
|
||||
int kmip_format_hex(const unsigned char *val, uint32_t length, bool prefix,
|
||||
int kmip_format_hex(const unsigned char *val, size_t length, bool prefix,
|
||||
char **str);
|
||||
|
||||
int kmip_parse_bignum(const char *str, bool has_prefix, BIGNUM **bn);
|
||||
@@ -58,4 +58,6 @@ void kmip_node_dump(struct kmip_node *node, bool debug);
|
||||
|
||||
enum kmip_tag kmip_find_v1_attribute_name_tag(struct kmip_node *parent);
|
||||
|
||||
FILE *fopen_nofollow(const char *path, const char *mode);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -28,12 +28,16 @@
|
||||
* @param parent the parent node or NULL if no parent exists.
|
||||
* @param node On return: the decoded node.The newly allocated
|
||||
* node has a reference count of 1.
|
||||
* @param max_nesting_level the maximum nesting levels of structures within the
|
||||
* KMIP node. If the nesting level is reached, E2BIG
|
||||
* is returned.
|
||||
* @param debug if true, debug messages are printed
|
||||
*
|
||||
* @returns 0 in case of success, or a negative errno value
|
||||
*/
|
||||
int kmip_decode_xml(const xmlNode *xml, struct kmip_node *parent,
|
||||
struct kmip_node **node, bool debug)
|
||||
struct kmip_node **node, size_t max_nesting_level,
|
||||
bool debug)
|
||||
{
|
||||
char *tag_attr = NULL, *name_attr = NULL, *type_attr = NULL;
|
||||
enum kmip_tag tag, v1_attr_tag = 0;
|
||||
@@ -44,6 +48,9 @@ int kmip_decode_xml(const xmlNode *xml, struct kmip_node *parent,
|
||||
int64_t int64;
|
||||
int rc = 0, i;
|
||||
|
||||
if (max_nesting_level == 0)
|
||||
return -E2BIG;
|
||||
|
||||
if (xml == NULL || node == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -122,7 +129,8 @@ int kmip_decode_xml(const xmlNode *xml, struct kmip_node *parent,
|
||||
if (child->type != XML_ELEMENT_NODE)
|
||||
continue;
|
||||
|
||||
rc = kmip_decode_xml(child, n, &e, debug);
|
||||
rc = kmip_decode_xml(child, n, &e,
|
||||
max_nesting_level - 1, debug);
|
||||
if (rc != 0) {
|
||||
kmip_debug(debug, "Failed to parse child "
|
||||
"element %d", i);
|
||||
@@ -452,6 +460,10 @@ int kmip_encode_xml(const struct kmip_node *node, xmlNode **xml, bool debug)
|
||||
|
||||
case KMIP_TYPE_DATE_TIME:
|
||||
tm = gmtime((time_t *)&node->date_time_value);
|
||||
if (tm == NULL) {
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
strftime(tmp_str, sizeof(tmp_str), KMIP_ISO8601_TIMESTAMP_UTC,
|
||||
tm);
|
||||
attr = xmlSetProp(ret_xml, (xmlChar *)KMIP_XML_VALUE,
|
||||
|
||||
@@ -258,7 +258,9 @@ static int sk_cca_get_library_functions(const struct sk_ext_cca_lib *cca_lib,
|
||||
*
|
||||
* @param cca_lib the CCA library structure
|
||||
* @param curve_nid the nid specifying the curve.
|
||||
* @param key_token a buffer to store the generated key token
|
||||
* @param key_token a buffer to store the generated key token. If NULL,
|
||||
* the required buffer size is returned in
|
||||
* key_token_length (size query).
|
||||
* @param key_token_length On entry: the size of the buffer
|
||||
* On return: the size of the key token
|
||||
* @param debug if true, debug messages are printed
|
||||
@@ -286,7 +288,7 @@ int SK_CCA_generate_ec_key_pair(const struct sk_ext_cca_lib *cca_lib,
|
||||
long param1 = 0;
|
||||
int rc;
|
||||
|
||||
if (cca_lib == NULL || key_token == NULL || key_token_length == NULL)
|
||||
if (cca_lib == NULL || key_token_length == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (key_token == NULL) {
|
||||
@@ -384,7 +386,9 @@ int SK_CCA_generate_ec_key_pair(const struct sk_ext_cca_lib *cca_lib,
|
||||
* 3, 5, 17, 257, or 65537. Specify zero to choose the
|
||||
* exponent by random (only possible for modulus_bits
|
||||
* up to 2048).
|
||||
* @param key_token a buffer to store the generated key token
|
||||
* @param key_token a buffer to store the generated key token. If NULL,
|
||||
* the required buffer size is returned in
|
||||
* key_token_length (size query).
|
||||
* @param key_token_length On entry: the size of the buffer
|
||||
* On return: the size of the key token
|
||||
* @param debug if true, debug messages are printed
|
||||
@@ -412,7 +416,7 @@ int SK_CCA_generate_rsa_key_pair(const struct sk_ext_cca_lib *cca_lib,
|
||||
long param1 = 0;
|
||||
int rc;
|
||||
|
||||
if (cca_lib == NULL || key_token == NULL || key_token_length == NULL)
|
||||
if (cca_lib == NULL || key_token_length == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (key_token == NULL) {
|
||||
@@ -459,7 +463,7 @@ int SK_CCA_generate_rsa_key_pair(const struct sk_ext_cca_lib *cca_lib,
|
||||
case 257:
|
||||
key_value_structure.public_exp_length = 2;
|
||||
key_value_structure.public_exponent[0] = 0x01;
|
||||
key_value_structure.public_exponent[0] = 0x01;
|
||||
key_value_structure.public_exponent[1] = 0x01;
|
||||
break;
|
||||
case 65537:
|
||||
key_value_structure.public_exp_length = 3;
|
||||
@@ -560,6 +564,11 @@ static const void *sk_cca_get_pka_section(const unsigned char *key_token,
|
||||
section_hdr = (struct cca_section_header *)&key_token[ofs];
|
||||
|
||||
while (section_hdr->section_identifier != section_id) {
|
||||
if (section_hdr->section_length <
|
||||
sizeof(struct cca_section_header)) {
|
||||
sk_debug(debug, "ERROR: invalid section length");
|
||||
return NULL;
|
||||
}
|
||||
ofs += section_hdr->section_length;
|
||||
if (ofs >= token_hdr->token_length) {
|
||||
sk_debug(debug, "ERROR: section %u not found",
|
||||
@@ -1385,7 +1394,7 @@ static int sk_cca_get_public_from_rsa_key(const unsigned char *key_token,
|
||||
return -EINVAL;
|
||||
}
|
||||
if (rsa_pub_section->section_header.section_length <
|
||||
sizeof(struct cca_ec_pub_key_section)) {
|
||||
sizeof(struct cca_rsa_pub_key_section)) {
|
||||
sk_debug(debug, "ERROR: invalid RSA public key section length");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -195,7 +195,7 @@ static int sk_ep11_generate_key_pair(const struct sk_ext_ep11_lib *ep11_lib,
|
||||
CK_RV rv;
|
||||
int rc;
|
||||
|
||||
if (ep11_lib == NULL || key_token == NULL || key_token_length == NULL)
|
||||
if (ep11_lib == NULL || key_token_length == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (key_token == NULL) {
|
||||
@@ -262,7 +262,9 @@ static int sk_ep11_generate_key_pair(const struct sk_ext_ep11_lib *ep11_lib,
|
||||
*
|
||||
* @param ep11_lib the Ep11 library structure
|
||||
* @param curve_nid the nid specifying the curve.
|
||||
* @param key_token a buffer to store the generated key token
|
||||
* @param key_token a buffer to store the generated key token. If NULL,
|
||||
* the required buffer size is returned in
|
||||
* key_token_length (size query).
|
||||
* @param key_token_length On entry: the size of the buffer
|
||||
* On return: the size of the key token
|
||||
* @param debug if true, debug messages are printed
|
||||
@@ -292,7 +294,7 @@ int SK_EP11_generate_ec_key_pair(const struct sk_ext_ep11_lib *ep11_lib,
|
||||
const struct sk_ec_curve_info *curve;
|
||||
int rc;
|
||||
|
||||
if (ep11_lib == NULL || key_token == NULL || key_token_length == NULL)
|
||||
if (ep11_lib == NULL || key_token_length == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
sk_debug(debug, "curve_nid: %d", curve_nid);
|
||||
@@ -331,7 +333,9 @@ int SK_EP11_generate_ec_key_pair(const struct sk_ext_ep11_lib *ep11_lib,
|
||||
* 3, 5, 17, 257, or 65537. Specify zero to choose the
|
||||
* exponent by random.
|
||||
* @param x9_31 if true, generate a X9.31 RSA key
|
||||
* @param key_token a buffer to store the generated key token
|
||||
* @param key_token a buffer to store the generated key token. If NULL,
|
||||
* the required buffer size is returned in
|
||||
* key_token_length (size query).
|
||||
* @param key_token_length On entry: the size of the buffer
|
||||
* On return: the size of the key token
|
||||
* @param debug if true, debug messages are printed
|
||||
@@ -365,7 +369,7 @@ int SK_EP11_generate_rsa_key_pair(const struct sk_ext_ep11_lib *ep11_lib,
|
||||
CK_ULONG priv_tmpl_num = sizeof(priv_tmpl) / sizeof(CK_ATTRIBUTE);
|
||||
int rc;
|
||||
|
||||
if (ep11_lib == NULL || key_token == NULL || key_token_length == NULL)
|
||||
if (ep11_lib == NULL || key_token_length == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
sk_debug(debug, "modulus_bits: %lu pub_exp: %u x9_31: %d",
|
||||
@@ -413,6 +417,8 @@ static unsigned char sk_ep11_parse_der_tag(const unsigned char *data,
|
||||
if (num > sizeof(size_t))
|
||||
return 0;
|
||||
*value_len = data[2];
|
||||
if (data_len < 2 + num)
|
||||
return 0;
|
||||
for (i = 1; i < num; i++) {
|
||||
*value_len <<= 8;
|
||||
*value_len |= data[2 + i];
|
||||
@@ -498,6 +504,8 @@ static int sk_ep11_parse_spki(const unsigned char *spki, size_t spki_len,
|
||||
pub_key, pub_key_len);
|
||||
if (tag != 0x03) /* BITSTRING */
|
||||
return -EINVAL;
|
||||
if (*pub_key_len == 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* skip unsused-bits byte */
|
||||
(*pub_key)++;
|
||||
@@ -555,7 +563,7 @@ int SK_EP11_get_key_type(const unsigned char *key_token,
|
||||
return -EINVAL;
|
||||
|
||||
spki_size = key_token_length - hdr->len;
|
||||
if (spki_size <= 0)
|
||||
if (spki_size == 0)
|
||||
return -EINVAL;
|
||||
|
||||
rc = sk_ep11_parse_spki(key_token + hdr->len, spki_size,
|
||||
@@ -702,7 +710,7 @@ static int sk_ep11_rsa_sign(const unsigned char *key_token,
|
||||
case RSA_X931_PADDING:
|
||||
mech.mechanism = CKM_RSA_X9_31;
|
||||
|
||||
if ((hdr->flags && PKEY_TYPE_EP11_FLAG_X9_31) == 0) {
|
||||
if ((hdr->flags & PKEY_TYPE_EP11_FLAG_X9_31) == 0) {
|
||||
sk_debug(debug, "ERROR: no RSA X9.31 key");
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -1375,7 +1383,7 @@ int SK_EP11_get_public_from_secure_key(const unsigned char *key_token,
|
||||
return -EINVAL;
|
||||
|
||||
spki_size = key_token_length - hdr->len;
|
||||
if (spki_size <= 0)
|
||||
if (spki_size == 0)
|
||||
return -EINVAL;
|
||||
|
||||
rc = sk_ep11_parse_spki(key_token + hdr->len, spki_size,
|
||||
|
||||
@@ -698,6 +698,7 @@ static int sk_pkey_meth_setup_pkey(EVP_PKEY *pkey,
|
||||
struct sk_pkey_data *data;
|
||||
EC_KEY *ec;
|
||||
RSA *rsa;
|
||||
int rc;
|
||||
|
||||
if (pkey == NULL || secure_key == NULL || secure_key_size == 0 ||
|
||||
funcs == NULL)
|
||||
@@ -733,12 +734,14 @@ static int sk_pkey_meth_setup_pkey(EVP_PKEY *pkey,
|
||||
ec = EVP_PKEY_get0_EC_KEY(pkey);
|
||||
if (ec == NULL) {
|
||||
sk_debug(debug, "EVP_PKEY_get0_EC_KEY failed");
|
||||
return -EIO;
|
||||
rc = -EIO;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!EC_KEY_set_ex_data(ec, sk_pkey_data_ec_index, data)) {
|
||||
sk_debug(debug, "EC_KEY_set_ex_data failed");
|
||||
return -EIO;
|
||||
rc = -EIO;
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
case EVP_PKEY_RSA:
|
||||
@@ -746,17 +749,29 @@ static int sk_pkey_meth_setup_pkey(EVP_PKEY *pkey,
|
||||
rsa = EVP_PKEY_get0_RSA(pkey);
|
||||
if (rsa == NULL) {
|
||||
sk_debug(debug, "EVP_PKEY_get0_RSA failed");
|
||||
return -EIO;
|
||||
rc = -EIO;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!RSA_set_ex_data(rsa, sk_pkey_data_rsa_index, data)) {
|
||||
sk_debug(debug, "RSA_set_ex_data failed");
|
||||
return -EIO;
|
||||
rc = -EIO;
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
rc = -EIO;
|
||||
goto error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
if (data != NULL) {
|
||||
OPENSSL_free(data->key_blob);
|
||||
OPENSSL_free(data);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -796,13 +811,13 @@ int SK_OPENSSL_init(bool debug)
|
||||
return -EIO;
|
||||
}
|
||||
sk_pkey_meth_default_method_rsa = EVP_PKEY_meth_find(EVP_PKEY_RSA);
|
||||
if (sk_pkey_meth_default_method_ec == NULL) {
|
||||
if (sk_pkey_meth_default_method_rsa == NULL) {
|
||||
sk_debug(debug, "ERROR: EVP_PKEY_meth_find(RSA) failed");
|
||||
return -EIO;
|
||||
}
|
||||
sk_pkey_meth_default_method_rsa_pss =
|
||||
EVP_PKEY_meth_find(EVP_PKEY_RSA_PSS);
|
||||
if (sk_pkey_meth_default_method_ec == NULL) {
|
||||
if (sk_pkey_meth_default_method_rsa_pss == NULL) {
|
||||
sk_debug(debug, "ERROR: EVP_PKEY_meth_find(RSA-PSS) failed");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@@ -10,10 +10,12 @@
|
||||
#include <string.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/sha.h>
|
||||
@@ -811,6 +813,35 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline FILE *fopen_nofollow(const char *path, const char *mode)
|
||||
{
|
||||
int flags = O_NOFOLLOW;
|
||||
int fd;
|
||||
FILE *fp;
|
||||
|
||||
/* Determine flags based on mode */
|
||||
if (mode[0] == 'r')
|
||||
flags |= (mode[1] == '+') ? O_RDWR : O_RDONLY;
|
||||
else if (mode[0] == 'w')
|
||||
flags |= O_CREAT | O_TRUNC |
|
||||
((mode[1] == '+') ? O_RDWR : O_WRONLY);
|
||||
else if (mode[0] == 'a')
|
||||
flags |= O_CREAT | O_APPEND |
|
||||
((mode[1] == '+') ? O_RDWR : O_WRONLY);
|
||||
else
|
||||
return NULL;
|
||||
|
||||
fd = open(path, flags, 0600);
|
||||
if (fd < 0)
|
||||
return NULL;
|
||||
|
||||
fp = fdopen(fd, mode);
|
||||
if (fp == NULL) {
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a X.509 certificate from the specified PEM file.
|
||||
@@ -863,7 +894,7 @@ int SK_UTIL_write_x509_certificate(const char *pem_filename, X509 *cert)
|
||||
if (pem_filename == NULL || cert == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
fp = fopen(pem_filename, "w");
|
||||
fp = fopen_nofollow(pem_filename, "w");
|
||||
if (fp == NULL)
|
||||
return -errno;
|
||||
|
||||
@@ -898,7 +929,7 @@ int SK_UTIL_write_x509_request(const char *pem_filename, X509_REQ *req,
|
||||
if (pem_filename == NULL || req == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
fp = fopen(pem_filename, "w");
|
||||
fp = fopen_nofollow(pem_filename, "w");
|
||||
if (fp == NULL)
|
||||
return -errno;
|
||||
|
||||
@@ -982,7 +1013,7 @@ int SK_UTIL_write_key_blob(const char *filename, unsigned char *key_blob,
|
||||
if (filename == NULL || key_blob == NULL || key_blob_len == 0)
|
||||
return -EINVAL;
|
||||
|
||||
fp = fopen(filename, "w");
|
||||
fp = fopen_nofollow(filename, "w");
|
||||
if (fp == NULL)
|
||||
return -errno;
|
||||
|
||||
@@ -1047,7 +1078,7 @@ int SK_UTIL_write_public_key(const char *pem_filename, EVP_PKEY *pkey)
|
||||
if (pem_filename == NULL || pkey == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
fp = fopen(pem_filename, "w");
|
||||
fp = fopen_nofollow(pem_filename, "w");
|
||||
if (fp == NULL)
|
||||
return -errno;
|
||||
|
||||
|
||||
@@ -89,11 +89,26 @@ static const struct {
|
||||
const char *name;
|
||||
enum util_fmt_t fmt;
|
||||
} formats[] = {
|
||||
{ "json", FMT_JSON },
|
||||
{ "json-seq", FMT_JSONSEQ },
|
||||
{ "jsonl", FMT_JSONL },
|
||||
{ "pairs", FMT_PAIRS },
|
||||
{ "csv", FMT_CSV },
|
||||
[FMT_JSON] = {
|
||||
.name = "json",
|
||||
.fmt = FMT_JSON
|
||||
},
|
||||
[FMT_JSONSEQ] = {
|
||||
.name = "json-seq",
|
||||
.fmt = FMT_JSONSEQ
|
||||
},
|
||||
[FMT_JSONL] = {
|
||||
.name = "jsonl",
|
||||
.fmt = FMT_JSONL
|
||||
},
|
||||
[FMT_PAIRS] = {
|
||||
.name = "pairs",
|
||||
.fmt = FMT_PAIRS
|
||||
},
|
||||
[FMT_CSV] = {
|
||||
.name = "csv",
|
||||
.fmt = FMT_CSV
|
||||
},
|
||||
};
|
||||
|
||||
/* Signal mask for blocking INT and TERM signals. */
|
||||
@@ -112,6 +127,11 @@ bool util_fmt_name_to_type(const char *name, enum util_fmt_t *type)
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *util_fmt_type_to_name(enum util_fmt_t type)
|
||||
{
|
||||
return formats[type].name;
|
||||
}
|
||||
|
||||
bool util_fmt_is_json(enum util_fmt_t type)
|
||||
{
|
||||
switch (type) {
|
||||
|
||||
@@ -12,13 +12,17 @@ static void zpci_print(struct zpci_dev *zdev)
|
||||
int i;
|
||||
|
||||
if (!zdev->conf) {
|
||||
printf("fid: %8x address: %s\n", zdev->fid, pci_addr);
|
||||
printf("fid:\t%4x address: %s\n", zdev->fid, pci_addr);
|
||||
} else {
|
||||
printf("fid: %8x address: %s uid: %4x%s pchid: %4x vfn: %4d port: %1d pft: %s ",
|
||||
printf("fid:\t%4x address: %s uid: %4x%s pchid: %4x vfn: %4d\n",
|
||||
zdev->fid, pci_addr, zdev->uid, (zdev->uid_is_unique) ? " (unique)" : "",
|
||||
zdev->pchid, zdev->vfn, zdev->port, zpci_pft_str(zdev));
|
||||
zdev->pchid, zdev->vfn);
|
||||
printf("\n");
|
||||
printf("\tport: %1d pft: %s subsystem_device: %4x subsystem_vendor: %4x\n",
|
||||
zdev->port, zpci_pft_str(zdev), zdev->subsystem_device,
|
||||
zdev->subsystem_vendor);
|
||||
if (zdev->num_netdevs) {
|
||||
printf("netdevs: ");
|
||||
printf("\tnetdevs: ");
|
||||
for (i = 0; i < zdev->num_netdevs; i++) {
|
||||
printf("%s (%s)", zdev->netdevs[i].name,
|
||||
zpci_operstate_str(zdev->netdevs[i].operstate));
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "lib/util_list.h"
|
||||
#include "lib/util_path.h"
|
||||
#include "lib/util_scandir.h"
|
||||
#include "lib/util_sys.h"
|
||||
|
||||
/**
|
||||
* Get the function type name for the given device
|
||||
@@ -137,7 +138,7 @@ const char *zpci_operstate_str(operstate_t state)
|
||||
static int zpci_populate_from_slot_dir(struct zpci_dev *zdev, const char *slot_dir,
|
||||
const char *slot_name)
|
||||
{
|
||||
char buf_addr[11]; /* "dddd:bb:dd\0" */
|
||||
char buf_addr[PCI_BDF_LEN];
|
||||
uint8_t bus, df;
|
||||
uint32_t domain;
|
||||
int val, rc;
|
||||
@@ -261,6 +262,16 @@ static int zpci_populate_from_dev_dir(struct zpci_dev *zdev)
|
||||
goto out_path;
|
||||
zdev->pft = val;
|
||||
|
||||
rc = util_file_read_i(&val, 16, "%s/subsystem_device", path);
|
||||
if (rc)
|
||||
goto out_path;
|
||||
zdev->subsystem_device = val;
|
||||
|
||||
rc = util_file_read_i(&val, 16, "%s/subsystem_vendor", path);
|
||||
if (rc)
|
||||
goto out_path;
|
||||
zdev->subsystem_vendor = val;
|
||||
|
||||
if (util_path_is_readable("%s/net", path)) {
|
||||
rc = zpci_populate_netdevices(zdev, path);
|
||||
if (rc)
|
||||
@@ -387,3 +398,46 @@ struct zpci_dev *zpci_find_by_netdev(struct util_list *zpci_list, char *netdev_n
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the NVMe device file name given a PCI address
|
||||
*
|
||||
* This function retrieves the NVMe device file "/dev/nvmeX"
|
||||
* for a given PCI address. The device name can be used to construct
|
||||
* the path /dev/nvmeX which is the NVMe's controller's character
|
||||
* device used for example to retrieve S.M.A.R.T. data.
|
||||
*
|
||||
* @param[in] pci_addr The "DDDD:bb:dd.f" format PCI address
|
||||
*
|
||||
* @return The NVMe device file name if one is found NULL otherwise
|
||||
*/
|
||||
char *zpci_get_nvme_device_node(const char *pci_addr)
|
||||
{
|
||||
char *path, *dev = NULL;
|
||||
char dev_addr[PCI_BDF_LEN];
|
||||
struct dirent **de_vec;
|
||||
int count, i;
|
||||
|
||||
path = util_path_sysfs("bus/pci/devices/%s/nvme", pci_addr);
|
||||
count = util_scandir(&de_vec, alphasort, path, "nvme*");
|
||||
if (count == -1) {
|
||||
warnx("Could not read directory %s: %s", path, strerror(errno));
|
||||
goto exit_path;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
util_asprintf(&dev, "/dev/%s", de_vec[i]->d_name);
|
||||
if (util_sys_get_dev_addr(dev, dev_addr) != 0)
|
||||
goto free_continue;
|
||||
if (strcmp(dev_addr, pci_addr) == 0)
|
||||
break;
|
||||
free_continue:
|
||||
free(dev);
|
||||
dev = NULL;
|
||||
}
|
||||
|
||||
util_scandir_free(de_vec, count);
|
||||
exit_path:
|
||||
free(path);
|
||||
return dev;
|
||||
}
|
||||
|
||||
@@ -742,6 +742,8 @@ static int read_cmdline(struct task_t *task)
|
||||
buf[i] = ' ';
|
||||
}
|
||||
name_lens.cmdline_len = num;
|
||||
if (name_lens.cmdline_len > MAX_CMD_LEN)
|
||||
name_lens.cmdline_len = MAX_CMD_LEN;
|
||||
cmdlnlenp = mon_record + sizeof(struct monwrite_hdr);
|
||||
cmdlnlenp += sizeof(struct procd_hdr);
|
||||
cmdlnlenp += sizeof(struct task_t);
|
||||
|
||||
@@ -1,407 +0,0 @@
|
||||
/*
|
||||
* opticsmon - Report optics monitoring data to firmware
|
||||
*
|
||||
* Copyright IBM Corp. 2024
|
||||
*
|
||||
* s390-tools is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/signalfd.h>
|
||||
#include <signal.h>
|
||||
#include <sys/timerfd.h>
|
||||
#include <time.h>
|
||||
#include <linux/if.h>
|
||||
|
||||
#include "lib/util_list.h"
|
||||
#include "lib/pci_list.h"
|
||||
#include "lib/util_prg.h"
|
||||
#include "lib/util_opt.h"
|
||||
#include "lib/util_fmt.h"
|
||||
#include "lib/util_libc.h"
|
||||
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#include "ethtool.h"
|
||||
#include "link_mon.h"
|
||||
#include "optics_info.h"
|
||||
#include "optics_sclp.h"
|
||||
#include "opticsmon_cli.h"
|
||||
|
||||
#define API_LEVEL 1
|
||||
|
||||
struct options {
|
||||
bool monitor;
|
||||
bool report;
|
||||
bool module_info;
|
||||
bool quiet;
|
||||
|
||||
uint32_t interval_seconds;
|
||||
};
|
||||
|
||||
struct opticsmon_ctx {
|
||||
struct options opts;
|
||||
struct ethtool_nl_ctx ethtool_ctx;
|
||||
struct link_mon_nl_ctx lctx;
|
||||
struct util_list *zpci_list;
|
||||
};
|
||||
|
||||
static const struct util_prg prg = {
|
||||
.desc = "Use opticsmon to monitor the health of the optical modules\n"
|
||||
"of directly attached PCI based NICs",
|
||||
.copyright_vec = { {
|
||||
.owner = "IBM Corp.",
|
||||
.pub_first = 2024,
|
||||
.pub_last = 2024,
|
||||
},
|
||||
UTIL_PRG_COPYRIGHT_END }
|
||||
};
|
||||
|
||||
static void parse_cmdline(int argc, char *argv[], struct options *opts)
|
||||
{
|
||||
uint32_t seconds;
|
||||
int cmd, ret;
|
||||
|
||||
util_prg_init(&prg);
|
||||
util_opt_init(opt_vec, NULL);
|
||||
|
||||
do {
|
||||
cmd = util_opt_getopt_long(argc, argv);
|
||||
|
||||
switch (cmd) {
|
||||
case 'm':
|
||||
opts->monitor = true;
|
||||
break;
|
||||
case 'r':
|
||||
opts->report = true;
|
||||
break;
|
||||
case 'q':
|
||||
opts->quiet = true;
|
||||
break;
|
||||
case OPT_DUMP:
|
||||
opts->module_info = true;
|
||||
break;
|
||||
case 'i':
|
||||
ret = sscanf(optarg, "%u", &seconds);
|
||||
if (ret != 1) {
|
||||
fprintf(stderr,
|
||||
"Failed to parse interval argument \"%s\" as seconds\n",
|
||||
optarg);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (seconds < 86400)
|
||||
opts->interval_seconds = seconds;
|
||||
break;
|
||||
case 'h':
|
||||
util_prg_print_help();
|
||||
util_opt_print_help();
|
||||
exit(EXIT_SUCCESS);
|
||||
case 'v':
|
||||
util_prg_print_version();
|
||||
exit(EXIT_SUCCESS);
|
||||
case -1:
|
||||
/* End of options string */
|
||||
break;
|
||||
}
|
||||
} while (cmd != -1);
|
||||
}
|
||||
|
||||
static int module_info_pair(struct optics *oi)
|
||||
{
|
||||
size_t b64_calclen, b64len;
|
||||
int rc = EXIT_SUCCESS;
|
||||
char *b64;
|
||||
|
||||
b64_calclen = (oi->size / 3) * 4;
|
||||
if (oi->size % 3 > 0)
|
||||
b64_calclen += 4;
|
||||
|
||||
b64 = util_zalloc(b64_calclen + 1); /* adds NUL byte */
|
||||
b64len = EVP_EncodeBlock((unsigned char *)b64, oi->raw, oi->size);
|
||||
if (b64len != b64_calclen) {
|
||||
fprintf(stderr, "encoding base64 via openssl failed\n");
|
||||
rc = EXIT_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
util_fmt_pair(FMT_QUOTE, "module_info", b64);
|
||||
out:
|
||||
free(b64);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void optics_json_print(struct opticsmon_ctx *ctx, struct zpci_netdev *nd, struct optics *oi)
|
||||
{
|
||||
util_fmt_obj_start(FMT_DEFAULT, "netdev");
|
||||
util_fmt_pair(FMT_QUOTE, "name", nd->name);
|
||||
util_fmt_pair(FMT_QUOTE, "operstate", zpci_operstate_str(nd->operstate));
|
||||
util_fmt_obj_start(FMT_DEFAULT, "optics");
|
||||
util_fmt_pair(FMT_QUOTE, "type", optics_type_str(optics_type(oi)));
|
||||
util_fmt_pair(FMT_QUOTE, "rx_los", optics_los_str(optics_rx_los(oi)));
|
||||
util_fmt_pair(FMT_QUOTE, "tx_los", optics_los_str(optics_tx_los(oi)));
|
||||
util_fmt_pair(FMT_QUOTE, "tx_fault", optics_los_str(optics_rx_los(oi)));
|
||||
if (ctx->opts.module_info)
|
||||
module_info_pair(oi);
|
||||
util_fmt_obj_end();
|
||||
util_fmt_obj_end();
|
||||
}
|
||||
|
||||
static int dump_adapter_data(struct opticsmon_ctx *ctx, struct zpci_dev *zdev)
|
||||
{
|
||||
struct optics **ois;
|
||||
int num_ois = 0;
|
||||
char *pci_addr;
|
||||
int i, rc;
|
||||
|
||||
ois = util_zalloc(sizeof(ois[0]) * zdev->num_netdevs);
|
||||
for (i = 0; i < zdev->num_netdevs; i++) {
|
||||
rc = ethtool_nl_get_optics(&ctx->ethtool_ctx, zdev->netdevs[i].name, &ois[i]);
|
||||
if (rc)
|
||||
goto free_ois;
|
||||
num_ois++;
|
||||
}
|
||||
if (!ctx->opts.quiet) {
|
||||
util_fmt_obj_start(FMT_DEFAULT, "adapter");
|
||||
util_fmt_pair(FMT_QUOTE, "pft", zpci_pft_str(zdev));
|
||||
util_fmt_obj_start(FMT_DEFAULT, "ids");
|
||||
util_fmt_pair(FMT_QUOTE, "fid", "0x%0x", zdev->fid);
|
||||
if (zdev->uid_is_unique)
|
||||
util_fmt_pair(FMT_QUOTE, "uid", "0x%0x", zdev->uid);
|
||||
pci_addr = zpci_pci_addr(zdev);
|
||||
util_fmt_pair(FMT_QUOTE, "pci_address", pci_addr);
|
||||
free(pci_addr);
|
||||
util_fmt_obj_end();
|
||||
util_fmt_obj_start(FMT_LIST, "netdevs");
|
||||
for (i = 0; i < zdev->num_netdevs; i++)
|
||||
optics_json_print(ctx, &zdev->netdevs[i], ois[i]);
|
||||
util_fmt_obj_end(); /* netdevs list */
|
||||
util_fmt_obj_end(); /* adapter */
|
||||
fflush(stdout);
|
||||
}
|
||||
if (ctx->opts.report) {
|
||||
for (i = 0; i < zdev->num_netdevs; i++) {
|
||||
rc = sclp_issue_optics_report(zdev, ois[i]);
|
||||
if (rc == -ENOTSUP) {
|
||||
fprintf(stderr, "Skipping %s which does not support reporting\n",
|
||||
zdev->netdevs[i].name);
|
||||
} else if (rc < 0) {
|
||||
fprintf(stderr, "Error issuing SCLP for optics data failed: %s\n",
|
||||
strerror(-rc));
|
||||
}
|
||||
}
|
||||
}
|
||||
free_ois:
|
||||
for (i = 0; i < num_ois; i++)
|
||||
optics_free(ois[i]);
|
||||
free(ois);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void zpci_list_reload(struct util_list **zpci_list)
|
||||
{
|
||||
if (*zpci_list)
|
||||
zpci_free_dev_list(*zpci_list);
|
||||
*zpci_list = zpci_dev_list();
|
||||
}
|
||||
|
||||
static void dump_all_adapter_data(struct opticsmon_ctx *ctx)
|
||||
{
|
||||
struct zpci_dev *zdev;
|
||||
|
||||
zpci_list_reload(&ctx->zpci_list);
|
||||
util_list_iterate(ctx->zpci_list, zdev) {
|
||||
/* Filter non-NIC devices and VFs */
|
||||
if (zpci_is_vf(zdev) || !zdev->num_netdevs)
|
||||
continue;
|
||||
dump_adapter_data(ctx, zdev);
|
||||
}
|
||||
}
|
||||
|
||||
static int oneshot_mode(struct opticsmon_ctx *ctx)
|
||||
{
|
||||
util_fmt_init(stdout, FMT_JSON, FMT_DEFAULT, API_LEVEL);
|
||||
if (!ctx->opts.quiet)
|
||||
util_fmt_obj_start(FMT_LIST, "adapters");
|
||||
dump_all_adapter_data(ctx);
|
||||
if (!ctx->opts.quiet)
|
||||
util_fmt_obj_end();
|
||||
util_fmt_exit();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
void on_link_change(struct zpci_netdev *netdev, void *arg)
|
||||
{
|
||||
struct opticsmon_ctx *ctx = arg;
|
||||
struct zpci_netdev *found_netdev;
|
||||
struct zpci_dev *zdev = NULL;
|
||||
int reloads = 1;
|
||||
|
||||
do {
|
||||
if (ctx->zpci_list) {
|
||||
zdev = zpci_find_by_netdev(ctx->zpci_list, netdev->name, &found_netdev);
|
||||
if (zdev) {
|
||||
/* Skip data collection if operational state is
|
||||
* unchanged
|
||||
*/
|
||||
if (found_netdev->operstate == netdev->operstate)
|
||||
return;
|
||||
/* Update operation state for VFs even though
|
||||
* they are skipped just for a consistent view
|
||||
*/
|
||||
found_netdev->operstate = netdev->operstate;
|
||||
/* Only collect optics data for PFs */
|
||||
if (!zpci_is_vf(zdev))
|
||||
dump_adapter_data(ctx, zdev);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Could be uninitalized list or a new device, retry after reload */
|
||||
zpci_list_reload(&ctx->zpci_list);
|
||||
reloads--;
|
||||
} while (reloads > 0);
|
||||
}
|
||||
|
||||
#define MAX_EVENTS 8
|
||||
|
||||
static int monitor_wait_loop(struct opticsmon_ctx *ctx, int sigfd, int timerfd)
|
||||
{
|
||||
struct epoll_event events[MAX_EVENTS];
|
||||
struct signalfd_siginfo fdsi;
|
||||
int i, nlfd, epfd, nfds;
|
||||
struct epoll_event ev;
|
||||
uint64_t expirations;
|
||||
ssize_t sread;
|
||||
|
||||
epfd = epoll_create1(EPOLL_CLOEXEC);
|
||||
|
||||
ev.events = EPOLLIN;
|
||||
ev.data.fd = sigfd;
|
||||
if (epoll_ctl(epfd, EPOLL_CTL_ADD, sigfd, &ev) == -1)
|
||||
return -EIO;
|
||||
|
||||
ev.events = EPOLLIN;
|
||||
ev.data.fd = timerfd;
|
||||
if (epoll_ctl(epfd, EPOLL_CTL_ADD, timerfd, &ev) == -1)
|
||||
return -EIO;
|
||||
|
||||
nlfd = link_mon_nl_waitfd_getfd(&ctx->lctx);
|
||||
ev.events = EPOLLIN;
|
||||
ev.data.fd = nlfd;
|
||||
if (epoll_ctl(epfd, EPOLL_CTL_ADD, nlfd, &ev) == -1)
|
||||
return -EIO;
|
||||
|
||||
while (1) {
|
||||
nfds = epoll_wait(epfd, events, MAX_EVENTS, -1);
|
||||
if (nfds < 0)
|
||||
return nfds;
|
||||
for (i = 0; i < nfds; i++) {
|
||||
/* signal fd */
|
||||
if (events[i].data.fd == sigfd) {
|
||||
sread = read(sigfd, &fdsi, sizeof(fdsi));
|
||||
if (sread != sizeof(fdsi))
|
||||
return -EIO;
|
||||
switch (fdsi.ssi_signo) {
|
||||
case SIGINT:
|
||||
case SIGTERM:
|
||||
case SIGQUIT:
|
||||
return 0;
|
||||
/* Unexpected signal */
|
||||
default:
|
||||
return -EIO;
|
||||
}
|
||||
/* timer fd */
|
||||
} else if (events[i].data.fd == timerfd) {
|
||||
sread = read(timerfd, &expirations, sizeof(uint64_t));
|
||||
if (sread != sizeof(uint64_t))
|
||||
return -EIO;
|
||||
if (!expirations)
|
||||
continue;
|
||||
dump_all_adapter_data(ctx);
|
||||
/* netlink fd */
|
||||
} else if (events[i].data.fd == nlfd) {
|
||||
link_mon_nl_waitfd_read(&ctx->lctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int monitor_mode(struct opticsmon_ctx *ctx)
|
||||
{
|
||||
struct itimerspec timerspec;
|
||||
int sigfd, timerfd, ret;
|
||||
sigset_t mask;
|
||||
|
||||
sigemptyset(&mask);
|
||||
sigaddset(&mask, SIGINT);
|
||||
sigaddset(&mask, SIGQUIT);
|
||||
sigaddset(&mask, SIGTERM);
|
||||
|
||||
if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
|
||||
return -EIO;
|
||||
|
||||
sigfd = signalfd(-1, &mask, 0);
|
||||
if (sigfd == -1) {
|
||||
fprintf(stderr, "Failed to create signalfd\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
timerfd = timerfd_create(CLOCK_MONOTONIC, 0);
|
||||
if (timerfd == -1) {
|
||||
fprintf(stderr, "Failed to create timerfd\n");
|
||||
ret = -EIO;
|
||||
goto close_signalfd;
|
||||
}
|
||||
|
||||
/* Set initial expiration to 1 ns so we gather optics data at startup */
|
||||
timerspec.it_value.tv_sec = 0;
|
||||
timerspec.it_value.tv_nsec = 1;
|
||||
timerspec.it_interval.tv_sec = ctx->opts.interval_seconds;
|
||||
timerspec.it_interval.tv_nsec = 0;
|
||||
ret = timerfd_settime(timerfd, 0, &timerspec, NULL);
|
||||
if (ret == -1) {
|
||||
fprintf(stderr, "Failed to arm timer\n");
|
||||
goto close_timerfd;
|
||||
}
|
||||
|
||||
util_fmt_init(stdout, FMT_JSONSEQ, FMT_DEFAULT, API_LEVEL);
|
||||
ret = link_mon_nl_waitfd_create(&ctx->lctx, on_link_change, ctx);
|
||||
if (ret) {
|
||||
fprintf(stderr, "Failed to create link monitoring socket\n");
|
||||
goto close_timerfd;
|
||||
}
|
||||
|
||||
monitor_wait_loop(ctx, sigfd, timerfd);
|
||||
|
||||
link_mon_nl_waitfd_destroy(&ctx->lctx);
|
||||
util_fmt_exit();
|
||||
close_signalfd:
|
||||
close(sigfd);
|
||||
close_timerfd:
|
||||
close(timerfd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct opticsmon_ctx ctx = { .opts = { .interval_seconds = 86400 } };
|
||||
int ret;
|
||||
|
||||
parse_cmdline(argc, argv, &ctx.opts);
|
||||
ethtool_nl_connect(&ctx.ethtool_ctx);
|
||||
if (ctx.opts.monitor)
|
||||
ret = monitor_mode(&ctx);
|
||||
else
|
||||
ret = oneshot_mode(&ctx);
|
||||
ethtool_nl_close(&ctx.ethtool_ctx);
|
||||
|
||||
if (ctx.zpci_list)
|
||||
zpci_free_dev_list(ctx.zpci_list);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -44,7 +44,20 @@
|
||||
#define MAX_GET_DATA 4094 /* maximum GET response data length */
|
||||
#define GET_AREA_LEN MAX_GET_DATA + 512 /* size for GET command area length */
|
||||
#define TIME_BUF_SIZE 128 /* buffer size for date and time string */
|
||||
#define MAX_OID_STR_LEN MAX_OID_LEN * 5 /* max OID string size */
|
||||
|
||||
/*
|
||||
* Define maximum SNMP OID string size.
|
||||
* An OID can have up to 128 sub-ids and each sub-id can have up to 10
|
||||
* digits. When converted to string, this means 1 character for the
|
||||
* period separator and 10 characters for the digits themselves. At
|
||||
* the end of OID string, we need one more character for the null
|
||||
* terminator. The unsigned long data type, which can have up to 20
|
||||
* digits is used to represent a sub-id. This means each sub-id
|
||||
* string now needs 20+1 characters instead of 10+1 in-order to avoid
|
||||
* compiler warnings.
|
||||
*/
|
||||
#define MAX_OID_STR_LEN (MAX_OID_LEN * 21) + 1
|
||||
|
||||
/* definitions for 2.6 qeth */
|
||||
#define QETH_SYSFILE "/sys/bus/ccwgroup/drivers/qeth/notifier_register"
|
||||
#define SIOC_QETH_ADP_SET_SNMP_CONTROL (SIOCDEVPRIVATE + 5)
|
||||
|
||||
@@ -110,7 +110,7 @@ int str_to_oid_conv ( char* uc_oid, oid* ul_oid )
|
||||
*********************************************************************/
|
||||
int oid_to_str_conv (oid* ul_oid, size_t length, char* uc_oid )
|
||||
{
|
||||
#define MAX_CHARS 50 /* size of buffer */
|
||||
#define MAX_CHARS 22 /* size of buffer */
|
||||
int i;
|
||||
short valid = TRUE;
|
||||
char buffer[MAX_CHARS]; /* buffer used for conversion */
|
||||
@@ -125,9 +125,9 @@ int oid_to_str_conv (oid* ul_oid, size_t length, char* uc_oid )
|
||||
{
|
||||
/* convert and append OID digit to return string */
|
||||
if (i == 0)
|
||||
sprintf( buffer, "%lu", ul_oid[i] );
|
||||
snprintf( buffer, sizeof(buffer), "%lu", ul_oid[i] );
|
||||
else
|
||||
sprintf( buffer, ".%lu", ul_oid[i] );
|
||||
snprintf( buffer, sizeof(buffer), ".%lu", ul_oid[i] );
|
||||
|
||||
strcat( uc_oid, buffer );
|
||||
} /* end for */
|
||||
|
||||
30
rust/Cargo.lock
generated
30
rust/Cargo.lock
generated
@@ -367,7 +367,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -917,7 +917,7 @@ dependencies = [
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -958,6 +958,7 @@ dependencies = [
|
||||
"s390_pv_core",
|
||||
"serde",
|
||||
"serde_test",
|
||||
"testing_logger",
|
||||
"thiserror",
|
||||
"zerocopy",
|
||||
]
|
||||
@@ -1118,7 +1119,7 @@ dependencies = [
|
||||
"getrandom 0.4.2",
|
||||
"once_cell",
|
||||
"rustix",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1128,7 +1129,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "230a1b821ccbd75b185820a1f1ff7b14d21da1e442e22c0863ea5f08771a8874"
|
||||
dependencies = [
|
||||
"rustix",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "testing_logger"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d92b727cb45d33ae956f7f46b966b25f1bc712092aeef9dba5ac798fc89f720"
|
||||
dependencies = [
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1212,9 +1222,21 @@ dependencies = [
|
||||
"clap",
|
||||
"libc",
|
||||
"log",
|
||||
"openssl",
|
||||
"s390_pv",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"utils_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "utils_macros"
|
||||
version = "0.12.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -11,6 +11,7 @@ members = [
|
||||
"pvsecret",
|
||||
"pvverify",
|
||||
"utils",
|
||||
"utils_macros",
|
||||
]
|
||||
resolver = "2"
|
||||
|
||||
|
||||
@@ -29,3 +29,4 @@ pv_core = { path = "../pv_core", package = "s390_pv_core", version = "0.12.0" }
|
||||
|
||||
[dev-dependencies]
|
||||
serde_test = "1.0.177"
|
||||
testing_logger = "0.1.1"
|
||||
|
||||
@@ -17,6 +17,8 @@ use crate::{assert_size, request::MagicValue, static_assert, Error, Result, PAGE
|
||||
pub enum SeHdrVersion {
|
||||
/// Secure Execution header v1
|
||||
One = 0x100,
|
||||
/// Secure Execution header v2
|
||||
Two = 0x200,
|
||||
}
|
||||
|
||||
/// Struct containing all SE-header tags.
|
||||
@@ -241,6 +243,7 @@ impl BootHdrTags {
|
||||
// Some sanity checks
|
||||
let hdr_version = match hdr_head.version.get() {
|
||||
0x100 => SeHdrVersion::One,
|
||||
0x200 => SeHdrVersion::Two,
|
||||
_ => {
|
||||
debug!("Unsupported hdr-version: {:0>4x}", hdr_head.version.get());
|
||||
return Err(Error::InvBootHdr);
|
||||
|
||||
@@ -7,12 +7,14 @@ use std::fmt::Display;
|
||||
use std::ops::Range;
|
||||
|
||||
use enum_dispatch::enum_dispatch;
|
||||
use openssl::bn::BigNumContext;
|
||||
use openssl::derive::Deriver;
|
||||
use openssl::ec::{EcGroup, EcKey};
|
||||
use openssl::ec::{EcGroup, EcKey, EcPoint};
|
||||
use openssl::error::ErrorStack;
|
||||
use openssl::hash::{DigestBytes, MessageDigest};
|
||||
use openssl::md::MdRef;
|
||||
use openssl::nid::Nid;
|
||||
use openssl::pkey::{HasPublic, Id, PKey, PKeyRef, Private, Public};
|
||||
use openssl::pkey::{HasPublic, Id, KeyType, PKey, PKeyRef, Private, Public};
|
||||
use openssl::pkey_ctx::{HkdfMode, PkeyCtx};
|
||||
use openssl::rand::rand_bytes;
|
||||
use openssl::rsa::Padding;
|
||||
@@ -23,8 +25,51 @@ use openssl::symm::{
|
||||
use pv_core::request::Confidential;
|
||||
|
||||
use crate::error::Result;
|
||||
use crate::openssl_extensions::PkeyEncapsulateContext;
|
||||
use crate::req::get_pub_ecdh_points;
|
||||
use crate::request::EcPubKeyCoord;
|
||||
use crate::Error;
|
||||
|
||||
/// Compute ECDH shared secret from public and private keys
|
||||
///
|
||||
/// It is expected that the public and private key are with respect to EC-P521.
|
||||
///
|
||||
/// Note that the output is the concatenation of the 80-bytes-left-padded x and
|
||||
/// 80-bytes-left-padded y coordinate.
|
||||
fn ecdh_shared_secret(
|
||||
pub_key: &PKeyRef<Public>,
|
||||
priv_key: &PKeyRef<Private>,
|
||||
) -> Result<[u8; 160], ErrorStack> {
|
||||
let pub_key = pub_key.ec_key()?;
|
||||
let priv_key = priv_key.ec_key()?;
|
||||
|
||||
// Verify both keys use the EC-P521 curve (SECP521R1)
|
||||
assert_eq!(
|
||||
pub_key.group().curve_name(),
|
||||
Some(Nid::SECP521R1),
|
||||
"Public key must use EC-P521 curve"
|
||||
);
|
||||
assert_eq!(
|
||||
priv_key.group().curve_name(),
|
||||
Some(Nid::SECP521R1),
|
||||
"Private key must use EC-P521 curve"
|
||||
);
|
||||
|
||||
pub_key.check_key()?;
|
||||
priv_key.check_key()?;
|
||||
let group = pub_key.group();
|
||||
let mut bn_ctx = BigNumContext::new()?;
|
||||
let mut point = EcPoint::new(group)?;
|
||||
point.mul2(
|
||||
group,
|
||||
pub_key.public_key(),
|
||||
priv_key.private_key(),
|
||||
&mut bn_ctx,
|
||||
)?;
|
||||
let coord = get_pub_ecdh_points(&point, group)?;
|
||||
Ok(coord)
|
||||
}
|
||||
|
||||
/// An AES256-GCM key that will purge itself out of the memory when going out of scope
|
||||
pub type Aes256GcmKey = Confidential<[u8; SymKeyType::AES_256_GCM_KEY_LEN]>;
|
||||
/// An AES256-XTS key that will purge itself out of the memory when going out of scope
|
||||
@@ -74,6 +119,7 @@ impl SymKeyType {
|
||||
}
|
||||
|
||||
/// Returns true if the [`SymKeyType`] is an AEAD key
|
||||
#[must_use]
|
||||
pub const fn is_aead(&self) -> bool {
|
||||
self.tag_len().is_some()
|
||||
}
|
||||
@@ -214,6 +260,220 @@ pub fn derive_aes256_gcm_key(k1: &PKeyRef<Private>, k2: &PKeyRef<Public>) -> Res
|
||||
))
|
||||
}
|
||||
|
||||
/// Determines the KeyType of a given PKey by testing against all known key types.
|
||||
///
|
||||
/// This function iterates through all known OpenSSL key types and uses the `is_a()`
|
||||
/// method to identify which type the provided key matches. This is more reliable than
|
||||
/// using `Id` to `KeyType` conversion, especially for newer key types like ML-KEM
|
||||
/// that may not have a direct `Id` mapping.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// * `key` - A reference to the PKey to identify
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// * `Some(KeyType)` - If the key matches one of the known key types
|
||||
/// * `None` - If the key type is not recognized or doesn't match any known types
|
||||
fn pkey_to_keytype<T>(key: &PKeyRef<T>) -> Option<KeyType> {
|
||||
const KNOWN_KEY_TYPES: &[KeyType] = &[
|
||||
KeyType::RSA,
|
||||
KeyType::RSA_PSS,
|
||||
KeyType::DSA,
|
||||
KeyType::DH,
|
||||
KeyType::EC,
|
||||
KeyType::HMAC,
|
||||
KeyType::CMAC,
|
||||
KeyType::X25519,
|
||||
KeyType::ED25519,
|
||||
KeyType::X448,
|
||||
KeyType::ED448,
|
||||
KeyType::ML_KEM_512,
|
||||
KeyType::ML_KEM_768,
|
||||
KeyType::ML_KEM_1024,
|
||||
];
|
||||
|
||||
KNOWN_KEY_TYPES
|
||||
.iter()
|
||||
.find(|&&key_type| key.is_a(key_type))
|
||||
.copied()
|
||||
}
|
||||
|
||||
fn key_type_str(t: KeyType) -> &'static str {
|
||||
if t == KeyType::RSA {
|
||||
"RSA"
|
||||
} else if t == KeyType::RSA_PSS {
|
||||
"RSA-PSS"
|
||||
} else if t == KeyType::DSA {
|
||||
"DSA"
|
||||
} else if t == KeyType::DH {
|
||||
"DH"
|
||||
} else if t == KeyType::EC {
|
||||
"EC"
|
||||
} else if t == KeyType::HMAC {
|
||||
"HMAC"
|
||||
} else if t == KeyType::CMAC {
|
||||
"CMAC"
|
||||
} else if t == KeyType::X25519 {
|
||||
"X25519"
|
||||
} else if t == KeyType::ED25519 {
|
||||
"ED25519"
|
||||
} else if t == KeyType::X448 {
|
||||
"X448"
|
||||
} else if t == KeyType::ED448 {
|
||||
"ED448"
|
||||
} else if t == KeyType::ML_KEM_512 {
|
||||
"ML-KEM-512"
|
||||
} else if t == KeyType::ML_KEM_768 {
|
||||
"ML-KEM-768"
|
||||
} else if t == KeyType::ML_KEM_1024 {
|
||||
"ML-KEM-1024"
|
||||
} else {
|
||||
"unknown"
|
||||
}
|
||||
}
|
||||
|
||||
/// Validates that a key matches the expected key type.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns an error if the key doesn't match the expected type.
|
||||
pub(crate) fn validate_key_type<T: HasPublic>(
|
||||
key: &PKeyRef<T>,
|
||||
key_name: &str,
|
||||
expected_type: KeyType,
|
||||
) -> Result<()> {
|
||||
if !key.is_a(expected_type) {
|
||||
return Err(Error::RetrInvKey {
|
||||
what: "key type",
|
||||
kind: key_name.to_string(),
|
||||
value: pkey_to_keytype(key)
|
||||
.map(key_type_str)
|
||||
.unwrap_or("unknown")
|
||||
.to_string(),
|
||||
exp: key_type_str(expected_type).to_string(),
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Validates that a key is an EC key with the specified curve.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns an error if the key is not an EC key or doesn't use the expected curve.
|
||||
pub(crate) fn validate_ec_key<T: HasPublic>(
|
||||
key: &PKeyRef<T>,
|
||||
key_name: &str,
|
||||
expected_curve: Nid,
|
||||
) -> Result<()> {
|
||||
if key.id() != Id::EC {
|
||||
return Err(Error::RetrInvKey {
|
||||
what: "key type",
|
||||
kind: key_name.to_string(),
|
||||
value: pkey_to_keytype(key)
|
||||
.map(key_type_str)
|
||||
.unwrap_or("unknown")
|
||||
.to_string(),
|
||||
exp: format!("EC ({})", expected_curve.long_name().unwrap_or("unknown")),
|
||||
});
|
||||
}
|
||||
let ec_key = key.ec_key()?;
|
||||
if ec_key.group().curve_name() != Some(expected_curve) {
|
||||
return Err(Error::RetrInvKey {
|
||||
what: "curve",
|
||||
kind: key_name.to_string(),
|
||||
value: ec_key
|
||||
.group()
|
||||
.curve_name()
|
||||
.and_then(|nid| nid.long_name().ok())
|
||||
.unwrap_or("unknown")
|
||||
.to_string(),
|
||||
exp: expected_curve.long_name().unwrap_or("unknown").to_string(),
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Derive a symmetric AES 256 GCM key from a private target key, a public
|
||||
/// customer key, and a public ML-KEM target key.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// The derived key and the ML-KEM ciphertext (KC).
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This function will return an error if something went bad in OpenSSL or the
|
||||
/// wrong key types were used.
|
||||
pub fn derive_aes256_gcm_key_hybrid(
|
||||
priv_ecdh_cust_key: &PKeyRef<Private>,
|
||||
pub_ecdh_target_key: &PKeyRef<Public>,
|
||||
pub_mlkem_target_key: &PKeyRef<Public>,
|
||||
) -> Result<(Aes256GcmKey, Vec<u8>)> {
|
||||
let mut buffer: Vec<u8> = vec![0, 0, 0, 1];
|
||||
|
||||
validate_ec_key(priv_ecdh_cust_key, "ECDH customer key", Nid::SECP521R1)?;
|
||||
validate_ec_key(pub_ecdh_target_key, "ECDH target key", Nid::SECP521R1)?;
|
||||
validate_key_type(
|
||||
pub_mlkem_target_key,
|
||||
"ML-KEM target key",
|
||||
KeyType::ML_KEM_1024,
|
||||
)?;
|
||||
|
||||
// Derive the ECDH shared secret
|
||||
let ecdh_derived_secret = ecdh_shared_secret(pub_ecdh_target_key, priv_ecdh_cust_key)?;
|
||||
assert_eq!(ecdh_derived_secret.as_ref().len(), 160);
|
||||
buffer.extend_from_slice(ecdh_derived_secret.as_ref());
|
||||
|
||||
// Derive the ML-KEM shared secret
|
||||
let mut ctx = PkeyCtx::new(pub_mlkem_target_key)?;
|
||||
ctx.encapsulate_init()?;
|
||||
let (mut ciphertext, mut shared_secret) = (vec![], vec![]);
|
||||
ctx.encapsulate_to_vec(&mut ciphertext, &mut shared_secret)?;
|
||||
assert_eq!(ciphertext.len(), 1568);
|
||||
assert_eq!(shared_secret.len(), 32);
|
||||
buffer.extend_from_slice(&shared_secret);
|
||||
|
||||
// Append the private ECDH customer key
|
||||
let pub_ecdh_cust_key = EcPubKeyCoord::try_from(priv_ecdh_cust_key)?;
|
||||
assert_eq!(pub_ecdh_cust_key.as_ref().len(), 160);
|
||||
buffer.extend_from_slice(pub_ecdh_cust_key.as_ref());
|
||||
|
||||
// Append the ciphertext
|
||||
buffer.extend_from_slice(&ciphertext);
|
||||
|
||||
// Append the public ECDH target key
|
||||
let pub_ecdh_target_key: EcPubKeyCoord = pub_ecdh_target_key.try_into()?;
|
||||
assert_eq!(pub_ecdh_target_key.as_ref().len(), 160);
|
||||
buffer.extend_from_slice(pub_ecdh_target_key.as_ref());
|
||||
|
||||
// Append the public ML-KEM target key
|
||||
assert_eq!(pub_mlkem_target_key.raw_public_key()?.len(), 1568);
|
||||
buffer.extend_from_slice(&pub_mlkem_target_key.raw_public_key()?);
|
||||
|
||||
// Append the magic string
|
||||
const STRING: &str = "PQC Secure Execution with Format-2 Key Slots KS2";
|
||||
assert_eq!(STRING.len(), 48);
|
||||
buffer.extend_from_slice(STRING.as_bytes());
|
||||
|
||||
// Sanity check
|
||||
assert_eq!(buffer.len(), 4 + 160 + 32 + 160 + 1568 + 160 + 1568 + 48);
|
||||
|
||||
let secr = Confidential::new(buffer);
|
||||
|
||||
// Panic: does not panic as SHA256 digest is 32 bytes long
|
||||
Ok((
|
||||
Aes256GcmKey::new(
|
||||
hash(MessageDigest::sha256(), secr.value())?
|
||||
.as_ref()
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
),
|
||||
ciphertext,
|
||||
))
|
||||
}
|
||||
|
||||
/// Generate a random array.
|
||||
///
|
||||
/// # Errors
|
||||
@@ -548,10 +808,167 @@ pub(crate) fn verify_signature<T: HasPublic>(
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
|
||||
use super::*;
|
||||
use crate::test_utils::*;
|
||||
use crate::{get_test_asset, PvCoreError};
|
||||
|
||||
/// Test that deterministic RNG contexts are thread-local and don't interfere.
|
||||
///
|
||||
/// Per OpenSSL documentation (RAND_get0_primary(3)):
|
||||
/// "The public and private DRBG are thread-local instances, which are used by
|
||||
/// RAND_bytes() and RAND_priv_bytes(), respectively."
|
||||
///
|
||||
/// Reference: <https://docs.openssl.org/3.1/man3/RAND_get0_primary/>
|
||||
///
|
||||
/// Note: RAND_set0_public() and RAND_set0_private() require OpenSSL >= 3.1.
|
||||
#[test]
|
||||
fn test_deterministic_rng_thread_isolation() {
|
||||
use std::sync::Barrier;
|
||||
|
||||
use openssl::rand::rand_bytes;
|
||||
|
||||
// Barriers to synchronize: thread1 installs → thread2 installs → both generate → both
|
||||
// complete
|
||||
let barrier_after_t1_install = Arc::new(Barrier::new(2));
|
||||
let barrier_after_t2_install = Arc::new(Barrier::new(2));
|
||||
let barrier_after_rand_bytes = Arc::new(Barrier::new(2));
|
||||
|
||||
let barrier1_clone = Arc::clone(&barrier_after_t1_install);
|
||||
let barrier2_clone = Arc::clone(&barrier_after_t2_install);
|
||||
let barrier3_clone = Arc::clone(&barrier_after_rand_bytes);
|
||||
|
||||
// Thread 1: Install deterministic RNG with specific entropy
|
||||
let thread1 = thread::spawn(move || {
|
||||
let entropy = [0x42u8; 4096];
|
||||
let nonce = [0x24u8; 48];
|
||||
|
||||
// Install thread-local deterministic RNG
|
||||
let _rng = DeterministicTestRandGuard::install(&entropy, &nonce).unwrap();
|
||||
|
||||
// Signal thread2 that we've installed our RNG
|
||||
barrier1_clone.wait();
|
||||
|
||||
// Wait for thread2 to install its RNG
|
||||
barrier2_clone.wait();
|
||||
|
||||
// Now generate bytes while thread2 also has its RNG installed
|
||||
let mut buf = [0u8; 32];
|
||||
rand_bytes(&mut buf).unwrap();
|
||||
|
||||
// Wait for thread2 to also complete rand_bytes
|
||||
barrier3_clone.wait();
|
||||
|
||||
buf
|
||||
});
|
||||
|
||||
// Thread 2: Install different deterministic RNG after thread1
|
||||
let thread2 = thread::spawn(move || {
|
||||
// Wait for thread1 to install its RNG first
|
||||
barrier_after_t1_install.wait();
|
||||
|
||||
// Now install our own thread-local deterministic RNG with different entropy
|
||||
let entropy = [0xAAu8; 4096];
|
||||
let nonce = [0x55u8; 48];
|
||||
let _rng = DeterministicTestRandGuard::install(&entropy, &nonce).unwrap();
|
||||
|
||||
// Signal thread1 that we've installed our RNG
|
||||
barrier_after_t2_install.wait();
|
||||
|
||||
// Generate bytes with our different entropy (concurrently with thread1)
|
||||
let mut buf = [0u8; 32];
|
||||
rand_bytes(&mut buf).unwrap();
|
||||
|
||||
// Wait for thread1 to also complete rand_bytes
|
||||
barrier_after_rand_bytes.wait();
|
||||
|
||||
buf
|
||||
});
|
||||
|
||||
let t1_buf = thread1.join().unwrap();
|
||||
let t2_buf = thread2.join().unwrap();
|
||||
|
||||
// Expected deterministic values for thread 1 (entropy=0x42, nonce=0x24)
|
||||
let expected_t1: [u8; 32] = [
|
||||
66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
|
||||
66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
|
||||
];
|
||||
|
||||
// Expected deterministic values for thread 2 (entropy=0xAA, nonce=0x55)
|
||||
let expected_t2: [u8; 32] = [
|
||||
170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170,
|
||||
170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170,
|
||||
];
|
||||
|
||||
// Verify each thread produced its expected deterministic output
|
||||
assert_eq!(
|
||||
t1_buf, expected_t1,
|
||||
"Thread 1 should produce deterministic output"
|
||||
);
|
||||
assert_eq!(
|
||||
t2_buf, expected_t2,
|
||||
"Thread 2 should produce deterministic output"
|
||||
);
|
||||
|
||||
// Also verify they are different (proves thread-local isolation)
|
||||
assert_ne!(
|
||||
t1_buf, t2_buf,
|
||||
"Different thread-local entropy should produce different output"
|
||||
);
|
||||
}
|
||||
|
||||
/// Test that the original RNG is properly restored after DeterministicTestRandGuard is dropped
|
||||
#[test]
|
||||
fn test_deterministic_rng_restoration() {
|
||||
use openssl::rand::rand_bytes;
|
||||
|
||||
// Generate random bytes with system RNG before installing deterministic RNG
|
||||
let mut before_buf = [0u8; 32];
|
||||
rand_bytes(&mut before_buf).unwrap();
|
||||
|
||||
let deterministic_buf = {
|
||||
let entropy = [0x42u8; 4096];
|
||||
let nonce = [0x24u8; 48];
|
||||
|
||||
// Install deterministic RNG
|
||||
let _rng = DeterministicTestRandGuard::install(&entropy, &nonce).unwrap();
|
||||
|
||||
// Generate deterministic bytes
|
||||
let mut buf = [0u8; 32];
|
||||
rand_bytes(&mut buf).unwrap();
|
||||
|
||||
// Expected deterministic output
|
||||
let expected: [u8; 32] = [
|
||||
66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
|
||||
66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
|
||||
];
|
||||
assert_eq!(buf, expected, "Should produce deterministic output");
|
||||
|
||||
buf
|
||||
// _rng is dropped here, should restore original RNG
|
||||
};
|
||||
|
||||
// Generate random bytes again with restored system RNG
|
||||
let mut after_buf = [0u8; 32];
|
||||
rand_bytes(&mut after_buf).unwrap();
|
||||
|
||||
// The system RNG should produce different random values each time
|
||||
// (extremely unlikely to match the deterministic output)
|
||||
assert_ne!(
|
||||
after_buf, deterministic_buf,
|
||||
"After restoration, system RNG should produce different random values"
|
||||
);
|
||||
|
||||
// Also verify that before and after are different (system RNG produces random values)
|
||||
// Note: This could theoretically fail with probability 1/2^256, but that's negligible
|
||||
assert_ne!(
|
||||
before_buf, after_buf,
|
||||
"System RNG should produce different random values on each call"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sign_ec() {
|
||||
let (ec_key, _) = get_test_keys();
|
||||
@@ -603,6 +1020,112 @@ mod tests {
|
||||
assert_eq!(&calc_key, &exp_key);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn derive_aes256_gcm_key_hybrid() {
|
||||
let (cust_key, host_key_1, host_key_2) = get_test_keys_hybrid();
|
||||
let entropy = [0x5au8; 4096];
|
||||
let nonce = [0xa5u8; 48];
|
||||
|
||||
let _rng = DeterministicTestRandGuard::install(&entropy, &nonce).unwrap();
|
||||
|
||||
let exp_key: Aes256GcmKey = [
|
||||
197, 167, 157, 112, 186, 112, 72, 125, 192, 219, 168, 132, 178, 167, 249, 123, 149, 3,
|
||||
151, 166, 162, 66, 120, 39, 41, 230, 143, 54, 172, 10, 200, 143,
|
||||
]
|
||||
.into();
|
||||
let exp_kc = [
|
||||
54, 117, 96, 77, 148, 147, 170, 100, 34, 177, 95, 7, 35, 243, 145, 115, 7, 87, 178, 9,
|
||||
169, 99, 193, 99, 244, 195, 23, 78, 11, 153, 221, 196, 5, 192, 253, 192, 86, 49, 194,
|
||||
236, 43, 69, 183, 125, 166, 87, 158, 188, 13, 152, 19, 6, 253, 29, 194, 0, 101, 236,
|
||||
28, 171, 3, 236, 53, 186, 191, 109, 7, 83, 220, 93, 126, 29, 19, 203, 201, 39, 59, 7,
|
||||
131, 51, 81, 73, 254, 69, 105, 185, 214, 179, 155, 194, 189, 122, 106, 130, 249, 48, 4,
|
||||
33, 245, 170, 163, 4, 223, 208, 138, 224, 203, 119, 105, 59, 187, 153, 235, 90, 79,
|
||||
127, 29, 136, 230, 142, 78, 83, 27, 131, 58, 126, 76, 53, 129, 20, 85, 108, 86, 64,
|
||||
244, 90, 84, 177, 239, 105, 90, 41, 118, 189, 88, 174, 224, 216, 29, 10, 123, 81, 212,
|
||||
203, 197, 120, 20, 190, 3, 45, 37, 194, 208, 249, 232, 221, 67, 10, 62, 121, 143, 169,
|
||||
227, 165, 17, 30, 85, 223, 44, 141, 114, 142, 105, 119, 187, 41, 46, 8, 6, 17, 29, 165,
|
||||
117, 254, 92, 174, 231, 25, 117, 69, 112, 216, 80, 73, 185, 54, 50, 119, 145, 220, 174,
|
||||
26, 105, 81, 114, 210, 144, 148, 109, 218, 64, 78, 231, 196, 229, 88, 46, 128, 106,
|
||||
125, 204, 58, 184, 127, 193, 207, 86, 163, 98, 164, 57, 242, 29, 59, 251, 227, 185, 60,
|
||||
18, 68, 74, 47, 203, 61, 164, 78, 245, 100, 87, 148, 210, 97, 158, 252, 79, 78, 50,
|
||||
143, 35, 231, 215, 211, 75, 133, 214, 227, 140, 27, 21, 46, 221, 84, 89, 165, 161, 227,
|
||||
46, 117, 193, 254, 190, 237, 130, 28, 57, 52, 14, 235, 154, 115, 172, 185, 67, 116, 34,
|
||||
242, 158, 209, 0, 126, 196, 93, 224, 29, 246, 145, 65, 73, 185, 196, 4, 107, 124, 241,
|
||||
157, 230, 168, 244, 238, 84, 188, 173, 17, 238, 26, 161, 24, 176, 229, 226, 33, 244,
|
||||
167, 41, 107, 156, 29, 226, 248, 64, 146, 191, 210, 234, 76, 144, 219, 92, 136, 173,
|
||||
241, 98, 0, 71, 135, 214, 196, 116, 63, 243, 73, 71, 130, 171, 86, 204, 149, 69, 164,
|
||||
20, 177, 122, 95, 226, 95, 126, 106, 160, 59, 97, 137, 8, 73, 113, 189, 172, 24, 114,
|
||||
60, 62, 249, 193, 3, 99, 34, 153, 42, 238, 77, 181, 80, 185, 223, 39, 8, 44, 215, 119,
|
||||
214, 30, 136, 19, 215, 35, 184, 69, 94, 10, 170, 179, 51, 183, 105, 237, 237, 48, 199,
|
||||
122, 159, 87, 183, 71, 230, 87, 102, 77, 81, 116, 28, 126, 195, 72, 50, 157, 223, 243,
|
||||
83, 36, 16, 168, 111, 209, 132, 12, 96, 56, 140, 57, 144, 75, 253, 119, 123, 168, 2,
|
||||
79, 214, 121, 80, 154, 93, 235, 222, 130, 181, 166, 97, 51, 106, 21, 138, 224, 8, 144,
|
||||
223, 162, 152, 183, 6, 80, 64, 144, 21, 155, 56, 255, 108, 248, 125, 196, 46, 99, 119,
|
||||
94, 104, 63, 46, 15, 165, 30, 98, 75, 212, 193, 116, 151, 189, 65, 42, 83, 253, 183,
|
||||
41, 195, 45, 206, 178, 66, 36, 215, 197, 105, 236, 79, 91, 135, 164, 71, 187, 199, 200,
|
||||
150, 226, 182, 254, 6, 234, 109, 3, 17, 116, 249, 44, 211, 184, 61, 189, 44, 181, 249,
|
||||
8, 58, 230, 236, 8, 188, 14, 178, 100, 120, 250, 29, 1, 204, 158, 46, 161, 39, 66, 76,
|
||||
42, 114, 149, 160, 31, 87, 254, 181, 224, 17, 162, 163, 99, 11, 34, 149, 50, 203, 205,
|
||||
224, 38, 18, 233, 161, 49, 7, 151, 63, 81, 68, 71, 174, 49, 22, 143, 93, 50, 0, 154,
|
||||
152, 178, 134, 147, 152, 118, 196, 241, 233, 67, 102, 149, 179, 213, 176, 118, 64, 172,
|
||||
143, 134, 196, 232, 154, 110, 129, 155, 159, 103, 117, 202, 11, 35, 75, 104, 5, 11,
|
||||
160, 147, 174, 49, 248, 45, 247, 16, 7, 64, 209, 255, 170, 243, 242, 40, 158, 94, 239,
|
||||
194, 225, 113, 24, 90, 243, 73, 137, 217, 175, 130, 50, 133, 139, 250, 145, 190, 76,
|
||||
151, 183, 30, 86, 146, 59, 171, 214, 211, 135, 203, 192, 42, 189, 90, 47, 152, 132,
|
||||
168, 252, 175, 71, 234, 118, 207, 161, 176, 254, 189, 54, 174, 160, 178, 158, 133, 122,
|
||||
63, 75, 95, 201, 55, 139, 2, 208, 232, 110, 74, 201, 196, 135, 244, 156, 87, 208, 101,
|
||||
203, 121, 187, 16, 106, 80, 120, 165, 44, 147, 182, 114, 173, 186, 185, 255, 99, 85,
|
||||
88, 26, 27, 43, 203, 176, 207, 88, 20, 253, 169, 210, 168, 109, 75, 234, 239, 8, 243,
|
||||
244, 65, 164, 193, 255, 240, 215, 54, 158, 188, 93, 93, 54, 46, 77, 152, 78, 174, 154,
|
||||
67, 248, 24, 235, 172, 240, 83, 224, 17, 100, 217, 15, 172, 176, 46, 85, 107, 105, 127,
|
||||
147, 158, 202, 255, 145, 237, 84, 223, 100, 214, 38, 133, 169, 112, 227, 138, 220, 125,
|
||||
72, 197, 5, 227, 94, 245, 42, 70, 33, 209, 243, 70, 229, 37, 118, 214, 147, 43, 87, 39,
|
||||
241, 107, 26, 169, 28, 72, 223, 133, 145, 44, 248, 213, 52, 127, 250, 99, 193, 115,
|
||||
113, 147, 89, 112, 237, 199, 208, 36, 155, 106, 144, 73, 249, 8, 116, 198, 107, 120,
|
||||
233, 145, 11, 155, 178, 7, 66, 157, 255, 206, 128, 155, 233, 111, 148, 194, 214, 238,
|
||||
252, 230, 96, 119, 30, 37, 73, 133, 129, 87, 185, 149, 251, 156, 17, 8, 83, 106, 207,
|
||||
98, 203, 100, 39, 199, 127, 253, 59, 37, 121, 161, 216, 146, 6, 178, 183, 243, 191, 91,
|
||||
106, 243, 132, 111, 216, 163, 87, 210, 197, 173, 146, 65, 131, 194, 96, 70, 6, 7, 192,
|
||||
45, 173, 71, 44, 134, 122, 60, 173, 208, 238, 22, 187, 208, 212, 51, 191, 185, 174, 3,
|
||||
125, 28, 134, 216, 209, 4, 224, 199, 16, 15, 56, 70, 188, 216, 92, 24, 96, 57, 125,
|
||||
138, 151, 73, 254, 245, 106, 53, 4, 150, 74, 43, 42, 4, 157, 238, 125, 168, 41, 224,
|
||||
22, 249, 45, 117, 32, 180, 161, 41, 39, 180, 96, 24, 2, 102, 57, 116, 34, 75, 90, 72,
|
||||
134, 176, 2, 196, 59, 143, 182, 201, 117, 178, 153, 81, 108, 167, 122, 139, 71, 197,
|
||||
55, 114, 60, 161, 130, 14, 29, 79, 152, 55, 136, 62, 190, 228, 202, 53, 126, 4, 173,
|
||||
99, 28, 190, 224, 255, 134, 123, 166, 162, 244, 55, 26, 81, 120, 207, 193, 10, 103,
|
||||
153, 215, 220, 12, 71, 67, 217, 154, 212, 44, 200, 232, 0, 178, 39, 44, 22, 7, 14, 215,
|
||||
183, 192, 104, 51, 46, 93, 102, 195, 65, 9, 191, 241, 237, 151, 5, 64, 103, 228, 162,
|
||||
41, 123, 29, 5, 80, 203, 198, 234, 230, 107, 53, 60, 58, 253, 47, 152, 22, 77, 81, 86,
|
||||
215, 132, 152, 135, 6, 218, 46, 92, 192, 218, 198, 234, 76, 178, 25, 203, 48, 61, 76,
|
||||
215, 96, 6, 49, 195, 37, 225, 10, 175, 222, 186, 133, 63, 50, 236, 215, 247, 17, 199,
|
||||
8, 134, 64, 246, 194, 167, 105, 15, 57, 62, 50, 51, 243, 192, 242, 122, 11, 46, 202,
|
||||
47, 10, 71, 153, 212, 226, 38, 12, 90, 150, 154, 152, 233, 7, 172, 111, 185, 160, 246,
|
||||
0, 166, 113, 90, 37, 203, 166, 43, 53, 255, 211, 127, 139, 73, 7, 10, 164, 1, 168, 223,
|
||||
87, 127, 43, 47, 87, 68, 84, 247, 223, 108, 108, 113, 36, 17, 50, 98, 236, 48, 10, 219,
|
||||
182, 107, 240, 198, 207, 20, 178, 9, 142, 14, 93, 163, 166, 147, 38, 176, 172, 156, 73,
|
||||
174, 238, 175, 231, 130, 159, 51, 128, 76, 34, 37, 138, 19, 3, 59, 71, 78, 144, 238,
|
||||
226, 214, 188, 27, 42, 142, 245, 238, 131, 190, 211, 240, 41, 122, 69, 124, 171, 75,
|
||||
115, 45, 144, 133, 176, 19, 81, 125, 230, 149, 235, 159, 6, 155, 195, 119, 62, 140, 50,
|
||||
52, 209, 124, 3, 93, 232, 20, 130, 138, 110, 60, 183, 177, 161, 52, 114, 91, 19, 211,
|
||||
156, 185, 202, 200, 36, 103, 253, 113, 45, 245, 177, 238, 43, 144, 38, 221, 0, 102, 50,
|
||||
255, 20, 154, 56, 156, 155, 92, 157, 57, 209, 77, 84, 88, 24, 116, 116, 54, 213, 222,
|
||||
76, 212, 193, 168, 216, 247, 125, 135, 114, 226, 128, 140, 250, 103, 82, 215, 238, 32,
|
||||
74, 252, 45, 224, 23, 95, 126, 124, 135, 124, 128, 53, 203, 40, 65, 222, 8, 83, 178,
|
||||
211, 64, 141, 64, 98, 188, 134, 100, 65, 166, 52, 249, 1, 206, 58, 55, 195, 23, 218,
|
||||
239, 41, 73, 88, 113, 148, 132, 209, 93, 37, 205, 58, 92, 14, 1, 133, 168, 162, 192,
|
||||
147, 70, 167, 101, 170, 152, 159, 0, 212, 26, 97, 49, 43, 217, 173, 38, 215, 136, 26,
|
||||
208, 244, 19, 83, 207, 38, 224, 254, 92, 169, 219, 236, 172, 49, 55, 98, 55, 15, 187,
|
||||
173, 114, 99, 130, 211, 78, 168, 221, 209, 250, 88, 189, 17, 186, 172, 129, 56, 90,
|
||||
238, 120, 23, 176, 87, 133, 81, 244, 29, 2, 215, 34, 88, 247, 231, 167, 56,
|
||||
];
|
||||
|
||||
let (exc_key, kc) =
|
||||
super::derive_aes256_gcm_key_hybrid(&cust_key, &host_key_1, &host_key_2).unwrap();
|
||||
|
||||
assert_eq!(exc_key, exp_key);
|
||||
assert_eq!(kc, exp_kc);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hkdf_rfc_5869() {
|
||||
use openssl::md::Md;
|
||||
@@ -776,4 +1299,94 @@ mod tests {
|
||||
}))
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn validate_ec_key_valid() {
|
||||
let (cust_key, host_key) = get_test_keys();
|
||||
|
||||
// Both test keys are SECP521R1 EC keys
|
||||
assert!(validate_ec_key(&cust_key, "customer key", Nid::SECP521R1).is_ok());
|
||||
assert!(validate_ec_key(&host_key, "host key", Nid::SECP521R1).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn validate_ec_key_wrong_curve() {
|
||||
let (cust_key, _) = get_test_keys();
|
||||
|
||||
// Test key is SECP521R1, but we expect SECP384R1
|
||||
let result = validate_ec_key(&cust_key, "customer key", Nid::SECP384R1);
|
||||
assert!(result.is_err());
|
||||
|
||||
if let Err(Error::RetrInvKey {
|
||||
what,
|
||||
kind,
|
||||
value,
|
||||
exp,
|
||||
}) = result
|
||||
{
|
||||
assert_eq!(what, "curve");
|
||||
assert_eq!(kind, "customer key");
|
||||
assert_eq!(value, "secp521r1");
|
||||
assert_eq!(exp, "secp384r1");
|
||||
} else {
|
||||
panic!("Expected RetrInvKey error");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn validate_ec_key_not_ec() {
|
||||
let keypair = crate::get_test_asset!("keys/rsa2048key.pem");
|
||||
let keypair = PKey::private_key_from_pem(keypair).unwrap();
|
||||
|
||||
// RSA key is not an EC key
|
||||
let result = validate_ec_key(&keypair, "EC key", Nid::SECP521R1);
|
||||
assert!(result.is_err());
|
||||
|
||||
if let Err(Error::RetrInvKey {
|
||||
what,
|
||||
kind,
|
||||
value,
|
||||
exp,
|
||||
}) = result
|
||||
{
|
||||
assert_eq!(what, "key type");
|
||||
assert_eq!(kind, "EC key");
|
||||
assert_eq!(value, "RSA");
|
||||
assert_eq!(exp, "EC (secp521r1)");
|
||||
} else {
|
||||
panic!("Expected RetrInvKey error");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn validate_mlkem_key_valid() {
|
||||
let (_, _, mlkem_key) = get_test_keys_hybrid();
|
||||
|
||||
// The third key from get_test_keys_hybrid is ML-KEM-1024
|
||||
assert!(validate_key_type(&mlkem_key, "ML-KEM key", KeyType::ML_KEM_1024).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn validate_mlkem_key_wrong_type() {
|
||||
let (ec_key, _) = get_test_keys();
|
||||
|
||||
// EC key is not ML-KEM
|
||||
let result = validate_key_type(&ec_key, "EC key", KeyType::ML_KEM_1024);
|
||||
assert!(result.is_err());
|
||||
|
||||
if let Err(Error::RetrInvKey {
|
||||
what,
|
||||
kind,
|
||||
value,
|
||||
exp,
|
||||
}) = result
|
||||
{
|
||||
assert_eq!(what, "key type");
|
||||
assert_eq!(kind, "EC key");
|
||||
assert_eq!(value, "EC");
|
||||
assert_eq!(exp, "ML-KEM-1024");
|
||||
} else {
|
||||
panic!("Expected RetrInvKey error");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,8 +64,11 @@ pub enum Error {
|
||||
#[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("Input contains an unknown add-secret request version {0}")]
|
||||
BinAsrcbInvVersion(u32),
|
||||
|
||||
#[error("Unsupported add-secret request version: {0}")]
|
||||
UnsupportedAddSecretVersion(u32),
|
||||
|
||||
#[error("Provided user-data key type ({key}) does not match with the user-data ({kind})")]
|
||||
AsrcbUserDataKeyMismatch { key: String, kind: UserDataType },
|
||||
@@ -84,6 +87,9 @@ pub enum Error {
|
||||
#[error("The provided host key document in {0} contains no certificate!")]
|
||||
NoHkdInFile(String),
|
||||
|
||||
#[error("The provided host key document in {0} contains the wrong number of keys!")]
|
||||
WrongNumberOfKeys(String),
|
||||
|
||||
#[error("Invalid input size ({0}) for boot hdr")]
|
||||
InvBootHdrSize(usize),
|
||||
|
||||
@@ -94,7 +100,7 @@ pub enum Error {
|
||||
BinArcbInvVersion(u32),
|
||||
|
||||
#[error(
|
||||
"The attestation request encrypted sice is to0 small {0}. Request probably tampered with."
|
||||
"The attestation request encrypted sice is too small {0}. Request probably tampered with."
|
||||
)]
|
||||
BinArcbSeaSmall(u32),
|
||||
|
||||
@@ -135,6 +141,12 @@ pub enum Error {
|
||||
|
||||
#[error("Unsupported cipher: {:?}", .0.as_raw())]
|
||||
UnsupportedCipher(Nid),
|
||||
|
||||
#[error("{}", .0)]
|
||||
InvalidHkd(String),
|
||||
|
||||
#[error("All host keys must use the same version (all hybrid or all non-hybrid)")]
|
||||
MixedHostkeyVersions,
|
||||
}
|
||||
|
||||
// used in macros
|
||||
@@ -173,8 +185,16 @@ pub enum HkdVerifyErrorType {
|
||||
IssuerMismatch,
|
||||
#[error("No CRL distribution points found")]
|
||||
NoCrlDP,
|
||||
#[error("CRL distribution point uses unsupported protocol (only HTTP/HTTPS allowed)")]
|
||||
InvalidCrlProtocol,
|
||||
#[error("The IBM Z signing key could not be verified. Error occurred at level {1}")]
|
||||
IbmSignInvalid(#[source] openssl::x509::X509VerifyResult, u32),
|
||||
#[error("Too many redirections during CRL download")]
|
||||
TooManyRedirectionsCrlDownload,
|
||||
#[error("CRL download exceeds maximum file size of {} MiB", .0 / (1024 * 1024))]
|
||||
CrlDownloadTooLarge(u64),
|
||||
#[error("CRL download failed")]
|
||||
CrlDownloadFailed,
|
||||
}
|
||||
|
||||
macro_rules! bail_hkd_verify {
|
||||
|
||||
@@ -89,13 +89,16 @@ pub use crate::error::HkdVerifyErrorType;
|
||||
|
||||
/// Functionalities to build UV requests
|
||||
pub mod request {
|
||||
pub use crate::brcb::{seek_se_hdr_start, BootHdrTags, SeImgMetaData};
|
||||
pub use crate::brcb::{seek_se_hdr_start, BootHdrTags, SeHdrVersion, SeImgMetaData};
|
||||
pub use crate::crypto::{
|
||||
decrypt_aead, derive_aes256_gcm_key, encrypt_aead, gen_ec_key, random_array,
|
||||
AeadDecryptionResult, AeadEncryptionResult, Aes256GcmKey, Aes256XtsKey, SymKey, SymKeyType,
|
||||
SHA_512_HASH_LEN,
|
||||
};
|
||||
pub use crate::req::{EcPubKeyCoord, Encrypt, HostKey, Keyslot, ReqEncrCtx, Request};
|
||||
pub use crate::req::{
|
||||
EcPubKeyCoord, Encrypt, HostKey, HybridPKey, Keyslot, KeyslotV1, KeyslotV2, ReqEncrCtx,
|
||||
Request,
|
||||
};
|
||||
pub use crate::verify::{CertVerifier, HkdVerifier, NoVerifyHkd};
|
||||
|
||||
/// Reexports some useful OpenSSL symbols
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// Copyright IBM Corp.
|
||||
|
||||
#![expect(unused)]
|
||||
#![cfg_attr(not(test), expect(unused))]
|
||||
|
||||
use std::ffi::CStr;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
@@ -14,5 +14,4 @@ mod stackable_crl;
|
||||
pub use akid::*;
|
||||
pub use bio::*;
|
||||
pub use crl::*;
|
||||
#[expect(unused_imports)]
|
||||
pub use ml_kem::*;
|
||||
|
||||
@@ -47,7 +47,10 @@ impl EcPubKeyCoord {
|
||||
|
||||
/// Get the pub ECDH coordinates in the format the Ultravisor expects it:
|
||||
/// The two coordinates are padded to 80 bytes each.
|
||||
fn get_pub_ecdh_points(pkey: &EcPointRef, grp: &EcGroupRef) -> Result<[u8; 160], ErrorStack> {
|
||||
pub(crate) fn get_pub_ecdh_points(
|
||||
pkey: &EcPointRef,
|
||||
grp: &EcGroupRef,
|
||||
) -> Result<[u8; 160], ErrorStack> {
|
||||
let mut x = BigNum::new()?;
|
||||
let mut y = BigNum::new()?;
|
||||
let mut bn_ctx = BigNumContext::new()?;
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
// Copyright IBM Corp.
|
||||
|
||||
//! Request header structure for UV requests.
|
||||
|
||||
use pv_core::request::{RequestMagic, RequestVersion};
|
||||
use zerocopy::{BigEndian, FromBytes, Immutable, IntoBytes, U32};
|
||||
|
||||
use crate::assert_size;
|
||||
@@ -25,13 +27,13 @@ pub struct RequestHdr {
|
||||
assert_size!(RequestHdr, 48);
|
||||
|
||||
impl RequestHdr {
|
||||
pub(crate) fn new(
|
||||
rqvn: u32,
|
||||
pub(super) fn new(
|
||||
rqvn: RequestVersion,
|
||||
rql: u32,
|
||||
iv: [u8; 12],
|
||||
nks: u8,
|
||||
sea: u32,
|
||||
magic: Option<[u8; 8]>,
|
||||
magic: Option<RequestMagic>,
|
||||
) -> Self {
|
||||
Self {
|
||||
magic: magic.unwrap_or_default(),
|
||||
|
||||
@@ -4,7 +4,56 @@
|
||||
|
||||
//! Host key types for UV requests
|
||||
|
||||
use openssl::pkey::{PKey, Public};
|
||||
use openssl::nid::Nid;
|
||||
use openssl::pkey::{KeyType, PKey, PKeyRef, Public};
|
||||
|
||||
use crate::crypto::{validate_ec_key, validate_key_type};
|
||||
pub use crate::error::Result;
|
||||
|
||||
/// Hybrid public key (ECDH and ML-KEM)
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct HybridPKey {
|
||||
/// ECDH public key
|
||||
pub(super) ec_key: PKey<Public>,
|
||||
|
||||
/// ML-KEM public key
|
||||
pub(super) mlkem_key: PKey<Public>,
|
||||
}
|
||||
|
||||
impl HybridPKey {
|
||||
/// Creates a new hybrid public key with validation.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `ec_key`: ECDH public key (must be SECP521R1)
|
||||
/// - `mlkem_key`: ML-KEM public key (must be ML-KEM-1024)
|
||||
///
|
||||
/// # Errors
|
||||
/// Returns an error if:
|
||||
/// - EC key is not SECP521R1 curve
|
||||
/// - ML-KEM key is not ML-KEM-1024
|
||||
pub fn new(ec_key: PKey<Public>, mlkem_key: PKey<Public>) -> Result<Self> {
|
||||
validate_ec_key(&ec_key, "ECDH key", Nid::SECP521R1)?;
|
||||
validate_key_type(&mlkem_key, "ML-KEM key", KeyType::ML_KEM_1024)?;
|
||||
|
||||
Ok(Self { ec_key, mlkem_key })
|
||||
}
|
||||
|
||||
/// Returns a reference to the EC key
|
||||
pub fn ec_key(&self) -> &PKeyRef<Public> {
|
||||
&self.ec_key
|
||||
}
|
||||
|
||||
/// Returns a reference to the ML-KEM key
|
||||
pub fn mlkem_key(&self) -> &PKeyRef<Public> {
|
||||
&self.mlkem_key
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<HybridPKey> for HybridPKey {
|
||||
fn as_ref(&self) -> &HybridPKey {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Versioned host keys container
|
||||
#[non_exhaustive]
|
||||
@@ -12,15 +61,33 @@ use openssl::pkey::{PKey, Public};
|
||||
pub enum HostKey {
|
||||
/// ECDH public key
|
||||
V1(PKey<Public>),
|
||||
|
||||
/// Hybrid public key (ECDH and ML-KEM)
|
||||
V2(HybridPKey),
|
||||
}
|
||||
|
||||
impl HostKey {
|
||||
/// Return the ECDH public key
|
||||
pub fn ec_key(&self) -> &PKey<Public> {
|
||||
match self {
|
||||
pub fn ec_key(&self) -> Option<&PKeyRef<Public>> {
|
||||
Some(match self {
|
||||
HostKey::V1(ec_key) => ec_key,
|
||||
HostKey::V2(hybrid) => hybrid.ec_key(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Return the ML-KEM public key
|
||||
pub fn mlkem_key(&self) -> Option<&PKeyRef<Public>> {
|
||||
match self {
|
||||
HostKey::V1(_) => None,
|
||||
HostKey::V2(hybrid) => Some(hybrid.mlkem_key()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Test if the hostkey is hybrid
|
||||
#[must_use]
|
||||
pub fn is_hybrid(&self) -> bool {
|
||||
matches!(self, HostKey::V2(_))
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<HostKey> for HostKey {
|
||||
@@ -28,3 +95,248 @@ impl AsRef<HostKey> for HostKey {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use openssl::ec::{EcGroup, EcKey};
|
||||
use openssl::pkey::Private;
|
||||
|
||||
use super::*;
|
||||
use crate::openssl_extensions::generate_ml_kem;
|
||||
use crate::test_utils::get_test_key_and_cert_hybrid;
|
||||
use crate::Error;
|
||||
|
||||
fn to_public_key(key: &PKey<Private>) -> Result<PKey<Public>> {
|
||||
let der = key.public_key_to_der()?;
|
||||
Ok(PKey::public_key_from_der(&der)?)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hostkey_v1_variant() {
|
||||
let (_, ec_key) = crate::test_utils::get_test_key_and_cert();
|
||||
let hostkey = HostKey::V1(ec_key.public_key().unwrap());
|
||||
|
||||
assert!(!hostkey.is_hybrid(), "V1 HostKey should not be hybrid");
|
||||
assert!(matches!(hostkey, HostKey::V1(_)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hostkey_v2_variant() {
|
||||
let (_, ec_key, mlkem_key) = get_test_key_and_cert_hybrid();
|
||||
let hybrid = HybridPKey::new(
|
||||
ec_key.public_key().unwrap(),
|
||||
mlkem_key.public_key().unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
let hostkey = HostKey::V2(hybrid);
|
||||
|
||||
assert!(hostkey.is_hybrid(), "V2 HostKey should be hybrid");
|
||||
assert!(matches!(hostkey, HostKey::V2(_)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hostkey_ec_key_access() {
|
||||
let (_, ec_key, mlkem_key) = get_test_key_and_cert_hybrid();
|
||||
let hybrid = HybridPKey::new(
|
||||
ec_key.public_key().unwrap(),
|
||||
mlkem_key.public_key().unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let v1_key = HostKey::V1(ec_key.public_key().unwrap());
|
||||
let v2_key = HostKey::V2(hybrid);
|
||||
|
||||
assert!(v1_key.ec_key().unwrap().public_key_to_der().is_ok());
|
||||
assert!(v2_key.ec_key().unwrap().public_key_to_der().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hostkey_v2_mlkem_key_access() {
|
||||
let (_, ec_key, mlkem_key) = get_test_key_and_cert_hybrid();
|
||||
let hybrid = HybridPKey::new(
|
||||
ec_key.public_key().unwrap(),
|
||||
mlkem_key.public_key().unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
let hostkey = HostKey::V2(hybrid);
|
||||
|
||||
assert!(hostkey.mlkem_key().unwrap().public_key_to_der().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hostkey_v1_has_no_mlkem_key() {
|
||||
let (_, ec_key) = crate::test_utils::get_test_key_and_cert();
|
||||
let hostkey = HostKey::V1(ec_key.public_key().unwrap());
|
||||
|
||||
assert!(hostkey.mlkem_key().is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hybrid_public_key_structure() {
|
||||
let (_, ec_key, mlkem_key) = get_test_key_and_cert_hybrid();
|
||||
let hybrid = HybridPKey::new(
|
||||
ec_key.public_key().unwrap(),
|
||||
mlkem_key.public_key().unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Verify both components are present and valid
|
||||
assert!(!hybrid.ec_key().public_key_to_der().unwrap().is_empty());
|
||||
assert!(!hybrid.mlkem_key().public_key_to_der().unwrap().is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hybrid_pkey_invalid_ec_curve() {
|
||||
// Generate a P-256 key instead of P-521
|
||||
let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
|
||||
let wrong_ec_key = PKey::from_ec_key(EcKey::generate(&group).unwrap()).unwrap();
|
||||
|
||||
let (_, _, mlkem_key) = get_test_key_and_cert_hybrid();
|
||||
|
||||
let result = HybridPKey::new(
|
||||
to_public_key(&wrong_ec_key).unwrap(),
|
||||
mlkem_key.public_key().unwrap(),
|
||||
);
|
||||
assert!(result.is_err(), "Should reject EC key with wrong curve");
|
||||
|
||||
if let Err(Error::RetrInvKey {
|
||||
what,
|
||||
kind,
|
||||
value,
|
||||
exp,
|
||||
}) = result
|
||||
{
|
||||
assert_eq!(what, "curve");
|
||||
assert_eq!(kind, "ECDH key");
|
||||
assert_eq!(value, "prime256v1");
|
||||
assert_eq!(exp, "secp521r1");
|
||||
} else {
|
||||
panic!("Expected RetrInvKey error for wrong curve");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hybrid_pkey_invalid_mlkem_type() {
|
||||
let (_, ec_key, _) = get_test_key_and_cert_hybrid();
|
||||
|
||||
// Generate ML-KEM-512 instead of ML-KEM-1024
|
||||
let wrong_mlkem_key = generate_ml_kem(KeyType::ML_KEM_512).unwrap();
|
||||
|
||||
let result = HybridPKey::new(
|
||||
ec_key.public_key().unwrap(),
|
||||
to_public_key(&wrong_mlkem_key).unwrap(),
|
||||
);
|
||||
assert!(result.is_err(), "Should reject ML-KEM key with wrong type");
|
||||
|
||||
if let Err(Error::RetrInvKey {
|
||||
what,
|
||||
kind,
|
||||
value,
|
||||
exp,
|
||||
}) = result
|
||||
{
|
||||
assert_eq!(what, "key type");
|
||||
assert_eq!(kind, "ML-KEM key");
|
||||
assert_eq!(value, "ML-KEM-512");
|
||||
assert_eq!(exp, "ML-KEM-1024");
|
||||
} else {
|
||||
panic!("Expected RetrInvKey error for wrong ML-KEM type");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hybrid_pkey_clone() {
|
||||
let (_, ec_key, mlkem_key) = get_test_key_and_cert_hybrid();
|
||||
let hybrid = HybridPKey::new(
|
||||
ec_key.public_key().unwrap(),
|
||||
mlkem_key.public_key().unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let cloned = hybrid.clone();
|
||||
|
||||
// Verify both original and clone have valid keys
|
||||
assert!(!hybrid.ec_key().public_key_to_der().unwrap().is_empty());
|
||||
assert!(!hybrid.mlkem_key().public_key_to_der().unwrap().is_empty());
|
||||
assert!(!cloned.ec_key().public_key_to_der().unwrap().is_empty());
|
||||
assert!(!cloned.mlkem_key().public_key_to_der().unwrap().is_empty());
|
||||
|
||||
// Verify the keys are equivalent
|
||||
assert_eq!(
|
||||
hybrid.ec_key().public_key_to_der().unwrap(),
|
||||
cloned.ec_key().public_key_to_der().unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
hybrid.mlkem_key().public_key_to_der().unwrap(),
|
||||
cloned.mlkem_key().public_key_to_der().unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hostkey_clone() {
|
||||
let (_, ec_key, mlkem_key) = get_test_key_and_cert_hybrid();
|
||||
let hybrid = HybridPKey::new(
|
||||
ec_key.public_key().unwrap(),
|
||||
mlkem_key.public_key().unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Test cloning V1
|
||||
let v1_key = HostKey::V1(ec_key.public_key().unwrap());
|
||||
let v1_cloned = v1_key.clone();
|
||||
assert!(!v1_cloned.is_hybrid());
|
||||
assert_eq!(
|
||||
v1_key.ec_key().unwrap().public_key_to_der().unwrap(),
|
||||
v1_cloned.ec_key().unwrap().public_key_to_der().unwrap()
|
||||
);
|
||||
|
||||
// Test cloning V2
|
||||
let v2_key = HostKey::V2(hybrid);
|
||||
let v2_cloned = v2_key.clone();
|
||||
assert!(v2_cloned.is_hybrid());
|
||||
assert_eq!(
|
||||
v2_key.ec_key().unwrap().public_key_to_der().unwrap(),
|
||||
v2_cloned.ec_key().unwrap().public_key_to_der().unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
v2_key.mlkem_key().unwrap().public_key_to_der().unwrap(),
|
||||
v2_cloned.mlkem_key().unwrap().public_key_to_der().unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hybrid_pkey_as_ref() {
|
||||
let (_, ec_key, mlkem_key) = get_test_key_and_cert_hybrid();
|
||||
let hybrid = HybridPKey::new(
|
||||
ec_key.public_key().unwrap(),
|
||||
mlkem_key.public_key().unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let hybrid_ref: &HybridPKey = hybrid.as_ref();
|
||||
assert!(!hybrid_ref.ec_key().public_key_to_der().unwrap().is_empty());
|
||||
assert!(!hybrid_ref
|
||||
.mlkem_key()
|
||||
.public_key_to_der()
|
||||
.unwrap()
|
||||
.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hostkey_as_ref() {
|
||||
let (_, ec_key, mlkem_key) = get_test_key_and_cert_hybrid();
|
||||
let hybrid = HybridPKey::new(
|
||||
ec_key.public_key().unwrap(),
|
||||
mlkem_key.public_key().unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let v1_key = HostKey::V1(ec_key.public_key().unwrap());
|
||||
let v1_ref: &HostKey = v1_key.as_ref();
|
||||
assert!(!v1_ref.is_hybrid());
|
||||
|
||||
let v2_key = HostKey::V2(hybrid);
|
||||
let v2_ref: &HostKey = v2_key.as_ref();
|
||||
assert!(v2_ref.is_hybrid());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,13 +4,11 @@
|
||||
|
||||
//! IBM Z Host key-slot implementations.
|
||||
|
||||
use openssl::hash::MessageDigest;
|
||||
use openssl::hash::{DigestBytes, MessageDigest};
|
||||
use openssl::pkey::{PKey, PKeyRef, Private, Public};
|
||||
|
||||
use super::ec_coord::EcPubKeyCoord;
|
||||
use super::encrypt::Encrypt;
|
||||
use crate::crypto::{derive_aes256_gcm_key, encrypt_aead, hash};
|
||||
use crate::request::HostKey;
|
||||
use crate::crypto::{derive_aes256_gcm_key, derive_aes256_gcm_key_hybrid, encrypt_aead, hash};
|
||||
use crate::req::{EcPubKeyCoord, Encrypt, HostKey, HybridPKey};
|
||||
use crate::Result;
|
||||
|
||||
/// IBM Z Host key-slot
|
||||
@@ -71,12 +69,107 @@ impl Encrypt for KeyslotV1 {
|
||||
}
|
||||
}
|
||||
|
||||
/// IBM Z hybrid (V2) Host key-slot
|
||||
///
|
||||
/// Layout in binary format:
|
||||
/// ```none
|
||||
/// _______________________________________________________________
|
||||
/// | Public Host Key Hash (64) |
|
||||
/// | Wrapped(=Encrypted) Request Protection Key(32) |
|
||||
/// | Key Slot Tag (16) |
|
||||
/// | ML-KEM Ciphertext (1568) |
|
||||
/// |_____________________________________________________________|
|
||||
/// ```
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct KeyslotV2 {
|
||||
ec_hostkey: PKey<Public>,
|
||||
mlkem_hostkey: PKey<Public>,
|
||||
}
|
||||
|
||||
impl KeyslotV2 {
|
||||
/// Size of a hybrid host-key hash
|
||||
pub const PHKH_SIZE: u32 = 0x40;
|
||||
/// Size of a complete V2 keyslot in bytes
|
||||
pub const SIZE: usize = 1680;
|
||||
|
||||
/// Creates a new HybridKeyslot from the provided hybrid public key
|
||||
pub fn new(hostkey: HybridPKey) -> Self {
|
||||
let HybridPKey { ec_key, mlkem_key } = hostkey;
|
||||
Self {
|
||||
ec_hostkey: ec_key,
|
||||
mlkem_hostkey: mlkem_key,
|
||||
}
|
||||
}
|
||||
|
||||
/// calculates the sha512 of this hybrid key
|
||||
pub fn sha512(&self) -> Result<DigestBytes> {
|
||||
let mut phk_buf = Vec::<u8>::with_capacity(160 + 1568);
|
||||
let ec_phk: EcPubKeyCoord = self.ec_hostkey.as_ref().try_into()?;
|
||||
phk_buf.extend_from_slice(ec_phk.as_ref());
|
||||
phk_buf.extend_from_slice(&self.mlkem_hostkey.raw_public_key()?);
|
||||
assert_eq!(phk_buf.len(), 160 + 1568);
|
||||
|
||||
let hash = hash(MessageDigest::sha512(), &phk_buf)?;
|
||||
assert_eq!(hash.len(), 64);
|
||||
Ok(hash)
|
||||
}
|
||||
|
||||
/// Encrypts `secret` using `self` and `priv_key` the encryption.
|
||||
///
|
||||
/// # Returns
|
||||
/// the encrypted data.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This function will return an error if OpenSSL could not encrypt the secret.
|
||||
pub fn encrypt(&self, secret: &[u8], priv_key: &PKeyRef<Private>) -> Result<Vec<u8>> {
|
||||
let mut res = Vec::with_capacity(1680);
|
||||
self.encrypt_to(secret, priv_key, &mut res)?;
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
/// Encrypts the given request protection key `prot_key`.
|
||||
///
|
||||
/// The AES256 encryption key is derived from `self` as public key, and `priv_key` as private
|
||||
/// key.
|
||||
///
|
||||
/// # Returns
|
||||
/// The encrypted HybridKeyslot.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This function will return an error if OpenSSL could not encrypt the secret.
|
||||
fn encrypt_to(
|
||||
&self,
|
||||
prot_key: &[u8],
|
||||
priv_key: &PKeyRef<Private>,
|
||||
to: &mut Vec<u8>,
|
||||
) -> Result<()> {
|
||||
let (derived_key, ciphertext) =
|
||||
derive_aes256_gcm_key_hybrid(priv_key, &self.ec_hostkey, &self.mlkem_hostkey)?;
|
||||
let mut wrpk_and_kst =
|
||||
encrypt_aead(&derived_key.into(), &[0; 12], &[], prot_key)?.into_buf();
|
||||
assert_eq!(wrpk_and_kst.len(), 48);
|
||||
|
||||
to.reserve(1680);
|
||||
let hash = self.sha512()?;
|
||||
assert_eq!(hash.len(), 64);
|
||||
to.extend_from_slice(&hash);
|
||||
to.append(&mut wrpk_and_kst);
|
||||
assert_eq!(ciphertext.len(), 1568);
|
||||
to.extend_from_slice(&ciphertext);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Versioned keyslot container
|
||||
#[non_exhaustive]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Keyslot {
|
||||
/// V1 key-slots with ECDH keys
|
||||
V1(KeyslotV1),
|
||||
/// V2 key-slots with hybrid ECDH/ML-KEM keys
|
||||
V2(KeyslotV2),
|
||||
}
|
||||
|
||||
impl Keyslot {
|
||||
@@ -84,27 +177,34 @@ impl Keyslot {
|
||||
pub fn new(hostkey: HostKey) -> Self {
|
||||
match hostkey {
|
||||
HostKey::V1(key) => Keyslot::V1(KeyslotV1::new(key)),
|
||||
HostKey::V2(key) => Keyslot::V2(KeyslotV2::new(key)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the public host key hash size for the given version of the key-slot in bytes
|
||||
#[must_use]
|
||||
pub fn phkh_size(&self) -> u32 {
|
||||
match self {
|
||||
Keyslot::V1(_) => KeyslotV1::PHKH_SIZE,
|
||||
Keyslot::V2(_) => KeyslotV2::PHKH_SIZE,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the size of the key-slot in bytes
|
||||
#[must_use]
|
||||
pub fn size(&self) -> usize {
|
||||
match self {
|
||||
Keyslot::V1(_) => KeyslotV1::SIZE,
|
||||
Keyslot::V2(_) => KeyslotV2::SIZE,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return whether the key-slot uses hybrid keys
|
||||
#[must_use]
|
||||
pub fn is_hybrid(&self) -> bool {
|
||||
match self {
|
||||
Keyslot::V1(_) => false,
|
||||
Keyslot::V2(_) => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -118,6 +218,7 @@ impl Encrypt for Keyslot {
|
||||
) -> Result<()> {
|
||||
match self {
|
||||
Keyslot::V1(ks) => ks.encrypt_to(secret, priv_key, to),
|
||||
Keyslot::V2(ks) => ks.encrypt_to(secret, priv_key, to),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -128,11 +229,17 @@ impl From<PKey<Public>> for Keyslot {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<HybridPKey> for Keyslot {
|
||||
fn from(key: HybridPKey) -> Self {
|
||||
Keyslot::V2(KeyslotV2::new(key))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::get_test_asset;
|
||||
use crate::test_utils::*;
|
||||
use crate::test_utils::{DeterministicTestRandGuard, *};
|
||||
|
||||
#[test]
|
||||
fn keyslot() {
|
||||
@@ -147,4 +254,214 @@ mod tests {
|
||||
let encr_ks = keyslot.encrypt(&[0x16u8; 32], &cust_key).unwrap();
|
||||
assert_ne!(exp_keyslot, encr_ks);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keyslot_v2() {
|
||||
// Install deterministic RNG for reproducible encryption
|
||||
let _guard = DeterministicTestRandGuard::install(&[0x42; 64], &[0x17; 16]).unwrap();
|
||||
|
||||
let (cust_key, host_key1, host_key2) = get_test_keys_hybrid();
|
||||
let host_key = HostKey::V2(HybridPKey::new(host_key1, host_key2).unwrap());
|
||||
let exp_keyslot = vec![
|
||||
255, 94, 191, 53, 220, 196, 47, 37, 93, 227, 234, 101, 1, 174, 171, 68, 42, 136, 92,
|
||||
238, 72, 6, 17, 77, 231, 225, 174, 22, 222, 188, 212, 15, 248, 145, 72, 126, 139, 17,
|
||||
233, 225, 156, 46, 233, 151, 54, 2, 175, 88, 215, 254, 243, 222, 37, 81, 50, 110, 18,
|
||||
76, 252, 12, 210, 146, 66, 23, 123, 246, 141, 14, 70, 157, 73, 124, 205, 112, 192, 82,
|
||||
160, 243, 2, 154, 134, 145, 176, 147, 30, 217, 221, 93, 170, 239, 165, 37, 30, 192, 47,
|
||||
94, 129, 165, 12, 137, 239, 12, 180, 199, 240, 160, 180, 205, 117, 84, 16, 148, 51, 48,
|
||||
243, 216, 50, 132, 187, 115, 137, 3, 109, 145, 172, 159, 224, 25, 63, 96, 241, 105, 89,
|
||||
35, 42, 180, 248, 35, 166, 81, 116, 175, 179, 252, 81, 188, 189, 42, 17, 60, 231, 132,
|
||||
32, 111, 90, 138, 201, 16, 3, 97, 246, 130, 173, 85, 218, 187, 232, 92, 52, 120, 56,
|
||||
142, 137, 101, 31, 21, 194, 186, 198, 38, 240, 58, 150, 93, 86, 18, 186, 5, 12, 41, 37,
|
||||
94, 162, 119, 16, 237, 82, 252, 178, 159, 57, 58, 162, 20, 173, 140, 10, 172, 203, 241,
|
||||
94, 110, 117, 32, 36, 217, 7, 168, 50, 105, 43, 33, 174, 140, 55, 88, 26, 233, 81, 253,
|
||||
98, 121, 190, 70, 146, 84, 186, 6, 51, 181, 2, 59, 216, 45, 78, 4, 82, 90, 21, 180, 99,
|
||||
239, 195, 254, 33, 171, 124, 97, 36, 110, 119, 142, 98, 125, 70, 236, 51, 192, 32, 8,
|
||||
214, 224, 101, 169, 45, 173, 137, 194, 78, 114, 224, 76, 174, 188, 133, 227, 167, 169,
|
||||
47, 241, 190, 15, 145, 217, 87, 254, 15, 150, 52, 138, 192, 230, 52, 129, 36, 8, 40,
|
||||
37, 126, 103, 85, 86, 25, 78, 53, 243, 107, 193, 18, 102, 3, 83, 212, 5, 252, 224, 241,
|
||||
7, 205, 220, 168, 183, 15, 37, 52, 190, 12, 9, 152, 124, 210, 65, 152, 210, 199, 81,
|
||||
95, 240, 141, 196, 236, 8, 249, 221, 116, 130, 42, 52, 208, 218, 180, 27, 249, 59, 245,
|
||||
21, 165, 142, 234, 140, 75, 89, 136, 250, 155, 157, 12, 154, 152, 188, 178, 227, 237,
|
||||
124, 111, 176, 131, 227, 238, 164, 22, 88, 80, 217, 42, 217, 80, 148, 118, 12, 136, 95,
|
||||
53, 69, 209, 131, 74, 91, 193, 253, 229, 146, 11, 58, 125, 19, 8, 229, 60, 177, 244,
|
||||
74, 41, 92, 91, 62, 64, 221, 20, 213, 227, 4, 40, 22, 177, 155, 236, 147, 165, 27, 4,
|
||||
99, 4, 151, 155, 82, 72, 151, 22, 102, 183, 192, 242, 18, 104, 146, 205, 107, 21, 254,
|
||||
88, 23, 69, 246, 57, 217, 249, 124, 246, 54, 163, 244, 38, 74, 215, 144, 50, 45, 142,
|
||||
36, 216, 88, 39, 70, 67, 88, 130, 1, 8, 205, 240, 159, 210, 205, 233, 237, 60, 81, 176,
|
||||
112, 172, 187, 121, 239, 198, 43, 17, 49, 55, 170, 228, 243, 255, 76, 72, 121, 125,
|
||||
157, 250, 93, 251, 55, 25, 4, 129, 67, 195, 30, 37, 6, 76, 10, 240, 178, 255, 151, 138,
|
||||
36, 255, 32, 237, 133, 162, 130, 91, 9, 238, 67, 134, 4, 86, 225, 179, 166, 219, 4,
|
||||
144, 7, 125, 248, 75, 132, 54, 56, 51, 237, 206, 252, 96, 9, 208, 140, 127, 143, 180,
|
||||
32, 179, 254, 18, 233, 187, 122, 159, 172, 77, 204, 9, 179, 242, 153, 18, 138, 82, 13,
|
||||
210, 140, 207, 9, 217, 216, 241, 106, 205, 109, 195, 223, 82, 172, 181, 48, 91, 124,
|
||||
235, 85, 17, 18, 166, 216, 86, 120, 185, 54, 147, 156, 84, 106, 30, 235, 234, 114, 27,
|
||||
23, 121, 210, 251, 136, 117, 53, 177, 28, 153, 144, 17, 70, 190, 206, 27, 135, 42, 227,
|
||||
39, 243, 86, 170, 11, 63, 191, 102, 89, 92, 137, 103, 59, 142, 236, 203, 156, 231, 255,
|
||||
30, 5, 86, 53, 59, 76, 181, 218, 184, 244, 21, 50, 100, 72, 81, 98, 193, 34, 58, 67,
|
||||
150, 15, 17, 162, 216, 119, 213, 203, 50, 27, 158, 61, 105, 134, 151, 200, 68, 103, 74,
|
||||
207, 12, 5, 163, 30, 198, 28, 41, 41, 97, 93, 251, 213, 133, 41, 225, 178, 67, 160, 85,
|
||||
132, 146, 1, 201, 99, 49, 185, 27, 150, 213, 165, 134, 45, 248, 204, 67, 145, 49, 81,
|
||||
35, 246, 25, 215, 209, 159, 106, 212, 14, 149, 193, 163, 90, 24, 83, 230, 178, 216,
|
||||
194, 130, 118, 169, 81, 49, 49, 145, 96, 206, 216, 15, 134, 43, 130, 25, 110, 84, 39,
|
||||
175, 223, 183, 209, 123, 5, 166, 244, 19, 89, 2, 47, 226, 3, 93, 156, 163, 67, 156,
|
||||
237, 17, 59, 69, 99, 94, 32, 180, 64, 64, 115, 75, 44, 241, 150, 43, 169, 17, 36, 125,
|
||||
216, 132, 92, 3, 244, 16, 83, 179, 192, 65, 133, 208, 19, 156, 17, 60, 54, 29, 253,
|
||||
237, 18, 158, 145, 142, 232, 147, 2, 91, 21, 145, 125, 204, 243, 161, 245, 110, 140,
|
||||
219, 206, 70, 235, 211, 167, 138, 104, 132, 248, 157, 65, 153, 216, 47, 125, 205, 237,
|
||||
137, 220, 25, 228, 146, 194, 10, 169, 201, 224, 88, 119, 38, 140, 120, 125, 140, 46,
|
||||
184, 221, 30, 10, 47, 34, 140, 173, 64, 38, 48, 77, 236, 206, 163, 111, 80, 46, 40,
|
||||
232, 63, 247, 222, 25, 20, 246, 143, 9, 107, 172, 180, 84, 188, 234, 102, 87, 181, 173,
|
||||
83, 14, 163, 170, 91, 29, 209, 93, 52, 158, 213, 6, 91, 71, 54, 244, 189, 198, 60, 21,
|
||||
131, 210, 35, 18, 36, 164, 188, 87, 54, 73, 208, 115, 11, 248, 57, 107, 93, 23, 49,
|
||||
129, 221, 61, 12, 172, 31, 199, 129, 196, 5, 184, 78, 226, 210, 83, 232, 153, 64, 17,
|
||||
119, 243, 45, 73, 50, 129, 35, 94, 243, 146, 86, 136, 202, 86, 87, 97, 193, 59, 160,
|
||||
181, 95, 150, 148, 117, 96, 31, 151, 97, 159, 53, 72, 171, 239, 210, 67, 207, 201, 109,
|
||||
160, 230, 235, 176, 35, 235, 98, 128, 166, 195, 144, 200, 156, 7, 72, 242, 15, 95, 99,
|
||||
69, 41, 219, 254, 244, 80, 158, 177, 64, 83, 11, 235, 98, 201, 130, 176, 119, 22, 214,
|
||||
135, 215, 37, 65, 108, 91, 34, 94, 0, 153, 161, 87, 144, 177, 12, 122, 205, 11, 72,
|
||||
233, 213, 63, 37, 12, 255, 235, 188, 194, 189, 65, 169, 185, 207, 131, 182, 243, 233,
|
||||
30, 245, 39, 42, 188, 157, 28, 121, 231, 194, 121, 250, 121, 11, 28, 252, 98, 151, 238,
|
||||
124, 56, 138, 106, 116, 187, 203, 21, 75, 239, 132, 19, 62, 43, 42, 12, 214, 87, 225,
|
||||
217, 169, 134, 183, 193, 241, 175, 140, 36, 147, 248, 86, 6, 58, 212, 72, 112, 0, 56,
|
||||
168, 128, 68, 253, 173, 225, 152, 167, 138, 254, 97, 123, 227, 163, 135, 198, 49, 49,
|
||||
138, 249, 234, 245, 78, 150, 140, 170, 199, 41, 206, 246, 19, 117, 241, 27, 112, 102,
|
||||
4, 94, 237, 30, 0, 68, 252, 163, 205, 10, 63, 146, 147, 37, 153, 197, 52, 162, 50, 250,
|
||||
219, 130, 197, 3, 60, 246, 133, 83, 140, 103, 227, 50, 212, 121, 165, 114, 139, 225,
|
||||
195, 145, 107, 249, 127, 194, 23, 112, 141, 242, 14, 218, 42, 131, 19, 245, 143, 73,
|
||||
79, 194, 135, 224, 171, 249, 169, 129, 160, 153, 75, 66, 26, 12, 254, 180, 212, 229,
|
||||
172, 134, 159, 122, 212, 219, 21, 29, 33, 11, 176, 149, 73, 169, 26, 150, 96, 133, 90,
|
||||
217, 18, 37, 244, 48, 249, 4, 180, 129, 9, 45, 219, 106, 215, 28, 81, 118, 48, 98, 109,
|
||||
167, 72, 107, 187, 78, 127, 251, 184, 170, 74, 57, 188, 91, 196, 229, 251, 70, 163, 68,
|
||||
227, 238, 71, 115, 155, 246, 146, 97, 208, 21, 245, 62, 127, 47, 79, 131, 217, 41, 153,
|
||||
52, 237, 159, 60, 98, 18, 169, 149, 6, 84, 135, 2, 45, 170, 165, 213, 201, 127, 23,
|
||||
209, 2, 158, 235, 240, 195, 255, 76, 54, 189, 113, 50, 105, 230, 191, 217, 29, 46, 181,
|
||||
80, 197, 60, 177, 243, 61, 52, 24, 140, 134, 147, 176, 198, 22, 92, 156, 217, 189, 134,
|
||||
17, 122, 53, 49, 14, 87, 128, 99, 207, 123, 113, 169, 195, 206, 127, 211, 21, 216, 166,
|
||||
18, 137, 110, 148, 70, 26, 54, 52, 113, 189, 45, 89, 254, 218, 247, 193, 71, 19, 153,
|
||||
35, 179, 49, 237, 199, 176, 251, 143, 95, 115, 195, 3, 122, 161, 243, 220, 39, 102,
|
||||
147, 134, 25, 172, 164, 167, 110, 123, 221, 177, 28, 236, 100, 165, 186, 179, 45, 189,
|
||||
183, 76, 171, 127, 209, 108, 220, 83, 207, 136, 98, 54, 76, 37, 188, 57, 157, 204, 109,
|
||||
150, 181, 110, 57, 5, 26, 168, 34, 11, 117, 3, 184, 147, 155, 122, 244, 251, 215, 1,
|
||||
211, 226, 185, 214, 120, 206, 212, 75, 203, 174, 140, 20, 93, 93, 207, 28, 15, 122, 9,
|
||||
83, 98, 107, 51, 202, 151, 220, 42, 95, 17, 141, 141, 201, 149, 253, 55, 169, 170, 237,
|
||||
166, 92, 92, 20, 89, 124, 167, 102, 161, 87, 97, 88, 20, 245, 175, 32, 111, 0, 2, 192,
|
||||
25, 63, 182, 10, 226, 165, 162, 223, 35, 243, 198, 189, 167, 137, 134, 207, 84, 240, 8,
|
||||
95, 137, 31, 159, 58, 211, 161, 94, 150, 54, 188, 145, 253, 206, 156, 130, 121, 192,
|
||||
221, 73, 249, 92, 91, 184, 211, 131, 206, 205, 183, 159, 195, 170, 47, 13, 131, 6, 132,
|
||||
103, 121, 40, 252, 250, 251, 85, 253, 68, 66, 211, 24, 104, 48, 150, 176, 62, 201, 161,
|
||||
93, 204, 120, 196, 159, 208, 199, 96, 228, 239, 29, 239, 128, 156, 14, 131, 25, 27,
|
||||
157, 249, 253, 250, 193, 148, 133, 59, 138, 202, 239,
|
||||
];
|
||||
|
||||
let keyslot = Keyslot::new(host_key);
|
||||
let encr_keyslot = keyslot.encrypt(&[0x17u8; 32], &cust_key).unwrap();
|
||||
|
||||
assert_eq!(encr_keyslot, exp_keyslot);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_keyslot_v2_constants() {
|
||||
// Test V2 keyslot constants
|
||||
assert_eq!(
|
||||
KeyslotV2::SIZE,
|
||||
1680,
|
||||
"V2 keyslot size should be 1680 bytes"
|
||||
);
|
||||
assert_eq!(
|
||||
KeyslotV2::PHKH_SIZE,
|
||||
0x40,
|
||||
"V2 PHKH size should be 64 bytes (SHA-512)"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_keyslot_v2_creation() {
|
||||
let (_, ec_key, mlkem_key) = get_test_key_and_cert_hybrid();
|
||||
let hybrid = HybridPKey::new(
|
||||
ec_key.public_key().unwrap(),
|
||||
mlkem_key.public_key().unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let keyslot = KeyslotV2::new(hybrid);
|
||||
|
||||
// Verify keyslot was created successfully
|
||||
assert!(keyslot.ec_hostkey.public_key_to_der().is_ok());
|
||||
assert!(keyslot.mlkem_hostkey.public_key_to_der().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_keyslot_enum_v1_variant() {
|
||||
let (_, host_key) = get_test_keys();
|
||||
let keyslot = Keyslot::V1(KeyslotV1(host_key));
|
||||
|
||||
assert_eq!(keyslot.phkh_size(), KeyslotV1::PHKH_SIZE);
|
||||
assert_eq!(keyslot.size(), KeyslotV1::SIZE);
|
||||
assert!(matches!(keyslot, Keyslot::V1(_)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_keyslot_enum_v2_variant() {
|
||||
let (_, ec_key, mlkem_key) = get_test_key_and_cert_hybrid();
|
||||
let hybrid = HybridPKey::new(
|
||||
ec_key.public_key().unwrap(),
|
||||
mlkem_key.public_key().unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
let keyslot = Keyslot::V2(KeyslotV2::new(hybrid));
|
||||
|
||||
assert_eq!(keyslot.phkh_size(), KeyslotV2::PHKH_SIZE);
|
||||
assert_eq!(keyslot.size(), KeyslotV2::SIZE);
|
||||
assert!(matches!(keyslot, Keyslot::V2(_)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_keyslot_from_hostkey_v1() {
|
||||
let (_, ec_key) = get_test_keys();
|
||||
let hostkey = HostKey::V1(ec_key);
|
||||
let keyslot = Keyslot::new(hostkey);
|
||||
|
||||
assert!(matches!(keyslot, Keyslot::V1(_)));
|
||||
assert_eq!(keyslot.size(), KeyslotV1::SIZE);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_keyslot_from_hostkey_v2() {
|
||||
let (_, ec_key, mlkem_key) = get_test_key_and_cert_hybrid();
|
||||
let hybrid = HybridPKey::new(
|
||||
ec_key.public_key().unwrap(),
|
||||
mlkem_key.public_key().unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
let hostkey = HostKey::V2(hybrid);
|
||||
let keyslot = Keyslot::new(hostkey);
|
||||
|
||||
assert!(matches!(keyslot, Keyslot::V2(_)));
|
||||
assert_eq!(keyslot.size(), KeyslotV2::SIZE);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_keyslot_from_hybrid_public_key() {
|
||||
let (_, ec_key, mlkem_key) = get_test_key_and_cert_hybrid();
|
||||
let hybrid = HybridPKey::new(
|
||||
ec_key.public_key().unwrap(),
|
||||
mlkem_key.public_key().unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let keyslot: Keyslot = hybrid.into();
|
||||
assert!(matches!(keyslot, Keyslot::V2(_)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_keyslot_sizes() {
|
||||
// Document the sizes for V1 and V2
|
||||
assert_eq!(KeyslotV1::SIZE, 80, "V1 keyslot size");
|
||||
assert_eq!(
|
||||
KeyslotV2::SIZE,
|
||||
1680,
|
||||
"V2 keyslot size (includes ML-KEM ciphertext)"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,9 +17,10 @@ mod request;
|
||||
|
||||
// Re-export public types
|
||||
pub use context::ReqEncrCtx;
|
||||
pub(crate) use ec_coord::get_pub_ecdh_points;
|
||||
pub use ec_coord::EcPubKeyCoord;
|
||||
pub use encrypt::{Aad, Encrypt};
|
||||
pub use header::RequestHdr;
|
||||
pub use hostkey::HostKey;
|
||||
pub use keyslot::{Keyslot, KeyslotV1};
|
||||
pub use hostkey::{HostKey, HybridPKey};
|
||||
pub use keyslot::{Keyslot, KeyslotV1, KeyslotV2};
|
||||
pub use request::{BinReqValues, Request};
|
||||
|
||||
@@ -51,7 +51,7 @@ pub trait Request {
|
||||
/// Add a host-key to this request
|
||||
///
|
||||
/// Must be called at least once, otherwise {`Request::encrypt`} will fail
|
||||
fn add_hostkey(&mut self, hostkey: HostKey);
|
||||
fn add_hostkey(&mut self, hostkey: HostKey) -> Result<()>;
|
||||
}
|
||||
|
||||
/// A struct to represent some parts of a binary/encrypted request.
|
||||
@@ -79,7 +79,7 @@ impl<'a> BinReqValues<'a> {
|
||||
let rql = hdr.rql.get() as usize;
|
||||
let sea = hdr.sea.get() as usize;
|
||||
|
||||
if rql < req.len() || sea + Self::TAG_LEN > rql {
|
||||
if req.len() < rql || sea + Self::TAG_LEN > rql {
|
||||
return Err(Error::BinRequestSmall);
|
||||
}
|
||||
let aad_size = rql - sea - Self::TAG_LEN;
|
||||
@@ -148,10 +148,9 @@ mod tests {
|
||||
use zerocopy::IntoBytes;
|
||||
|
||||
use super::*;
|
||||
use crate::crypto::SymKey;
|
||||
use crate::get_test_asset;
|
||||
use crate::req::header::RequestHdr;
|
||||
use crate::req::{Aad, HostKey, Keyslot, ReqEncrCtx};
|
||||
use crate::request::SymKey;
|
||||
use crate::req::{Aad, HybridPKey, Keyslot};
|
||||
use crate::test_utils::*;
|
||||
|
||||
static TEST_MAGIC: [u8; 8] = 0x12345689abcdef00u64.to_be_bytes();
|
||||
@@ -187,6 +186,37 @@ mod tests {
|
||||
assert_eq!(&aad, &aad_exp);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn encr_build_aad_v2() {
|
||||
let (cust_key, host_key1, host_key2) = get_test_keys_hybrid();
|
||||
let ks = Keyslot::new(HostKey::V2(HybridPKey::new(host_key1, host_key2).unwrap()));
|
||||
let ctx = ReqEncrCtx::new_aes_256(
|
||||
Some([0x11; 12]),
|
||||
Some(cust_key),
|
||||
Some(SymKey::Aes256([0x17; 32].into())),
|
||||
)
|
||||
.unwrap();
|
||||
let v = [0x55; 8];
|
||||
let aad = Aad::Plain(&v);
|
||||
let aad = ctx
|
||||
.build_aad(0x200, &vec![aad, Aad::Ks(&ks)], 16, Some(TEST_MAGIC))
|
||||
.unwrap();
|
||||
|
||||
let aad_exp = vec![
|
||||
0x12, 0x34, 0x56, 0x89, 0xab, 0xcd, 0xef, 0, // progr
|
||||
0, 0, 2, 0, // vers
|
||||
0, 0, 6, 232, // size
|
||||
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, // iv
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // res
|
||||
1, // nks
|
||||
0, 0, 0, 0, // res
|
||||
0, 0, 0, 16, // sea
|
||||
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, // aad
|
||||
];
|
||||
// only compare non-randomized part
|
||||
assert_eq!(aad[..aad_exp.len()], aad_exp);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn encr_build_aad_nks_no() {
|
||||
let ctx = ReqEncrCtx::new_aes_256(Some([0x11; 12]), None, None).unwrap();
|
||||
@@ -210,6 +240,21 @@ mod tests {
|
||||
let aad = ctx.build_aad(0x200, &aad, 16, Some(TEST_MAGIC));
|
||||
assert!(matches!(aad, Err(Error::ManyHostkeys)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn encr_build_aad_nks_many_v2() {
|
||||
let (_, host_key1, host_key2) = get_test_keys_hybrid();
|
||||
let host_key = HostKey::V2(HybridPKey::new(host_key1, host_key2).unwrap());
|
||||
let ctx = ReqEncrCtx::new_aes_256(Some([0x11; 12]), None, None).unwrap();
|
||||
|
||||
let ks: Vec<Keyslot> = (0..257).map(|_| Keyslot::new(host_key.clone())).collect();
|
||||
let mut aad = Vec::<Aad>::new();
|
||||
ks.iter().for_each(|ks| aad.push(Aad::Ks(ks)));
|
||||
|
||||
let aad = ctx.build_aad(0x200, &aad, 16, Some(TEST_MAGIC));
|
||||
assert!(matches!(aad, Err(Error::ManyHostkeys)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn encr_build_aad_nks() {
|
||||
let (_, host_key) = get_test_keys();
|
||||
@@ -229,6 +274,25 @@ mod tests {
|
||||
assert_eq!(aad.get(39).unwrap(), &3u8);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn encr_build_aad_nks_v2() {
|
||||
let (_, host_key1, host_key2) = get_test_keys_hybrid();
|
||||
let host_key = HostKey::V2(HybridPKey::new(host_key1, host_key2).unwrap());
|
||||
let ctx = ReqEncrCtx::new_aes_256(Some([0x11; 12]), None, None).unwrap();
|
||||
|
||||
let ks = [
|
||||
Keyslot::new(host_key.clone()),
|
||||
Keyslot::new(host_key.clone()),
|
||||
Keyslot::new(host_key),
|
||||
];
|
||||
let mut aad = Vec::<Aad>::new();
|
||||
ks.iter().for_each(|ks| aad.push(Aad::Ks(ks)));
|
||||
|
||||
let aad = ctx.build_aad(0x200, &aad, 16, Some(TEST_MAGIC)).unwrap();
|
||||
|
||||
assert_eq!(aad.get(39).unwrap(), &3u8);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn req_hdr() {
|
||||
let hdr = RequestHdr::new(0x200, 22, [0x11; 12], 15, 44, None);
|
||||
@@ -262,4 +326,18 @@ mod tests {
|
||||
];
|
||||
assert_eq!(hdr_bin, &hdr_bin_exp);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bin_req_values_buffer_too_small() {
|
||||
// Create a valid header with request length set to 200 bytes
|
||||
let hdr = RequestHdr::new(0x200, 200, [0x11; 12], 1, 32, Some(TEST_MAGIC));
|
||||
let hdr_bin = hdr.as_bytes();
|
||||
|
||||
// Create a buffer that's smaller than the declared request length (48
|
||||
// bytes)
|
||||
let small_buffer = Vec::from(hdr_bin);
|
||||
|
||||
let result = BinReqValues::get(&small_buffer);
|
||||
assert!(matches!(result, Err(Error::BinRequestSmall)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// Copyright IBM Corp. 2023
|
||||
// Copyright IBM Corp.
|
||||
|
||||
// DO NOT USE ANY OF THESE ITEMS IN PRODUCTION CODE
|
||||
// USED FOR INTERNAL UNIT AND FVT TESTING ONLY!!!
|
||||
use std::ffi::c_void;
|
||||
use std::fs;
|
||||
use std::mem::{size_of, ManuallyDrop};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::ptr::NonNull;
|
||||
|
||||
use openssl::bn::BigNum;
|
||||
use openssl::ec::{EcGroup, EcKey};
|
||||
@@ -86,6 +89,27 @@ pub fn get_test_key_and_cert() -> (PKey<Private>, X509) {
|
||||
(cust_key, host_key)
|
||||
}
|
||||
|
||||
pub fn get_test_key_and_cert_hybrid() -> (PKey<Private>, X509, X509) {
|
||||
let pub_key = get_test_asset!("keys/public_cust.bin");
|
||||
let priv_key = get_test_asset!("keys/private_cust.bin");
|
||||
let host_key = get_test_asset!("keys/host.ec.crt");
|
||||
let host_keys = get_test_asset!("keys/host.hybrid.crt");
|
||||
|
||||
assert_eq!(pub_key.len(), 160);
|
||||
assert_eq!(priv_key.len(), 80);
|
||||
|
||||
let cust_key = get_keypair(pub_key, priv_key).unwrap();
|
||||
let host_key1 = X509::from_pem(host_key).unwrap();
|
||||
let host_keys = X509::stack_from_pem(host_keys).unwrap();
|
||||
assert_eq!(host_keys.len(), 2);
|
||||
|
||||
println!("host_key1 = {host_key1:?}");
|
||||
println!("host_keys[0] = {:?}", host_keys[0]);
|
||||
println!("host_keys[1] = {:?}", host_keys[1]);
|
||||
|
||||
(cust_key, host_key1, host_keys[1].clone())
|
||||
}
|
||||
|
||||
/// TEST ONLY! Get a fixed private/public pair and a fixed public key
|
||||
///
|
||||
/// Intended for TESTING only. All parts of the key including the private key are checked in git and
|
||||
@@ -95,6 +119,15 @@ pub fn get_test_keys() -> (PKey<Private>, PKey<Public>) {
|
||||
(cust_key, host.public_key().unwrap())
|
||||
}
|
||||
|
||||
pub fn get_test_keys_hybrid() -> (PKey<Private>, PKey<Public>, PKey<Public>) {
|
||||
let (cust_key, host_key_1, host_key_2) = get_test_key_and_cert_hybrid();
|
||||
(
|
||||
cust_key,
|
||||
host_key_1.public_key().unwrap(),
|
||||
host_key_2.public_key().unwrap(),
|
||||
)
|
||||
}
|
||||
|
||||
fn read_ecdh_pubkey(coords: &[u8]) -> Result<PKey<Public>, ErrorStack> {
|
||||
assert!(coords.len() == 160);
|
||||
let x = BigNum::from_slice(&coords[..80])?;
|
||||
@@ -118,3 +151,379 @@ fn get_keypair(pub_coords: &[u8], priv_num: &[u8]) -> Result<PKey<Private>, Erro
|
||||
key.check_key()?;
|
||||
PKey::from_ec_key(key)
|
||||
}
|
||||
|
||||
// To regenerate these bindings, run:
|
||||
// bindgen bindgen_wrapper.h -o bindgen_output.rs \
|
||||
// --allowlist-function "RAND_get0_public" \
|
||||
// --allowlist-function "RAND_get0_private" --allowlist-function "EVP_RAND_fetch" \
|
||||
// --allowlist-function "EVP_RAND_free" --allowlist-function "EVP_RAND_CTX_new" \
|
||||
// --allowlist-function "EVP_RAND_CTX_free" --allowlist-function "EVP_RAND_CTX_up_ref" \
|
||||
// --allowlist-function "EVP_RAND_instantiate" --allowlist-function "RAND_set0_public" \
|
||||
// --allowlist-function "RAND_set0_private" --allowlist-type "OSSL_PARAM"
|
||||
// where bindgen_wrapper.h contains:
|
||||
// #include <openssl/provider.h>
|
||||
// #include <openssl/rand.h>
|
||||
// #include <openssl/evp.h>
|
||||
// #include <openssl/params.h>
|
||||
mod ffi {
|
||||
use std::ffi::{c_char, c_int, c_uchar, c_uint, c_void};
|
||||
|
||||
#[repr(C)]
|
||||
pub struct OsslParam {
|
||||
pub key: *const c_char,
|
||||
pub data_type: c_uint,
|
||||
pub data: *mut c_void,
|
||||
pub data_size: usize,
|
||||
pub return_size: usize,
|
||||
}
|
||||
|
||||
pub enum OsslLibCtx {}
|
||||
pub enum OsslProvider {}
|
||||
pub enum EvpRand {}
|
||||
pub enum EvpRandCtx {}
|
||||
|
||||
unsafe extern "C" {
|
||||
pub fn RAND_get0_public(ctx: *mut OsslLibCtx) -> *mut EvpRandCtx;
|
||||
pub fn RAND_get0_private(ctx: *mut OsslLibCtx) -> *mut EvpRandCtx;
|
||||
pub fn EVP_RAND_fetch(
|
||||
libctx: *mut OsslLibCtx,
|
||||
algorithm: *const c_char,
|
||||
properties: *const c_char,
|
||||
) -> *mut EvpRand;
|
||||
pub fn EVP_RAND_free(rand: *mut EvpRand);
|
||||
pub fn EVP_RAND_CTX_new(rand: *mut EvpRand, parent: *mut EvpRandCtx) -> *mut EvpRandCtx;
|
||||
pub fn EVP_RAND_CTX_free(ctx: *mut EvpRandCtx);
|
||||
pub fn EVP_RAND_CTX_up_ref(ctx: *mut EvpRandCtx) -> c_int;
|
||||
pub fn EVP_RAND_instantiate(
|
||||
ctx: *mut EvpRandCtx,
|
||||
strength: c_uint,
|
||||
prediction_resistance: c_int,
|
||||
pstr: *const c_uchar,
|
||||
pstr_len: usize,
|
||||
params: *const OsslParam,
|
||||
) -> c_int;
|
||||
pub fn RAND_set0_public(ctx: *mut OsslLibCtx, rand: *mut EvpRandCtx) -> c_int;
|
||||
pub fn RAND_set0_private(ctx: *mut OsslLibCtx, rand: *mut EvpRandCtx) -> c_int;
|
||||
}
|
||||
}
|
||||
|
||||
// Constants for OSSL_PARAM construction
|
||||
const OSSL_PARAM_OCTET_STRING: u32 = 5;
|
||||
const OSSL_PARAM_UNSIGNED_INTEGER: u32 = 2;
|
||||
const OSSL_PARAM_END: u32 = 0;
|
||||
|
||||
fn ossl_param_end() -> ffi::OsslParam {
|
||||
ffi::OsslParam {
|
||||
key: std::ptr::null(),
|
||||
data_type: OSSL_PARAM_END,
|
||||
data: std::ptr::null_mut(),
|
||||
data_size: 0,
|
||||
return_size: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn ossl_param_octet_string(name: &'static [u8], data: &mut [u8]) -> ffi::OsslParam {
|
||||
// SAFETY: Constructing OSSL_PARAM for octet string.
|
||||
// - name is a static null-terminated C string, valid for 'static
|
||||
// - data is a valid mutable slice, pointer remains valid during param usage
|
||||
// - Pointer casts are safe as they preserve alignment and validity
|
||||
ffi::OsslParam {
|
||||
key: name.as_ptr().cast(),
|
||||
data_type: OSSL_PARAM_OCTET_STRING,
|
||||
data: data.as_mut_ptr().cast(),
|
||||
data_size: data.len(),
|
||||
return_size: data.len(),
|
||||
}
|
||||
}
|
||||
|
||||
fn ossl_param_uint(name: &'static [u8], value: &mut u32) -> ffi::OsslParam {
|
||||
// SAFETY: Constructing OSSL_PARAM for unsigned integer.
|
||||
// - name is a static null-terminated C string, valid for 'static
|
||||
// - value is a valid mutable reference, pointer remains valid during param usage
|
||||
// - Pointer cast to c_void is safe as it preserves alignment and validity
|
||||
ffi::OsslParam {
|
||||
key: name.as_ptr().cast(),
|
||||
data_type: OSSL_PARAM_UNSIGNED_INTEGER,
|
||||
data: (value as *mut u32).cast::<c_void>(),
|
||||
data_size: size_of::<u32>(),
|
||||
return_size: size_of::<u32>(),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct FetchedRand(NonNull<ffi::EvpRand>);
|
||||
|
||||
impl FetchedRand {
|
||||
const TEST_RAND_NAME: &'static [u8] = b"TEST-RAND\0";
|
||||
|
||||
fn fetch_test_rand() -> Result<Self, ErrorStack> {
|
||||
// SAFETY: Calling OpenSSL C API with valid parameters.
|
||||
// - null_mut() is valid for optional OSSL_LIB_CTX parameter
|
||||
// - Self::TEST_RAND_NAME is a valid null-terminated C string
|
||||
// - null() is valid for optional properties parameter
|
||||
// - Returns null on error, which we handle via NonNull::new
|
||||
let rand = unsafe {
|
||||
ffi::EVP_RAND_fetch(
|
||||
std::ptr::null_mut(),
|
||||
Self::TEST_RAND_NAME.as_ptr().cast(),
|
||||
std::ptr::null(),
|
||||
)
|
||||
};
|
||||
NonNull::new(rand).map(Self).ok_or_else(ErrorStack::get)
|
||||
}
|
||||
|
||||
fn as_ptr(&self) -> *mut ffi::EvpRand {
|
||||
self.0.as_ptr()
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for FetchedRand {
|
||||
fn drop(&mut self) {
|
||||
// SAFETY: self.0 is a valid non-null EVP_RAND pointer that we own.
|
||||
// This is the only place we call free, preventing double-free.
|
||||
unsafe {
|
||||
ffi::EVP_RAND_free(self.0.as_ptr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct RandCtx(NonNull<ffi::EvpRandCtx>);
|
||||
|
||||
impl RandCtx {
|
||||
fn new(rand: &FetchedRand) -> Result<Self, ErrorStack> {
|
||||
// SAFETY: Calling OpenSSL C API with valid parameters.
|
||||
// - rand.as_ptr() is a valid non-null EVP_RAND pointer
|
||||
// - null_mut() is valid for optional parent parameter
|
||||
// - Returns null on error, which we handle via NonNull::new
|
||||
let ctx = unsafe { ffi::EVP_RAND_CTX_new(rand.as_ptr(), std::ptr::null_mut()) };
|
||||
NonNull::new(ctx).map(Self).ok_or_else(ErrorStack::get)
|
||||
}
|
||||
|
||||
fn up_ref(ptr: *mut ffi::EvpRandCtx) -> Result<Self, ErrorStack> {
|
||||
let ptr = NonNull::new(ptr).ok_or_else(ErrorStack::get)?;
|
||||
// SAFETY: ptr is a valid non-null EVP_RAND_CTX pointer.
|
||||
// EVP_RAND_CTX_up_ref increments the reference count.
|
||||
// Returns 1 on success, 0 on failure.
|
||||
let rc = unsafe { ffi::EVP_RAND_CTX_up_ref(ptr.as_ptr()) };
|
||||
if rc == 1 {
|
||||
Ok(Self(ptr))
|
||||
} else {
|
||||
Err(ErrorStack::get())
|
||||
}
|
||||
}
|
||||
|
||||
fn current_public() -> Result<Option<Self>, ErrorStack> {
|
||||
// SAFETY: RAND_get0_public returns a borrowed pointer (no ownership transfer).
|
||||
// Returns null if no public RNG is set, which we handle.
|
||||
let ptr = unsafe { ffi::RAND_get0_public(std::ptr::null_mut()) };
|
||||
if ptr.is_null() {
|
||||
Ok(None)
|
||||
} else {
|
||||
Self::up_ref(ptr).map(Some)
|
||||
}
|
||||
}
|
||||
|
||||
fn current_private() -> Result<Option<Self>, ErrorStack> {
|
||||
// SAFETY: RAND_get0_private returns a borrowed pointer (no ownership transfer).
|
||||
// Returns null if no private RNG is set, which we handle.
|
||||
let ptr = unsafe { ffi::RAND_get0_private(std::ptr::null_mut()) };
|
||||
if ptr.is_null() {
|
||||
Ok(None)
|
||||
} else {
|
||||
Self::up_ref(ptr).map(Some)
|
||||
}
|
||||
}
|
||||
|
||||
fn as_ptr(&self) -> *mut ffi::EvpRandCtx {
|
||||
self.0.as_ptr()
|
||||
}
|
||||
|
||||
fn instantiate_test_rand(&self, entropy: &[u8], nonce: &[u8]) -> Result<(), ErrorStack> {
|
||||
// See https://docs.openssl.org/3.1/man7/EVP_RAND-TEST-RAND/#description
|
||||
// for the available parameters.
|
||||
const TEST_ENTROPY_PARAM: &[u8] = b"test_entropy\0";
|
||||
const TEST_NONCE_PARAM: &[u8] = b"test_nonce\0";
|
||||
const STRENGTH_PARAM: &[u8] = b"strength\0";
|
||||
|
||||
let mut entropy = entropy.to_vec();
|
||||
let mut nonce = nonce.to_vec();
|
||||
let mut strength = 256u32;
|
||||
let params = [
|
||||
ossl_param_uint(STRENGTH_PARAM, &mut strength),
|
||||
ossl_param_octet_string(TEST_ENTROPY_PARAM, &mut entropy),
|
||||
ossl_param_octet_string(TEST_NONCE_PARAM, &mut nonce),
|
||||
ossl_param_end(),
|
||||
];
|
||||
|
||||
// SAFETY: Calling OpenSSL C API with valid parameters.
|
||||
// - self.as_ptr() is a valid non-null EVP_RAND_CTX pointer
|
||||
// - strength is a valid u32 value
|
||||
// - prediction_resistance=0 is valid
|
||||
// - pstr=null and pstr_len=0 indicate no personalization string
|
||||
// - params points to a valid array of OSSL_PARAM with proper terminator
|
||||
// - All mutable references in params remain valid for the call duration
|
||||
let rc = unsafe {
|
||||
ffi::EVP_RAND_instantiate(
|
||||
self.as_ptr(),
|
||||
strength,
|
||||
0,
|
||||
std::ptr::null(),
|
||||
0,
|
||||
params.as_ptr(),
|
||||
)
|
||||
};
|
||||
if rc == 1 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ErrorStack::get())
|
||||
}
|
||||
}
|
||||
|
||||
fn install_as_public(self) -> Result<InstalledRandCtx, ErrorStack> {
|
||||
// SAFETY: Calling OpenSSL C API to transfer ownership.
|
||||
// - self.as_ptr() is a valid non-null EVP_RAND_CTX pointer
|
||||
// - RAND_set0_public takes ownership of the context on success (rc==1)
|
||||
// - We wrap in ManuallyDrop to prevent double-free since OpenSSL now owns it
|
||||
let rc = unsafe { ffi::RAND_set0_public(std::ptr::null_mut(), self.as_ptr()) };
|
||||
if rc == 1 {
|
||||
Ok(InstalledRandCtx(ManuallyDrop::new(self)))
|
||||
} else {
|
||||
Err(ErrorStack::get())
|
||||
}
|
||||
}
|
||||
|
||||
fn install_as_private(self) -> Result<InstalledRandCtx, ErrorStack> {
|
||||
// SAFETY: Calling OpenSSL C API to transfer ownership.
|
||||
// - self.as_ptr() is a valid non-null EVP_RAND_CTX pointer
|
||||
// - RAND_set0_private takes ownership of the context on success (rc==1)
|
||||
// - We wrap in ManuallyDrop to prevent double-free since OpenSSL now owns it
|
||||
let rc = unsafe { ffi::RAND_set0_private(std::ptr::null_mut(), self.as_ptr()) };
|
||||
if rc == 1 {
|
||||
Ok(InstalledRandCtx(ManuallyDrop::new(self)))
|
||||
} else {
|
||||
Err(ErrorStack::get())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for RandCtx {
|
||||
fn drop(&mut self) {
|
||||
// SAFETY: self.0 is a valid non-null EVP_RAND_CTX pointer that we own.
|
||||
// This is only called when ownership was NOT transferred to OpenSSL.
|
||||
// InstalledRandCtx uses ManuallyDrop to prevent this from running after transfer.
|
||||
unsafe {
|
||||
ffi::EVP_RAND_CTX_free(self.0.as_ptr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct InstalledRandCtx(ManuallyDrop<RandCtx>);
|
||||
|
||||
impl Drop for InstalledRandCtx {
|
||||
fn drop(&mut self) {
|
||||
// SAFETY: Ownership of the EVP_RAND_CTX was transferred to OpenSSL
|
||||
// via RAND_set0_public/private, so we must not call EVP_RAND_CTX_free.
|
||||
// ManuallyDrop prevents RandCtx::drop from running automatically.
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct PreviousRandCtx(Option<RandCtx>);
|
||||
|
||||
impl PreviousRandCtx {
|
||||
fn capture_public() -> Result<Self, ErrorStack> {
|
||||
RandCtx::current_public().map(Self)
|
||||
}
|
||||
|
||||
fn capture_private() -> Result<Self, ErrorStack> {
|
||||
RandCtx::current_private().map(Self)
|
||||
}
|
||||
|
||||
fn restore_public(&mut self) {
|
||||
let Some(ctx) = self.0.take() else {
|
||||
return;
|
||||
};
|
||||
// SAFETY: Restoring previously captured RNG context.
|
||||
// - ctx.as_ptr() is a valid non-null EVP_RAND_CTX pointer
|
||||
// - RAND_set0_public takes ownership of the context
|
||||
// - We forget ctx to prevent double-free since OpenSSL now owns it
|
||||
// - Ignoring return value as restoration is best-effort during cleanup
|
||||
let _ = unsafe { ffi::RAND_set0_public(std::ptr::null_mut(), ctx.as_ptr()) };
|
||||
std::mem::forget(ctx);
|
||||
}
|
||||
|
||||
fn restore_private(&mut self) {
|
||||
let Some(ctx) = self.0.take() else {
|
||||
return;
|
||||
};
|
||||
// SAFETY: Restoring previously captured RNG context.
|
||||
// - ctx.as_ptr() is a valid non-null EVP_RAND_CTX pointer
|
||||
// - RAND_set0_private takes ownership of the context
|
||||
|
||||
// - We forget ctx to prevent double-free since OpenSSL now owns it
|
||||
// - Ignoring return value as restoration is best-effort during cleanup
|
||||
let _ = unsafe { ffi::RAND_set0_private(std::ptr::null_mut(), ctx.as_ptr()) };
|
||||
std::mem::forget(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DeterministicTestRandGuard {
|
||||
previous_public: PreviousRandCtx,
|
||||
previous_private: PreviousRandCtx,
|
||||
_public: InstalledRandCtx,
|
||||
_private: InstalledRandCtx,
|
||||
}
|
||||
|
||||
impl DeterministicTestRandGuard {
|
||||
/// Install OpenSSL >= 3 TEST-RAND as the thread-local public/private RNG for deterministic
|
||||
/// tests.
|
||||
///
|
||||
/// The supplied entropy is consumed across generate calls. The nonce is replayed for each
|
||||
/// nonce request. Per OpenSSL documentation, the public and private DRBG instances are
|
||||
/// thread-local, so each thread can safely install its own deterministic RNG without
|
||||
/// affecting other threads.
|
||||
///
|
||||
/// # Thread Safety
|
||||
///
|
||||
/// From OpenSSL documentation (RAND_get0_primary(3)):
|
||||
/// > "The public and private DRBG are thread-local instances, which are used by
|
||||
/// > RAND_bytes() and RAND_priv_bytes(), respectively."
|
||||
///
|
||||
/// Reference: <https://docs.openssl.org/3.1/man3/RAND_get0_primary/>
|
||||
///
|
||||
/// **Note:** RAND_set0_public() and RAND_set0_private() require OpenSSL >= 3.1.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns an OpenSSL error if the TEST-RAND provider cannot be configured.
|
||||
pub fn install(entropy: &[u8], nonce: &[u8]) -> Result<Self, ErrorStack> {
|
||||
let previous_public = PreviousRandCtx::capture_public()?;
|
||||
let previous_private = PreviousRandCtx::capture_private()?;
|
||||
let rand = FetchedRand::fetch_test_rand()?;
|
||||
|
||||
let public = RandCtx::new(&rand)?;
|
||||
public.instantiate_test_rand(entropy, nonce)?;
|
||||
let public = public.install_as_public()?;
|
||||
|
||||
let private = RandCtx::new(&rand)?;
|
||||
private.instantiate_test_rand(entropy, nonce)?;
|
||||
let private = private.install_as_private()?;
|
||||
|
||||
Ok(Self {
|
||||
previous_public,
|
||||
previous_private,
|
||||
_public: public,
|
||||
_private: private,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for DeterministicTestRandGuard {
|
||||
fn drop(&mut self) {
|
||||
self.previous_private.restore_private();
|
||||
self.previous_public.restore_public();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
use std::mem::size_of;
|
||||
|
||||
use pv_core::static_assert;
|
||||
use zerocopy::{BigEndian, FromBytes, Immutable, IntoBytes, KnownLayout, U32};
|
||||
|
||||
use super::additional::{FW_STATE_SIZE, PHKH_SIZE, SECRET_STORE_HASH_SIZE};
|
||||
@@ -14,7 +15,7 @@ use crate::misc::Flags;
|
||||
use crate::req::{Aad, BinReqValues, HostKey, Keyslot, ReqEncrCtx};
|
||||
use crate::request::{Confidential, MagicValue, Request, RequestVersion, SymKey, Zeroize};
|
||||
use crate::uv::UvFlags;
|
||||
use crate::{assert_size, static_assert, Error, Result};
|
||||
use crate::{assert_size, Error, Result};
|
||||
#[cfg(doc)]
|
||||
use crate::{
|
||||
request::SymKeyType,
|
||||
@@ -60,9 +61,9 @@ use crate::{
|
||||
/// let hkd = s390_pv::misc::read_certs(&std::fs::read("host-key-document.crt")?)?;
|
||||
/// // IBM issued HKD certificates typically have one X509
|
||||
/// let hkd = hkd.first().unwrap().public_key()?;
|
||||
/// arcb.add_hostkey(HostKey::V1(hkd));
|
||||
/// arcb.add_hostkey(HostKey::V1(hkd))?;
|
||||
/// // you can add multiple hostkeys
|
||||
/// // arcb.add_hostkey(another_hkd);
|
||||
/// // arcb.add_hostkey(HostKey::V1(another_hkd))?;
|
||||
/// // encrypt it
|
||||
/// let ctx = ReqEncrCtx::random(SymKeyType::Aes256Gcm)?;
|
||||
/// let arcb = arcb.encrypt(&ctx)?;
|
||||
@@ -106,7 +107,13 @@ impl AttestationRequest {
|
||||
|
||||
/// Returns a reference to the flags of this [`AttestationRequest`].
|
||||
pub fn flags(&self) -> &AttestationFlags {
|
||||
&self.aad.flags
|
||||
self.aad.flags()
|
||||
}
|
||||
|
||||
/// Returns the request version, derived from the type of added host-keys.
|
||||
/// Returns [`AttestationVersion::One`] if no host-keys have been added yet.
|
||||
pub fn version(&self) -> AttestationVersion {
|
||||
self.version
|
||||
}
|
||||
|
||||
/// Returns a copy of the confidential data of this [`AttestationRequest`].
|
||||
@@ -142,6 +149,7 @@ impl AttestationRequest {
|
||||
let values = BinReqValues::get(arcb)?;
|
||||
match values.version().try_into()? {
|
||||
AttestationVersion::One => (),
|
||||
AttestationVersion::Two => (),
|
||||
};
|
||||
|
||||
Ok(values)
|
||||
@@ -235,8 +243,19 @@ impl Request for AttestationRequest {
|
||||
ctx.encrypt_aead(&aad, conf).map(|res| res.into_buf())
|
||||
}
|
||||
|
||||
fn add_hostkey(&mut self, hostkey: HostKey) {
|
||||
self.keyslots.push(Keyslot::new(hostkey))
|
||||
fn add_hostkey(&mut self, hostkey: HostKey) -> Result<()> {
|
||||
match self.version {
|
||||
AttestationVersion::One if !hostkey.is_hybrid() => Ok(()),
|
||||
AttestationVersion::Two if hostkey.is_hybrid() => Ok(()),
|
||||
AttestationVersion::One => Err(Error::InvalidHkd(
|
||||
"Add classical hostkey to a v1 attestation request".to_string(),
|
||||
)),
|
||||
AttestationVersion::Two => Err(Error::InvalidHkd(
|
||||
"Add hybrid key to a v2 attetstation request".to_string(),
|
||||
)),
|
||||
}?;
|
||||
self.keyslots.push(Keyslot::new(hostkey));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,6 +265,8 @@ impl Request for AttestationRequest {
|
||||
pub enum AttestationVersion {
|
||||
/// Version 1 (= 0x0100)
|
||||
One = 0x0100,
|
||||
/// Version 2 (= 0x0200)
|
||||
Two = 0x0200,
|
||||
}
|
||||
|
||||
impl TryFrom<u32> for AttestationVersion {
|
||||
@@ -254,6 +275,8 @@ impl TryFrom<u32> for AttestationVersion {
|
||||
fn try_from(value: u32) -> Result<Self> {
|
||||
if value == Self::One as u32 {
|
||||
Ok(Self::One)
|
||||
} else if value == Self::Two as u32 {
|
||||
Ok(Self::Two)
|
||||
} else {
|
||||
Err(Error::BinArcbInvVersion(value))
|
||||
}
|
||||
@@ -412,8 +435,8 @@ impl Zeroize for ReqConfData {
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::get_test_asset;
|
||||
use crate::request::SymKey;
|
||||
use crate::test_utils::get_test_keys;
|
||||
use crate::request::{HybridPKey, SymKey};
|
||||
use crate::test_utils::{get_test_keys, get_test_keys_hybrid};
|
||||
|
||||
const ARPK: [u8; 32] = [0x17; 32];
|
||||
const NONCE: [u8; 16] = [0xab; 16];
|
||||
@@ -421,6 +444,8 @@ mod test {
|
||||
|
||||
fn mk_arcb() -> Vec<u8> {
|
||||
let (cust_key, host_key) = get_test_keys();
|
||||
let host_key = HostKey::V1(host_key);
|
||||
|
||||
let ctx = ReqEncrCtx::new_aes_256(
|
||||
Some([0x55; 12]),
|
||||
Some(cust_key),
|
||||
@@ -443,7 +468,37 @@ mod test {
|
||||
arcb.conf.value_mut().nonce = NONCE;
|
||||
arcb.conf.value_mut().meas_key = MEAS;
|
||||
|
||||
arcb.add_hostkey(HostKey::V1(host_key));
|
||||
arcb.add_hostkey(host_key).unwrap();
|
||||
arcb.encrypt(&ctx).unwrap()
|
||||
}
|
||||
|
||||
fn mk_arcb_v2() -> Vec<u8> {
|
||||
let (cust_key, host_key1, host_key2) = get_test_keys_hybrid();
|
||||
let host_key = HostKey::V2(HybridPKey::new(host_key1, host_key2).unwrap());
|
||||
|
||||
let ctx = ReqEncrCtx::new_aes_256(
|
||||
Some([0x55; 12]),
|
||||
Some(cust_key),
|
||||
Some(SymKey::Aes256(ARPK.into())),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut flags = AttestationFlags::default();
|
||||
flags.set_image_phkh();
|
||||
flags.set_attest_phkh();
|
||||
|
||||
let mut arcb = AttestationRequest::new(
|
||||
AttestationVersion::Two,
|
||||
AttestationMeasAlg::HmacSha512,
|
||||
flags,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// manually set confidential data (API does not allow this)
|
||||
arcb.conf.value_mut().nonce = NONCE;
|
||||
arcb.conf.value_mut().meas_key = MEAS;
|
||||
|
||||
arcb.add_hostkey(host_key).unwrap();
|
||||
arcb.encrypt(&ctx).unwrap()
|
||||
}
|
||||
|
||||
@@ -455,6 +510,32 @@ mod test {
|
||||
assert_eq!(request, exp);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arcb_v2() {
|
||||
let request = mk_arcb_v2();
|
||||
// Expected bytes for a V2 ARCB: rqvn = 0x0200 (bytes 8-11), rest deterministic.
|
||||
// The first 288 bytes cover header + customer-public-key + one V2 keyslot header.
|
||||
let exp: [u8; 288] = [
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 7, 208, 85, 85, 85, 85, 85, 85, 85, 85, 85,
|
||||
85, 85, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 80, 112, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 199,
|
||||
93, 52, 249, 22, 82, 219, 69, 123, 11, 32, 156, 70, 164, 145, 164, 78, 226, 177, 110,
|
||||
35, 194, 216, 218, 241, 22, 103, 138, 98, 242, 76, 227, 50, 197, 153, 95, 8, 69, 107,
|
||||
102, 177, 109, 213, 90, 146, 197, 7, 241, 227, 26, 247, 140, 100, 168, 46, 122, 84, 27,
|
||||
21, 19, 80, 21, 242, 2, 134, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 64, 128, 88,
|
||||
167, 241, 165, 195, 80, 151, 83, 58, 2, 169, 56, 121, 231, 222, 103, 186, 40, 11, 206,
|
||||
131, 101, 236, 148, 178, 185, 8, 245, 137, 195, 169, 152, 216, 190, 30, 99, 7, 215, 74,
|
||||
224, 26, 220, 70, 130, 95, 246, 187, 111, 160, 92, 17, 71, 207, 226, 204, 244, 162, 79,
|
||||
61, 131, 61, 218, 112, 255, 94, 191, 53, 220, 196, 47, 37, 93, 227, 234, 101, 1, 174,
|
||||
171, 68, 42, 136, 92, 238, 72, 6, 17, 77, 231, 225, 174, 22, 222, 188, 212, 15, 248,
|
||||
145, 72, 126, 139, 17, 233, 225, 156, 46, 233, 151, 54, 2, 175, 88, 215, 254, 243, 222,
|
||||
37, 81, 50, 110, 18, 76, 252, 12, 210, 146, 66, 23,
|
||||
];
|
||||
|
||||
// only compare non-randomized part
|
||||
assert_eq!(request[..288], exp[..288]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn auth_bin() {
|
||||
let request = mk_arcb();
|
||||
@@ -464,6 +545,15 @@ mod test {
|
||||
assert_eq!(exp, auth_bin.as_bytes());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn auth_bin_v2() {
|
||||
let request = mk_arcb_v2();
|
||||
let auth_bin = AttestationRequest::auth_bin(&request).unwrap();
|
||||
let exp = &request[0x30..0x40];
|
||||
|
||||
assert_eq!(exp, auth_bin.as_bytes());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decrypt_bin() {
|
||||
let request = mk_arcb();
|
||||
@@ -473,6 +563,100 @@ mod test {
|
||||
assert_eq!(conf.nonce().as_ref().unwrap().value(), &NONCE);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decrypt_bin_v2() {
|
||||
let request = mk_arcb_v2();
|
||||
let arpk = SymKey::Aes256(ARPK.into());
|
||||
let (_, conf) = AttestationRequest::decrypt_bin(&request, &arpk).unwrap();
|
||||
assert_eq!(conf.measurement_key(), &MEAS);
|
||||
assert_eq!(conf.nonce().as_ref().unwrap().value(), &NONCE);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arcb_v1_version() {
|
||||
// Without any host-keys, version defaults to One
|
||||
let arcb = AttestationRequest::new(
|
||||
AttestationVersion::One,
|
||||
AttestationMeasAlg::HmacSha512,
|
||||
AttestationFlags::default(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(arcb.version(), AttestationVersion::One);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn arcb_v2_version() {
|
||||
// After adding a V2 host-key, version is Two
|
||||
let mut arcb = AttestationRequest::new(
|
||||
AttestationVersion::Two,
|
||||
AttestationMeasAlg::HmacSha512,
|
||||
AttestationFlags::default(),
|
||||
)
|
||||
.unwrap();
|
||||
let (_, host_key1, host_key2) = get_test_keys_hybrid();
|
||||
arcb.add_hostkey(HostKey::V2(HybridPKey::new(host_key1, host_key2).unwrap()))
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(arcb.version(), AttestationVersion::Two);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn attestation_version_try_from() {
|
||||
// Test version conversion from u32
|
||||
assert_eq!(
|
||||
AttestationVersion::try_from(0x0100).unwrap(),
|
||||
AttestationVersion::One
|
||||
);
|
||||
assert_eq!(
|
||||
AttestationVersion::try_from(0x0200).unwrap(),
|
||||
AttestationVersion::Two
|
||||
);
|
||||
|
||||
// Invalid version should error
|
||||
assert!(AttestationVersion::try_from(0x0300).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn attestation_flags_expected_size() {
|
||||
// Test expected additional data size calculation for V1
|
||||
let mut flags = AttestationFlags::default();
|
||||
|
||||
// Image PHKH flag - should be 32 bytes
|
||||
flags.set_image_phkh();
|
||||
assert_eq!(flags.expected_additional_size(), 32);
|
||||
|
||||
// Add attest PHKH flag - should be 64 bytes (32 + 32)
|
||||
flags.set_attest_phkh();
|
||||
assert_eq!(flags.expected_additional_size(), 64);
|
||||
|
||||
// Add secret store hash - should be 128 bytes (64 + 64)
|
||||
flags.set_secret_store_hash();
|
||||
assert_eq!(flags.expected_additional_size(), 128);
|
||||
|
||||
// Add firmware state - should be 448 bytes (128 + 320)
|
||||
flags.set_firmware_state();
|
||||
assert_eq!(flags.expected_additional_size(), 448);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn confidential_data_v2() {
|
||||
// Test confidential data extraction (version-independent)
|
||||
let arcb = AttestationRequest::new(
|
||||
AttestationVersion::Two,
|
||||
AttestationMeasAlg::HmacSha512,
|
||||
AttestationFlags::default(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let conf = arcb.confidential_data();
|
||||
|
||||
// Should have measurement key and nonce
|
||||
assert_eq!(conf.measurement_key().len(), 64);
|
||||
assert!(conf.nonce().is_some());
|
||||
assert_eq!(conf.nonce().as_ref().unwrap().value().len(), 16);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decrypt_bin_fail_magic() {
|
||||
let arpk = SymKey::Aes256(ARPK.into());
|
||||
@@ -484,6 +668,17 @@ mod test {
|
||||
assert!(matches!(ret, Err(Error::NoArcb)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decrypt_bin_fail_magic_v2() {
|
||||
let arpk = SymKey::Aes256(ARPK.into());
|
||||
let mut tamp_arcb = mk_arcb_v2();
|
||||
|
||||
// tamper magic
|
||||
tamp_arcb[0] = 17;
|
||||
let ret = AttestationRequest::decrypt_bin(&tamp_arcb, &arpk);
|
||||
assert!(matches!(ret, Err(Error::NoArcb)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decrypt_bin_fail_mai() {
|
||||
let arpk = SymKey::Aes256(ARPK.into());
|
||||
@@ -499,6 +694,21 @@ mod test {
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decrypt_bin_fail_mai_v2() {
|
||||
let arpk = SymKey::Aes256(ARPK.into());
|
||||
let mut tamp_arcb = mk_arcb_v2();
|
||||
|
||||
// tamper MAI
|
||||
tamp_arcb[0x3b] = 17;
|
||||
let ret = AttestationRequest::decrypt_bin(&tamp_arcb, &arpk);
|
||||
println!("{ret:?}");
|
||||
assert!(matches!(
|
||||
ret,
|
||||
Err(Error::PvCore(pv_core::Error::BinArcbInvAlgorithm(17)))
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decrypt_bin_fail_aad() {
|
||||
let arpk = SymKey::Aes256(ARPK.into());
|
||||
@@ -509,4 +719,15 @@ mod test {
|
||||
let ret = AttestationRequest::decrypt_bin(&tamp_arcb, &arpk);
|
||||
assert!(matches!(ret, Err(Error::GcmTagMismatch)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decrypt_bin_fail_aad_v2() {
|
||||
let arpk = SymKey::Aes256(ARPK.into());
|
||||
let mut tamp_arcb = mk_arcb_v2();
|
||||
|
||||
// tamper AAD
|
||||
tamp_arcb[0x3c] = 17;
|
||||
let ret = AttestationRequest::decrypt_bin(&tamp_arcb, &arpk);
|
||||
assert!(matches!(ret, Err(Error::GcmTagMismatch)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ use std::mem::size_of;
|
||||
|
||||
use openssl::hash::MessageDigest;
|
||||
use openssl::pkey::{PKeyRef, Private};
|
||||
use pv_core::misc::write_file;
|
||||
use zerocopy::{BigEndian, IntoBytes, U16, U32};
|
||||
|
||||
use super::AttNonce;
|
||||
@@ -101,6 +102,7 @@ impl AttestationItems {
|
||||
}
|
||||
items.extend_from_slice(additional);
|
||||
assert!(items.len() == size);
|
||||
write_file("additional_data_parsed", &items, "blah").unwrap();
|
||||
Self(items.into())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,31 +6,32 @@ use openssl::md::Md;
|
||||
use openssl::pkey::{PKey, Private};
|
||||
use pv_core::request::RequestVersion;
|
||||
use pv_core::secret::AddSecretMagic;
|
||||
use pv_core::static_assert;
|
||||
use pv_core::uv::SecretId;
|
||||
use zerocopy::{Immutable, IntoBytes};
|
||||
|
||||
use super::guest_secret::ListableSecretHdr;
|
||||
use super::guest_secret::{ListableSecretHdr, SecretAuth};
|
||||
use super::user_data::UserData;
|
||||
use crate::crypto::{hkdf_rfc_5869, AeadEncryptionResult};
|
||||
use crate::misc::Flags;
|
||||
use crate::req::{Aad, BinReqValues, HostKey, Keyslot, ReqEncrCtx};
|
||||
use crate::req::{Aad, BinReqValues, HostKey, Keyslot, ReqEncrCtx, RequestHdr};
|
||||
use crate::request::{BootHdrTags, Confidential, Request};
|
||||
use crate::secret::{ExtSecret, GuestSecret};
|
||||
use crate::uv::{ConfigUid, UvFlags};
|
||||
use crate::{assert_size, Result};
|
||||
use crate::{assert_size, Error, Result};
|
||||
|
||||
/// Authenticated data w/o user data
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy, IntoBytes, Immutable)]
|
||||
struct ReqAuthData {
|
||||
struct ReqAuthDataV1 {
|
||||
flags: UvFlags,
|
||||
boot_tags: BootHdrTags,
|
||||
cuid: ConfigUid,
|
||||
reserved90: [u8; 0x100],
|
||||
}
|
||||
assert_size!(ReqAuthData, 0x1e8);
|
||||
assert_size!(ReqAuthDataV1, 0x1e8);
|
||||
|
||||
impl ReqAuthData {
|
||||
impl ReqAuthDataV1 {
|
||||
fn new<F: Into<UvFlags>>(boot_tags: BootHdrTags, flags: F) -> Self {
|
||||
Self {
|
||||
flags: flags.into(),
|
||||
@@ -41,6 +42,30 @@ impl ReqAuthData {
|
||||
}
|
||||
}
|
||||
|
||||
/// Authenticated data w/o user data for v2 header: move up secret header 2
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, IntoBytes, Immutable)]
|
||||
struct ReqAuthDataV2 {
|
||||
flags: UvFlags,
|
||||
boot_tags: BootHdrTags,
|
||||
cuid: ConfigUid,
|
||||
secr_auth: [u8; 0x30],
|
||||
reservedd0: [u8; 0x100 - 0x30],
|
||||
}
|
||||
assert_size!(ReqAuthDataV2, 0x1e8);
|
||||
|
||||
impl ReqAuthDataV2 {
|
||||
fn new<F: Into<UvFlags>>(boot_tags: BootHdrTags, flags: F, secr_auth: [u8; 0x30]) -> Self {
|
||||
Self {
|
||||
flags: flags.into(),
|
||||
boot_tags,
|
||||
cuid: [0; 0x10],
|
||||
secr_auth,
|
||||
reservedd0: [0; 0xd0],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ReqConfData {
|
||||
secret: GuestSecret,
|
||||
@@ -92,6 +117,8 @@ impl From<AddSecretFlags> for UvFlags {
|
||||
pub enum AddSecretVersion {
|
||||
/// Version 1 (= 0x0100)
|
||||
One = 0x0100,
|
||||
/// Version 2 (= 0x0200)
|
||||
Two = 0x0200,
|
||||
|
||||
#[cfg(not(doc))]
|
||||
#[cfg(any(debug_assertions, test))]
|
||||
@@ -99,17 +126,182 @@ pub enum AddSecretVersion {
|
||||
Inv = 0,
|
||||
}
|
||||
|
||||
impl TryFrom<u32> for AddSecretVersion {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(value: u32) -> Result<Self> {
|
||||
if value == Self::One as u32 {
|
||||
Ok(Self::One)
|
||||
} else if value == Self::Two as u32 {
|
||||
Ok(Self::Two)
|
||||
} else {
|
||||
Err(Error::BinAsrcbInvVersion(value))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AddSecretVersion> for RequestVersion {
|
||||
fn from(val: AddSecretVersion) -> Self {
|
||||
val as Self
|
||||
}
|
||||
}
|
||||
|
||||
impl From<crate::request::SeHdrVersion> for AddSecretVersion {
|
||||
fn from(val: crate::request::SeHdrVersion) -> Self {
|
||||
match val {
|
||||
crate::request::SeHdrVersion::One => AddSecretVersion::One,
|
||||
crate::request::SeHdrVersion::Two => AddSecretVersion::Two,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for authenticated data in add-secret requests.
|
||||
///
|
||||
/// This trait provides a common interface for different versions of authenticated data,
|
||||
/// allowing flexible addition of new versions in the future.
|
||||
trait ReqAuthData: IntoBytes + Immutable {
|
||||
/// Get the configuration UID
|
||||
fn cuid(&self) -> &ConfigUid;
|
||||
|
||||
/// Set the configuration UID
|
||||
fn set_cuid(&mut self, cuid: ConfigUid);
|
||||
|
||||
/// Get the boot tags
|
||||
fn boot_tags(&self) -> &BootHdrTags;
|
||||
|
||||
/// Get the flags
|
||||
fn flags(&self) -> &UvFlags;
|
||||
}
|
||||
|
||||
impl ReqAuthData for ReqAuthDataV1 {
|
||||
fn cuid(&self) -> &ConfigUid {
|
||||
&self.cuid
|
||||
}
|
||||
|
||||
fn set_cuid(&mut self, cuid: ConfigUid) {
|
||||
self.cuid = cuid;
|
||||
}
|
||||
|
||||
fn boot_tags(&self) -> &BootHdrTags {
|
||||
&self.boot_tags
|
||||
}
|
||||
|
||||
fn flags(&self) -> &UvFlags {
|
||||
&self.flags
|
||||
}
|
||||
}
|
||||
|
||||
impl ReqAuthData for ReqAuthDataV2 {
|
||||
fn cuid(&self) -> &ConfigUid {
|
||||
&self.cuid
|
||||
}
|
||||
|
||||
fn set_cuid(&mut self, cuid: ConfigUid) {
|
||||
self.cuid = cuid;
|
||||
}
|
||||
|
||||
fn boot_tags(&self) -> &BootHdrTags {
|
||||
&self.boot_tags
|
||||
}
|
||||
|
||||
fn flags(&self) -> &UvFlags {
|
||||
&self.flags
|
||||
}
|
||||
}
|
||||
|
||||
/// Enum holding version-specific authenticated data
|
||||
#[derive(Debug)]
|
||||
enum ReqAuthDataVersion {
|
||||
V1(ReqAuthDataV1),
|
||||
V2(ReqAuthDataV2),
|
||||
}
|
||||
|
||||
impl ReqAuthDataVersion {
|
||||
fn new(
|
||||
version: AddSecretVersion,
|
||||
boot_tags: BootHdrTags,
|
||||
flags: AddSecretFlags,
|
||||
conf_data: &SecretAuth,
|
||||
) -> Result<Self> {
|
||||
Ok(match version {
|
||||
AddSecretVersion::One => Self::V1(ReqAuthDataV1::new(boot_tags, flags)),
|
||||
AddSecretVersion::Two => Self::V2(ReqAuthDataV2::new(
|
||||
boot_tags,
|
||||
flags,
|
||||
conf_data.get(version).try_into().expect(
|
||||
"SecretAuth::get() must return exactly 0x30 bytes for AddSecretVersion::Two",
|
||||
),
|
||||
)),
|
||||
#[cfg(any(debug_assertions, test))]
|
||||
AddSecretVersion::Inv => panic!("Invalid version for production use"),
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn cuid(&self) -> &ConfigUid {
|
||||
match self {
|
||||
Self::V1(v) => v.cuid(),
|
||||
Self::V2(v) => v.cuid(),
|
||||
}
|
||||
}
|
||||
|
||||
fn set_cuid(&mut self, cuid: ConfigUid) {
|
||||
match self {
|
||||
Self::V1(v) => v.set_cuid(cuid),
|
||||
Self::V2(v) => v.set_cuid(cuid),
|
||||
}
|
||||
}
|
||||
|
||||
fn boot_tags(&self) -> &BootHdrTags {
|
||||
match self {
|
||||
Self::V1(v) => v.boot_tags(),
|
||||
Self::V2(v) => v.boot_tags(),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn flags(&self) -> &UvFlags {
|
||||
match self {
|
||||
Self::V1(v) => v.flags(),
|
||||
Self::V2(v) => v.flags(),
|
||||
}
|
||||
}
|
||||
|
||||
fn as_bytes(&self) -> &[u8] {
|
||||
match self {
|
||||
Self::V1(v) => v.as_bytes(),
|
||||
Self::V2(v) => v.as_bytes(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Add-secret request Control Block
|
||||
///
|
||||
/// An ASRCB wraps a secret to securely transport it to the Ultravisor.
|
||||
///
|
||||
/// Layout:
|
||||
/// Layout V2:
|
||||
/// ```none
|
||||
/// _______________________________________________________________
|
||||
/// | 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 |
|
||||
/// | Secret header (48) |
|
||||
/// | Reserved(208) |
|
||||
/// | User Data(512) (reserved) |
|
||||
/// | Customer Public Key (160) generated for each request |
|
||||
/// | N Keyslots(1680 each) |
|
||||
/// | --------------------------------------------------- |
|
||||
/// | Secret to add (Secret type dependent)(may be 0 bytes) | Encrypted
|
||||
/// | Extension secret(32) Optional, defaults to 0 | Encrypted
|
||||
/// | --------------------------------------------------- |
|
||||
/// | AES GCM Tag (16) |
|
||||
/// |_____________________________________________________________|
|
||||
/// ```
|
||||
///
|
||||
/// Layout V1:
|
||||
/// ```none
|
||||
/// _______________________________________________________________
|
||||
/// | generic header (48)
|
||||
@@ -133,15 +325,19 @@ impl From<AddSecretVersion> for RequestVersion {
|
||||
#[derive(Debug)]
|
||||
pub struct AddSecretRequest {
|
||||
version: AddSecretVersion,
|
||||
aad: ReqAuthData,
|
||||
aad: ReqAuthDataVersion,
|
||||
keyslots: Vec<Keyslot>,
|
||||
conf: ReqConfData,
|
||||
user_data: UserData,
|
||||
}
|
||||
static_assert!(AddSecretRequest::USER_DATA_OFFS == 0x218);
|
||||
static_assert!(
|
||||
AddSecretRequest::USER_DATA_OFFS == size_of::<RequestHdr>() + size_of::<ReqAuthDataV2>()
|
||||
);
|
||||
|
||||
impl AddSecretRequest {
|
||||
/// Offset of the user-data in the add-secret request in bytes
|
||||
pub(super) const V1_USER_DATA_OFFS: usize = 0x218;
|
||||
pub(super) const USER_DATA_OFFS: usize = size_of::<RequestHdr>() + size_of::<ReqAuthDataV1>();
|
||||
|
||||
/// Create a new add-secret request.
|
||||
///
|
||||
@@ -152,22 +348,23 @@ impl AddSecretRequest {
|
||||
secret: GuestSecret,
|
||||
boot_tags: BootHdrTags,
|
||||
flags: AddSecretFlags,
|
||||
) -> Self {
|
||||
Self {
|
||||
conf: ReqConfData {
|
||||
extension_secret: Confidential::new([0; 32]),
|
||||
secret,
|
||||
},
|
||||
aad: ReqAuthData::new(boot_tags, flags),
|
||||
) -> Result<Self> {
|
||||
let conf = ReqConfData {
|
||||
extension_secret: Confidential::new([0; 32]),
|
||||
secret,
|
||||
};
|
||||
Ok(Self {
|
||||
aad: ReqAuthDataVersion::new(version, boot_tags, flags, &conf.secret.auth())?,
|
||||
conf,
|
||||
keyslots: vec![],
|
||||
version,
|
||||
user_data: UserData::Null,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Sets the Configuration Unique Id of this [`AddSecretRequest`].
|
||||
pub fn set_cuid(&mut self, cuid: ConfigUid) {
|
||||
self.aad.cuid = cuid;
|
||||
self.aad.set_cuid(cuid);
|
||||
}
|
||||
|
||||
/// Sets the extension secret of this [`AddSecretRequest`].
|
||||
@@ -182,7 +379,7 @@ impl AddSecretRequest {
|
||||
ExtSecret::Derived(cck) => hkdf_rfc_5869(
|
||||
Md::sha512(),
|
||||
cck.value(),
|
||||
self.aad.boot_tags.tag(),
|
||||
self.aad.boot_tags().tag(),
|
||||
DER_EXT_SECRET_INFO,
|
||||
)?
|
||||
.into(),
|
||||
@@ -221,7 +418,6 @@ impl AddSecretRequest {
|
||||
let cust_pub_key = ctx.key_coords()?;
|
||||
let secr_auth = self.conf.secret.auth();
|
||||
let user_data = self.user_data.data();
|
||||
|
||||
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 {
|
||||
@@ -232,7 +428,13 @@ impl AddSecretRequest {
|
||||
}
|
||||
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.get()));
|
||||
// write secret header (1) only for v1
|
||||
match self.version {
|
||||
AddSecretVersion::One => aad.push(Aad::Plain(secr_auth.get(AddSecretVersion::One))),
|
||||
AddSecretVersion::Two => {}
|
||||
#[cfg(any(debug_assertions, test))]
|
||||
_ => return Err(Error::UnsupportedAddSecretVersion(self.version as u32)),
|
||||
}
|
||||
|
||||
ctx.build_aad(self.version.into(), &aad, conf_len, self.user_data.magic())
|
||||
}
|
||||
@@ -273,7 +475,7 @@ impl AddSecretRequest {
|
||||
// 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,
|
||||
Self::USER_DATA_OFFS,
|
||||
)?;
|
||||
|
||||
// encrypt again with signed data
|
||||
@@ -309,7 +511,101 @@ impl Request for AddSecretRequest {
|
||||
}
|
||||
}
|
||||
|
||||
fn add_hostkey(&mut self, hostkey: HostKey) {
|
||||
self.keyslots.push(Keyslot::new(hostkey))
|
||||
fn add_hostkey(&mut self, hostkey: HostKey) -> Result<()> {
|
||||
match self.version {
|
||||
AddSecretVersion::One if !hostkey.is_hybrid() => Ok(()),
|
||||
AddSecretVersion::Two if hostkey.is_hybrid() => Ok(()),
|
||||
AddSecretVersion::One => Err(Error::InvalidHkd(
|
||||
"Add classical hostkey to a v1 attestation request".to_string(),
|
||||
)),
|
||||
AddSecretVersion::Two => Err(Error::InvalidHkd(
|
||||
"Add hybrid key to a v2 attetstation request".to_string(),
|
||||
)),
|
||||
#[cfg(any(debug_assertions, test))]
|
||||
AddSecretVersion::Inv => panic!("Invalid version for production use"),
|
||||
}?;
|
||||
self.keyslots.push(Keyslot::new(hostkey));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::request::SeHdrVersion;
|
||||
|
||||
#[test]
|
||||
fn add_secret_version_v1() {
|
||||
// Test V1 version constant
|
||||
assert_eq!(AddSecretVersion::One as u32, 0x0100);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_secret_version_v2() {
|
||||
// Test V2 version constant
|
||||
assert_eq!(AddSecretVersion::Two as u32, 0x0200);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_secret_version_conversion_v1() {
|
||||
// Test conversion from SeHdrVersion to AddSecretVersion for V1
|
||||
let v1: AddSecretVersion = SeHdrVersion::One.into();
|
||||
assert_eq!(v1, AddSecretVersion::One);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_secret_version_conversion_v2() {
|
||||
// Test conversion from SeHdrVersion to AddSecretVersion for V2
|
||||
let v2: AddSecretVersion = SeHdrVersion::Two.into();
|
||||
assert_eq!(v2, AddSecretVersion::Two);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_secret_version_into_request_version() {
|
||||
// Test conversion from AddSecretVersion to RequestVersion
|
||||
let v1: RequestVersion = AddSecretVersion::One.into();
|
||||
assert_eq!(v1, 0x0100);
|
||||
|
||||
let v2: RequestVersion = AddSecretVersion::Two.into();
|
||||
assert_eq!(v2, 0x0200);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_secret_flags_default() {
|
||||
// Test default flags have no bits set
|
||||
let flags = AddSecretFlags::default();
|
||||
let uv_flags: UvFlags = flags.into();
|
||||
|
||||
// Default should have all bits cleared
|
||||
assert_eq!(uv_flags.as_bytes(), &[0u8; 8]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_secret_flags_disable_dump() {
|
||||
// Test disable dump flag sets bit 0
|
||||
let mut flags = AddSecretFlags::default();
|
||||
flags.set_disable_dump();
|
||||
|
||||
let uv_flags: UvFlags = flags.into();
|
||||
|
||||
// Bit 0 should be set, so bytes should not be all zeros
|
||||
assert_ne!(uv_flags.as_bytes(), &[0u8; 8]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn req_auth_data_size() {
|
||||
// Test ReqAuthData size constant
|
||||
use std::mem::size_of;
|
||||
|
||||
assert_eq!(size_of::<ReqAuthDataV1>(), 0x1e8);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(debug_assertions, test))]
|
||||
fn add_secret_version_inv_for_testing() {
|
||||
// Test that invalid version exists for testing
|
||||
assert_eq!(AddSecretVersion::Inv as u32, 0);
|
||||
assert_ne!(AddSecretVersion::Inv, AddSecretVersion::One);
|
||||
assert_ne!(AddSecretVersion::Inv, AddSecretVersion::Two);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ use super::asrcb::AddSecretRequest;
|
||||
use crate::crypto::{hash, random_array, SymKeyType};
|
||||
use crate::request::openssl::{NID_ED25519, NID_ED448};
|
||||
use crate::request::Confidential;
|
||||
use crate::secret::AddSecretVersion;
|
||||
use crate::uv::{
|
||||
AesSizes, AesXtsSizes, EcCurves, HmacShaSizes, ListableSecretType, RetrievableSecret,
|
||||
RetrieveCmd, SecretId,
|
||||
@@ -388,12 +389,18 @@ pub(crate) enum SecretAuth {
|
||||
}
|
||||
|
||||
impl SecretAuth {
|
||||
const NULL_HDR: NullSecretHdr = NullSecretHdr::new();
|
||||
const NULL_HDR_V1: NullSecretHdrV1 = NullSecretHdrV1::new();
|
||||
const NULL_HDR_V2: NullSecretHdrV2 = NullSecretHdrV2::new();
|
||||
const UPDATE_CCK_HDR: UpdateCckHdr = UpdateCckHdr::new();
|
||||
|
||||
pub fn get(&self) -> &[u8] {
|
||||
pub fn get(&self, version: AddSecretVersion) -> &[u8] {
|
||||
match self {
|
||||
Self::Null => Self::NULL_HDR.as_bytes(),
|
||||
Self::Null => match version {
|
||||
AddSecretVersion::One => Self::NULL_HDR_V1.as_bytes(),
|
||||
AddSecretVersion::Two => Self::NULL_HDR_V2.as_bytes(),
|
||||
#[cfg(any(debug_assertions, test))]
|
||||
_ => panic!("Invalid AddSecretVersion"),
|
||||
},
|
||||
Self::Listable(h) => h.as_bytes(),
|
||||
Self::UpdateCck => Self::UPDATE_CCK_HDR.as_bytes(),
|
||||
}
|
||||
@@ -402,15 +409,15 @@ impl SecretAuth {
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
|
||||
struct NullSecretHdr {
|
||||
struct NullSecretHdrV1 {
|
||||
res0: u16,
|
||||
kind: U16<BigEndian>,
|
||||
secret_len: U32<BigEndian>,
|
||||
res8: u64,
|
||||
}
|
||||
assert_size!(NullSecretHdr, 0x10);
|
||||
assert_size!(NullSecretHdrV1, 0x10);
|
||||
|
||||
impl NullSecretHdr {
|
||||
impl NullSecretHdrV1 {
|
||||
const fn new() -> Self {
|
||||
Self {
|
||||
res0: 0,
|
||||
@@ -421,6 +428,29 @@ impl NullSecretHdr {
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
|
||||
struct NullSecretHdrV2 {
|
||||
res0: u16,
|
||||
kind: U16<BigEndian>,
|
||||
secret_len: U32<BigEndian>,
|
||||
res8: u64,
|
||||
reserved1: [u8; 32],
|
||||
}
|
||||
assert_size!(NullSecretHdrV2, 0x30);
|
||||
|
||||
impl NullSecretHdrV2 {
|
||||
const fn new() -> Self {
|
||||
Self {
|
||||
res0: 0,
|
||||
kind: U16::new(ListableSecretType::NULL),
|
||||
secret_len: U32::ZERO,
|
||||
res8: 0,
|
||||
reserved1: [0; 32],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, IntoBytes, FromBytes, Immutable, KnownLayout)]
|
||||
pub(crate) struct ListableSecretHdr {
|
||||
@@ -701,7 +731,7 @@ mod test {
|
||||
let gs_bytes = gs.auth();
|
||||
let exp = vec![0u8, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||
|
||||
assert_eq!(exp, gs_bytes.get());
|
||||
assert_eq!(exp, gs_bytes.get(AddSecretVersion::One));
|
||||
assert_eq!(&Vec::<u8>::new(), gs.confidential())
|
||||
}
|
||||
|
||||
@@ -716,7 +746,7 @@ mod test {
|
||||
let mut exp = vec![0u8, 0, 0, 2, 0, 0, 0, 0x20, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||
exp.extend([1; 32]);
|
||||
|
||||
assert_eq!(exp, gs_bytes_auth.get());
|
||||
assert_eq!(exp, gs_bytes_auth.get(AddSecretVersion::One));
|
||||
assert_eq!(&[2; 32], gs.confidential());
|
||||
}
|
||||
|
||||
@@ -729,7 +759,7 @@ mod test {
|
||||
secret: vec![2; 32].into(),
|
||||
};
|
||||
let auth = gs.auth();
|
||||
let gs_bytes_auth = auth.get();
|
||||
let gs_bytes_auth = auth.get(AddSecretVersion::One);
|
||||
let mut exp = vec![0u8, 0, 0, 3, 0, 0, 0, 0x20, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||
exp.extend([1; 32]);
|
||||
|
||||
@@ -746,7 +776,7 @@ mod test {
|
||||
let mut exp = vec![0u8, 0, 0, 0x16, 0, 0, 0, 0x20];
|
||||
exp.extend([0; 40]);
|
||||
|
||||
assert_eq!(exp, gs_bytes_auth.get());
|
||||
assert_eq!(exp, gs_bytes_auth.get(AddSecretVersion::One));
|
||||
assert_eq!(&[2; 32], gs.confidential());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,6 +133,7 @@ impl RetrievedSecret {
|
||||
RetrievedSecret::ProtectedKey(p) => p.into_bytes(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the data in PEM format.
|
||||
///
|
||||
/// # Errors
|
||||
|
||||
@@ -10,7 +10,7 @@ use crate::crypto::{sign_msg, verify_signature};
|
||||
use crate::req::BinReqValues;
|
||||
use crate::request::openssl::pkey::{HasParams, HasPublic, Id, PKey, PKeyRef, Private, Public};
|
||||
use crate::request::RequestMagic;
|
||||
use crate::secret::{AddSecretMagic, AddSecretRequest, AddSecretVersion, UserDataType};
|
||||
use crate::secret::{AddSecretMagic, AddSecretRequest, UserDataType};
|
||||
use crate::{assert_size, Error, Result};
|
||||
|
||||
/// User data.
|
||||
@@ -261,21 +261,19 @@ pub fn verify_asrcb_and_get_user_data(
|
||||
// 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
|
||||
|| req_len < AddSecretRequest::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) = asrcb.split_at_mut(AddSecretRequest::USER_DATA_OFFS);
|
||||
let user_data = &mut user_data[..UserData::USER_DATA_SIZE];
|
||||
|
||||
// depending on the user_data_type do:
|
||||
|
||||
@@ -2,18 +2,14 @@
|
||||
//
|
||||
// Copyright IBM Corp. 2023
|
||||
|
||||
use core::slice;
|
||||
use std::path::Path;
|
||||
|
||||
#[cfg(not(test))]
|
||||
use helper::download_first_crl_from_x509;
|
||||
use helper::{download_first_crl_from_x509, StoreSetupMode};
|
||||
use log::{debug, trace};
|
||||
use openssl::error::ErrorStack;
|
||||
use openssl::stack::Stack;
|
||||
use openssl::x509::store::X509Store;
|
||||
use openssl::x509::{CrlStatus, X509NameRef, X509Ref, X509StoreContext, X509StoreContextRef, X509};
|
||||
#[cfg(test)]
|
||||
use test::download_first_crl_from_x509;
|
||||
|
||||
use crate::error::bail_hkd_verify;
|
||||
use crate::misc::{read_certs, read_file};
|
||||
@@ -184,26 +180,51 @@ impl CertVerifier {
|
||||
Q: AsRef<Path>,
|
||||
R: AsRef<Path>,
|
||||
{
|
||||
let mut store = helper::store_setup(root_ca_path, crl_paths, cert_paths)?;
|
||||
let mut untr_certs = Vec::with_capacity(cert_paths.len());
|
||||
for path in cert_paths {
|
||||
let mut crt = read_certs(&read_file(path, "certificate")?)?;
|
||||
if !offline {
|
||||
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);
|
||||
}
|
||||
let (ibm_z_sign_key, chain) = helper::extract_ibm_sign_key(untr_certs.clone())?;
|
||||
let root_ca_verification = match root_ca_path {
|
||||
Some(_) => helper::RootCaVerification::SkipPinning,
|
||||
None => helper::RootCaVerification::RootCaOrganizationPinning("DigiCert"),
|
||||
};
|
||||
|
||||
// remove the IBM signing certificate from chain.
|
||||
// We have to verify them separately as they are not marked as intermediate certs
|
||||
let (ibm_z_sign_key, chain) = helper::extract_ibm_sign_key(untr_certs)?;
|
||||
// Two-round verification:
|
||||
//
|
||||
// Round 1: Verify chain without CRL checks before downloading files
|
||||
// from URLs from (yet) untrusted certificates.
|
||||
let store_builder = helper::store_setup(
|
||||
root_ca_path.as_ref(),
|
||||
crl_paths,
|
||||
cert_paths,
|
||||
StoreSetupMode::WithoutCrlCheck,
|
||||
)?;
|
||||
helper::verify_chain(
|
||||
&store_builder.build(),
|
||||
&chain,
|
||||
&[&ibm_z_sign_key],
|
||||
&root_ca_verification,
|
||||
)?;
|
||||
|
||||
let store = store.build();
|
||||
helper::verify_chain(&store, &chain, slice::from_ref(&ibm_z_sign_key))?;
|
||||
// Round 2: Download CRLs and verify again, but this time with CRL checks
|
||||
let mut store_builder = helper::store_setup(
|
||||
root_ca_path,
|
||||
crl_paths,
|
||||
cert_paths,
|
||||
StoreSetupMode::WithCrlCheck,
|
||||
)?;
|
||||
if !offline {
|
||||
for cert in &untr_certs {
|
||||
if let Some(crls) = download_first_crl_from_x509(cert)? {
|
||||
crls.iter().try_for_each(|c| store_builder.add_crl(c))?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let store = store_builder.build();
|
||||
helper::verify_chain(&store, &chain, &[&ibm_z_sign_key], &root_ca_verification)?;
|
||||
|
||||
Ok(Self {
|
||||
store,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,45 +4,27 @@
|
||||
|
||||
#![cfg(test)]
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
use openssl::stack::Stack;
|
||||
use openssl::x509::X509Crl;
|
||||
|
||||
use super::helper::*;
|
||||
use super::{helper, *};
|
||||
use crate::test_utils::*;
|
||||
use crate::utils::read_crls;
|
||||
use crate::verify::helper::StoreSetupMode;
|
||||
use crate::Error;
|
||||
use crate::HkdVerifyErrorType::*;
|
||||
|
||||
// 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)?)
|
||||
}
|
||||
|
||||
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]
|
||||
fn store_setup() {
|
||||
let ibm_path = get_cert_asset_path("ibm.crt");
|
||||
let inter_path = get_cert_asset_path("inter.crt");
|
||||
let crls: [String; 0] = [];
|
||||
|
||||
let store = helper::store_setup(None::<String>, &crls, &[&ibm_path, &inter_path]);
|
||||
let store = helper::store_setup(
|
||||
None::<String>,
|
||||
&crls,
|
||||
&[&ibm_path, &inter_path],
|
||||
StoreSetupMode::WithCrlCheck,
|
||||
);
|
||||
assert!(store.is_ok());
|
||||
}
|
||||
|
||||
@@ -65,20 +47,51 @@ fn verify_chain_offline() {
|
||||
let root_crt = get_cert_asset_path("root_ca.chained.crt");
|
||||
let certs: [String; 0] = [];
|
||||
|
||||
let store = helper::store_setup(Some(&root_crt), &[&inter_crl], &certs)
|
||||
.unwrap()
|
||||
.build();
|
||||
let store = helper::store_setup(
|
||||
Some(&root_crt),
|
||||
&[&inter_crl],
|
||||
&certs,
|
||||
StoreSetupMode::WithCrlCheck,
|
||||
)
|
||||
.unwrap()
|
||||
.build();
|
||||
|
||||
let mut sk = Stack::<X509>::new().unwrap();
|
||||
sk.push(inter_crt).unwrap();
|
||||
assert!(verify_chain(&store, &sk, &[ibm_crt]).is_ok());
|
||||
assert!(verify_chain(
|
||||
&store,
|
||||
&sk,
|
||||
&[&ibm_crt],
|
||||
&RootCaVerification::RootCaOrganizationPinning(
|
||||
"International Business Machines Corporationn"
|
||||
)
|
||||
)
|
||||
.is_err());
|
||||
assert!(verify_chain(
|
||||
&store,
|
||||
&sk,
|
||||
&[&ibm_crt],
|
||||
&RootCaVerification::RootCaOrganizationPinning("International")
|
||||
)
|
||||
.is_err());
|
||||
assert!(verify_chain(
|
||||
&store,
|
||||
&sk,
|
||||
&[&ibm_crt],
|
||||
&RootCaVerification::RootCaOrganizationPinning(
|
||||
"International Business Machines Corporation"
|
||||
)
|
||||
)
|
||||
.is_ok());
|
||||
|
||||
assert!(verify_chain(&store, &sk, &[&ibm_crt], &RootCaVerification::SkipPinning).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dist_points() {
|
||||
let crt = load_gen_cert("ibm.crt");
|
||||
let res = x509_dist_points(&crt);
|
||||
let exp = vec!["inter_ca.crl"];
|
||||
let exp = vec!["http://inter_ca.crl"];
|
||||
assert_eq!(res, exp);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
use openssl::ec::{EcGroup, EcKey};
|
||||
use openssl::nid::Nid;
|
||||
use openssl::pkey::Private;
|
||||
use s390_pv::request::openssl::pkey::{PKey, Public};
|
||||
use s390_pv::request::{BootHdrTags, HostKey, ReqEncrCtx, Request, SymKey};
|
||||
use s390_pv::request::openssl::pkey::PKey;
|
||||
use s390_pv::request::{BootHdrTags, HostKey, HybridPKey, ReqEncrCtx, Request, SymKey};
|
||||
use s390_pv::secret::{
|
||||
verify_asrcb_and_get_user_data, AddSecretFlags, AddSecretRequest, AddSecretVersion, ExtSecret,
|
||||
GuestSecret,
|
||||
};
|
||||
use s390_pv::test_utils::get_test_keys;
|
||||
use s390_pv::test_utils::{get_test_keys, get_test_keys_hybrid, DeterministicTestRandGuard};
|
||||
use s390_pv::uv::ConfigUid;
|
||||
use s390_pv::{get_test_asset, Result};
|
||||
|
||||
@@ -29,8 +29,13 @@ fn create_asrcb(
|
||||
hkd: HostKey,
|
||||
ctx: &ReqEncrCtx,
|
||||
) -> Result<Vec<u8>> {
|
||||
let mut asrcb = AddSecretRequest::new(AddSecretVersion::One, guest_secret, TAGS, flags);
|
||||
let asrcb = match hkd {
|
||||
HostKey::V1(_) => AddSecretRequest::new(AddSecretVersion::One, guest_secret, TAGS, flags),
|
||||
HostKey::V2(_) => AddSecretRequest::new(AddSecretVersion::Two, guest_secret, TAGS, flags),
|
||||
_ => unreachable!("Unknown HostKey version"),
|
||||
};
|
||||
|
||||
let mut asrcb = asrcb?;
|
||||
if let Some(s) = ext_secret {
|
||||
asrcb.set_ext_secret(s)?
|
||||
};
|
||||
@@ -38,12 +43,25 @@ fn create_asrcb(
|
||||
asrcb.set_cuid(c);
|
||||
};
|
||||
|
||||
asrcb.add_hostkey(hkd);
|
||||
asrcb.add_hostkey(hkd)?;
|
||||
asrcb.encrypt(ctx)
|
||||
}
|
||||
|
||||
fn get_crypto() -> (PKey<Public>, ReqEncrCtx) {
|
||||
fn get_crypto() -> (HostKey, ReqEncrCtx) {
|
||||
let (cust_key, host_key) = get_test_keys();
|
||||
let host_key = HostKey::V1(host_key);
|
||||
let ctx = ReqEncrCtx::new_aes_256(
|
||||
Some([0x55; 12]),
|
||||
Some(cust_key),
|
||||
Some(SymKey::Aes256([0x17; 32].into())),
|
||||
)
|
||||
.unwrap();
|
||||
(host_key, ctx)
|
||||
}
|
||||
|
||||
fn get_crypto_v2() -> (HostKey, ReqEncrCtx) {
|
||||
let (cust_key, host_key1, host_key2) = get_test_keys_hybrid();
|
||||
let host_key = HostKey::V2(HybridPKey::new(host_key1, host_key2).unwrap());
|
||||
let ctx = ReqEncrCtx::new_aes_256(
|
||||
Some([0x55; 12]),
|
||||
Some(cust_key),
|
||||
@@ -67,14 +85,25 @@ where
|
||||
true => Some(CUID),
|
||||
false => None,
|
||||
};
|
||||
create_asrcb(
|
||||
guest_secret,
|
||||
ext_secret.into(),
|
||||
flags,
|
||||
cuid,
|
||||
HostKey::V1(host_key),
|
||||
&ctx,
|
||||
)
|
||||
create_asrcb(guest_secret, ext_secret.into(), flags, cuid, host_key, &ctx)
|
||||
}
|
||||
|
||||
fn gen_asrcb_v2<E>(
|
||||
guest_secret: GuestSecret,
|
||||
ext_secret: E,
|
||||
flags: AddSecretFlags,
|
||||
cuid: bool,
|
||||
) -> Result<Vec<u8>>
|
||||
where
|
||||
E: Into<Option<ExtSecret>>,
|
||||
{
|
||||
let _guard = DeterministicTestRandGuard::install(&[0x42; 4096], &[0x11; 32]).unwrap();
|
||||
let (host_key, ctx) = get_crypto_v2();
|
||||
let cuid = match cuid {
|
||||
true => Some(CUID),
|
||||
false => None,
|
||||
};
|
||||
create_asrcb(guest_secret, ext_secret.into(), flags, cuid, host_key, &ctx)
|
||||
}
|
||||
|
||||
fn association() -> GuestSecret {
|
||||
@@ -96,9 +125,21 @@ fn no_flag() -> AddSecretFlags {
|
||||
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());
|
||||
AddSecretRequest::new(AddSecretVersion::One, GuestSecret::Null, TAGS, no_flag())
|
||||
.expect("AddSecretRequest::new failed");
|
||||
|
||||
asrcb.add_hostkey(HostKey::V1(host_key));
|
||||
asrcb.add_hostkey(host_key).unwrap();
|
||||
asrcb.set_user_data(user_data, Some(skey)).unwrap();
|
||||
asrcb.encrypt(&ctx).unwrap()
|
||||
}
|
||||
|
||||
fn create_signed_asrcb_v2(skey: PKey<Private>, user_data: Vec<u8>) -> Vec<u8> {
|
||||
let (host_key, ctx) = get_crypto_v2();
|
||||
let mut asrcb =
|
||||
AddSecretRequest::new(AddSecretVersion::Two, GuestSecret::Null, TAGS, no_flag())
|
||||
.expect("AddSecretRequest::new failed");
|
||||
|
||||
asrcb.add_hostkey(host_key).unwrap();
|
||||
asrcb.set_user_data(user_data, Some(skey)).unwrap();
|
||||
asrcb.encrypt(&ctx).unwrap()
|
||||
}
|
||||
@@ -108,9 +149,10 @@ 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());
|
||||
AddSecretRequest::new(AddSecretVersion::One, GuestSecret::Null, TAGS, no_flag())
|
||||
.expect("AddSecretRequest::new failed");
|
||||
|
||||
asrcb.add_hostkey(HostKey::V1(host_key));
|
||||
asrcb.add_hostkey(host_key).unwrap();
|
||||
asrcb.set_user_data(user_data_orig.clone(), None).unwrap();
|
||||
let asrcb = asrcb.encrypt(&ctx).unwrap();
|
||||
|
||||
@@ -121,6 +163,7 @@ fn null_none_default_ncuid_one_user_unsgn() {
|
||||
&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();
|
||||
@@ -242,8 +285,11 @@ fn null_none_default_ncuid_one() {
|
||||
fn null_none_default_cuid_seven() {
|
||||
let (hkd, ctx) = get_crypto();
|
||||
let mut asrcb =
|
||||
AddSecretRequest::new(AddSecretVersion::One, GuestSecret::Null, TAGS, no_flag());
|
||||
(0..7).for_each(|_| asrcb.add_hostkey(HostKey::V1(hkd.clone())));
|
||||
AddSecretRequest::new(AddSecretVersion::One, GuestSecret::Null, TAGS, no_flag())
|
||||
.expect("AddSecretRequest::new failed");
|
||||
for _ in 0..7 {
|
||||
asrcb.add_hostkey(hkd.clone()).unwrap()
|
||||
}
|
||||
asrcb.set_cuid(CUID);
|
||||
let asrcb = asrcb.encrypt(&ctx).unwrap();
|
||||
|
||||
@@ -259,3 +305,164 @@ fn verify_no_user_data() {
|
||||
Ok(None)
|
||||
))
|
||||
}
|
||||
|
||||
// V2 tests (using hybrid keys)
|
||||
|
||||
#[test]
|
||||
fn null_none_default_ncuid_two_user_unsgn() {
|
||||
let _guard = DeterministicTestRandGuard::install(&[0x42; 4096], &[0x11; 32]).unwrap();
|
||||
let user_data_orig = vec![0x56; 0x183];
|
||||
let (host_key, ctx) = get_crypto_v2();
|
||||
let mut asrcb =
|
||||
AddSecretRequest::new(AddSecretVersion::Two, GuestSecret::Null, TAGS, no_flag())
|
||||
.expect("AddSecretRequest::new failed");
|
||||
|
||||
asrcb.add_hostkey(host_key).unwrap();
|
||||
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_two_user_ec() {
|
||||
let _guard = DeterministicTestRandGuard::install(&[0x42; 4096], &[0x11; 32]).unwrap();
|
||||
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_v2(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_two_user_rsa2048() {
|
||||
let _guard = DeterministicTestRandGuard::install(&[0x42; 4096], &[0x11; 32]).unwrap();
|
||||
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_v2(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_two_user_rsa3072() {
|
||||
let _guard = DeterministicTestRandGuard::install(&[0x42; 4096], &[0x11; 32]).unwrap();
|
||||
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_v2(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_two() {
|
||||
let _guard = DeterministicTestRandGuard::install(&[0x42; 4096], &[0x11; 32]).unwrap();
|
||||
let asrcb = gen_asrcb_v2(GuestSecret::Null, None, no_flag(), true).unwrap();
|
||||
let exp = get_test_asset!("exp/asrcb/null_none_default_cuid_two");
|
||||
assert_eq!(asrcb, exp);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn assoc_none_default_cuid_two() {
|
||||
let asrcb = gen_asrcb_v2(association(), None, no_flag(), true).unwrap();
|
||||
let exp = get_test_asset!("exp/asrcb/assoc_none_default_cuid_two");
|
||||
assert_eq!(asrcb, exp);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn null_simple_default_cuid_two() {
|
||||
let asrcb = gen_asrcb_v2(GuestSecret::Null, ext_simple(), no_flag(), true).unwrap();
|
||||
let exp = get_test_asset!("exp/asrcb/null_simple_default_cuid_two");
|
||||
assert_eq!(asrcb, exp);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn assoc_simple_default_cuid_two() {
|
||||
let asrcb = gen_asrcb_v2(association(), ext_simple(), no_flag(), true).unwrap();
|
||||
let exp = get_test_asset!("exp/asrcb/assoc_simple_default_cuid_two");
|
||||
assert_eq!(asrcb, exp);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn null_derived_default_cuid_two() {
|
||||
let asrcb = gen_asrcb_v2(GuestSecret::Null, ext_derived(), no_flag(), true).unwrap();
|
||||
let exp = get_test_asset!("exp/asrcb/null_derived_default_cuid_two");
|
||||
assert_eq!(asrcb, exp);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn assoc_derived_default_cuid_two() {
|
||||
let asrcb = gen_asrcb_v2(association(), ext_derived(), no_flag(), true).unwrap();
|
||||
let exp = get_test_asset!("exp/asrcb/assoc_derived_default_cuid_two");
|
||||
assert_eq!(asrcb, exp);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn null_none_dump_cuid_two() {
|
||||
let mut flags = no_flag();
|
||||
flags.set_disable_dump();
|
||||
let asrcb = gen_asrcb_v2(GuestSecret::Null, None, flags, true).unwrap();
|
||||
let exp = get_test_asset!("exp/asrcb/null_none_dump_cuid_two");
|
||||
assert_eq!(asrcb, exp);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn null_none_default_ncuid_two() {
|
||||
let asrcb = gen_asrcb_v2(GuestSecret::Null, None, no_flag(), false).unwrap();
|
||||
let exp = get_test_asset!("exp/asrcb/null_none_default_ncuid_two");
|
||||
assert_eq!(asrcb, exp);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn null_none_default_cuid_seven_two() {
|
||||
let _guard = DeterministicTestRandGuard::install(&[0x42; 4096], &[0x11; 32]).unwrap();
|
||||
let (hkd, ctx) = get_crypto_v2();
|
||||
let mut asrcb =
|
||||
AddSecretRequest::new(AddSecretVersion::Two, GuestSecret::Null, TAGS, no_flag())
|
||||
.expect("AddSecretRequest::new failed");
|
||||
for _ in 0..7 {
|
||||
asrcb.add_hostkey(hkd.clone()).unwrap()
|
||||
}
|
||||
asrcb.set_cuid(CUID);
|
||||
let asrcb = asrcb.encrypt(&ctx).unwrap();
|
||||
|
||||
let exp = get_test_asset!("exp/asrcb/null_none_default_cuid_seven_two");
|
||||
assert_eq!(asrcb, exp);
|
||||
}
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIE/TCCAuWgAwIBAgIUWT/F3gP9fOTTq3yOMVskcXM8vOAwDQYJKoZIhvcNAQEN
|
||||
MIIFBDCCAuygAwIBAgIUD2bTT6yk21U+ojAQnf3iw5w2EEowDQYJKoZIhvcNAQEN
|
||||
BQAwgcwxCzAJBgNVBAYTAlVTMTQwMgYDVQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2lu
|
||||
ZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFs
|
||||
IEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMREwDwYDVQQIDAhOZXcgWW9y
|
||||
azEVMBMGA1UEBwwMUG91Z2hrZWVwc2llMScwJQYDVQQLDB5JQk0gWiBIb3N0IEtl
|
||||
eSBTaWduaW5nIFNlcnZpY2UwIBcNMjQwMzIxMTQ1MjM5WhgPMjM4ODEyMjMxNDUy
|
||||
MzlaMIG2MQswCQYDVQQGEwJVUzE0MDIGA1UECgwrSW50ZXJuYXRpb25hbCBCdXNp
|
||||
eSBTaWduaW5nIFNlcnZpY2UwIBcNMjYwNzAyMDg0NzQ4WhgPMjM5MTA0MDUwODQ3
|
||||
NDhaMIG2MQswCQYDVQQGEwJVUzE0MDIGA1UECgwrSW50ZXJuYXRpb25hbCBCdXNp
|
||||
bmVzcyBNYWNoaW5lcyBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrSW50ZXJuYXRpb25h
|
||||
bCBCdXNpbmVzcyBNYWNoaW5lcyBDb3Jwb3JhdGlvbjERMA8GA1UECAwITmV3IFlv
|
||||
cmsxDzANBgNVBAcMBkFybW9uazEXMBUGA1UECwwOSUJNIFogSG9zdCBLZXkwgZsw
|
||||
EAYHKoZIzj0CAQYFK4EEACMDgYYABAAT1zpBNemPCT0tEx2S9qnlPxyBgxKl6BSX
|
||||
ghqf3MfOqQKIUdKEbxP0nr2QtIR/MwvBp4YhjxZ9AZtzVtXbQrULTAGlKK4qcf1I
|
||||
W1rYZ5S0b4dmvh2HbIv9wZLWKaZ/ovnvAJk949WDCbBzC3Dy1E3zCaYPefLHHNve
|
||||
dWX8RtFUhnTqm6NxMG8wHQYDVR0fBBYwFDASoBCgDoYMZmFrZV9pYm0uY3J0MA4G
|
||||
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
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIAXR6FCIgd+fjhO/WJ
|
||||
KwLTP01mBDtYkWbVE71jshjLLpZHunRpsYKbQKCwaDmMYLRrQnTxPgZH1PVKzguI
|
||||
7M7n9zyhgYkDgYYABAAT1zpBNemPCT0tEx2S9qnlPxyBgxKl6BSXghqf3MfOqQKI
|
||||
UdKEbxP0nr2QtIR/MwvBp4YhjxZ9AZtzVtXbQrULTAGlKK4qcf1IW1rYZ5S0b4dm
|
||||
vh2HbIv9wZLWKaZ/ovnvAJk949WDCbBzC3Dy1E3zCaYPefLHHNvedWX8RtFUhnTq
|
||||
mw==
|
||||
MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIBoV15DZCYEBy2dx5Q
|
||||
7PjcNBni/J3FXBka2MZdy402KKrrW6mZI554n4IlpNeyL9Tb4bMp4glYdDsoHLp/
|
||||
jbZ4K4ChgYkDgYYABAGXMdZTHQ6O1boDC7ncHiILfFqHBRkOaEPsNTntrxSdyWj7
|
||||
CCAa/VkUKVxq3CnyXqbUv8V/fNncU/ibw0o1m/T3SABExiXKfuKl1rUm99FfFeZO
|
||||
2uuIcg0pzbGf+opPttIyR+zp1LLbF3eDo0PEovBLT1J1s6iUIbx8hyfMwUG5Jmxd
|
||||
iA==
|
||||
-----END PRIVATE KEY-----
|
||||
|
||||
@@ -3,18 +3,18 @@ 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=
|
||||
MScwJQYDVQQLDB5JQk0gWiBIb3N0IEtleSBTaWduaW5nIFNlcnZpY2UXDTI2MDYy
|
||||
MjEwNDc0OFoYDzIzOTEwNDA1MTA0NzQ4WjAVMBMCAgIrFw0yNjA3MDExMDQ3NDha
|
||||
oCMwITAfBgNVHSMEGDAWgBRWnIhXOCFjqLnM9VMe9E7HEhbxKzANBgkqhkiG9w0B
|
||||
AQ0FAAOCAgEAQIp0vuCpPifq82vs30SfcTn0ppIeM2s7TSpGL8AVC0+56x8RXl+O
|
||||
1QUw4gOWtlO4m7legzGbCu1Wh3gXFb+6nUhWhT0egtAneoNDXRSHGXdo0nWAoH3J
|
||||
XUN/PaipGvDIEZF/UnehYoRrLG307CgJBQkCErFVvI6XJxqGtc6wgsQM2a5A72zV
|
||||
jlPEAbCsj5k+y7XzJ+vFVA531IHjdtYrEVMh2T0dN821n/yCwwecuMP4semlqYx0
|
||||
xJNm2y4whvyQnDpg4YIfLw5LUc9otvztLYW8h3Si34TO0ApJ6TpEdBdFx23jm/jJ
|
||||
VbfM+g2wFoqsW621BiHn9S1KYD0ENSsbaG6BVRm/CTbPNYw6AdgZS1ggZ+a30NCn
|
||||
ktg6wxVmXK0I3fzgTcOnaspr/rxkBjDi16sfob9yUuaBuTBOgMO0suq7BEFIl97Q
|
||||
tpkVVz9mb53Ixt/ZuF6QpB4DqOyksS8YehBJc9nOGMknOxcS1zYrWJzVJyyrKrlB
|
||||
3VHQ4aYE0WsmP+dpX/QE+gj9/Mp6cvTywVSjW/d9zGOyrSvS/ViU1qsMWrr2iy23
|
||||
tIOaWRVJBi0TX8S8om4ACgi/qwYGTAcH32Hde0nKy07Bm7JJjGUtJbfLzkM/2rjW
|
||||
qvmPlmmPWJxMyVYoY9+mamuDd2jRtJyoULrE5hCIupFKVV7Di8RQJJc=
|
||||
-----END X509 CRL-----
|
||||
|
||||
@@ -1,38 +1,38 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIGrTCCBJWgAwIBAgIUMCRfNPXX7mCzJea1P3mCUDqZdB0wDQYJKoZIhvcNAQEL
|
||||
MIIGtDCCBJygAwIBAgIUJvPxAmw0HNfQtDlcHDQQXvh5AegwDQYJKoZIhvcNAQEL
|
||||
BQAwgbUxCzAJBgNVBAYTAlVTMTQwMgYDVQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2lu
|
||||
ZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFs
|
||||
IEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMREwDwYDVQQIDAhOZXcgWW9y
|
||||
azEPMA0GA1UEBwwGQXJtb25rMRYwFAYDVQQLDA1JQk0gWiBSb290IENBMCAXDTI0
|
||||
MDMyMTE0NTIzOVoYDzIzODgxMjIzMTQ1MjM5WjCBzDELMAkGA1UEBhMCVVMxNDAy
|
||||
azEPMA0GA1UEBwwGQXJtb25rMRYwFAYDVQQLDA1JQk0gWiBSb290IENBMCAXDTI2
|
||||
MDcwMjA4NDc0OFoYDzIzOTEwNDA1MDg0NzQ4WjCBzDELMAkGA1UEBhMCVVMxNDAy
|
||||
BgNVBAoMK0ludGVybmF0aW9uYWwgQnVzaW5lc3MgTWFjaGluZXMgQ29ycG9yYXRp
|
||||
b24xNDAyBgNVBAMMK0ludGVybmF0aW9uYWwgQnVzaW5lc3MgTWFjaGluZXMgQ29y
|
||||
cG9yYXRpb24xETAPBgNVBAgMCE5ldyBZb3JrMRUwEwYDVQQHDAxQb3VnaGtlZXBz
|
||||
aWUxJzAlBgNVBAsMHklCTSBaIEhvc3QgS2V5IFNpZ25pbmcgU2VydmljZTCCAiIw
|
||||
DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALIvcLAKt2DM5rTc1nOhyVT2EbNy
|
||||
CA1Sy+l1mSloBRVqjyk464mvlqq9p/CDO1e6tWiFhdEFChuTYzzDOxHazLjPc2Y5
|
||||
U+r0QYYY8KK6jLQDj4crChPMJoJ0HZbmlWe/3uMl7lmrVMyHgqqOftQ52etBCGDn
|
||||
d/RV7U4OC+MJ01ePYUcABxPh3APA+DDV5eZ2b1k74JzLvXa+SGA82MPDQYc70Waf
|
||||
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
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
@@ -1,52 +1,52 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
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
|
||||
vpiaRjhZtk5MLPJs9mTHq1STrzL9
|
||||
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
|
||||
Lt5nZ3XPsdhCctZyYGqQjq5YsoGNU1yr
|
||||
-----END PRIVATE KEY-----
|
||||
|
||||
@@ -3,18 +3,18 @@ MIIDRjCCAS4CAQEwDQYJKoZIhvcNAQENBQAwgb0xCzAJBgNVBAYTAlVTMTQwMgYD
|
||||
VQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9u
|
||||
MTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFsIEJ1c2luZXNzIE1hY2hpbmVzIENvcnBv
|
||||
cmF0aW9uMREwDwYDVQQIDAhOZXcgWW9yazEPMA0GA1UEBwwGQXJtb25rMR4wHAYD
|
||||
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=
|
||||
VQQLDBVJQk0gWiBJbnRlcm1lZGlhdGUgQ0EXDTI2MDYyMjEwNDc0N1oYDzIzOTEw
|
||||
NDA1MTA0NzQ3WjAVMBMCAgG8Fw0yNjA3MDExMDQ3NDdaoCMwITAfBgNVHSMEGDAW
|
||||
gBRBgPq0WBDRF/Zb2D4wpASJVmNL5TANBgkqhkiG9w0BAQ0FAAOCAgEAhEMl0/XK
|
||||
3bLp1PMsjB4QrgfAqm8DV5I2WXxrHc0anooAlEqIPEGea5FO4UkL0oxz3Ffxo09O
|
||||
Blh9xwAZOOfvjp1mkRucpd2QEdznOlIikL9NXWNMM7Bm9Lljla8pdBrIZQSrBAoi
|
||||
WC3StSccD88Evoua87YH98MyO2md4zeDfDdICzZTrYqWWRhbghiJ/vPQwFY/SM+4
|
||||
uGp47egoxt8lTMNpPbqBV9+ptZvarvICIQmlRTU4ncWKVb2LmNYJ7zJXeJqEqtsX
|
||||
Ti/fIhnZd26IHXfmEp2VNJOp9ODZATiSCZ9od90y/Dhbi2ZmR3hFTU/VrKgzeqzb
|
||||
Qbi+dLKvaVf4HGWVxOUuSY9279W3aLkCbP5iL9qGtjE6hL0XncCDR0ifADTN7zye
|
||||
1o/OcZr7VT4V6a4dBm/5kNJh3RB8fcLGgrn1Rfa+2GSniFOCMjZCjdMlGHq4WmPb
|
||||
yvOLLF2AD8P7PwLxMJ28Elbg9TN7OiV19ALB5ZgEFoBwan4zIWtkekw+pafEqQma
|
||||
cDGx197fUf39bYWxGSpALsP3pptNrTsNmUNdhJuLxO2kq5jFQMXRq+yl5VG7JTms
|
||||
b/VhB86fOt16hHZQto3gKvd0wXvjCRGiYvOJLjbDQG3e8ghTCGU+40CwWhdC0q0A
|
||||
5k1z1ruYUj1mI0+TMGkz5MbyJ3dmgh3JTmQ=
|
||||
-----END X509 CRL-----
|
||||
|
||||
@@ -1,37 +1,38 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIGjDCCBHSgAwIBAgIUKp3mjstxJ9gXt3S7lpKjri2dEUwwDQYJKoZIhvcNAQEL
|
||||
MIIGkzCCBHugAwIBAgIUd+Tu7LLVqsmeGQbJ5IAjvORmZzAwDQYJKoZIhvcNAQEL
|
||||
BQAwgbUxCzAJBgNVBAYTAlVTMTQwMgYDVQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2lu
|
||||
ZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFs
|
||||
IEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMREwDwYDVQQIDAhOZXcgWW9y
|
||||
azEPMA0GA1UEBwwGQXJtb25rMRYwFAYDVQQLDA1JQk0gWiBSb290IENBMCAXDTI0
|
||||
MDMyMTE0NTIzOFoYDzIzODgxMjIzMTQ1MjM4WjCBvTELMAkGA1UEBhMCVVMxNDAy
|
||||
azEPMA0GA1UEBwwGQXJtb25rMRYwFAYDVQQLDA1JQk0gWiBSb290IENBMCAXDTI2
|
||||
MDcwMjA4NDc0N1oYDzIzOTEwNDA1MDg0NzQ3WjCBvTELMAkGA1UEBhMCVVMxNDAy
|
||||
BgNVBAoMK0ludGVybmF0aW9uYWwgQnVzaW5lc3MgTWFjaGluZXMgQ29ycG9yYXRp
|
||||
b24xNDAyBgNVBAMMK0ludGVybmF0aW9uYWwgQnVzaW5lc3MgTWFjaGluZXMgQ29y
|
||||
cG9yYXRpb24xETAPBgNVBAgMCE5ldyBZb3JrMQ8wDQYDVQQHDAZBcm1vbmsxHjAc
|
||||
BgNVBAsMFUlCTSBaIEludGVybWVkaWF0ZSBDQTCCAiIwDQYJKoZIhvcNAQEBBQAD
|
||||
ggIPADCCAgoCggIBAK+kNJHAUL4dcMnjElivyuzkO2UwTUlJcKQCBmWRHYQjRbP5
|
||||
akJx8SZ+wI0Spo00hG4sV2BxA83J+Yrked53DEzlR+RxojA16vXzlUO8c9KH2dJQ
|
||||
E17PgZnu7/hECmQcT69ZJAOh78ILEXRYk+2ixSTaZRTtchJdzfXIQ0633O2Mi/7z
|
||||
z5idQmQeXbitC3QIZeNzwitl2FLXPIw6MUnktOKNjQSNxMr9AU8q1cfOoICJQs0J
|
||||
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
|
||||
ZLaX284IyQ==
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
@@ -1,52 +1,52 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
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
|
||||
M9Wd2js5nPPh0AN3Px1643vFYcAQ
|
||||
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
|
||||
xToCDsY72xtSlqKcRx1Jyo5xXSPvd68=
|
||||
-----END PRIVATE KEY-----
|
||||
|
||||
@@ -3,18 +3,18 @@ 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
|
||||
VQQLDA1JQk0gWiBSb290IENBFw0yNjA2MjIxMDQ3NDZaGA8yMzkxMDQwNTEwNDc0
|
||||
NlowFTATAgIBTRcNMjYwNzAxMTA0NzQ2WqAjMCEwHwYDVR0jBBgwFoAUDz/nhP/+
|
||||
DIPql2WnuHiBw1W1pCowDQYJKoZIhvcNAQENBQADggIBAMZqebVQ5uXrSOjIbzH8
|
||||
RJCo9JjUH3XQJaKQrZW8QWpZKzY2rpLU1Ag6C8jM8qHAEPpkaLbwcpZUOV3g4AEw
|
||||
K5ezIe8VVJK7aHH96XYoIuYVXmohk0M39IEf14sIB5BkCX8aDC8dFekyZf23Uv/T
|
||||
zwjl7RDc4MAaeV4zKGZ0TBAOT9w1Rfek/U4jwQfvuOvY1Mw5wn7SJrrfE4waaPwK
|
||||
Nklpd6VsxvMgmLKV7BU3rEwndkbtkAWyWJw2F1L6p93ZNUBILDFc5o2f5qnLp6Yj
|
||||
qvEZmWUWO7+Y0qNdsOjljmX0XfuWhLuWB2zq6LceR1hr52XABvJAFIDuFnelfgeh
|
||||
c1rXpZThZSNwNhTVcZr4eLIJ/uR3UtIdl5uTkWY8Gsm3jaC9IoPADlSN+fOMV9eR
|
||||
1u0q2XBj0DafadDjeAevxM9xw8S/ToklqgYPRQSA3nq38EVE8c7Klkv9x/Ar2U3M
|
||||
5GGeDIphX93dzi7j1VAWw0fuylY8Bg69NJ9+889K+shDzIL3xBbXEC8RhmiHFi3H
|
||||
We2O2dtrVb62gUd/WgSTxu3OG3mqWPwPU94zK38zPyndDF41YGp70ur7wHkFPcfJ
|
||||
0WopCMqdEWBrUc8ZPZ1EBw9cAd44i+hVQB4x7qzNCmHJWi2942kpGv1vJ+IfUr9/
|
||||
0MtaUK+nInHcSPuyxhdlb6BE
|
||||
-----END X509 CRL-----
|
||||
|
||||
@@ -1,37 +1,37 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIGXzCCBEegAwIBAgIUC2OH79tloDOfMBeyDBA84epTMKYwDQYJKoZIhvcNAQEL
|
||||
MIIGXzCCBEegAwIBAgIULbCWZUfOIiRXCiGx8jr2mhqjQrswDQYJKoZIhvcNAQEL
|
||||
BQAwgbUxCzAJBgNVBAYTAlVTMTQwMgYDVQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2lu
|
||||
ZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFs
|
||||
IEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMREwDwYDVQQIDAhOZXcgWW9y
|
||||
azEPMA0GA1UEBwwGQXJtb25rMRYwFAYDVQQLDA1JQk0gWiBSb290IENBMCAXDTI0
|
||||
MDMyMTE0NTIzOFoYDzIzODgxMjIzMTQ1MjM4WjCBtTELMAkGA1UEBhMCVVMxNDAy
|
||||
azEPMA0GA1UEBwwGQXJtb25rMRYwFAYDVQQLDA1JQk0gWiBSb290IENBMCAXDTI2
|
||||
MDcwMjA4NDc0NloYDzIzOTEwNDA1MDg0NzQ2WjCBtTELMAkGA1UEBhMCVVMxNDAy
|
||||
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
|
||||
AoICAQDgdpk9Tu3dKO1O2orgftU2GkgARccHONa/NqnTcqaw5vbgWU8CiC99ejvC
|
||||
z5ER0R3xldjU3uTh2UXgQCY2Qf51lsYNx7CgjFVzTaoJ9FhD96mEIYtMWPMoF1SR
|
||||
mxxeGQCJHfMtB3ammatkXKV8ia9GlGQFtQU6Mh0CmNZelrvs7zXvYRMfW4oQX1zb
|
||||
9s4n1E+gxErTRw+PlK2LmOPO7AAMrrGn2sbxaoqJijMWOysekYZaNfaKkOOzyuXn
|
||||
fa8bcG6qAQWmQX56aUYTiwPNtyovFvUancgDg4bP5hD4hEsl2NRSQZQggt663NWK
|
||||
ALQBbL6qeJDI+WlAf83TbDVV8wGPuwGKE79+ES+TnT0GhhanEJ2J2swm3IcEVuya
|
||||
pEay0NAfoEfuzgyYYerekeAvqHbvRIxFjR1Hh5QvkGjmmr376E4CkeyXaqjFSl6o
|
||||
XamS0gSVfvnT/jYm9SGVFafA38ZGx2iEOMtybwJM+frp5F6DqwRG/dKgJ0W4nW/N
|
||||
E2iB2JJhVR9iaR973d/4G5vL5WVFUGv3b6VyZZAPftSzPoqPqGEaKGaHprECPUDQ
|
||||
fR1wdLYUuQfqgVnj1sKWT8YWNNc+11idVU/hPF3Yu9dSPVaEdYIQiQ0NNqnhneO/
|
||||
IVsOz4xBbh++frq8H16k0xqkOJuC6mCZaU4YxWy8SZ7jukyCywIDAQABo2MwYTAP
|
||||
BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQPP+eE
|
||||
//4Mg+qXZae4eIHDVbWkKjAdBgNVHQ4EFgQUDz/nhP/+DIPql2WnuHiBw1W1pCow
|
||||
DQYJKoZIhvcNAQELBQADggIBADxbNKDguPbfyhUOmrXcOPdzNWGvr51Cm0OZLOod
|
||||
nUcP9rkmEZYMZkmAGYCMkiK/HCd22iOXyHW+OYvq7zdLlaWuMfE6wxwWZ8bK3NQC
|
||||
3w0HPyAOcxknvGnHLnmi4+sKz+ZwVn816EgYv2iytVdfjclVK0Zvoa6COc0C085e
|
||||
kWe0hWFuqbVRzmtqoQauwxU9+rfY21/GtiZbkOiAo6VP9qqfrq3hDBoF/WT2gGVT
|
||||
GPuz6j+m2D2ai2s1rWLJfLfcSIySZ67tMmg3lL/8FrxLVmZ15XjuX8Y1M4XhjdV3
|
||||
G+9XSeuvyqWBrN1l99U3BvAVozqI0rEx7PqH8dpirwuYWRrJM7bZbuOvdVAT3wpE
|
||||
ypfXOkjVmTCkvJH2wrupywiVIu7vANJ6poV4zo+f6GJvM8iv2z8S3NmM7vt7NFFX
|
||||
1Q6HFmlAgAW5SRQ49ClKZAftW5fiOCwkpWsRY6REeKz/bF4anm0vVZpPutM1BYRx
|
||||
yw4xZihWcfxipzeX+HRuxYZIpuQaUnTKWl9QgCxKzUwNitSL/bp1uI/H+TgRR29w
|
||||
6ns+M9ZufO7oiuAPBAjw1TTQ8f4C+8qxJIxqKZxqk9TkmDK2+hLkbdBx1hcIBJHY
|
||||
ClfQLQOBEL1l3nZd2wnZRkdaVPKj235CB05PTeAlrmYHGmhAKhmBpV2eY0J8EFf5
|
||||
STAx
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
@@ -1,52 +1,52 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
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
|
||||
2lXPecP5/ilaLLUhs7SijqHzcKiNL80=
|
||||
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
|
||||
DFiJLuJwaQVArPexRziXnDrbb0bQkBe2
|
||||
-----END PRIVATE KEY-----
|
||||
|
||||
@@ -3,18 +3,18 @@ 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
|
||||
VQQLDA1JQk0gWiBSb290IENBFw0yNjA2MjIxMDQ3NDZaGA8yMzkxMDQwNTEwNDc0
|
||||
NlowFTATAgIBTRcNMjYwNzAxMTA0NzQ2WqAjMCEwHwYDVR0jBBgwFoAUIlsT6zAF
|
||||
eYbpsFsGeGMQDoofNl4wDQYJKoZIhvcNAQENBQADggIBACnVIJGdrqX0b2vUQ9Oc
|
||||
DTfN6KMlmt5mKD9c7c24OPOVo7y1lGEGcanGsZ8/0mZ7G5dIqWU0yxXnMD1U3cbm
|
||||
nKGHkor/gyvP6hdozFUWIc5EVebDJvnIfj4L0kEVFE+wUO3iqtNnbQjvBo90iq9W
|
||||
j+TTD+QQAMGKQyi3AwEL6nVrOZiUwjaJCdaV41zXxn7hiyfN89T4xM/f1TnRZ+xw
|
||||
5ELqGN77PBWaEWf3XyLIbxt/2xJL03zmV8cEHmdPG37i/p82mcYxqkwRlU6iCJeQ
|
||||
CQ39GNQd9avGm5+cUchAmdZf+tQLVcKsKqjZ7Cq0yihxKoYwOngeOZswF3NueGIP
|
||||
jXi3jnA8f0vr1uDilleYkIs5At9IAMq2oA8czKelcIIqQLiTaj03m6u0ehb4VWmA
|
||||
T9LWR6RtuBS0d2Lx8cYapzU0tnnU9mOemixljqLqnURmhfI2yRuh9f2FuzD2n5Pv
|
||||
H4WHpc2a2Uoz4ub+v93j1ZScDCb+xTmOJ6HfJ2V6A8FYIaD21X1n8n4yc+WeV4Ta
|
||||
aBqoWI3TihzwJGvc67Zjfdkt7KhUZ6heJZHRrPVKWbDIVL7NVFnx53ANkOZ18pWt
|
||||
IzJb2xWQlP3u9e1JX4yqVw75woZxQKE3v60F0UGofamRB375lGDYrsufD5Sz1XOl
|
||||
Cwl/78PBFBOkcvgVCubeR9cU
|
||||
-----END X509 CRL-----
|
||||
|
||||
@@ -12,7 +12,7 @@ from cryptography.x509.oid import NameOID
|
||||
ONE_DAY = datetime.timedelta(1, 0, 0)
|
||||
|
||||
|
||||
def createEcKeyPair(curve=ec.SECP521R1):
|
||||
def createEcKeyPair(curve=ec.SECP521R1()):
|
||||
return ec.generate_private_key(curve=curve, backend=default_backend())
|
||||
|
||||
|
||||
@@ -72,8 +72,8 @@ def createCert(
|
||||
pub_key=None,
|
||||
):
|
||||
sha = hashes.SHA256
|
||||
not_before = not_before or datetime.datetime.utcnow()
|
||||
not_after = not_after or datetime.datetime.utcnow() + datetime.timedelta(
|
||||
not_before = not_before or datetime.datetime.now(datetime.UTC)
|
||||
not_after = not_after or datetime.datetime.now(datetime.UTC) + datetime.timedelta(
|
||||
days=365 * 365
|
||||
)
|
||||
crl_dp = None
|
||||
@@ -216,7 +216,7 @@ def getPrivKey(path, create_priv_key):
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
MOCKUP_CRL_DIST = ""
|
||||
MOCKUP_CRL_DIST = "http://"
|
||||
|
||||
# create root CA
|
||||
root_ca_subject = x509.Name(
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIE+DCCAuCgAwIBAgIUBSLhuGTvxPbggG70ISL2R6DDGZcwDQYJKoZIhvcNAQEN
|
||||
MIIE/zCCAuegAwIBAgIURQZKxfTuf0H43V0uJcBaFGTxwfMwDQYJKoZIhvcNAQEN
|
||||
BQAwgcwxCzAJBgNVBAYTAlVTMTQwMgYDVQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2lu
|
||||
ZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFs
|
||||
IEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMREwDwYDVQQIDAhOZXcgWW9y
|
||||
azEVMBMGA1UEBwwMUG91Z2hrZWVwc2llMScwJQYDVQQLDB5JQk0gWiBIb3N0IEtl
|
||||
eSBTaWduaW5nIFNlcnZpY2UwIBcNMjQwMzIxMTQ1MjM5WhgPMjM4ODEyMjMxNDUy
|
||||
MzlaMIG2MQswCQYDVQQGEwJVUzE0MDIGA1UECgwrSW50ZXJuYXRpb25hbCBCdXNp
|
||||
eSBTaWduaW5nIFNlcnZpY2UwIBcNMjYwNzAyMDg0NzQ4WhgPMjM5MTA0MDUwODQ3
|
||||
NDhaMIG2MQswCQYDVQQGEwJVUzE0MDIGA1UECgwrSW50ZXJuYXRpb25hbCBCdXNp
|
||||
bmVzcyBNYWNoaW5lcyBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrSW50ZXJuYXRpb25h
|
||||
bCBCdXNpbmVzcyBNYWNoaW5lcyBDb3Jwb3JhdGlvbjERMA8GA1UECAwITmV3IFlv
|
||||
cmsxDzANBgNVBAcMBkFybW9uazEXMBUGA1UECwwOSUJNIFogSG9zdCBLZXkwgZsw
|
||||
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==
|
||||
EAYHKoZIzj0CAQYFK4EEACMDgYYABADmnrO8fwhFRmvTAeT91LiGJatTUNRhTr+S
|
||||
Pf9glpJGFemv1amiV89qBYij6IuYJDhSYAQNllegWfntvzDbCOhDvAH0SY9Ivhd7
|
||||
7nA20M0Z9FuUNaFBRAkUB8VhVPC+lMM7i/0QA3FCWQEP1V28oXSyIOO7SF77GAb8
|
||||
U8dobSvrGtb7dKNzMHEwHwYDVR0fBBgwFjAUoBKgEIYOaHR0cDovL2libS5jcmww
|
||||
DgYDVR0PAQH/BAQDAgMIMB8GA1UdIwQYMBaAFP4r9a6YMGLiFEhK51N4O3+mmIbt
|
||||
MB0GA1UdDgQWBBTLpumJYUrj5XZpdF8A3HUH8Iz3yjANBgkqhkiG9w0BAQ0FAAOC
|
||||
AgEAPoZhxpmjEf2mv+Gqwt0z0yG/J3/R2UVO5tHw5L/WWgr8zKWtdVPca9fIFFiT
|
||||
bRam+m59hDVZ1nIg0SGmxEfsdJmxfk2h3cI9IJDF3CfELKmfUaVISL1zykdSBzIG
|
||||
J4PO3WmUo3W/F41OzaRiSqY4I+8gOXwZmX4bTAFFNYQ9KI9JEJbY5ZM7oKd9Ts57
|
||||
lPDWgKf9luN3Teuw+8tj+3G3lzfZ8hO7RThNLi2qr8t0VPecps7ZwNLR+AXLs0F8
|
||||
Olx3IIhe7REHZnMqTaVJVlHPUi4REpoI7A3jT6S8AnNsEVjxsIbmJtwJEwwlVMU2
|
||||
E3e046RhNUqyHY5ahBPrgBUVadO0/b8QDW+vLAwbm5yr6E//h7Ygit8grA2l2LtS
|
||||
vuMEOnsLec1vTcDaeTtDpDJePP6naAc/ZXM+N1riebOYleKlsCylSAEZsoHT0unu
|
||||
jRCSTtr5YlWHIP7cQbn9YS8gmvMFU+M+0iNsKqs85o3hbcqchRm8DcLGiDD+FC4k
|
||||
2soTE2K3OaVsfYvfxUcA8vvGOeO13gZplpdL0iw+r1aMm7jhiljf6buF8ZwvsAVC
|
||||
o1N7uHuOr7Z3hONSbw4GWHFkWy82SIlbM3xNL3geDl7TX3VZFR4OTeIXSskuVOSg
|
||||
tLwBY1/RM2ZkDnraxi0XDfNJZRiFK4WVZz/tJSGgrF0YT4M=
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIA8rPNC6rxZR+GxSxb
|
||||
qWRreFGnWRQGd22nHWKAvQmrA5GlXTtWQMoL8il9Jb1OnrQPPo620nQpzA1GXo4U
|
||||
BUqgYoShgYkDgYYABAHGO0MnpQa6Q2IxgqV7AGwd3OwBnYOJjYJFhzrwY+wQacmJ
|
||||
jWeNyHahBCxu4bM8vDr70SF5vZFrWpcWpc9JTY5AagFCFDqIfSvLJ6lKJuCog5Rf
|
||||
MsWJpG2j/MnK7MxG+Ph0R+ItmLFbWFxCV5YOT43olhwYZr/pd9qHPAD96UEDM8Ja
|
||||
nA==
|
||||
MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIA0FE54XL97lOXcJa0
|
||||
hM+jtHL3zaUQ1up5GOlzcU/4YJ1zGvyXuhOPoC0+tO+Tm6FyVpr5kuYvnix+ixRP
|
||||
Kbq0q6ihgYkDgYYABADmnrO8fwhFRmvTAeT91LiGJatTUNRhTr+SPf9glpJGFemv
|
||||
1amiV89qBYij6IuYJDhSYAQNllegWfntvzDbCOhDvAH0SY9Ivhd77nA20M0Z9FuU
|
||||
NaFBRAkUB8VhVPC+lMM7i/0QA3FCWQEP1V28oXSyIOO7SF77GAb8U8dobSvrGtb7
|
||||
dA==
|
||||
-----END PRIVATE KEY-----
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIE+DCCAuCgAwIBAgIUC3KzCH9KUb8ZaY6J/97gqebLoIYwDQYJKoZIhvcNAQEN
|
||||
MIIE/zCCAuegAwIBAgIUZ2LzT6AgSHsm2Y0wV0byf4dkroswDQYJKoZIhvcNAQEN
|
||||
BQAwgcwxCzAJBgNVBAYTAlVTMTQwMgYDVQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2lu
|
||||
ZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFs
|
||||
IEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMREwDwYDVQQIDAhOZXcgWW9y
|
||||
azEVMBMGA1UEBwwMUG91Z2hrZWVwc2llMScwJQYDVQQLDB5JQk0gWiBIb3N0IEtl
|
||||
eSBTaWduaW5nIFNlcnZpY2UwIBcNMjQwMzIxMTQ1MjM5WhgPMjM4ODEyMjMxNDUy
|
||||
MzlaMIG2MQswCQYDVQQGEwJVUzE0MDIGA1UECgwrSW50ZXJuYXRpb25hbCBCdXNp
|
||||
eSBTaWduaW5nIFNlcnZpY2UwIBcNMjYwNzAyMDg0NzQ4WhgPMjM5MTA0MDUwODQ3
|
||||
NDhaMIG2MQswCQYDVQQGEwJVUzE0MDIGA1UECgwrSW50ZXJuYXRpb25hbCBCdXNp
|
||||
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==
|
||||
EAYHKoZIzj0CAQYFK4EEACMDgYYABAE69tLPv1D4DIFTgQo+P57ZABDoxe6x5Rjy
|
||||
+NYiRi/Nfir11CxVGQDaYDfUFsb4peQJz6haxqXfXmm4MWlIbdWa1gHMf3GQl/xt
|
||||
IGGbJURxnBIR3rj2pqd0DqbONj8blnQTCWLSHsLsgyI6WWK4RHd9ZtER0UQDxoQc
|
||||
c8Htsuh1+SKo6qNzMHEwHwYDVR0fBBgwFjAUoBKgEIYOaHR0cDovL2libS5jcmww
|
||||
DgYDVR0PAQH/BAQDAgMIMB8GA1UdIwQYMBaAFP4r9a6YMGLiFEhK51N4O3+mmIbt
|
||||
MB0GA1UdDgQWBBTjTQZrKFQ5geqc4+9zl31SO5w4DTANBgkqhkiG9w0BAQ0FAAOC
|
||||
AgEAFvvK0+jphYgn93vZDB06EG7wH4EsEe6dDmG8E2N+SCbjWigTYElemKOl5ION
|
||||
i3G1Wluc2SEN2gHX4MRnHQNE7bxUAX8IhbKNW0+xcQX3BOT/mPbWsrrHkvkBTzO0
|
||||
wQPIUVtGjRe1igL4b/Pv29fWsphOjHm1ZyqIr9V5Qk0hhOWsQ8i4zspTks0OGSml
|
||||
OPIY4iB/DyvUWcwsI5ZhdyK1l0ZKKS8zxWWKT4BgRtR4WGFUArkb+7fWYpIl91CE
|
||||
xE+TVTIhjuTyajZG1/wPtzI3TrQPjB5LKv5OvqroLMamuMeQG+CydFEOUb7z05Zk
|
||||
f4PU6ryvB2hPAwnzqKtf+TNWimiuqPM06pEZRSpUKcoXzJiNIweICkoOllQDrx4m
|
||||
g5pvjVT23FeDuEQWLiB9XMFmx46Thv1AGkP+gKbaLIjkxrfWEomEoY6/6VDeFjFl
|
||||
FxEYSvnazQ5K5tBQ2rA46OvpdpbIifI+x1aaP45snKQ/wvoeRfXySV9B5S/ESzrM
|
||||
xVgAY++/lteSzvUJaC+ZVKkvjIIznxNHnHG8GrFKPFZqoUS10zGKiYve9yXQITK2
|
||||
n32heLzy+SM4Qcso43f+3n0R0KrdjOn3peXakfNEFaGkJQvMdeYQpZkALDHXpbGi
|
||||
TA4C4qSTGP89TrEpGWpuAKuMHP5Vqf7y/EDr8Y4xP1TPRFo=
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIAQNfN5BLLLAdhlwGk
|
||||
Ve8w2t+9x4LWR9st6CLCYHnTgc2gr4+HqgcMwmNuj3cA8ENBvIShUnHkX2E+9CyP
|
||||
3W1ZN8OhgYkDgYYABAE3KDrdCdVeBV34NicA8AoP7hItcwxgXHOQF+V02N6b5AR7
|
||||
w3YDHE/JSzSoZZIYiqdy8SmeD5GtwHLV8tLQ8xnadgHT0BesGS02w0H5foGzzZOH
|
||||
ZW3AfbdH4MpssR4Bf1jqL0jw6eV+oiMStDuZ44zri7PFjvVByt6MoeSvh5qAXCQG
|
||||
/w==
|
||||
MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIBLVCOgktjIJCL3ZpC
|
||||
vX2xQjXVWPiWaWxbx9OGPQArsCwbAtJ+Oa7TDaJRRi0EHEJIs72ZPhozNRYppQoe
|
||||
IQPiqWyhgYkDgYYABAE69tLPv1D4DIFTgQo+P57ZABDoxe6x5Rjy+NYiRi/Nfir1
|
||||
1CxVGQDaYDfUFsb4peQJz6haxqXfXmm4MWlIbdWa1gHMf3GQl/xtIGGbJURxnBIR
|
||||
3rj2pqd0DqbONj8blnQTCWLSHsLsgyI6WWK4RHd9ZtER0UQDxoQcc8Htsuh1+SKo
|
||||
6g==
|
||||
-----END PRIVATE KEY-----
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIE+TCCAuGgAwIBAgIUWlKUd1HKU8R7cjv5NJdWhHzhT5cwDQYJKoZIhvcNAQEN
|
||||
MIIFADCCAuigAwIBAgIUU+2QY0/U0dID7GqyyHWsrN6astkwDQYJKoZIhvcNAQEN
|
||||
BQAwgcYxCzAJBgNVBAYTAlVTMTQwMgYDVQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2lu
|
||||
ZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFs
|
||||
IEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMREwDwYDVQQIDAhOZXcgWW9y
|
||||
azEPMA0GA1UEBwwGQXJtb25rMScwJQYDVQQLDB5JQk0gWiBIb3N0IEtleSBTaWdu
|
||||
aW5nIFNlcnZpY2UwIBcNMjQwMzIxMTQ1MjM5WhgPMjM4ODEyMjMxNDUyMzlaMIG2
|
||||
aW5nIFNlcnZpY2UwIBcNMjYwNzAyMDg0NzQ4WhgPMjM5MTA0MDUwODQ3NDhaMIG2
|
||||
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=
|
||||
zj0CAQYFK4EEACMDgYYABADmnrO8fwhFRmvTAeT91LiGJatTUNRhTr+SPf9glpJG
|
||||
Femv1amiV89qBYij6IuYJDhSYAQNllegWfntvzDbCOhDvAH0SY9Ivhd77nA20M0Z
|
||||
9FuUNaFBRAkUB8VhVPC+lMM7i/0QA3FCWQEP1V28oXSyIOO7SF77GAb8U8dobSvr
|
||||
Gtb7dKN6MHgwJgYDVR0fBB8wHTAboBmgF4YVaHR0cDovL2libV9hcm1vbmsuY3Js
|
||||
MA4GA1UdDwEB/wQEAwIDCDAfBgNVHSMEGDAWgBT+K/WumDBi4hRISudTeDt/ppiG
|
||||
7TAdBgNVHQ4EFgQUy6bpiWFK4+V2aXRfANx1B/CM98owDQYJKoZIhvcNAQENBQAD
|
||||
ggIBACFCebna0DLGqzp3DYY3bdOIuCD5qCfYHxEB0OCMeOsFT3Fev+nDKijJ9vqI
|
||||
F9yCKE9ddWNygNZ3GDMFss1GjYcMeCecvy8nr3xiR02V1vLZxjlgd0qwSGUOg+jE
|
||||
trumFLoURc4xB6gu9F6vaN6fW7mlYJtOjHLtcKf226WkYYFgsrD0nhzGYosqeFRQ
|
||||
JMfLQAmqfCU1z2CwADWK8SVZvAqOY8cdtrXnrvO4fM+lDmx7ZhGeAfChq8bo5EJP
|
||||
pSjOjlgZx+m0teCJgmWvRIeq1IM5ntaZ6/BArMxlhUYuA/g9AvW6xnHuFT1yy00z
|
||||
DXe1aTjbBS2/jo3Iaow99Qf20bthm9h+kpaNyaBkSgWrZewhYc7TfyWRKQ72x4Ob
|
||||
VQ0nzpt5uRSTXv+BGFk8MzDj20pxxa3C6j1skfEp3Us1Z5VJjkXf9v2039bOehEv
|
||||
SV2w01sFeuqMLbyiL6eXKIItn/SMy6Vq9muwdr0XUwlyp4Hmwiws9cJC0b7Rie7M
|
||||
7TiNLIviCRumV2JM4As6zS4pI/ljBXEaKi16SQnOERNYJx6QzQy8Uv7HKREHXa7P
|
||||
12cfpjA4Xw1RhrLpd9B9ZQL7AS52cWiKqNI26pR0pOuf5EEN3oour0byVoYN7FQs
|
||||
ypmaGcd2dEJoytW0QnxVrcpjtU4OX6YMFGfkBifsTSNy/lWz
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIE9jCCAt6gAwIBAgIUSpwJMAovpO3Z9SuY7Zw+/pv3bLEwDQYJKoZIhvcNAQEN
|
||||
MIIE/TCCAuWgAwIBAgIUJI5RArOzzLAWps20JDkSDSb8YD8wDQYJKoZIhvcNAQEN
|
||||
BQAwgcwxCzAJBgNVBAYTAlVTMTQwMgYDVQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2lu
|
||||
ZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFs
|
||||
IEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMREwDwYDVQQIDAhOZXcgWW9y
|
||||
azEVMBMGA1UEBwwMUG91Z2hrZWVwc2llMScwJQYDVQQLDB5JQk0gWiBIb3N0IEtl
|
||||
eSBTaWduaW5nIFNlcnZpY2UwHhcNMjIwMzIyMTU1MjM5WhcNMjMwMzIyMTU1MjM5
|
||||
eSBTaWduaW5nIFNlcnZpY2UwHhcNMjQwNzAyMTA0NzQ4WhcNMjUwNzAyMTA0NzQ4
|
||||
WjCBtjELMAkGA1UEBhMCVVMxNDAyBgNVBAoMK0ludGVybmF0aW9uYWwgQnVzaW5l
|
||||
c3MgTWFjaGluZXMgQ29ycG9yYXRpb24xNDAyBgNVBAMMK0ludGVybmF0aW9uYWwg
|
||||
QnVzaW5lc3MgTWFjaGluZXMgQ29ycG9yYXRpb24xETAPBgNVBAgMCE5ldyBZb3Jr
|
||||
MQ8wDQYDVQQHDAZBcm1vbmsxFzAVBgNVBAsMDklCTSBaIEhvc3QgS2V5MIGbMBAG
|
||||
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=
|
||||
ByqGSM49AgEGBSuBBAAjA4GGAAQA5p6zvH8IRUZr0wHk/dS4hiWrU1DUYU6/kj3/
|
||||
YJaSRhXpr9WpolfPagWIo+iLmCQ4UmAEDZZXoFn57b8w2wjoQ7wB9EmPSL4Xe+5w
|
||||
NtDNGfRblDWhQUQJFAfFYVTwvpTDO4v9EANxQlkBD9VdvKF0siDju0he+xgG/FPH
|
||||
aG0r6xrW+3SjczBxMB8GA1UdHwQYMBYwFKASoBCGDmh0dHA6Ly9pYm0uY3JsMA4G
|
||||
A1UdDwEB/wQEAwIDCDAfBgNVHSMEGDAWgBT+K/WumDBi4hRISudTeDt/ppiG7TAd
|
||||
BgNVHQ4EFgQUy6bpiWFK4+V2aXRfANx1B/CM98owDQYJKoZIhvcNAQENBQADggIB
|
||||
ABb7ufyi/LVMefLjFCfUpf0iiCuUq81DYKLI5AZ0Gs+Oip0OM0FfADCz2Gyrm1VR
|
||||
97wK1DLRJ4fFFEE5EOL+pNVGjMGUAwmhcR1xPAhV2AJ7jD/xYNZmdnFjQE060S1n
|
||||
NFOZP9WLyf4jf+aFUTKxpmfRej2Js3WziqRYYEGODmoatIeZtcMc1/IZnxAxntww
|
||||
sDl8jFCnnzUPJELMh0ADFBFNUpfnlXKG3W66rMKzKAHAcl96rpWWBOEZ0i/1oGuz
|
||||
l1/P8DzlJhqR+VJMeX7Ume9z0/ZUy3Zy4puXAcflrx8r+vH4BDCJsebuEjJAvgHz
|
||||
uRor3WgOj+3w3do+pYX0eqaMCCJ15o0X9TWnR89mUqYav7TeHiim06vnpLSgmK19
|
||||
1Lvj91l0ua3BSgqWAQe8rwBxvFOg9oC5Kc+GsCPunJb69lUskaS88foA8PZ5c/34
|
||||
tSMj3jXcGAXY86qxAfDjejWR+sF7uVW3Fqr/RKJ12TzPYVnwvzvio6BeHey6Eyg/
|
||||
4EWHjymQwfPpyIYpKp0nYvE/PfqT46sFtVA74Z3nw/WxDHUmo7l70X+LfU/TYi3+
|
||||
qUyomwxSBTuWxUtBcNiTfMk/8yuTv8D38RLdpMUuE9Xbfd4DLO9OSgMLrkJmPvLc
|
||||
r8Km9zHV0N5/KA5EyewrPBsClDOwN15bqncbk+RG8hUL
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFAzCCAuugAwIBAgIUELm+ubD3lNPrFxtCj86wMh7lYEcwDQYJKoZIhvcNAQEN
|
||||
MIIFCzCCAvOgAwIBAgIUfBiRwLX9KVgvBmm8F3oCdB+ai2AwDQYJKoZIhvcNAQEN
|
||||
BQAwgckxCzAJBgNVBAYTAlVTMTQwMgYDVQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2lu
|
||||
ZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFs
|
||||
IEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMREwDwYDVQQIDAhOZXcgWW9y
|
||||
azEVMBMGA1UEBwwMUG91Z2hrZWVwc2llMSQwIgYDVQQLDBtLZXkgU2lnbmluZyBT
|
||||
ZXJ2aWNlIEludmFsaWQwIBcNMjQwMzIxMTQ1MjM5WhgPMjM4ODEyMjMxNDUyMzla
|
||||
ZXJ2aWNlIEludmFsaWQwIBcNMjYwNzAyMDg0NzQ4WhgPMjM5MTA0MDUwODQ3NDha
|
||||
MIG2MQswCQYDVQQGEwJVUzE0MDIGA1UECgwrSW50ZXJuYXRpb25hbCBCdXNpbmVz
|
||||
cyBNYWNoaW5lcyBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrSW50ZXJuYXRpb25hbCBC
|
||||
dXNpbmVzcyBNYWNoaW5lcyBDb3Jwb3JhdGlvbjERMA8GA1UECAwITmV3IFlvcmsx
|
||||
DzANBgNVBAcMBkFybW9uazEXMBUGA1UECwwOSUJNIFogSG9zdCBLZXkwgZswEAYH
|
||||
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
|
||||
KoZIzj0CAQYFK4EEACMDgYYABADRQ0Xq0/NUVMVazLQK2oZ7TbJdL+ZtXeQawN/9
|
||||
j70DUpufvfbFLflnfjCD7dWoMGZlAV+pfrIRB3fI4YKvzGWdEwA/PgEDYpxS0onE
|
||||
XtdAvveL+3+Bb8f3s68z8+UH+fDtIKZRLen8yDvEua0WpPGPoE8Xga5ZOoAJHWeO
|
||||
RVsPGypz36OBgTB/MC0GA1UdHwQmMCQwIqAgoB6GHGh0dHA6Ly9pYm1fd3Jvbmdf
|
||||
c3ViamVjdC5jcmwwDgYDVR0PAQH/BAQDAgMIMB8GA1UdIwQYMBaAFGI+YnrDs4Q2
|
||||
f3a0zSucoJYGJqYnMB0GA1UdDgQWBBTefgLJvMQh0wA+A1PQV2yFHVV7vTANBgkq
|
||||
hkiG9w0BAQ0FAAOCAgEAQflAXs9mWGhK5WXVYzSx44S+C+U6eab3N9NCoYQXOv14
|
||||
z96bxRi+J8yB91cZ5Z+Px4gtdzZihNx8fIoGN7aHwNzfBuRhCYxCOGRwN35MnIk5
|
||||
sKXpvZ2hVIvM7SQ4HMujJPjfUesKNWXBGTILe+nXf9KIruznd0VcFtbAEkpN0t5v
|
||||
z/L7zpWOI6R9lYGgaEzfHn2Bw8lm28rLP0u0QrOfUcJiNcnVvhUfdfHvBLzchOF4
|
||||
A3mIO8gl1VRNacxmB9ZqpVML2hck17oXm2wmF8oAsXMPjOBk4uv/DrK5EZufByB3
|
||||
yaQaL3gunxBiEQs7vAzxVN3IpoHuXWzeWm39ttgVKDRu2URUhRILS6sK4Xar0Xoi
|
||||
CPvf5tOsdkTn2+OzS9iDl5JiHVGkJTVa8qAd/wDZ1Zq2SrECJM8gObp0Aom/JH0z
|
||||
/NlJs+W/CCMwDhV4hVyJ/2Io54AaOEeFiLaBtwR/Tgm16B87pAwgRqmWbVUIJbIr
|
||||
Vv5hz6s3SS/w/KnjfgzZt/amQnEOLEqFDUCFb1iPPX7yor40nJU99b9GxknuOtzG
|
||||
1zMxJj+9OMm3BT+2F2+BYF010uJG4d8CmbOf6nKn8x6QBQN/sUfqk3pMnVdx3Lg4
|
||||
BTScZcuPVEZ2hqAHOiVu7U544vALW1HLQCcN7iB2T7DIjIYsY4dhjkgQwezoZ3A=
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIB48Wl8pvlD/o6F7YG
|
||||
sFfCXNQRbKbppIrywEBkfNG0VzfXazBOLD41bcdPEBh1111kSYgn46uUVxjabyLp
|
||||
BgQthf2hgYkDgYYABAB/2mDXj/QP7fcpxLTNfFfuh/X1Y/RS8XK+Y4v+0nisTQhe
|
||||
3MK8BZ7D0bcB872s8EJCYZ1OYr5O2epQgv2hbk4T1wCGKe+Pjf2QHTtswXMpPf87
|
||||
R3etF+zWR+CYH+5N5uQhjW9Ueeq7wve3A61e+Atz7IzTKVlM29kT0XvIsYtazn6u
|
||||
sg==
|
||||
MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIBTCcA3Wwdesq/meh+
|
||||
lZDOSRex3E2nJawTEFuCoOCI/6Pqf1jw/LjkfzVcRM85vQ/E+MVH+j3mL28nlYNW
|
||||
Mxl8VqOhgYkDgYYABADRQ0Xq0/NUVMVazLQK2oZ7TbJdL+ZtXeQawN/9j70DUpuf
|
||||
vfbFLflnfjCD7dWoMGZlAV+pfrIRB3fI4YKvzGWdEwA/PgEDYpxS0onEXtdAvveL
|
||||
+3+Bb8f3s68z8+UH+fDtIKZRLen8yDvEua0WpPGPoE8Xga5ZOoAJHWeORVsPGypz
|
||||
3w==
|
||||
-----END PRIVATE KEY-----
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIE+DCCAuCgAwIBAgIUMi8utJhRyr5bbvABnCn/Q9/vJ0kwDQYJKoZIhvcNAQEN
|
||||
MIIE/zCCAuegAwIBAgIUCpd1IYj2RH4Kc0Pi6+ZzfdZv7n0wDQYJKoZIhvcNAQEN
|
||||
BQAwgcwxCzAJBgNVBAYTAlVTMTQwMgYDVQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2lu
|
||||
ZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFs
|
||||
IEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMREwDwYDVQQIDAhOZXcgWW9y
|
||||
azEVMBMGA1UEBwwMUG91Z2hrZWVwc2llMScwJQYDVQQLDB5JQk0gWiBIb3N0IEtl
|
||||
eSBTaWduaW5nIFNlcnZpY2UwIBcNMjQwMzIxMTQ1MjM5WhgPMjM4ODEyMjMxNDUy
|
||||
MzlaMIG2MQswCQYDVQQGEwJVUzE0MDIGA1UECgwrSW50ZXJuYXRpb25hbCBCdXNp
|
||||
eSBTaWduaW5nIFNlcnZpY2UwIBcNMjYwNzAyMDg0NzQ4WhgPMjM5MTA0MDUwODQ3
|
||||
NDhaMIG2MQswCQYDVQQGEwJVUzE0MDIGA1UECgwrSW50ZXJuYXRpb25hbCBCdXNp
|
||||
bmVzcyBNYWNoaW5lcyBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrSW50ZXJuYXRpb25h
|
||||
bCBCdXNpbmVzcyBNYWNoaW5lcyBDb3Jwb3JhdGlvbjERMA8GA1UECAwITmV3IFlv
|
||||
cmsxDzANBgNVBAcMBkFybW9uazEXMBUGA1UECwwOSUJNIFogSG9zdCBLZXkwgZsw
|
||||
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==
|
||||
EAYHKoZIzj0CAQYFK4EEACMDgYYABAFOncuQfjViGAC/g8Nt6B+11h18++MD1+bO
|
||||
LgZwk94C5u8gntb0I20QqeMFFuqmNMouFk6amimv64J6dNnaFXVh/QHOTTjZugyt
|
||||
p2WB2SpySjRIbtOsG3HFrAeSDJNr+a87NcMzq+s6aRdv5krVrKcSkpQrPnxVYV2Y
|
||||
oc1zEdsEyw6M0aNzMHEwHwYDVR0fBBgwFjAUoBKgEIYOaHR0cDovL2libS5jcmww
|
||||
DgYDVR0PAQH/BAQDAgMIMB8GA1UdIwQYMBaAFP4r9a6YMGLiFEhK51N4O3+mmIbt
|
||||
MB0GA1UdDgQWBBRSJBCuVdARV15CwCDKg4XUkfQfITANBgkqhkiG9w0BAQ0FAAOC
|
||||
AgEALhMxuxt6kmvhBUVbxkwBS+6W19SOPhyIGbgWpiZabF2WcapQUYDwWqovswZ6
|
||||
YIR1H19rEThXUArpMUy2PFk89zum1WLdK5j3URNRptyCFOTP+485fIpkPnDURIQ7
|
||||
PWcTAL1pPmVZpXyNWem+Yolwmkt8vA5tGAopnbp5gcvoN+bfiDr7kwOUd958p2yr
|
||||
xwDqaRBxzYCniLV38wrcVVMK0fWS7L8SmV0cprh4FBhsDdLLFgZAiM/Bex97soPo
|
||||
nBRHLinB1I6VoRVWikBkCnTsD/i9ofqoFRcvZRNcnWgM3eNi5e+zoBKBSvLW+xcS
|
||||
9sjNkbneWgTg0cKGqkkXwG4gccf4G2K4s6x64lo6Tkukp7q7uAvN6KVj6r2D8ATQ
|
||||
09TAgRd6EbMbZCXC4kFZweCbpCoNubypXIuCCL5uZyftT2Ji+r/WFE6X23tUChu0
|
||||
7B4kNyipl15tNQvMc/6AEZ30C+QlPd+q9EyFJfajKriOqrwrfqFutfOVqKkFC6Mx
|
||||
WSvTR8R/kwLvXfSgwWDfeBesULnOs8GryrSQIlzoT2eUxeB+J4qxtHavIH9Z8vBV
|
||||
anT+TdboVO8GrWtgXBr38WtY8xEsvMcYMxzHZ2GcJ6V3qDE+4EcbPl/FuwFck+gJ
|
||||
3feiz9/iV1ajuVgLhvX11JmR65sbQQrLPFHm+vm7Xv0n0fU=
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIBLz0ExeBJrxd5gA7C
|
||||
YFJLVuNd4CPNc/jsOLIMnIbLHSegdOtQn9tief97k5rZdz/MQzWp7rCmsLUYw/fM
|
||||
ktUQjJKhgYkDgYYABAHkrwf4hZ7M5ahoYHT0u1Xgl28qxURcdNmWkYDA5u1Y2mGX
|
||||
Qq85BakAOyfxl/FF/cBrLm0eLVFpePumqgPna3El1gAs9p2SFwN74MmcLhbwPmGn
|
||||
WmzVrOh9cNS988XYf01E74966r4MKpAGxSNPKDwu4doXFVAYRH/wtcgbjlk+Qi3c
|
||||
9w==
|
||||
MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIAK7ON/fwW9+CMylco
|
||||
dAlDMVp0PeEPci/5GxVkb33rkUVct7wRXceSKg5N19L6+o7d3iyKt1G4Qm8L5cgq
|
||||
FsdQxYahgYkDgYYABAFOncuQfjViGAC/g8Nt6B+11h18++MD1+bOLgZwk94C5u8g
|
||||
ntb0I20QqeMFFuqmNMouFk6amimv64J6dNnaFXVh/QHOTTjZugytp2WB2SpySjRI
|
||||
btOsG3HFrAeSDJNr+a87NcMzq+s6aRdv5krVrKcSkpQrPnxVYV2Yoc1zEdsEyw6M
|
||||
0Q==
|
||||
-----END PRIVATE KEY-----
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIE/TCCAuWgAwIBAgIUPRltRSFZSbucmw20u9TN7WHxG8UwDQYJKoZIhvcNAQEN
|
||||
MIIFBDCCAuygAwIBAgIUNuVS85z9zeYfWs6GLZLJ20TLASYwDQYJKoZIhvcNAQEN
|
||||
BQAwgcwxCzAJBgNVBAYTAlVTMTQwMgYDVQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2lu
|
||||
ZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFs
|
||||
IEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMREwDwYDVQQIDAhOZXcgWW9y
|
||||
azEVMBMGA1UEBwwMUG91Z2hrZWVwc2llMScwJQYDVQQLDB5JQk0gWiBIb3N0IEtl
|
||||
eSBTaWduaW5nIFNlcnZpY2UwIBcNMjQwMzIxMTQ1MjM5WhgPMjM4ODEyMjMxNDUy
|
||||
MzlaMIG2MQswCQYDVQQGEwJVUzE0MDIGA1UECgwrSW50ZXJuYXRpb25hbCBCdXNp
|
||||
eSBTaWduaW5nIFNlcnZpY2UwIBcNMjYwNzAyMDg0NzQ4WhgPMjM5MTA0MDUwODQ3
|
||||
NDhaMIG2MQswCQYDVQQGEwJVUzE0MDIGA1UECgwrSW50ZXJuYXRpb25hbCBCdXNp
|
||||
bmVzcyBNYWNoaW5lcyBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrSW50ZXJuYXRpb25h
|
||||
bCBCdXNpbmVzcyBNYWNoaW5lcyBDb3Jwb3JhdGlvbjERMA8GA1UECAwITmV3IFlv
|
||||
cmsxDzANBgNVBAcMBkFybW9uazEXMBUGA1UECwwOSUJNIFogSG9zdCBLZXkwgZsw
|
||||
EAYHKoZIzj0CAQYFK4EEACMDgYYABAHGO0MnpQa6Q2IxgqV7AGwd3OwBnYOJjYJF
|
||||
hzrwY+wQacmJjWeNyHahBCxu4bM8vDr70SF5vZFrWpcWpc9JTY5AagFCFDqIfSvL
|
||||
J6lKJuCog5RfMsWJpG2j/MnK7MxG+Ph0R+ItmLFbWFxCV5YOT43olhwYZr/pd9qH
|
||||
PAD96UEDM8JanKNxMG8wHQYDVR0fBBYwFDASoBCgDoYMbm90YXZhaWxhYmxlMA4G
|
||||
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
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
@@ -3,57 +3,57 @@ 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=
|
||||
MScwJQYDVQQLDB5JQk0gWiBIb3N0IEtleSBTaWduaW5nIFNlcnZpY2UXDTI2MDYy
|
||||
MjEwNDc0OFoYDzIzOTEwNDA1MTA0NzQ4WjA8MBMCAgIrFw0yNjA3MDExMDQ3NDha
|
||||
MCUCFAqXdSGI9kR+CnND4uvmc33Wb+59Fw0yNjA3MDExMDQ3NDhaoCMwITAfBgNV
|
||||
HSMEGDAWgBT+K/WumDBi4hRISudTeDt/ppiG7TANBgkqhkiG9w0BAQ0FAAOCAgEA
|
||||
fxBxN6giXdLaG5lWLbigI78WQoEzOxWeYbzUpqmn+QFd9YiJCNMaGz2XWl/MBZEl
|
||||
gmpHNOEzOM5Ze5dRfbLDAzBBFghNGrDDQURMw0ASZfHX6WsL7MOoBqTeg4xbFESk
|
||||
dXT9YCH/wS5sn5YgkKDh2jqHQya8c4TtWfuWYW/Anyo8wVhgcYAnAiSJZgSUciq5
|
||||
964Ci2v4pifpQBbpx1MAaOgU7kkY59v+AHhWfxJ7whJra8DA+v6XEim7Y/uABW0N
|
||||
Yzp+rcSZdDanFq5OC8YE9Kn0c7bHvFi0bDf/AmOB9D64OHc3PRQInubN7aNaQ89N
|
||||
T+wgFhN2yMSuh4YB+RJ3C1aouGszzC275vYEcc2Iw2OdQQkTu7dhhV+pEfvkhh4x
|
||||
myBgJKEBqidXDAe1SjGtNP+G0pF6XcQDc3lkSsw+btW1YjQIbv7uayuDfz7aqbh8
|
||||
vPdP5QKWocPkIOL8sv4JFiETfVWqVMH42vE+ixC3+enunLxqJAUxqMZSfKuCtPYb
|
||||
PhnSuZZ+rTfXpFfYZMMUTMhrx618+uttcQGosdYNv9e4YSR8pLvIPFef/wfWqpLL
|
||||
Yy8xYSGOUJ9f8vfh0aIkcRiLbjSgnyJeSlQVRnF0w4FeTjm3QeY2gcdMzaIo3oyH
|
||||
G23dJvzGq19Y5h4ShZoACuasTIKtaxLm0gjwCYBWZO8=
|
||||
-----END X509 CRL-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIGsTCCBJmgAwIBAgIUMwTHYM3peBjwVRi6iICr6FVn0cMwDQYJKoZIhvcNAQEL
|
||||
MIIGuDCCBKCgAwIBAgIUMX4D3d8lY30ZIeB/PpAi4vEPvfcwDQYJKoZIhvcNAQEL
|
||||
BQAwgb0xCzAJBgNVBAYTAlVTMTQwMgYDVQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2lu
|
||||
ZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFs
|
||||
IEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMREwDwYDVQQIDAhOZXcgWW9y
|
||||
azEPMA0GA1UEBwwGQXJtb25rMR4wHAYDVQQLDBVJQk0gWiBJbnRlcm1lZGlhdGUg
|
||||
Q0EwIBcNMjQwMzIxMTQ1MjM4WhgPMjM4ODEyMjMxNDUyMzhaMIHMMQswCQYDVQQG
|
||||
Q0EwIBcNMjYwNzAyMDg0NzQ4WhgPMjM5MTA0MDUwODQ3NDhaMIHMMQswCQYDVQQG
|
||||
EwJVUzE0MDIGA1UECgwrSW50ZXJuYXRpb25hbCBCdXNpbmVzcyBNYWNoaW5lcyBD
|
||||
b3Jwb3JhdGlvbjE0MDIGA1UEAwwrSW50ZXJuYXRpb25hbCBCdXNpbmVzcyBNYWNo
|
||||
aW5lcyBDb3Jwb3JhdGlvbjERMA8GA1UECAwITmV3IFlvcmsxFTATBgNVBAcMDFBv
|
||||
dWdoa2VlcHNpZTEnMCUGA1UECwweSUJNIFogSG9zdCBLZXkgU2lnbmluZyBTZXJ2
|
||||
aWNlMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxNqcFB9GSj+nC1PV
|
||||
OTIAvzTuo3X7bTbohEPrIDDsEcGyVzQtfagI9vkxhhGLhXxIXrkwEI4u75DeLBdq
|
||||
ZR3KFJ3QD+jHW12EWNpmSYu272CEAJeb/SBJaFbh40WbY1BsTP+3zI5QMwVTmCH5
|
||||
QqODD+GU0fDSo9Gti0yX4rxOY+54jDC77AhSlU55rYruBoIXVe4CcPUpqzZLgqB2
|
||||
cTJ5g7lokGqc6w9pveCznVYGPfcdDt+ePGssOvrfBOJnn6N44tTRAG623BrpctXi
|
||||
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
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
@@ -3,19 +3,19 @@ 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=
|
||||
MScwJQYDVQQLDB5JQk0gWiBIb3N0IEtleSBTaWduaW5nIFNlcnZpY2UXDTI2MDYy
|
||||
MjEwNDc0OFoYDzIzOTEwNDA1MTA0NzQ4WjA8MBMCAgIrFw0yNjA3MDExMDQ3NDha
|
||||
MCUCFAqXdSGI9kR+CnND4uvmc33Wb+59Fw0yNjA3MDExMDQ3NDhaoCMwITAfBgNV
|
||||
HSMEGDAWgBT+K/WumDBi4hRISudTeDt/ppiG7TANBgkqhkiG9w0BAQ0FAAOCAgEA
|
||||
fxBxN6giXdLaG5lWLbigI78WQoEzOxWeYbzUpqmn+QFd9YiJCNMaGz2XWl/MBZEl
|
||||
gmpHNOEzOM5Ze5dRfbLDAzBBFghNGrDDQURMw0ASZfHX6WsL7MOoBqTeg4xbFESk
|
||||
dXT9YCH/wS5sn5YgkKDh2jqHQya8c4TtWfuWYW/Anyo8wVhgcYAnAiSJZgSUciq5
|
||||
964Ci2v4pifpQBbpx1MAaOgU7kkY59v+AHhWfxJ7whJra8DA+v6XEim7Y/uABW0N
|
||||
Yzp+rcSZdDanFq5OC8YE9Kn0c7bHvFi0bDf/AmOB9D64OHc3PRQInubN7aNaQ89N
|
||||
T+wgFhN2yMSuh4YB+RJ3C1aouGszzC275vYEcc2Iw2OdQQkTu7dhhV+pEfvkhh4x
|
||||
myBgJKEBqidXDAe1SjGtNP+G0pF6XcQDc3lkSsw+btW1YjQIbv7uayuDfz7aqbh8
|
||||
vPdP5QKWocPkIOL8sv4JFiETfVWqVMH42vE+ixC3+enunLxqJAUxqMZSfKuCtPYb
|
||||
PhnSuZZ+rTfXpFfYZMMUTMhrx618+uttcQGosdYNv9e4YSR8pLvIPFef/wfWqpLL
|
||||
Yy8xYSGOUJ9f8vfh0aIkcRiLbjSgnyJeSlQVRnF0w4FeTjm3QeY2gcdMzaIo3oyH
|
||||
G23dJvzGq19Y5h4ShZoACuasTIKtaxLm0gjwCYBWZO8=
|
||||
-----END X509 CRL-----
|
||||
|
||||
@@ -1,38 +1,38 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIGsTCCBJmgAwIBAgIUMwTHYM3peBjwVRi6iICr6FVn0cMwDQYJKoZIhvcNAQEL
|
||||
MIIGuDCCBKCgAwIBAgIUMX4D3d8lY30ZIeB/PpAi4vEPvfcwDQYJKoZIhvcNAQEL
|
||||
BQAwgb0xCzAJBgNVBAYTAlVTMTQwMgYDVQQKDCtJbnRlcm5hdGlvbmFsIEJ1c2lu
|
||||
ZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMTQwMgYDVQQDDCtJbnRlcm5hdGlvbmFs
|
||||
IEJ1c2luZXNzIE1hY2hpbmVzIENvcnBvcmF0aW9uMREwDwYDVQQIDAhOZXcgWW9y
|
||||
azEPMA0GA1UEBwwGQXJtb25rMR4wHAYDVQQLDBVJQk0gWiBJbnRlcm1lZGlhdGUg
|
||||
Q0EwIBcNMjQwMzIxMTQ1MjM4WhgPMjM4ODEyMjMxNDUyMzhaMIHMMQswCQYDVQQG
|
||||
Q0EwIBcNMjYwNzAyMDg0NzQ4WhgPMjM5MTA0MDUwODQ3NDhaMIHMMQswCQYDVQQG
|
||||
EwJVUzE0MDIGA1UECgwrSW50ZXJuYXRpb25hbCBCdXNpbmVzcyBNYWNoaW5lcyBD
|
||||
b3Jwb3JhdGlvbjE0MDIGA1UEAwwrSW50ZXJuYXRpb25hbCBCdXNpbmVzcyBNYWNo
|
||||
aW5lcyBDb3Jwb3JhdGlvbjERMA8GA1UECAwITmV3IFlvcmsxFTATBgNVBAcMDFBv
|
||||
dWdoa2VlcHNpZTEnMCUGA1UECwweSUJNIFogSG9zdCBLZXkgU2lnbmluZyBTZXJ2
|
||||
aWNlMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxNqcFB9GSj+nC1PV
|
||||
OTIAvzTuo3X7bTbohEPrIDDsEcGyVzQtfagI9vkxhhGLhXxIXrkwEI4u75DeLBdq
|
||||
ZR3KFJ3QD+jHW12EWNpmSYu272CEAJeb/SBJaFbh40WbY1BsTP+3zI5QMwVTmCH5
|
||||
QqODD+GU0fDSo9Gti0yX4rxOY+54jDC77AhSlU55rYruBoIXVe4CcPUpqzZLgqB2
|
||||
cTJ5g7lokGqc6w9pveCznVYGPfcdDt+ePGssOvrfBOJnn6N44tTRAG623BrpctXi
|
||||
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
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user