lsh123 / xmlsec

XML Security Library
Other
133 stars 100 forks source link

Unable to decrypt XML with multiple recipients #319

Closed kevinmoll-lightdeck closed 3 years ago

kevinmoll-lightdeck commented 3 years ago

The xmlsec library (and command line tool) allows an xml file to be encrypted with multiple recipients. However, the decryption mechanisms only allow the resulting files to be decrypted with the first recipient.

Steps to reproduce problem:

1) Create 2 private/public key pairs openssl genrsa -out private1.pem 2048 openssl rsa -in private1.pem -outform PEM -pubout -out public1.pem openssl genrsa -out private2.pem 2048 openssl rsa -in private2.pem -outform PEM -pubout -out public2.pem

2) Encrypt an xml file with a separate template file (inputTestFiles.zip) xmlsec1 encrypt --pubkey-pem:pub1 public1.pem --pubkey-pem:pub2 public2.pem --session-key des-192 --xml-data note.xml session-key-template.xml > encrypted.xml

3) Decrypt the file with the private key associated with public1.pem succeeds: xmlsec1 decrypt --privkey-pem private1.pem encrypted.xml

4) Decrypting the file with the private key associated with public2.pem fails: xmlsec1 decrypt --privkey-pem private2.pem encrypted.xml with the following error messages: func=xmlSecOpenSSLRsaPkcs1Process:file=kt_rsa.c:line=309:obj=rsa-1_5:subj=RSA_private_decrypt:error=4:crypto library function failed:size=256; openssl error: 67571871: rsa routines: RSA_padding_check_PKCS1_type_2 pkcs decoding error func=xmlSecOpenSSLRsaPkcs1Execute:file=kt_rsa.c:line=225:obj=rsa-1_5:subj=xmlSecOpenSSLRsaPkcs1Process:error=1:xmlsec library function failed: func=xmlSecTransformDefaultPushBin:file=transforms.c:line=1921:obj=rsa-1_5:subj=xmlSecTransformExecute:error=1:xmlsec library function failed:final=1 func=xmlSecTransformDefaultPushBin:file=transforms.c:line=1946:obj=rsa-1_5:subj=xmlSecTransformPushBin:error=1:xmlsec library function failed:final=1;outSize=256 func=xmlSecTransformCtxBinaryExecute:file=transforms.c:line=934:obj=unknown:subj=xmlSecTransformCtxPushBin:error=1:xmlsec library function failed:dataSize=349 func=xmlSecEncCtxDecryptToBuffer:file=xmlenc.c:line=610:obj=unknown:subj=xmlSecTransformCtxBinaryExecute:error=1:xmlsec library function failed: func=xmlSecKeyDataEncryptedKeyXmlRead:file=keyinfo.c:line=1304:obj=enc-key:subj=unknown:error=61:maximum encrypted key level:cur=1;max=1 func=xmlSecKeyInfoNodeRead:file=keyinfo.c:line=117:obj=enc-key:subj=xmlSecKeyDataXmlRead:error=1:xmlsec library function failed:node=EncryptedKey func=xmlSecKeysMngrGetKey:file=keys.c:line=1230:obj=unknown:subj=xmlSecKeyInfoNodeRead:error=1:xmlsec library function failed:node=KeyInfo func=xmlSecEncCtxEncDataNodeRead:file=xmlenc.c:line=777:obj=unknown:subj=unknown:error=45:key is not found:encMethod=tripledes-cbc func=xmlSecEncCtxDecryptToBuffer:file=xmlenc.c:line=592:obj=unknown:subj=xmlSecEncCtxEncDataNodeRead:error=1:xmlsec library function failed: func=xmlSecEncCtxDecrypt:file=xmlenc.c:line=520:obj=unknown:subj=xmlSecEncCtxDecryptToBuffer:error=1:xmlsec library function failed: Error: failed to decrypt file Error: failed to decrypt file "encrypted.xml"

5) If the encrypted file (encrypted.xml) is edited to remove the first <EncryptedKey> element from (the outer) <KeyInfo> element, decryption succeeds indicating that the encryption routine is successfully encrypting the session key for each of the associated public keys.

kevinmoll-lightdeck commented 3 years ago

Proposed fix: In the error output, the offending line appears to be: library function failed: func=xmlSecKeyDataEncryptedKeyXmlRead:file=keyinfo.c:line=1304:obj=enc-key:subj=unknown:error=61:maximum encrypted key level:cur=1;max=1

The encrypted key depth should not have hit the maximum as there aren't nested keys here.

In keyinfo.c (xmlSecKeyDataEncryptedKeyXmlRead), the current encryption depth is increased on entry ++keyInfoCtx->curEncryptedKeyLevel; and decremented on exit: --keyInfoCtx->curEncryptedKeyLevel;

However, on intermediate return statements when handling an error, keyInfoCtx->curEncryptedKeyLevel is not restored. Inserting --keyInfoCtx->curEncryptedKeyLevel before each return statement appears to resolve the problem allowing the encrypted document to be decrypted using the second recipient's private key w/o hand editing the document to remove the EncryptedKey element for the first recipient.

lsh123 commented 3 years ago

Good catch and thanks for a detailed repro steps! Very easy to follow and fix:

https://github.com/lsh123/xmlsec/pull/320