Port to pycryptography and pyasn1 and make keyring optional

pyOpenSSL 24.0.0 removed several APIs required by pccsadmin, so
porting to pycryptography is required on Fedora. Since RHEL does
not ship pyOpenSSL, the port is useful here too.

Using pyasn1 instead of asn1 gives stronger validation during
parsing and brings compatibility with RHEL that lacks python3-asn1

The keyring package needs to be optional on RHEL which lacks this
module (currently).

Also drop the inappropriate pccs port number change

Related: https://issues.redhat.com/browse/RHEL-121612
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
Daniel P. Berrangé 2025-12-04 15:52:29 +00:00
parent 391d603fde
commit 12589a1af6
29 changed files with 1012 additions and 249 deletions

View File

@ -1,7 +1,7 @@
From 9746d1048b23a3431d898f2375a8d849127ebde7 Mon Sep 17 00:00:00 2001
From cf39f86bcca57579013cee5967d39cdaca15cbc4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Mon, 26 Feb 2024 12:19:51 +0000
Subject: [PATCH 100/120] Drop use of bundled pre-built openssl
Subject: [PATCH 100/126] Drop use of bundled pre-built openssl
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
@ -188,5 +188,5 @@ index a20a3cd..c8e1d01 100644
debug:
$(PCKCERTSEL_VERBOSE)$(MAKE) DEBUG=1 all
--
2.49.0
2.51.1

View File

@ -1,7 +1,7 @@
From 50bbd267076608a9b0a3b5e23bcbc8bfadfb09d7 Mon Sep 17 00:00:00 2001
From b36d8f61a5a18dc5edfbd632e5f2373bcf365b3e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Fri, 1 Mar 2024 12:05:01 +0000
Subject: [PATCH 101/120] Improve debuggability of build system
Subject: [PATCH 101/126] Improve debuggability of build system
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
@ -128,5 +128,5 @@ index 894e616..7962d10 100644
.PHONY: qal
qal:
--
2.49.0
2.51.1

View File

@ -1,7 +1,7 @@
From 2f0e63c015f83aa2248b8afa04c1928b6aa8b0fb Mon Sep 17 00:00:00 2001
From 9a185a6103e9637b785e498d4c4e4c990e7a3478 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Mon, 26 Feb 2024 12:19:51 +0000
Subject: [PATCH 102/120] Support build time setting of enclave load directory
Subject: [PATCH 102/126] Support build time setting of enclave load directory
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
@ -259,5 +259,5 @@ index d9c2bac..1065949 100644
App_Link_Flags += -lcurl -ldl -lpthread
ifeq ($(STANDALONE), 1)
--
2.49.0
2.51.1

View File

@ -1,7 +1,7 @@
From 5fddd2225147e4372a6ff09350bdd495c3fdd4f8 Mon Sep 17 00:00:00 2001
From b92d97f6037cb2e56d343cb979767d51655b097f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Tue, 27 Feb 2024 15:46:41 +0000
Subject: [PATCH 103/120] Look for versioned sgx_urts library in
Subject: [PATCH 103/126] Look for versioned sgx_urts library in
PCKRetrievalTool
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
@ -40,5 +40,5 @@ index d77a6eb..d195717 100644
}
#endif
--
2.49.0
2.51.1

View File

@ -1,33 +1,35 @@
From d758e815930fe6ca3d19ab880c8cb839001746ce Mon Sep 17 00:00:00 2001
From eca1c479b23dd8e8c87e90988204c08b5e0c3edc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Tue, 27 Feb 2024 20:28:24 +0000
Subject: [PATCH 104/120] Don't import pypac in pccsadmin
Date: Fri, 4 Oct 2024 17:41:37 +0100
Subject: [PATCH 104/126] pccsadmin: only import 'pypac' module on Windows
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The code only uses the pypac module when executing on Windows
hosts. It should not be imported when packaged for Linux
environments to avoid a redundant python dependency.
The PACSession object is only used in a code path that runs on
Windows, so don't try to import this on Linux, to avoid the
redundant dependency.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
tools/PccsAdminTool/lib/intelsgx/pcs.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
tools/PccsAdminTool/lib/intelsgx/pcs.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/tools/PccsAdminTool/lib/intelsgx/pcs.py b/tools/PccsAdminTool/lib/intelsgx/pcs.py
index 9f1d224..af1e78e 100644
index 9f1d224..046c781 100644
--- a/tools/PccsAdminTool/lib/intelsgx/pcs.py
+++ b/tools/PccsAdminTool/lib/intelsgx/pcs.py
@@ -5,7 +5,7 @@ import json
@@ -5,8 +5,9 @@ import json
import binascii
from urllib import parse
from OpenSSL import crypto
-from pypac import PACSession
+#from pypac import PACSession
from platform import system
+if system() == 'Windows':
+ from pypac import PACSession
from lib.intelsgx.credential import Credentials
from requests.adapters import HTTPAdapter
from urllib3.util import Retry
--
2.49.0
2.51.1

View File

@ -1,7 +1,7 @@
From 1d85ecfb88b08772efdaeb241b09502383e1123c Mon Sep 17 00:00:00 2001
From c8820c38a16ba9c572a6eafefd010b60ba037dde Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Thu, 29 Feb 2024 14:21:36 +0000
Subject: [PATCH 105/120] Look for PCKRetrievalTool config file in /etc/
Subject: [PATCH 105/126] Look for PCKRetrievalTool config file in /etc/
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
@ -39,5 +39,5 @@ index e423f38..36f219b 100644
if(strnlen(local_configuration_file_path ,MAX_PATH)+strnlen(LOCAL_NETWORK_SETTING,MAX_PATH)+sizeof(char) > MAX_PATH) {
return false;
--
2.49.0
2.51.1

View File

@ -1,7 +1,7 @@
From ac4041d449135696b66c9d147d29f0967e2df1c3 Mon Sep 17 00:00:00 2001
From 06874f59bd6693f0f42a999dcfbdc0233d9a4bd2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Fri, 28 Mar 2025 16:00:27 +0000
Subject: [PATCH 106/120] Honour CFLAGS/CXXFLAGS/LDFLAGS for various tools and
Subject: [PATCH 106/126] Honour CFLAGS/CXXFLAGS/LDFLAGS for various tools and
libraries
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
@ -205,5 +205,5 @@ index 4937fe9..83aefee 100644
LDFLAGS += '-Wl,-rpath,$$ORIGIN'
CXXFLAGS += '-DSTANDALONE'
--
2.49.0
2.51.1

View File

@ -1,7 +1,7 @@
From 95b111ae4a42f872e467a58058cfc87d5a5d089d Mon Sep 17 00:00:00 2001
From 44eefb7f574b33cb0cf5239948e7d633f1d71dd5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Thu, 3 Oct 2024 14:42:29 +0100
Subject: [PATCH 107/120] qgs: add space between program name & first arg in
Subject: [PATCH 107/126] qgs: add space between program name & first arg in
usage
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
@ -35,5 +35,5 @@ index 478dbfe..3618b5a 100644
exit(1);
}
--
2.49.0
2.51.1

View File

@ -1,7 +1,7 @@
From 0df9bd861d54722365e891911c18924af16cd732 Mon Sep 17 00:00:00 2001
From 6c38e13fbee555045aec98f6e159531a385bce53 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Fri, 4 Oct 2024 09:43:17 +0100
Subject: [PATCH 108/120] qgs: protect against format strings in QL log
Subject: [PATCH 108/126] qgs: protect against format strings in QL log
messages
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
@ -35,5 +35,5 @@ index 77838c3..1e97b58 100644
}
--
2.49.0
2.51.1

View File

@ -1,7 +1,7 @@
From 480ac4becb93a54184c024fa1945c1a2890488fb Mon Sep 17 00:00:00 2001
From d1cbef970b8ee800a313b818927449a7dcf1a685 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Thu, 3 Oct 2024 16:57:35 +0100
Subject: [PATCH 109/120] qgs: add --debug parameter to control logging
Subject: [PATCH 109/126] qgs: add --debug parameter to control logging
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
@ -125,5 +125,5 @@ index 3618b5a..47f6c26 100644
exit(1);
}
--
2.49.0
2.51.1

View File

