Sync patches from Fedora 43, to fix multiple pccs npm security flaws, and fix typo in pccsadmin help text. CVE-2026-23745, CVE-2026-23950, CVE-2026-24842, CVE-2025-13465, CVE-2025-15284 Resolves: RHEL-145005, RHEL-144190, RHEL-142482, RHEL-138075, RHEL-140108 Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
342 lines
12 KiB
Diff
342 lines
12 KiB
Diff
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/136] 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 97aa2783..eaed331b 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.52.0
|
|
|