1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
|
From: Scott Cantor <scantor@apache.org>
Date: Wed, 1 Aug 2018 13:02:21 +0000
Subject: Default KeyInfo resolver doesn't check for empty element content
The Apache Santuario XML Security for C++ library contained a
number of code paths at risk of dereferencing null pointers when
processing various kinds of malformed KeyInfo hints typically found
in signed or encrypted XML. The usual effect is a crash, and in the
case of the Shibboleth SP software, a crash in the shibd daemon.
This is a combination of two upstream commits with some unrelated
whitespace changes removed. Quite much of it is still indentation
change because of the added conditionals. Best viewed with tabstop=4,
for example with 'LESS=Rx4 git show --ignore-space-changes'.
Thanks: Scott Cantor
Upstream bug:
https://issues.apache.org/jira/projects/SANTUARIO/issues/SANTUARIO-491
CVE: not assigned yet
Closes: #905332
---
xsec/dsig/DSIGKeyInfoValue.hpp | 8 +--
xsec/enc/XSECKeyInfoResolverDefault.cpp | 108 +++++++++++++++++++-------------
2 files changed, 69 insertions(+), 47 deletions(-)
diff --git a/xsec/dsig/DSIGKeyInfoValue.hpp b/xsec/dsig/DSIGKeyInfoValue.hpp
index f652679..d6da5d5 100644
--- a/xsec/dsig/DSIGKeyInfoValue.hpp
+++ b/xsec/dsig/DSIGKeyInfoValue.hpp
@@ -117,7 +117,7 @@ public:
* @returns a pointer to the DSA P string value.
*/
- const XMLCh * getDSAP(void) const {return mp_PTextNode->getNodeValue();}
+ const XMLCh * getDSAP() const {return mp_PTextNode ? mp_PTextNode->getNodeValue() : NULL;}
/**
* \brief Get Q value
@@ -125,7 +125,7 @@ public:
* @returns a pointer to the DSA Q string value.
*/
- const XMLCh * getDSAQ(void) const {return mp_QTextNode->getNodeValue();}
+ const XMLCh * getDSAQ() const {return mp_QTextNode ? mp_QTextNode->getNodeValue() : NULL;}
/**
* \brief Get G value
@@ -133,7 +133,7 @@ public:
* @returns a pointer to the DSA G string value.
*/
- const XMLCh * getDSAG(void) const {return mp_GTextNode->getNodeValue();}
+ const XMLCh * getDSAG() const {return mp_GTextNode ? mp_GTextNode->getNodeValue() : NULL;}
/**
* \brief Get Y value
@@ -141,7 +141,7 @@ public:
* @returns a pointer to the DSA Y string value.
*/
- const XMLCh * getDSAY(void) const {return mp_YTextNode->getNodeValue();}
+ const XMLCh * getDSAY() const {return mp_YTextNode ? mp_YTextNode->getNodeValue() : NULL;}
/**
* \brief Get Modulus
diff --git a/xsec/enc/XSECKeyInfoResolverDefault.cpp b/xsec/enc/XSECKeyInfoResolverDefault.cpp
index 52cdfe3..c4c81cb 100644
--- a/xsec/enc/XSECKeyInfoResolverDefault.cpp
+++ b/xsec/enc/XSECKeyInfoResolverDefault.cpp
@@ -79,13 +79,11 @@ XSECCryptoKey * XSECKeyInfoResolverDefault::resolveKey(DSIGKeyInfoList * lst) {
case (DSIGKeyInfo::KEYINFO_X509) :
{
ret = NULL;
- const XMLCh * x509Str;
- XSECCryptoX509 * x509 = XSECPlatformUtils::g_cryptoProvider->X509();
- Janitor<XSECCryptoX509> j_x509(x509);
-
- x509Str = ((DSIGKeyInfoX509 *) lst->item(i))->getCertificateItem(0);
+ const XMLCh* x509Str = ((const DSIGKeyInfoX509 *) lst->item(i))->getCertificateItem(0);
- if (x509Str != 0) {
+ if (x509Str) {
+ XSECCryptoX509 * x509 = XSECPlatformUtils::g_cryptoProvider->X509();
+ Janitor<XSECCryptoX509> j_x509(x509);
// The crypto interface classes work UTF-8
safeBuffer transX509;
@@ -104,66 +102,90 @@ XSECCryptoKey * XSECKeyInfoResolverDefault::resolveKey(DSIGKeyInfoList * lst) {
case (DSIGKeyInfo::KEYINFO_VALUE_DSA) :
{
- XSECCryptoKeyDSA * dsa = XSECPlatformUtils::g_cryptoProvider->keyDSA();
- Janitor<XSECCryptoKeyDSA> j_dsa(dsa);
-
- safeBuffer value;
-
- value << (*mp_formatter << ((DSIGKeyInfoValue *) lst->item(i))->getDSAP());
- dsa->loadPBase64BigNums(value.rawCharBuffer(), (unsigned int) strlen(value.rawCharBuffer()));
- value << (*mp_formatter << ((DSIGKeyInfoValue *) lst->item(i))->getDSAQ());
- dsa->loadQBase64BigNums(value.rawCharBuffer(), (unsigned int) strlen(value.rawCharBuffer()));
- value << (*mp_formatter << ((DSIGKeyInfoValue *) lst->item(i))->getDSAG());
- dsa->loadGBase64BigNums(value.rawCharBuffer(), (unsigned int) strlen(value.rawCharBuffer()));
- value << (*mp_formatter << ((DSIGKeyInfoValue *) lst->item(i))->getDSAY());
- dsa->loadYBase64BigNums(value.rawCharBuffer(), (unsigned int) strlen(value.rawCharBuffer()));
-
- j_dsa.release();
- return dsa;
+ const DSIGKeyInfoValue* dsaval = (const DSIGKeyInfoValue *) lst->item(i);
+ if (dsaval->getDSAP() || dsaval->getDSAQ() || dsaval->getDSAG() || dsaval->getDSAY()) {
+
+ XSECCryptoKeyDSA * dsa = XSECPlatformUtils::g_cryptoProvider->keyDSA();
+ Janitor<XSECCryptoKeyDSA> j_dsa(dsa);
+
+ safeBuffer value;
+
+ if (dsaval->getDSAP()) {
+ value << (*mp_formatter << dsaval->getDSAP());
+ dsa->loadPBase64BigNums(value.rawCharBuffer(), (unsigned int) strlen(value.rawCharBuffer()));
+ }
+ if (dsaval->getDSAQ()) {
+ value << (*mp_formatter << dsaval->getDSAQ());
+ dsa->loadQBase64BigNums(value.rawCharBuffer(), (unsigned int) strlen(value.rawCharBuffer()));
+ }
+ if (dsaval->getDSAG()) {
+ value << (*mp_formatter << dsaval->getDSAG());
+ dsa->loadGBase64BigNums(value.rawCharBuffer(), (unsigned int) strlen(value.rawCharBuffer()));
+ }
+ if (dsaval->getDSAY()) {
+ value << (*mp_formatter << dsaval->getDSAY());
+ dsa->loadYBase64BigNums(value.rawCharBuffer(), (unsigned int) strlen(value.rawCharBuffer()));
+ }
+
+ j_dsa.release();
+ return dsa;
+ }
}
break;
case (DSIGKeyInfo::KEYINFO_VALUE_RSA) :
{
+ const DSIGKeyInfoValue* rsaval = (const DSIGKeyInfoValue *) lst->item(i);
+ if (rsaval->getRSAModulus() && rsaval->getRSAExponent()) {
- XSECCryptoKeyRSA * rsa = XSECPlatformUtils::g_cryptoProvider->keyRSA();
- Janitor<XSECCryptoKeyRSA> j_rsa(rsa);
+ XSECCryptoKeyRSA* rsa = XSECPlatformUtils::g_cryptoProvider->keyRSA();
+ Janitor<XSECCryptoKeyRSA> j_rsa(rsa);
- safeBuffer value;
+ safeBuffer value;
- value << (*mp_formatter << ((DSIGKeyInfoValue *) lst->item(i))->getRSAModulus());
- rsa->loadPublicModulusBase64BigNums(value.rawCharBuffer(), (unsigned int) strlen(value.rawCharBuffer()));
- value << (*mp_formatter << ((DSIGKeyInfoValue *) lst->item(i))->getRSAExponent());
- rsa->loadPublicExponentBase64BigNums(value.rawCharBuffer(), (unsigned int) strlen(value.rawCharBuffer()));
+ value << (*mp_formatter << rsaval->getRSAModulus());
+ rsa->loadPublicModulusBase64BigNums(value.rawCharBuffer(), (unsigned int) strlen(value.rawCharBuffer()));
+ value << (*mp_formatter << rsaval->getRSAExponent());
+ rsa->loadPublicExponentBase64BigNums(value.rawCharBuffer(), (unsigned int) strlen(value.rawCharBuffer()));
- j_rsa.release();
- return rsa;
+ j_rsa.release();
+ return rsa;
+ }
}
break;
case (DSIGKeyInfo::KEYINFO_VALUE_EC) :
{
+ const DSIGKeyInfoValue* ecval = (const DSIGKeyInfoValue *) lst->item(i);
+ if (ecval->getECPublicKey() && ecval->getECNamedCurve()) {
- XSECCryptoKeyEC* ec = XSECPlatformUtils::g_cryptoProvider->keyEC();
- Janitor<XSECCryptoKeyEC> j_ec(ec);
+ XSECCryptoKeyEC* ec = XSECPlatformUtils::g_cryptoProvider->keyEC();
+ Janitor<XSECCryptoKeyEC> j_ec(ec);
- safeBuffer value;
- value << (*mp_formatter << ((DSIGKeyInfoValue *) lst->item(i))->getECPublicKey());
- XSECAutoPtrChar curve(((DSIGKeyInfoValue *) lst->item(i))->getECNamedCurve());
- if (curve.get()) {
- ec->loadPublicKeyBase64(curve.get(), value.rawCharBuffer(), (unsigned int) strlen(value.rawCharBuffer()));
- j_ec.release();
- return ec;
+ safeBuffer value;
+
+ value << (*mp_formatter << ecval->getECPublicKey());
+ XSECAutoPtrChar curve(ecval->getECNamedCurve());
+ if (curve.get()) {
+ ec->loadPublicKeyBase64(curve.get(), value.rawCharBuffer(), (unsigned int) strlen(value.rawCharBuffer()));
+ j_ec.release();
+ return ec;
+ }
}
}
break;
case (DSIGKeyInfo::KEYINFO_DERENCODED) :
{
- safeBuffer value;
- value << (*mp_formatter << ((DSIGKeyInfoDEREncoded *) lst->item(i))->getData());
- return XSECPlatformUtils::g_cryptoProvider->keyDER(value.rawCharBuffer(), (unsigned int)strlen(value.rawCharBuffer()), true);
+ const DSIGKeyInfoDEREncoded* derval = (const DSIGKeyInfoDEREncoded *) lst->item(i);
+ if (derval->getData()) {
+
+ safeBuffer value;
+
+ value << (*mp_formatter << derval->getData());
+ return XSECPlatformUtils::g_cryptoProvider->keyDER(value.rawCharBuffer(), (unsigned int)strlen(value.rawCharBuffer()), true);
+ }
}
break;
|