@ -1,7 +1,7 @@
From e559fba635b7736a54a446e25afc268b2a27513c Mon Sep 17 00:00:00 2001
From 64c49b04e7e22358f3afee834a434a6cfdff4a9b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Tue, 8 Oct 2024 10:13:02 +0100
Subject: [PATCH 110/120] pccsadmin: remove leftover debugging 'print(args)'
Subject: [PATCH 110/126] pccsadmin: remove leftover debugging 'print(args)'
statement
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
@ -29,5 +29,5 @@ index ffee326..8e447c5 100755
if args.command == 'put' and args.url and args.url.endswith("/appraisalpolicy"):
if not args.fmspc or not args.input_file:
--
2.49.0
2.51.1

View File

@ -1,7 +1,7 @@
From 6a2d951d6a1d21a1c45256c81eaf1acd6f010d46 Mon Sep 17 00:00:00 2001
From 32ac12f933e813b80348840821e1deaedf797a00 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Fri, 17 Jan 2025 15:39:39 +0000
Subject: [PATCH 111/120] Fix soname version for libsgx_qe3_logic.so library
Subject: [PATCH 111/126] Fix soname version for libsgx_qe3_logic.so library
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
@ -51,5 +51,5 @@ index 9b8c936..c92d782 100644
$(BUILD_DIR):
--
2.49.0
2.51.1

View File

@ -1,7 +1,7 @@
From 63e5a14cbae060060ee1de4eae177cc2f7b1f851 Mon Sep 17 00:00:00 2001
From ac446d8943858e6dccec924451b8a8a3be4d9c4a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Thu, 6 Feb 2025 20:08:59 +0000
Subject: [PATCH 112/120] Workaround broken GCC 15
Subject: [PATCH 112/126] Workaround broken GCC 15
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
@ -36,5 +36,5 @@ index 15fbdd4..4400544 100644
private:
struct alignas(A)_T_instantiator_
--
2.49.0
2.51.1

View File

@ -1,7 +1,7 @@
From 3cb471cfd9309a61c6cacf99ef8959c8d6c3079c Mon Sep 17 00:00:00 2001
From fa8c4f150fe32dafd875c5f45a9e588775235e35 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Wed, 2 Apr 2025 18:39:31 +0100
Subject: [PATCH 113/120] Don't disable cf-protection for qgs
Subject: [PATCH 113/126] Don't disable cf-protection for qgs
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
@ -27,5 +27,5 @@ index 8228bdf..5116d85 100644
DEPENDS = ${QGS_OBJS test_client.o:.o=.d}
--
2.49.0
2.51.1

View File

@ -1,7 +1,7 @@
From 218ff444583b58dc122ac69507b50c6e9f711581 Mon Sep 17 00:00:00 2001
From 2d83da9d5f5fb7399b0d7ec6ac410a6bf52b2add Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Thu, 3 Apr 2025 17:44:48 +0100
Subject: [PATCH 114/120] Delete broken checks for GCC version that break
Subject: [PATCH 114/126] Delete broken checks for GCC version that break
-fstack-protector-strong
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
@ -201,5 +201,5 @@ index b6968c6..1d2106b 100644
ifdef DEBUG
COMMON_FLAGS += -O0 -ggdb -DDEBUG -UNDEBUG
--
2.49.0
2.51.1

View File

@ -1,7 +1,7 @@
From 8c70d52e120ff2f2e878975db2ac7253b28319cf Mon Sep 17 00:00:00 2001
From 40d434d75ff4978cd968b4d140af5aa8c8f602c2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Mon, 26 Feb 2024 12:19:51 +0000
Subject: [PATCH 115/120] Use distro provided rapidjson package
Subject: [PATCH 115/126] Use distro provided rapidjson package
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
@ -170,5 +170,5 @@ index c8e1d01..6f1440a 100644
# the library shared object name
LIB_NAME := libPCKCertSelection.a
--
2.49.0
2.51.1

View File

@ -1,7 +1,7 @@
From 9313ac72fda37a90096979cabae7d4294ef7ba42 Mon Sep 17 00:00:00 2001
From 605d9bcc0003c869e785376bbc3dbecc670c934d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Wed, 16 Apr 2025 11:48:52 +0100
Subject: [PATCH 116/120] Don't stomp on "VERBOSE" variable
Subject: [PATCH 116/126] Don't stomp on "VERBOSE" variable
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
@ -97,5 +97,5 @@ index 3d474bb..0f593f5 100644
- $(VERBOSE) rm -vrf $(TARGET) $(SIGNING_MATERIAL)
+ $(CMD_VERBOSE) rm -vrf $(TARGET) $(SIGNING_MATERIAL)
--
2.49.0
2.51.1

View File

@ -1,7 +1,7 @@
From 22171373ad5c818b5a57339ba607ff9876e34939 Mon Sep 17 00:00:00 2001
From d7299915f42cd068744ce02e358865085f2f12bf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Fri, 2 May 2025 14:48:24 +0100
Subject: [PATCH 117/120] qgs: add -m=MODE parameter for UNIX socket mode
Subject: [PATCH 117/126] qgs: add -m=MODE parameter for UNIX socket mode
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
@ -99,5 +99,5 @@ index 47f6c26..4628b18 100644
io_service.run();
QGS_LOG_INFO("Quit main loop\n");
--
2.49.0
2.51.1

View File

@ -1,174 +0,0 @@
From 2f42f8333820bb555778df38aaf27d02a5533ef6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Tue, 27 Feb 2024 15:46:41 +0000
Subject: [PATCH 118/120] Switch default PCCS port number from 8081 to 10801
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Port 8081 is a very poor choice of port number, since it is
both assigned to existing softrware in /etc/services, and
a fairly common "alternative" HTTP port that application
developers use for ad-hoc services.
Move it to 10801 which is not assigned in /etc/services and
thus unlikely to clash with other software.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
QuoteGeneration/pccs/config/default.json | 2 +-
QuoteGeneration/qcnl/inc/qcnl_config.h | 2 +-
QuoteGeneration/qcnl/linux/sgx_default_qcnl.conf | 4 ++--
QuoteGeneration/qcnl/linux/sgx_default_qcnl_dev.conf | 2 +-
tools/PCKRetrievalTool/App/App.cpp | 4 ++--
tools/PCKRetrievalTool/network_setting.conf | 4 ++--
tools/PccsAdminTool/pccsadmin.py | 12 ++++++------
7 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/QuoteGeneration/pccs/config/default.json b/QuoteGeneration/pccs/config/default.json
index 13e00e2..7be5c6e 100644
--- a/QuoteGeneration/pccs/config/default.json
+++ b/QuoteGeneration/pccs/config/default.json
@@ -1,5 +1,5 @@
{
- "HTTPS_PORT" : 8081,
+ "HTTPS_PORT" : 10801,
"hosts" : "127.0.0.1",
"uri": "https://api.trustedservices.intel.com/sgx/certification/v4/",
"ApiKey": "",
diff --git a/QuoteGeneration/qcnl/inc/qcnl_config.h b/QuoteGeneration/qcnl/inc/qcnl_config.h
index 71b9a99..b9f2262 100644
--- a/QuoteGeneration/qcnl/inc/qcnl_config.h
+++ b/QuoteGeneration/qcnl/inc/qcnl_config.h
@@ -82,7 +82,7 @@ protected:
// TCB update type, "early" or "standard"
string tcb_update_type_;
- QcnlConfig() : server_url_("https://localhost:8081/sgx/certification/v4/"),
+ QcnlConfig() : server_url_("https://localhost:10801/sgx/certification/v4/"),
use_secure_cert_(true),
collateral_service_url_(server_url_),
collateral_version_("3.0"),
diff --git a/QuoteGeneration/qcnl/linux/sgx_default_qcnl.conf b/QuoteGeneration/qcnl/linux/sgx_default_qcnl.conf
index 7df3995..af26a7e 100644
--- a/QuoteGeneration/qcnl/linux/sgx_default_qcnl.conf
+++ b/QuoteGeneration/qcnl/linux/sgx_default_qcnl.conf
@@ -2,7 +2,7 @@
// *** ATTENTION : This file is in JSON format so the keys are case sensitive. Don't change them.
//PCCS server address
- "pccs_url": "https://localhost:8081/sgx/certification/v4/"
+ "pccs_url": "https://localhost:10801/sgx/certification/v4/"
// To accept insecure HTTPS certificate, set this option to false
,"use_secure_cert": true
@@ -37,7 +37,7 @@
// If local_pck_url is defined, the QCNL will try to retrieve PCK cert chain from local_pck_url first,
// and failover to pccs_url as in legacy mode.
- //,"local_pck_url": "http://localhost:8081/sgx/certification/v4/"
+ //,"local_pck_url": "http://localhost:10801/sgx/certification/v4/"
// If local_pck_url is not defined, set pck_cache_expire_hours to a none-zero value will enable local cache.
// The PCK certificates will be cached in memory and then to the disk drive.
diff --git a/QuoteGeneration/qcnl/linux/sgx_default_qcnl_dev.conf b/QuoteGeneration/qcnl/linux/sgx_default_qcnl_dev.conf
index 08ee41c..f398b7d 100644
--- a/QuoteGeneration/qcnl/linux/sgx_default_qcnl_dev.conf
+++ b/QuoteGeneration/qcnl/linux/sgx_default_qcnl_dev.conf
@@ -8,7 +8,7 @@
// It is recommended to use "3.1" for DCAP 1.12 release and later
//PCCS server address
- "pccs_url": "https://localhost:8081/sgx/certification/v4/",
+ "pccs_url": "https://localhost:10801/sgx/certification/v4/",
// To accept insecure HTTPS certificate, set this option to false
"use_secure_cert": false,
diff --git a/tools/PCKRetrievalTool/App/App.cpp b/tools/PCKRetrievalTool/App/App.cpp
index a34710d..17196e2 100644
--- a/tools/PCKRetrievalTool/App/App.cpp
+++ b/tools/PCKRetrievalTool/App/App.cpp
@@ -67,7 +67,7 @@ uint32_t COMM_API sgx_tool_get_launch_token(
void PrintHelp() {
printf("Usage: %s [OPTION] \n", VER_PRODUCTNAME_STR);
- printf("Example: %s -f pck_retrieval_result.csv -url https://localhost:8081 -user_token 123456 -use_secure_cert true -platform_id\n", VER_PRODUCTNAME_STR);
+ printf("Example: %s -f pck_retrieval_result.csv -url https://localhost:10801 -user_token 123456 -use_secure_cert true -platform_id\n", VER_PRODUCTNAME_STR);
printf( "\nOptions:\n");
printf( " -f filename - output the retrieval result to the \"filename\"\n");
printf( " -url cache_server_address - cache server's address \n");
@@ -171,7 +171,7 @@ int parse_arg(int argc, const char *argv[])
}
}
else if (strncmp(argv[i], "-defaulturl", 11) == 0) {
- server_url_string = "https://localhost:8081";
+ server_url_string = "https://localhost:10801";
continue;
}
else if (strncmp(argv[i], "-proxy_type",11) == 0) {
diff --git a/tools/PCKRetrievalTool/network_setting.conf b/tools/PCKRetrievalTool/network_setting.conf
index 7aa5d71..3600191 100644
--- a/tools/PCKRetrievalTool/network_setting.conf
+++ b/tools/PCKRetrievalTool/network_setting.conf
@@ -1,9 +1,9 @@
# #############################################################
# PCCS server address
# support V3 version PCCS
-#PCCS_URL=https://localhost:8081/sgx/certification/v3/platforms
+#PCCS_URL=https://localhost:10801/sgx/certification/v3/platforms
# support V4 version PCCS
-#PCCS_URL=https://localhost:8081/sgx/certification/v4/platforms
+#PCCS_URL=https://localhost:10801/sgx/certification/v4/platforms
# To accept insecure HTTPS cert, set this option to FALSE
#USE_SECURE_CERT=TRUE
# When PCCS running in REQ mode, set "tcb update type": STANDARD, EARLY or ALL
diff --git a/tools/PccsAdminTool/pccsadmin.py b/tools/PccsAdminTool/pccsadmin.py
index 8e447c5..f286827 100755
--- a/tools/PccsAdminTool/pccsadmin.py
+++ b/tools/PccsAdminTool/pccsadmin.py
@@ -16,7 +16,7 @@ from urllib.parse import unquote
import traceback
PCS_SERVICE_URL = 'https://api.trustedservices.intel.com/sgx/certification/v4/'
-PCCS_SERVICE_URL = 'https://localhost:8081/sgx/certification/v4'
+PCCS_SERVICE_URL = 'https://localhost:10801/sgx/certification/v4'
def main():
parser = argparse.ArgumentParser(description="Administrator tool for PCCS")
@@ -26,7 +26,7 @@ def main():
# subparser for get
parser_get = subparsers.add_parser('get', formatter_class=argparse.RawTextHelpFormatter)
# add optional arguments for get
- parser_get.add_argument("-u", "--url", help="The URL of the PCCS's GET platforms API; default: https://localhost:8081/sgx/certification/v4/platforms")
+ parser_get.add_argument("-u", "--url", help="The URL of the PCCS's GET platforms API; default: https://localhost:10801/sgx/certification/v4/platforms")
parser_get.add_argument("-o", "--output_file", help="The output file name for platform list; default: platform_list.json")
parser_get.add_argument("-s", "--source", help=
"reg - Get platforms from registration table.(default)\n"
@@ -37,12 +37,12 @@ def main():
# subparser for put
description_put = (
"This put command supports the following formats([] means optional):\n"
- "1. pccsadmin put [-u https://localhost:8081/sgx/certification/v4/platformcollateral] [-i collateral_file(*.json)]\n"
- "2. pccsamdin put -u https://localhost:8081/sgx/certification/v4/appraisalpolicy [-d] -f fmspc -i policy_file(*.jwt)"
+ "1. pccsadmin put [-u https://localhost:10801/sgx/certification/v4/platformcollateral] [-i collateral_file(*.json)]\n"
+ "2. pccsamdin put -u https://localhost:10801/sgx/certification/v4/appraisalpolicy [-d] -f fmspc -i policy_file(*.jwt)"
)
parser_put = subparsers.add_parser('put', description=description_put, formatter_class=argparse.RawTextHelpFormatter)
# add optional arguments for put
- parser_put.add_argument("-u", "--url", help="The URL of the PCCS's API; default: https://localhost:8081/sgx/certification/v4/platformcollateral")
+ parser_put.add_argument("-u", "--url", help="The URL of the PCCS's API; default: https://localhost:10801/sgx/certification/v4/platformcollateral")
parser_put.add_argument("-i", "--input_file", help="The input file name for platform collaterals or appraisal policy;\
\nFor /platformcollateral API, default is platform_collaterals.json;\
\nFor /appraisalpolicy API, the filename of the jwt file must be provided explicitly.")
@@ -71,7 +71,7 @@ def main():
# subparser for refresh
parser_refresh = subparsers.add_parser('refresh')
# add optional arguments for refresh
- parser_refresh.add_argument("-u", "--url", help="The URL of the PCCS's refresh API; default: https://localhost:8081/sgx/certification/v4/refresh")
+ parser_refresh.add_argument("-u", "--url", help="The URL of the PCCS's refresh API; default: https://localhost:10801/sgx/certification/v4/refresh")
parser_refresh.add_argument("-f", "--fmspc", help="Only refresh certificates for specified FMSPCs. Format: [FMSPC1, FMSPC2, ..., FMSPCn]")
parser_refresh.set_defaults(func=pccs_refresh)
--
2.49.0

View File

@ -1,7 +1,7 @@
From 308e939ffc44c4720833aa518b0d19be1e01a186 Mon Sep 17 00:00:00 2001
From b108e8c9a0c9143e8fd930186c21d34d9cddaea7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Tue, 27 Feb 2024 13:38:49 +0000
Subject: [PATCH 119/120] Sanitize paths to all resources in PCCS server
Subject: [PATCH 118/126] pccs: sanitize paths to all resources
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
@ -104,5 +104,5 @@ index 6f910ee..6eb9d15 100644
const migration = migrations.find(migration => migration.name === name);
logger.debug(`Resolving migration: ${name}, found: ${migration ? migration.name : 'none'}`);
--
2.49.0
2.51.1

View File

@ -1,7 +1,7 @@
From 512591ff394d7b04925893480519ebc1d29aefc7 Mon Sep 17 00:00:00 2001
From 6c6e7427cf14455a56828db5c39f26ca8658a18d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Wed, 9 Jul 2025 16:41:59 +0100
Subject: [PATCH 120/120] pccs: only pass ApiKey if it is set
Subject: [PATCH 119/126] pccs: only pass ApiKey if it is set
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
@ -67,5 +67,5 @@ index 99ccea6..4f6c903 100644
}
--
2.49.0
2.51.1

View File

@ -0,0 +1,104 @@
From 2b540452538b12a47340b03d6118d3df281a6638 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Thu, 4 Dec 2025 13:31:54 +0000
Subject: [PATCH 120/126] pccsadmin: make 'keyring' module optional
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This is not available in some distros, and since it is merely a
convenience to avoid repeated password entry, it can be made
optional.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
.../PccsAdminTool/lib/intelsgx/credential.py | 53 +++++++++++--------
1 file changed, 30 insertions(+), 23 deletions(-)
diff --git a/tools/PccsAdminTool/lib/intelsgx/credential.py b/tools/PccsAdminTool/lib/intelsgx/credential.py
index 638cd88..cebecad 100644
--- a/tools/PccsAdminTool/lib/intelsgx/credential.py
+++ b/tools/PccsAdminTool/lib/intelsgx/credential.py
@@ -1,4 +1,7 @@
-import keyring
+try:
+ import keyring
+except:
+ keyring = None
import getpass
class Credentials:
@@ -8,11 +11,12 @@ class Credentials:
def get_admin_token(self):
admin_token = ""
- try:
- print("Please note: A prompt may appear asking for your keyring password to access stored credentials.")
- admin_token = keyring.get_password(self.APPNAME, self.KEY_ADMINTOKEN)
- except keyring.errors.KeyringError as ke:
- admin_token = ""
+ if keyring is not None:
+ try:
+ print("Please note: A prompt may appear asking for your keyring password to access stored credentials.")
+ admin_token = keyring.get_password(self.APPNAME, self.KEY_ADMINTOKEN)
+ except keyring.errors.KeyringError as ke:
+ admin_token = ""
while admin_token is None or admin_token == '':
admin_token = getpass.getpass(prompt="Please input your administrator password for PCCS service:")
@@ -25,21 +29,23 @@ class Credentials:
return admin_token
def set_admin_token(self, token):
- try:
- print("Please note: A prompt may appear asking for your keyring password to access stored credentials.")
- keyring.set_password(self.APPNAME, self.KEY_ADMINTOKEN, token)
- except keyring.errors.PasswordSetError as ke:
- print("Failed to store admin token.")
- return False
+ if keyring is not None:
+ try:
+ print("Please note: A prompt may appear asking for your keyring password to access stored credentials.")
+ keyring.set_password(self.APPNAME, self.KEY_ADMINTOKEN, token)
+ except keyring.errors.PasswordSetError as ke:
+ print("Failed to store admin token.")
+ return False
return True
def get_pcs_api_key(self):
pcs_api_key = ""
- try:
- print("Please note: A prompt may appear asking for your keyring password to access stored credentials.")
- pcs_api_key = keyring.get_password(self.APPNAME, self.KEY_PCS_APIKEY)
- except keyring.errors.KeyringError as ke:
- pcs_api_key = ""
+ if keyring is not None:
+ try:
+ print("Please note: A prompt may appear asking for your keyring password to access stored credentials.")
+ pcs_api_key = keyring.get_password(self.APPNAME, self.KEY_PCS_APIKEY)
+ except keyring.errors.KeyringError as ke:
+ pcs_api_key = ""
while pcs_api_key is None or pcs_api_key == '':
pcs_api_key = getpass.getpass(prompt="Please input ApiKey for Intel PCS:")
@@ -52,10 +58,11 @@ class Credentials:
return pcs_api_key
def set_pcs_api_key(self, apikey):
- try:
- print("Please note: A prompt may appear asking for your keyring password to access stored credentials.")
- keyring.set_password(self.APPNAME, self.KEY_PCS_APIKEY, apikey)
- except keyring.errors.PasswordSetError as ke:
- print("Failed to store PCS API key.")
- return False
+ if keyring is not None:
+ try:
+ print("Please note: A prompt may appear asking for your keyring password to access stored credentials.")
+ keyring.set_password(self.APPNAME, self.KEY_PCS_APIKEY, apikey)
+ except keyring.errors.PasswordSetError as ke:
+ print("Failed to store PCS API key.")
+ return False
return True
--
2.51.1

View File

@ -0,0 +1,341 @@
From b9954581944446455876728bdab816090d773715 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Thu, 4 Dec 2025 13:54:19 +0000
Subject: [PATCH 121/126] pccsadmin: convert from asn1 to pyasn1 python module
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The pyasn1 module decodes using a formal object model so is more robust,
as well as being more widely available in distros.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
tools/PccsAdminTool/lib/intelsgx/pckcert.py | 267 +++++++++++++-------
1 file changed, 177 insertions(+), 90 deletions(-)
diff --git a/tools/PccsAdminTool/lib/intelsgx/pckcert.py b/tools/PccsAdminTool/lib/intelsgx/pckcert.py
index 97aa278..eaed331 100644
--- a/tools/PccsAdminTool/lib/intelsgx/pckcert.py
+++ b/tools/PccsAdminTool/lib/intelsgx/pckcert.py
@@ -1,76 +1,171 @@
from cryptography import x509
from cryptography.x509.oid import ObjectIdentifier
from cryptography.hazmat.backends import default_backend
-import asn1
-import struct
+import pyasn1
+from pyasn1.codec.der.decoder import decode as der_decoder
+from pyasn1.type import namedtype
+from pyasn1.type import namedval
+from pyasn1.type import opentype
+from pyasn1.type import univ
+
+
+id_cdp_extensionStr = '2.5.29.31'
+id_ce_sGXExtensionsStr = '1.2.840.113741.1.13.1'
+
+id_ce_sGXExtensions = univ.ObjectIdentifier(id_ce_sGXExtensionsStr)
+
+id_ce_sGXExtensions_pPID = univ.ObjectIdentifier(id_ce_sGXExtensionsStr + ".1")
+id_ce_sGXExtensions_tCB = univ.ObjectIdentifier(id_ce_sGXExtensionsStr + ".2")
+id_ce_sGXExtensions_pCE_ID = univ.ObjectIdentifier(id_ce_sGXExtensionsStr + ".3")
+id_ce_sGXExtensions_fMSPC = univ.ObjectIdentifier(id_ce_sGXExtensionsStr + ".4")
+id_ce_sGXExtensions_sGXType = univ.ObjectIdentifier(id_ce_sGXExtensionsStr + ".5")
+id_ce_sGXExtensions_platformInstanceID = univ.ObjectIdentifier(id_ce_sGXExtensionsStr + ".6")
+id_ce_sGXExtensions_configuration = univ.ObjectIdentifier(id_ce_sGXExtensionsStr + ".7")
+
+id_ce_tCB_sGXTCBComp01SVN = univ.ObjectIdentifier(id_ce_sGXExtensionsStr + ".2.1")
+id_ce_tCB_sGXTCBComp02SVN = univ.ObjectIdentifier(id_ce_sGXExtensionsStr + ".2.2")
+id_ce_tCB_sGXTCBComp03SVN = univ.ObjectIdentifier(id_ce_sGXExtensionsStr + ".2.3")
+id_ce_tCB_sGXTCBComp04SVN = univ.ObjectIdentifier(id_ce_sGXExtensionsStr + ".2.4")
+id_ce_tCB_sGXTCBComp05SVN = univ.ObjectIdentifier(id_ce_sGXExtensionsStr + ".2.5")
+id_ce_tCB_sGXTCBComp06SVN = univ.ObjectIdentifier(id_ce_sGXExtensionsStr + ".2.6")
+id_ce_tCB_sGXTCBComp07SVN = univ.ObjectIdentifier(id_ce_sGXExtensionsStr + ".2.7")
+id_ce_tCB_sGXTCBComp08SVN = univ.ObjectIdentifier(id_ce_sGXExtensionsStr + ".2.8")
+id_ce_tCB_sGXTCBComp09SVN = univ.ObjectIdentifier(id_ce_sGXExtensionsStr + ".2.9")
+id_ce_tCB_sGXTCBComp10SVN = univ.ObjectIdentifier(id_ce_sGXExtensionsStr + ".2.10")
+id_ce_tCB_sGXTCBComp11SVN = univ.ObjectIdentifier(id_ce_sGXExtensionsStr + ".2.11")
+id_ce_tCB_sGXTCBComp12SVN = univ.ObjectIdentifier(id_ce_sGXExtensionsStr + ".2.12")
+id_ce_tCB_sGXTCBComp13SVN = univ.ObjectIdentifier(id_ce_sGXExtensionsStr + ".2.13")
+id_ce_tCB_sGXTCBComp14SVN = univ.ObjectIdentifier(id_ce_sGXExtensionsStr + ".2.14")
+id_ce_tCB_sGXTCBComp15SVN = univ.ObjectIdentifier(id_ce_sGXExtensionsStr + ".2.15")
+id_ce_tCB_sGXTCBComp16SVN = univ.ObjectIdentifier(id_ce_sGXExtensionsStr + ".2.16")
+id_ce_tCB_pCESVN = univ.ObjectIdentifier(id_ce_sGXExtensionsStr + ".2.17")
+id_ce_tCB_cPUSVN = univ.ObjectIdentifier(id_ce_sGXExtensionsStr + ".2.18")
+
+id_ce_configuration_dynamicPlatform = univ.ObjectIdentifier(id_ce_sGXExtensionsStr + ".7.1")
+id_ce_configuration_cachedKeys = univ.ObjectIdentifier(id_ce_sGXExtensionsStr + ".7.2")
+id_ce_configuration_sMTEnabled = univ.ObjectIdentifier(id_ce_sGXExtensionsStr + ".7.3")
+
+
+class SgxExtensionPPID(univ.OctetString):
+ pass
+
+
+class SgxCPUSVN(univ.OctetString):
+ pass
+
+
+tcbAttributeMap = {
+ id_ce_tCB_sGXTCBComp01SVN: univ.Integer(),
+ id_ce_tCB_sGXTCBComp02SVN: univ.Integer(),
+ id_ce_tCB_sGXTCBComp03SVN: univ.Integer(),
+ id_ce_tCB_sGXTCBComp04SVN: univ.Integer(),
+ id_ce_tCB_sGXTCBComp05SVN: univ.Integer(),
+ id_ce_tCB_sGXTCBComp06SVN: univ.Integer(),
+ id_ce_tCB_sGXTCBComp07SVN: univ.Integer(),
+ id_ce_tCB_sGXTCBComp08SVN: univ.Integer(),
+ id_ce_tCB_sGXTCBComp09SVN: univ.Integer(),
+ id_ce_tCB_sGXTCBComp10SVN: univ.Integer(),
+ id_ce_tCB_sGXTCBComp11SVN: univ.Integer(),
+ id_ce_tCB_sGXTCBComp12SVN: univ.Integer(),
+ id_ce_tCB_sGXTCBComp13SVN: univ.Integer(),
+ id_ce_tCB_sGXTCBComp14SVN: univ.Integer(),
+ id_ce_tCB_sGXTCBComp15SVN: univ.Integer(),
+ id_ce_tCB_sGXTCBComp16SVN: univ.Integer(),
+ id_ce_tCB_pCESVN: univ.Integer(),
+ id_ce_tCB_cPUSVN: SgxCPUSVN(),
+}
+
+
+class SgxExtensionTCBEntry(univ.Sequence):
+ componentType = namedtype.NamedTypes(
+ namedtype.NamedType('tCBId', univ.ObjectIdentifier()),
+ namedtype.NamedType('tCBValue', univ.Any(),
+ openType=opentype.OpenType('tCBId',
+ tcbAttributeMap))
+ )
+
+
+class SgxExtensionTCB(univ.SequenceOf):
+ componentType = SgxExtensionTCBEntry()
+
+
+class SgxExtensionPCEID(univ.OctetString):
+ pass
+
+
+class SgxExtensionFMSPC(univ.OctetString):
+ pass
+
+
+class SgxExtensionSGXType(univ.Enumerated):
+ namedValues = namedval.NamedValues(
+ ('standard', 0),
+ ('scalable', 1),
+ ('scalableWithIntegrity', 2)
+ )
+
+
+class SgxExtensionPlatformInstanceID(univ.OctetString):
+ pass
+
+
+configurationAttributeMap = {
+ id_ce_configuration_dynamicPlatform: univ.Boolean(),
+ id_ce_configuration_cachedKeys: univ.Boolean(),
+ id_ce_configuration_sMTEnabled: univ.Boolean(),
+}
+
+
+class SgxExtensionConfigurationEntry(univ.Sequence):
+ componentType = namedtype.NamedTypes(
+ namedtype.NamedType('configurationId', univ.ObjectIdentifier()),
+ namedtype.NamedType('configurationValue', univ.Any(),
+ openType=opentype.OpenType('configurationId',
+ configurationAttributeMap))
+ )
+
+
+class SgxExtensionConfiguration(univ.SequenceOf):
+ componentType = SgxExtensionConfigurationEntry()
+
+
+extensionAttributeMap = {
+ id_ce_sGXExtensions_pPID: SgxExtensionPPID(),
+ id_ce_sGXExtensions_tCB: SgxExtensionTCB(),
+ id_ce_sGXExtensions_pCE_ID: SgxExtensionPCEID(),
+ id_ce_sGXExtensions_fMSPC: SgxExtensionFMSPC(),
+ id_ce_sGXExtensions_sGXType: SgxExtensionSGXType(),
+ id_ce_sGXExtensions_platformInstanceID: SgxExtensionPlatformInstanceID(),
+ id_ce_sGXExtensions_configuration: SgxExtensionConfiguration(),
+}
+
+
+class SgxExtensionEntry(univ.Sequence):
+ componentType = namedtype.NamedTypes(
+ namedtype.NamedType('sGXExtensionId', univ.ObjectIdentifier()),
+ namedtype.NamedType('sGXExtensionValue', univ.Any(),
+ openType=opentype.OpenType('sGXExtensionId',
+ extensionAttributeMap))
+ )
+
+
+class SgxExtension(univ.SequenceOf):
+ componentType = SgxExtensionEntry()
-# This is a very simplistic ASN1 parser. Production code should use
-# something like ans1c to build a parser from the ASN1 spec file so
-# that it can check and enforce data validity.
class SgxPckCertificateExtensions:
- id_ce_sGXExtensions = '1.2.840.113741.1.13.1'
- id_ce_sGXExtensions_tCB= id_ce_sGXExtensions+".2"
- id_ce_sGXExtensions_configuration= id_ce_sGXExtensions+".7"
- id_cdp_extension = '2.5.29.31'
- decoder= asn1.Decoder()
- _data= {}
- ca= ''
- oids= {
- id_ce_sGXExtensions: 'sGXExtensions',
- id_ce_sGXExtensions+".1": 'pPID',
- id_ce_sGXExtensions_tCB: 'tCB',
- id_ce_sGXExtensions_tCB+".1": 'tCB-sGXTCBComp01SVN',
- id_ce_sGXExtensions_tCB+".2": 'tCB-sGXTCBComp02SVN',
- id_ce_sGXExtensions_tCB+".3": 'tCB-sGXTCBComp03SVN',
- id_ce_sGXExtensions_tCB+".4": 'tCB-sGXTCBComp04SVN',
- id_ce_sGXExtensions_tCB+".5": 'tCB-sGXTCBComp05SVN',
- id_ce_sGXExtensions_tCB+".6": 'tCB-sGXTCBComp06SVN',
- id_ce_sGXExtensions_tCB+".7": 'tCB-sGXTCBComp07SVN',
- id_ce_sGXExtensions_tCB+".8": 'tCB-sGXTCBComp08SVN',
- id_ce_sGXExtensions_tCB+".9": 'tCB-sGXTCBComp09SVN',
- id_ce_sGXExtensions_tCB+".10": 'tCB-sGXTCBComp10SVN',
- id_ce_sGXExtensions_tCB+".11": 'tCB-sGXTCBComp11SVN',
- id_ce_sGXExtensions_tCB+".12": 'tCB-sGXTCBComp12SVN',
- id_ce_sGXExtensions_tCB+".13": 'tCB-sGXTCBComp13SVN',
- id_ce_sGXExtensions_tCB+".14": 'tCB-sGXTCBComp14SVN',
- id_ce_sGXExtensions_tCB+".15": 'tCB-sGXTCBComp15SVN',
- id_ce_sGXExtensions_tCB+".16": 'tCB-sGXTCBComp16SVN',
- id_ce_sGXExtensions_tCB+".17": 'tCB-pCESVN',
- id_ce_sGXExtensions_tCB+".18": 'tCB-cPUSVN',
- id_ce_sGXExtensions+".3": 'pCE-ID',
- id_ce_sGXExtensions+".4": 'fMSPC',
- id_ce_sGXExtensions+".5": 'sGXType',
- id_ce_sGXExtensions+".6": 'platformInstanceID',
- id_ce_sGXExtensions_configuration: 'configuration',
- id_ce_sGXExtensions_configuration+".1": 'dynamicPlatform',
- id_ce_sGXExtensions_configuration+".2": 'cachedKeys',
- id_ce_sGXExtensions_configuration+".3": 'sMTEnabled'
- }
-
- def _parse_asn1(self, d, oid, lnr=asn1.Numbers.ObjectIdentifier):
- tag= self.decoder.peek()
- while tag:
- if tag.typ == asn1.Types.Constructed:
- self.decoder.enter()
- if ( lnr == asn1.Numbers.ObjectIdentifier ):
- d[self.oids[oid]]= {}
- self._parse_asn1(d[self.oids[oid]], oid, tag.nr)
- else:
- self._parse_asn1(d, oid, tag.nr)
- self.decoder.leave()
- elif tag.typ == asn1.Types.Primitive:
- tag, value= self.decoder.read()
- if ( tag.nr == asn1.Numbers.ObjectIdentifier ):
- oid= value
- else:
- d[self.oids[oid]]= value
- lnr= tag.nr
- tag= self.decoder.peek()
- return
+
+ def __init__(self):
+ self.ca= ''
+ self._data= None
+
+ def _parse_asn1(self, extensionData):
+ parsed, extra= der_decoder(extensionData,
+ asn1Spec=SgxExtension(),
+ decodeOpenTypes=True)
+ return parsed
def parse_pem_certificate(self, pem):
- self._data= {}
cert= x509.load_pem_x509_certificate(pem, default_backend())
issuerCN = cert.issuer.rfc4514_string()
if (issuerCN.find('Processor') != -1) :
@@ -81,63 +176,55 @@ class SgxPckCertificateExtensions:
self.ca = None
sgxext= cert.extensions.get_extension_for_oid(
- ObjectIdentifier(self.id_ce_sGXExtensions)
+ ObjectIdentifier(id_ce_sGXExtensionsStr)
)
- self.decoder.start(sgxext.value.value)
- self._parse_asn1(self._data, self.id_ce_sGXExtensions)
+ self._data= self._parse_asn1(sgxext.value.value)
def get_root_ca_crl(self, pem):
- self._data= {}
cert= x509.load_pem_x509_certificate(pem, default_backend())
cdpext= cert.extensions.get_extension_for_oid(
- ObjectIdentifier(self.id_cdp_extension)
+ ObjectIdentifier(id_cdp_extensionStr)
)
return getattr(getattr(cdpext.value[0], "_full_name")[0], "value")
- def data(self, field=None):
- if 'sGXExtensions' not in self._data:
- return None
-
- d= self._data['sGXExtensions']
-
- if field:
- if field in d:
- return d[field]
+ def data(self, field):
+ if self._data is None:
return None
- return d
+ ent = list(filter(lambda e: e['sGXExtensionId'] == field, self._data))[0]
+ return ent['sGXExtensionValue']
def _hex_data(self, field):
val= self.data(field)
if val is None:
return None
- return val.hex()
+ return bytes(val).hex()
# Commonly-needed data fields
#------------------------------
def get_fmspc(self):
- return self._hex_data('fMSPC')
+ return self._hex_data(id_ce_sGXExtensions_fMSPC)
def get_ca(self):
return self.ca
def get_tcbm(self):
- tcb= self.data('tCB')
+ tcb= self.data(id_ce_sGXExtensions_tCB)
if tcb is None:
return None
- return tcb['tCB-cPUSVN'].hex() + self.get_pcesvn()
+ ent= list(filter(lambda e: e['tCBId'] == id_ce_tCB_cPUSVN, tcb))[0]
+ return bytes(ent["tCBValue"]).hex() + self.get_pcesvn()
def get_pceid(self):
- return self._hex_data('pCE-ID')
+ return self._hex_data(id_ce_sGXExtensions_pCE_ID)
def get_ppid(self):
- return self._hex_data('pPID')
+ return self._hex_data(id_ce_sGXExtensions_pPID)
def get_pcesvn(self):
- tcb= self.data('tCB')
- # pCESVN should be packed little-endian
- pcesvn= struct.pack('<H', tcb['tCB-pCESVN'])
- return pcesvn.hex()
+ tcb= self.data(id_ce_sGXExtensions_tCB)
+ ent= list(filter(lambda e: e['tCBId'] == id_ce_tCB_pCESVN, tcb))[0]
+ return int(ent["tCBValue"]).to_bytes(2, byteorder='little').hex()
--
2.51.1

View File

@ -0,0 +1,67 @@
From d44b9ac3e89e17452678758634e6dbca6c5a099a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Mon, 8 Dec 2025 17:47:01 +0000
Subject: [PATCH 122/126] pccsadmin: fully switch to pycryptography for CRL
verification
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The pyopenssl 24.3.0 removed the CRL object and its related
methods. pccsadmin was already using the pycryptography CRL
object for the verification task, so fully switch to use it
for loading the CRL to begin with.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
tools/PccsAdminTool/lib/intelsgx/pcs.py | 13 ++++---------
1 file changed, 4 insertions(+), 9 deletions(-)
diff --git a/tools/PccsAdminTool/lib/intelsgx/pcs.py b/tools/PccsAdminTool/lib/intelsgx/pcs.py
index 046c781..e68864d 100644
--- a/tools/PccsAdminTool/lib/intelsgx/pcs.py
+++ b/tools/PccsAdminTool/lib/intelsgx/pcs.py
@@ -101,11 +101,6 @@ class PCS:
# Copy our list so we don't modify the original
pychain= pychain_in[:]
- # PyOpenSSL doesn't have methods for verifying a CRL issuer,
- # so we need to translate from it to cryptography.
-
- crl= pycrl.to_cryptography()
-
# The chain_pem is our CRL issuer and the CA for the issuer.
# Verify that first.
@@ -118,13 +113,13 @@ class PCS:
signer_key= pycert.get_pubkey().to_cryptography_key()
- if not crl.is_signature_valid(signer_key):
+ if not pycrl.is_signature_valid(signer_key):
self.error("Could not verify CRL signature")
return False
# Check the crl issuer
- if pycrl.get_issuer() != pycert.get_subject():
+ if pycrl.issuer != pycert.get_subject():
self.error("CRL issuer doesn't match issuer chain")
return False
@@ -516,10 +511,10 @@ class PCS:
crl= response.content
if self.ApiVersion<3:
crl_str= str(crl, dec)
- pycrl= crypto.load_crl(crypto.FILETYPE_PEM, crl)
+ pycrl= x509.load_pem_x509_crl(crl)
else:
crl_str= binascii.hexlify(crl).decode(dec)
- pycrl= crypto.load_crl(crypto.FILETYPE_ASN1, crl)
+ pycrl= x509.load_der_x509_crl(crl)
if not self.verify_crl_trust(pychain, pycrl):
self.error("Could not validate certificate using trust chain")
--
2.51.1

View File

@ -0,0 +1,178 @@
From d14f914ea644d7c1b2312780688d55fbb13892bc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Mon, 8 Dec 2025 17:48:11 +0000
Subject: [PATCH 123/126] pccsadmin: use more of pycryptography instead of
pyopenssl
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
pyopenssl docs are indicating that the 'crypto' module is liable to
see further deprecation, suggesting use of pycryptography instead.
pccsadmin code already uses pycryptography for CRLs, so extend this
to use it for loading certificates too. They are converted back to
pyopenssl objects for verification.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
tools/PccsAdminTool/lib/intelsgx/pcs.py | 49 ++++++++++++++-----------
1 file changed, 28 insertions(+), 21 deletions(-)
diff --git a/tools/PccsAdminTool/lib/intelsgx/pcs.py b/tools/PccsAdminTool/lib/intelsgx/pcs.py
index e68864d..f6b58a6 100644
--- a/tools/PccsAdminTool/lib/intelsgx/pcs.py
+++ b/tools/PccsAdminTool/lib/intelsgx/pcs.py
@@ -5,6 +5,10 @@ import json
import binascii
from urllib import parse
from OpenSSL import crypto
+from cryptography import x509
+from cryptography.exceptions import InvalidSignature
+from cryptography.hazmat.primitives import hashes
+from cryptography.hazmat.primitives.asymmetric import ec
from platform import system
if system() == 'Windows':
from pypac import PACSession
@@ -17,6 +21,9 @@ certBegin= '-----BEGIN CERTIFICATE-----'
certEnd= '-----END CERTIFICATE-----'
certEndOffset= len(certEnd)
+def CN(name):
+ return name.get_attributes_for_oid(x509.NameOID.COMON_NAME)[0].value
+
class PCS:
BaseUrl= ''
ApiVersion= 3
@@ -93,7 +100,7 @@ class PCS:
store= crypto.X509Store()
for tcert in pychain:
- store.add_cert(tcert)
+ store.add_cert(crypto.X509.from_cryptography(tcert))
return store
@@ -111,7 +118,7 @@ class PCS:
# Now verify the CRL signature
- signer_key= pycert.get_pubkey().to_cryptography_key()
+ signer_key= pycert.public_key()
if not pycrl.is_signature_valid(signer_key):
self.error("Could not verify CRL signature")
@@ -119,7 +126,7 @@ class PCS:
# Check the crl issuer
- if pycrl.issuer != pycert.get_subject():
+ if pycrl.issuer != pycert.subject:
self.error("CRL issuer doesn't match issuer chain")
return False
@@ -129,7 +136,8 @@ class PCS:
store= self.init_cert_store(pychain)
for pycert in pycerts:
- store_ctx= crypto.X509StoreContext(store, pycert)
+ store_ctx= crypto.X509StoreContext(
+ store, crypto.X509.from_cryptography(pycert))
try:
store_ctx.verify_certificate()
except crypto.X509StoreContextError as e:
@@ -161,22 +169,21 @@ class PCS:
sig= bytes([0x30,len(r)+len(s)+4,2,len(r)]) + r + bytes([2,len(s)]) + s
try:
- crypto.verify(pycert, sig, msg, "sha256")
- except crypto.Error as e:
+ pycert.public_key().verify(
+ sig, msg, ec.ECDSA(hashes.SHA256()))
+ except InvalidSignature as e:
self.error('Signature verification failed: {:s}'.format(str(e)))
return False
return True
def pem_to_pycert(self, cert_pem):
- return crypto.load_certificate(crypto.FILETYPE_PEM, cert_pem)
+ return x509.load_pem_x509_certificate(cert_pem.encode("utf-8"))
def pems_to_pycerts(self, certs_pem):
pycerts= []
for cert_pem in certs_pem:
- pycerts.append(
- crypto.load_certificate(crypto.FILETYPE_PEM, cert_pem)
- )
+ pycerts.append(self.pem_to_pycert(cert_pem))
return pycerts
def parse_chain_pem(self, chain_pem):
@@ -209,9 +216,9 @@ class PCS:
cert0= chain_in[0]
cert1= chain_in[1]
- if cert0.get_subject() == cert1.get_issuer():
+ if cert0.subject == cert1.issuer:
return chain_in
- elif cert1.get_subject() == cert0.get_issuer():
+ elif cert1.subject == cert0.issuer:
chain_in.reverse()
return chain_in
else:
@@ -224,7 +231,7 @@ class PCS:
for i in range(1, len(chain_in)):
cert= chain_in[i]
pcert= chain_in[i-1]
- if cert.get_issuer() != pcert.get_subject():
+ if cert.issuer != pcert.subject:
sorted= False
break
@@ -240,10 +247,10 @@ class PCS:
rootidx= -1
for i in range(0, len(chain)):
cert= chain[i]
- subject= cert.get_subject()
- issuer= cert.get_issuer()
- cert_subjects[subject.CN]= cert
- print("cert: {:s} <- {:s}" . format(subject.CN, issuer.CN))
+ subject= cert.subject
+ issuer= cert.issuer
+ cert_subjects[CN(subject)]= cert
+ print("cert: {:s} <- {:s}" . format(CN(subject), CN(issuer)))
if subject == issuer:
if len(sorted_chain) > 0:
@@ -262,8 +269,8 @@ class PCS:
issuer_to= {}
for cert in chain:
- issuer= cert.get_issuer().CN
- subject= cert.get_subject().CN
+ issuer= CN(cert.issuer)
+ subject= CN(cert.subject)
if issuer in issued_by:
self.error('multiple certs issued by same cert in chain')
@@ -280,7 +287,7 @@ class PCS:
if len(sorted_chain) > 0:
for cert in chain:
- issuer= cert.get_issuer().CN
+ issuer= CN(cert.issuer)
if issuer not in issued_by:
if len(sorted_chain) > 0:
self.error('multiple certs with no issuer')
@@ -296,7 +303,7 @@ class PCS:
cert= sorted_chain[0]
while len(sorted_chain) < lchain:
- issuer_subject= cert.get_subject().der()
+ issuer_subject= CN(cert.subject)
if issuer_subject not in issuer_to:
self.error('cert in chain with no issuer')
--
2.51.1

View File

@ -0,0 +1,104 @@
From 9d3da2fd99ba2832fcaa4067dd5db3f7f349c306 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Wed, 3 Dec 2025 17:59:09 +0000
Subject: [PATCH 124/126] pccsadmin: prefer pycryptography over pyopenssl
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The only part of pccsadmin that still needs pyopenssl is certificate
verification. As of pycryptography 45.0.0, there are sufficient APIs
available to replace the remaining usage of pyopenssl.
Since new pycryptography is still not widely available in distros,
keep pyopenssl code as a fallback.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
tools/PccsAdminTool/lib/intelsgx/pcs.py | 60 +++++++++++++++++++------
1 file changed, 47 insertions(+), 13 deletions(-)
diff --git a/tools/PccsAdminTool/lib/intelsgx/pcs.py b/tools/PccsAdminTool/lib/intelsgx/pcs.py
index f6b58a6..eeb2969 100644
--- a/tools/PccsAdminTool/lib/intelsgx/pcs.py
+++ b/tools/PccsAdminTool/lib/intelsgx/pcs.py
@@ -4,11 +4,28 @@ import requests
import json
import binascii
from urllib import parse
-from OpenSSL import crypto
+
from cryptography import x509
from cryptography.exceptions import InvalidSignature
-from cryptography.hazmat.primitives import hashes
+from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import ec
+
+# Prefer pycryptography for cert verification if new
+# enough, but fallback to pyopenssl
+try:
+ # 'verification' module available from >= 42.0.0, but
+ # the required 'ExtensionPolicy' API is from >= 45.0.0
+ from cryptography.x509 import verification
+ if not hasattr(verification, 'ExtensionPolicy'):
+ verification = None
+ else:
+ crypto = None
+except ImportError:
+ verification = None
+
+if verification is None:
+ from OpenSSL import crypto
+
from platform import system
if system() == 'Windows':
from pypac import PACSession
@@ -133,17 +150,34 @@ class PCS:
return True
def verify_cert_trust(self, pychain, pycerts):
- store= self.init_cert_store(pychain)
-
- for pycert in pycerts:
- store_ctx= crypto.X509StoreContext(
- store, crypto.X509.from_cryptography(pycert))
- try:
- store_ctx.verify_certificate()
- except crypto.X509StoreContextError as e:
- # Printing or logging the error details
- print(e)
- return False
+ if verification is not None:
+ store= verification.Store(pychain)
+
+ builder= verification.PolicyBuilder().store(store)
+ builder= builder.extension_policies(
+ ee_policy=verification.ExtensionPolicy.permit_all(),
+ ca_policy=verification.ExtensionPolicy.webpki_defaults_ca())
+
+ verifier= builder.build_client_verifier()
+ for pycert in pycerts:
+ try:
+ verifier.verify(pycert,[])
+ except verification.VerificationError as e:
+ # Printing or logging the error details
+ print(e)
+ return False
+ else:
+ store= self.init_cert_store(pychain)
+
+ for pycert in pycerts:
+ store_ctx= crypto.X509StoreContext(
+ store, crypto.X509.from_cryptography(pycert))
+ try:
+ store_ctx.verify_certificate()
+ except crypto.X509StoreContextError as e:
+ # Printing or logging the error details
+ print(e)
+ return False
return True
--
2.51.1

View File

@ -0,0 +1,75 @@
From 262c1cb978d31130d3558d2a29690b1eace52c64 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Mon, 8 Dec 2025 17:56:59 +0000
Subject: [PATCH 125/126] pccsadmin: add fallback for when pyopenssl is not
available
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RHEL does not ship pyopenssl, however, the pycryptography that is
included is also too old to support certificate verification. Add
a further fallback that can invoke the 'openssl' command line tool
to verify certificates.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
tools/PccsAdminTool/lib/intelsgx/pcs.py | 28 +++++++++++++++++++++++--
1 file changed, 26 insertions(+), 2 deletions(-)
diff --git a/tools/PccsAdminTool/lib/intelsgx/pcs.py b/tools/PccsAdminTool/lib/intelsgx/pcs.py
index eeb2969..1368b57 100644
--- a/tools/PccsAdminTool/lib/intelsgx/pcs.py
+++ b/tools/PccsAdminTool/lib/intelsgx/pcs.py
@@ -24,7 +24,14 @@ except ImportError:
verification = None
if verification is None:
- from OpenSSL import crypto
+ try:
+ from OpenSSL import crypto
+ except ModuleNotFoundError:
+ # Fallback to spawning 'openssl' binary if
+ # pyopenssl is not available
+ crypto = None
+ import tempfile
+ import subprocess
from platform import system
if system() == 'Windows':
@@ -166,7 +173,7 @@ class PCS:
# Printing or logging the error details
print(e)
return False
- else:
+ elif crypto is not None:
store= self.init_cert_store(pychain)
for pycert in pycerts:
@@ -178,6 +185,23 @@ class PCS:
# Printing or logging the error details
print(e)
return False
+ else:
+ with tempfile.NamedTemporaryFile("wb") as chainfile:
+ for cert in pychain:
+ chainfile.write(cert.public_bytes(serialization.Encoding.PEM))
+ chainfile.flush()
+
+ for cert in pycerts:
+ with tempfile.NamedTemporaryFile("wb") as certfile:
+ certfile.write(cert.public_bytes(serialization.Encoding.PEM))
+ certfile.flush()
+
+ try:
+ subprocess.check_call(["openssl", "verify",
+ "-CAfile", chainfile.name, certfile.name],
+ stdout=subprocess.DEVNULL)
+ except subprocess.CalledProcessError as e:
+ return False
return True
--
2.51.1

View File

@ -0,0 +1,55 @@
From 8081c78698b7a1e5ec183eca3318f98396680545 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Thu, 4 Dec 2025 18:05:14 +0000
Subject: [PATCH 126/126] pccsadmin: ignore errors trying to clear the keyring
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
On authentication errors with PCS, an attempt is made to clear the
keyring. This may fail if the user's login environment has no keyring
configured. The user would have declined to store the key when first
prompted, so there would be nothing to clear either in this case.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
tools/PccsAdminTool/lib/intelsgx/pcs.py | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/tools/PccsAdminTool/lib/intelsgx/pcs.py b/tools/PccsAdminTool/lib/intelsgx/pcs.py
index 1368b57..dd4eba4 100644
--- a/tools/PccsAdminTool/lib/intelsgx/pcs.py
+++ b/tools/PccsAdminTool/lib/intelsgx/pcs.py
@@ -404,7 +404,13 @@ class PCS:
if response.status_code != 200:
print(str(response.content, 'utf-8'))
if response.status_code == 401:
- Credentials().set_pcs_api_key('') #reset ApiKey
+ try:
+ Credentials().set_pcs_api_key('') #reset ApiKey
+ except:
+ # If keyring is unavailable, we don't want to trigger
+ # traceback, as the user may have declined to save
+ # the key in the keyring earlier
+ pass
return None
# Verify expected headers
@@ -479,7 +485,13 @@ class PCS:
if response.status_code != 200:
print(str(response.content, 'utf-8'))
if response.status_code == 401:
- Credentials().set_pcs_api_key('') #reset ApiKey
+ try:
+ Credentials().set_pcs_api_key('') #reset ApiKey
+ except:
+ # If keyring is unavailable, we don't want to trigger
+ # traceback, as the user may have declined to save
+ # the key in the keyring earlier
+ pass
return None
# Verify expected headers
--
2.51.1

View File

@ -350,7 +350,7 @@ Patch0102: 0102-Support-build-time-setting-of-enclave-load-directory.patch
# https://github.com/intel/SGXDataCenterAttestationPrimitives/pull/434
Patch0103: 0103-Look-for-versioned-sgx_urts-library-in-PCKRetrievalT.patch
# https://github.com/intel/SGXDataCenterAttestationPrimitives/pull/429
Patch0104: 0104-Don-t-import-pypac-in-pccsadmin.patch
Patch0104: 0104-pccsadmin-only-import-pypac-module-on-Windows.patch
Patch0105: 0105-Look-for-PCKRetrievalTool-config-file-in-etc.patch
Patch0106: 0106-Honour-CFLAGS-CXXFLAGS-LDFLAGS-for-various-tools-and.patch
# https://github.com/intel/SGXDataCenterAttestationPrimitives/pull/428
@ -365,9 +365,15 @@ Patch0114: 0114-Delete-broken-checks-for-GCC-version-that-break-fsta.patch
#Patch0115: 0115-Use-distro-provided-rapidjson-package.patch
Patch0116: 0116-Don-t-stomp-on-VERBOSE-variable.patch
Patch0117: 0117-qgs-add-m-MODE-parameter-for-UNIX-socket-mode.patch
Patch0118: 0118-Switch-default-PCCS-port-number-from-8081-to-10801.patch
Patch0119: 0119-Sanitize-paths-to-all-resources-in-PCCS-server.patch
Patch0120: 0120-pccs-only-pass-ApiKey-if-it-is-set.patch
Patch0118: 0118-pccs-sanitize-paths-to-all-resources.patch
Patch0119: 0119-pccs-only-pass-ApiKey-if-it-is-set.patch
Patch0120: 0120-pccsadmin-make-keyring-module-optional.patch
Patch0121: 0121-pccsadmin-convert-from-asn1-to-pyasn1-python-module.patch
Patch0122: 0122-pccsadmin-fully-switch-to-pycryptography-for-CRL-ver.patch
Patch0123: 0123-pccsadmin-use-more-of-pycryptography-instead-of-pyop.patch
Patch0124: 0124-pccsadmin-prefer-pycryptography-over-pyopenssl.patch
Patch0125: 0125-pccsadmin-add-fallback-for-when-pyopenssl-is-not-ava.patch
Patch0126: 0126-pccsadmin-ignore-errors-trying-to-clear-the-keyring.patch
# 0200-0299 -> against intel-sgx-ssl.git
Patch0200: 0200-Enable-pointing-sgxssl-build-to-alternative-glibc-he.patch
@ -528,12 +534,17 @@ SGX Provisioning Certificate Caching Service
%package -n sgx-pccs-admin
Summary: SGX Provisioning Certificate Caching Service Admin Tool
Requires: python3-asn1
Requires: python3-pyOpenSSL
Requires: python3-pyasn1
Requires: python3-cryptography
%if 0%{?fedora}
Requires: python3-keyring
%endif
Requires: python3-requests
Requires: python3-urllib3
Requires: python3-setuptools
%if 0%{?rhel}
Requires: openssl
%endif
Requires: sgx-libs = %{version}-%{release}
# pccs admin tool can be used against a remote pccs
# so don't force a hard dep