|
Mixe for Privacy and Anonymity in the Internet
|
00001 /* 00002 Copyright (c) 2000, The JAP-Team 00003 All rights reserved. 00004 Redistribution and use in source and binary forms, with or without modification, 00005 are permitted provided that the following conditions are met: 00006 00007 - Redistributions of source code must retain the above copyright notice, 00008 this list of conditions and the following disclaimer. 00009 00010 - Redistributions in binary form must reproduce the above copyright notice, 00011 this list of conditions and the following disclaimer in the documentation and/or 00012 other materials provided with the distribution. 00013 00014 - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors 00015 may be used to endorse or promote products derived from this software without specific 00016 prior written permission. 00017 00018 00019 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS 00020 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 00021 AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS 00022 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00023 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 00024 OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 00025 IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00026 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE 00027 */ 00028 /* 00029 * CAMultiSignature.cpp 00030 * 00031 * Created on: 17.07.2008 00032 * Author: zenoxx 00033 */ 00034 #include "StdAfx.h" 00035 #include "CABase64.hpp" 00036 #include "CAUtil.hpp" 00037 #include "xml/DOM_Output.hpp" 00038 #include "CASignature.hpp" 00039 #include "CAMultiSignature.hpp" 00040 00041 CAMultiSignature::CAMultiSignature() 00042 { 00043 m_signatures = NULL; 00044 m_sigCount = 0; 00045 m_xoredID = new UINT8[SHA_DIGEST_LENGTH]; 00046 for(SINT32 i = 0; i<SHA_DIGEST_LENGTH; i++) 00047 { 00048 m_xoredID[i] = 0; 00049 } 00050 } 00051 00052 CAMultiSignature::~CAMultiSignature() 00053 { 00054 SIGNATURE* tmp; 00055 while(m_signatures != NULL) 00056 { 00057 //delete Signer and CertStore 00058 delete m_signatures->pSig; 00059 delete m_signatures->pCerts; 00060 m_signatures->pCerts = NULL; 00061 m_signatures->pSig = NULL; 00062 delete[] m_signatures->pSKI; 00063 m_signatures->pSKI = NULL; 00064 //store current pointer 00065 tmp = m_signatures; 00066 //go to next signature 00067 m_signatures = m_signatures->next; 00068 //delete current signature 00069 delete tmp; 00070 tmp = NULL; 00071 } 00072 } 00073 00074 00075 SINT32 CAMultiSignature::findSKI(const UINT8* a_strSKI) 00076 { 00077 SIGNATURE* tmp = m_signatures; 00078 UINT8 tmpSKI[200]; 00079 00080 if (tmp == NULL) 00081 { 00082 return E_UNKNOWN; 00083 } 00084 00085 while(tmp != NULL) 00086 { 00087 if (getSKI(tmpSKI, 200, tmp->pSKI) == E_SUCCESS && 00088 strncmp((char*)a_strSKI, (char*)tmpSKI, strlen((char*)tmpSKI) ) == 0) 00089 { 00090 return E_SUCCESS; 00091 } 00092 tmp = tmp->next; 00093 } 00094 00095 if (getSKI(tmpSKI, 200, m_xoredID) == E_SUCCESS && 00096 strncmp((char*)a_strSKI, (char*)tmpSKI, strlen((char*)tmpSKI) ) == 0) 00097 { 00098 return E_SUCCESS; 00099 } 00100 00101 return E_NOT_FOUND; 00102 } 00103 00104 SINT32 CAMultiSignature::addSignature(CASignature* a_signature, CACertStore* a_certs, UINT8* a_ski, UINT32 a_skiLen) 00105 { 00106 if(a_signature == NULL || a_certs == NULL || a_ski == NULL || a_skiLen != SHA_DIGEST_LENGTH) 00107 return E_UNKNOWN; 00108 for(SINT32 i=0; i<SHA_DIGEST_LENGTH; i++) 00109 { 00110 m_xoredID[i] = m_xoredID[i] ^ a_ski[i]; 00111 } 00112 SIGNATURE* newSignature = new SIGNATURE; 00113 newSignature->pSig = a_signature; 00114 newSignature->pCerts = a_certs; 00115 newSignature->pSKI = new UINT8[a_skiLen]; 00116 memcpy(newSignature->pSKI, a_ski, a_skiLen); 00117 newSignature->next = m_signatures; 00118 m_signatures = newSignature; 00119 m_sigCount++; 00120 return E_SUCCESS; 00121 } 00122 00123 SINT32 CAMultiSignature::signXML(UINT8* in,UINT32 inlen,UINT8* out,UINT32* outlen, bool appendCerts) 00124 { 00125 if(in == NULL || inlen < 1 || out == NULL || outlen == NULL) 00126 return E_UNKNOWN; 00127 00128 XERCES_CPP_NAMESPACE::DOMDocument* doc = parseDOMDocument(in, inlen); 00129 if(doc == NULL) 00130 return E_UNKNOWN; 00131 DOMElement* root = doc->getDocumentElement(); 00132 if(signXML(root, appendCerts) != E_SUCCESS) 00133 return E_UNKNOWN; 00134 return DOM_Output::dumpToMem(root,out,outlen); 00135 } 00136 00137 SINT32 CAMultiSignature::signXML(DOMNode* node, bool appendCerts) 00138 { 00139 if(m_sigCount == 0) 00140 { 00141 CAMsg::printMsg(LOG_ERR, "Trying to sign a document with no signature-keys set!"); 00142 return E_UNKNOWN; 00143 } 00144 00145 //getting the Document an the Node to sign 00146 XERCES_CPP_NAMESPACE::DOMDocument* doc = NULL; 00147 DOMNode* elemRoot = NULL; 00148 if(node->getNodeType() == DOMNode::DOCUMENT_NODE) 00149 { 00150 doc = (XERCES_CPP_NAMESPACE::DOMDocument*)node; 00151 elemRoot = doc->getDocumentElement(); 00152 } 00153 else 00154 { 00155 elemRoot = node; 00156 doc = node->getOwnerDocument(); 00157 } 00158 00159 //check if there are already Signatures and if so remove them first... 00160 DOMNode* tmpSignature = NULL; 00161 while(getDOMChildByName(elemRoot, "Signature", tmpSignature, false) == E_SUCCESS) 00162 { 00163 DOMNode* n = elemRoot->removeChild(tmpSignature); 00164 if (n != NULL) 00165 { 00166 n->release(); 00167 n = NULL; 00168 } 00169 } 00170 //get SHA1-Digest 00171 UINT32 len = 0; 00172 UINT8* canonicalBuff = DOM_Output::makeCanonical(elemRoot, &len); 00173 if(canonicalBuff == NULL) 00174 { 00175 return E_UNKNOWN; 00176 } 00177 UINT8 dgst[SHA_DIGEST_LENGTH]; 00178 SHA1(canonicalBuff, len, dgst); 00179 delete[] canonicalBuff; 00180 canonicalBuff = NULL; 00181 00182 UINT8 digestValue[512]; 00183 len = 512; 00184 if(CABase64::encode(dgst, SHA_DIGEST_LENGTH, digestValue, &len) != E_SUCCESS) 00185 { 00186 return E_UNKNOWN; 00187 } 00188 00189 //append a signature for each SIGNATURE element we have 00190 SIGNATURE* currentSignature = m_signatures; 00191 UINT32 sigCount = 0; 00192 for(UINT32 i=0; i<m_sigCount; i++) 00193 { 00194 //Creating the Sig-InfoBlock.... 00195 DOMElement* elemSignedInfo = createDOMElement(doc, "SignedInfo"); 00196 DOMElement* elemCanonicalizationMethod = createDOMElement(doc, "CanonicalizationMethod"); 00197 DOMElement* elemSignatureMethod = createDOMElement(doc, "SignatureMethod"); 00198 DOMElement* elemReference = createDOMElement(doc, "Reference"); 00199 elemReference->setAttribute(XMLString::transcode("URI"), XMLString::transcode("")); 00200 DOMElement* elemDigestMethod = createDOMElement(doc, "DigestMethod"); 00201 if(currentSignature->pSig->isDSA()) //DSA-Signature 00202 { 00203 setDOMElementAttribute(elemSignatureMethod, "Algorithm", (UINT8*)DSA_SHA1_REFERENCE); 00204 } 00205 else if(currentSignature->pSig->isRSA()) 00206 { 00207 setDOMElementAttribute(elemSignatureMethod, "Algorithm", (UINT8*)RSA_SHA1_REFERENCE); 00208 } 00209 #ifdef ECC 00210 else if(currentSignature->pSig->isECDSA()) 00211 { 00212 setDOMElementAttribute(elemSignatureMethod, "Algorithm", (UINT8*)ECDSA_SHA1_REFERENCE); 00213 } 00214 #endif //ECC 00215 setDOMElementAttribute(elemDigestMethod, "Algorithm", (UINT8*)SHA1_REFERENCE); 00216 DOMElement* elemDigestValue = createDOMElement(doc, "DigestValue"); 00217 setDOMElementValue(elemDigestValue, digestValue); 00218 00219 elemSignedInfo->appendChild(elemCanonicalizationMethod); 00220 elemSignedInfo->appendChild(elemSignatureMethod); 00221 elemSignedInfo->appendChild(elemReference); 00222 elemReference->appendChild(elemDigestMethod); 00223 elemReference->appendChild(elemDigestValue); 00224 00225 // Signing the SignInfo block.... 00226 canonicalBuff = DOM_Output::makeCanonical(elemSignedInfo,&len); 00227 if(canonicalBuff==NULL) 00228 { 00229 return E_UNKNOWN; 00230 } 00231 00232 UINT32 sigLen = currentSignature->pSig->getSignatureSize(); 00233 UINT8* sigBuff=new UINT8[sigLen]; 00234 SINT32 ret = currentSignature->pSig->sign(canonicalBuff, len, sigBuff, &sigLen); 00235 delete[] canonicalBuff; 00236 canonicalBuff = NULL; 00237 if(ret != E_SUCCESS) 00238 { 00239 currentSignature = currentSignature->next; 00240 delete[] sigBuff; 00241 continue; 00242 } 00243 UINT sigSize = 255; 00244 UINT8 sig[255]; 00245 if(CABase64::encode(sigBuff, sigLen, sig, &sigSize) != E_SUCCESS) 00246 { 00247 currentSignature = currentSignature->next; 00248 delete[] sigBuff; 00249 continue; 00250 } 00251 00252 //Makeing the whole Signature-Block.... 00253 DOMElement* elemSignature = createDOMElement(doc,"Signature"); 00254 DOMElement* elemSignatureValue = createDOMElement(doc,"SignatureValue"); 00255 setDOMElementValue(elemSignatureValue,sig); 00256 elemSignature->appendChild(elemSignedInfo); 00257 elemSignature->appendChild(elemSignatureValue); 00258 00259 //Append KeyInfo if neccassary 00260 if(appendCerts) 00261 { 00262 //Making KeyInfo-Block 00263 DOMElement* tmpElemCerts = NULL; 00264 if(currentSignature->pCerts->encode(tmpElemCerts, doc) == E_SUCCESS && tmpElemCerts != NULL) 00265 { 00266 DOMElement* elemKeyInfo = createDOMElement(doc, "KeyInfo"); 00267 elemKeyInfo->appendChild(tmpElemCerts); 00268 elemSignature->appendChild(elemKeyInfo); 00269 } 00270 } 00271 elemRoot->appendChild(elemSignature); 00272 sigCount++; 00273 00274 //goto next Signature 00275 currentSignature = currentSignature->next; 00276 delete[] sigBuff; 00277 } 00278 if(sigCount > 0) 00279 { 00280 //CAMsg::printMsg(LOG_DEBUG, "Appended %d Signature(s) to XML-Structure\n", sigCount); 00281 return E_SUCCESS; 00282 } 00283 return E_UNKNOWN; 00284 } 00285 00286 SINT32 CAMultiSignature::verifyXML(const UINT8* const in,UINT32 inlen, CACertificate* a_cert) 00287 { 00288 XERCES_CPP_NAMESPACE::DOMDocument* doc = parseDOMDocument(in,inlen); 00289 if(doc == NULL) 00290 { 00291 return E_UNKNOWN; 00292 } 00293 DOMElement* root = doc->getDocumentElement(); 00294 if(root == NULL) 00295 { 00296 return E_UNKNOWN; 00297 } 00298 return CAMultiSignature::verifyXML(root, a_cert); 00299 } 00300 00301 SINT32 CAMultiSignature::verifyXML(DOMNode* root, CACertificate* a_cert) 00302 { 00303 CASignature* sigVerifier = new CASignature(); 00304 if(sigVerifier->setVerifyKey(a_cert) != E_SUCCESS) 00305 { 00306 CAMsg::printMsg(LOG_ERR, "Failed to set verify Key!"); 00307 return E_UNKNOWN; 00308 } 00309 UINT8* signatureMethod = sigVerifier->getSignatureMethod(); 00310 00311 UINT32 signatureElementsCount = MAX_SIGNATURE_ELEMENTS; 00312 DOMNode* signatureElements[MAX_SIGNATURE_ELEMENTS]; 00313 00314 getSignatureElements((DOMElement*)root, signatureElements, &signatureElementsCount); 00315 CAMsg::printMsg(LOG_DEBUG, "Found %d Signature(s) in XML-Structure\n", signatureElementsCount); 00316 00317 UINT8 dgst[255]; 00318 UINT32 dgstlen=255; 00319 UINT8* out = NULL; 00320 UINT32 outlen; 00321 bool verified = false; 00322 //go through all appended Signatures an try to verify them with the given cert 00323 for(UINT32 i=0; i<signatureElementsCount; i++) 00324 { 00325 dgstlen=255; 00326 CAMsg::printMsg(LOG_DEBUG, "Trying to verify signature %d of %d!\n", i+1, signatureElementsCount); 00327 DOMNode* elemSignature = signatureElements[i]; 00328 00329 if(elemSignature == NULL) 00330 { 00331 CAMsg::printMsg(LOG_DEBUG, "Error: signature element is NULL\n"); 00332 continue; 00333 } 00334 DOMNode* elemSigInfo; 00335 getDOMChildByName(elemSignature, "SignedInfo", elemSigInfo); 00336 if(elemSigInfo == NULL) 00337 { 00338 CAMsg::printMsg(LOG_DEBUG, "Error: signed info is NULL\n"); 00339 continue; 00340 } 00341 //check if SignatureMethod fits... 00342 DOMNode* elemSigMethod; 00343 getDOMChildByName(elemSigInfo, "SignatureMethod", elemSigMethod); 00344 UINT32 algLen = 255; 00345 UINT8 algorithm[255]; 00346 getDOMElementAttribute(elemSigMethod, (const char*)"Algorithm", algorithm, &algLen); 00347 //if signatureMethod is set check if its equal 00348 if(signatureMethod != NULL && 00349 strncmp((const char*)algorithm, (const char*)signatureMethod, algLen) != E_SUCCESS) 00350 { 00351 CAMsg::printMsg(LOG_DEBUG, "Did NOT find matching SignatureMethods: %s and %s!\n", signatureMethod, algorithm); 00352 continue; 00353 } 00354 DOMNode* elemSigValue; 00355 getDOMChildByName(elemSignature, "SignatureValue", elemSigValue); 00356 if(elemSigValue == NULL) 00357 { 00358 CAMsg::printMsg(LOG_DEBUG, "Error: signature value is NULL\n"); 00359 continue; 00360 } 00361 DOMNode* elemReference; 00362 getDOMChildByName(elemSigInfo, "Reference", elemReference); 00363 if(elemReference == NULL) 00364 { 00365 CAMsg::printMsg(LOG_DEBUG, "Error: signature reference is NULL\n"); 00366 continue; 00367 } 00368 DOMNode* elemDigestValue; 00369 getDOMChildByName(elemReference, "DigestValue", elemDigestValue); 00370 if(elemDigestValue == NULL) 00371 { 00372 CAMsg::printMsg(LOG_DEBUG, "Error: digest value is NULL\n"); 00373 continue; 00374 } 00375 if(getDOMElementValue(elemDigestValue,dgst,&dgstlen)!=E_SUCCESS) 00376 { 00377 CAMsg::printMsg(LOG_DEBUG, "Error: could not get digest value from XML\n"); 00378 continue; 00379 } 00380 if(CABase64::decode(dgst,dgstlen,dgst,&dgstlen)!=E_SUCCESS) 00381 { 00382 CAMsg::printMsg(LOG_DEBUG, "Error: could not decode digest value\n"); 00383 continue; 00384 } 00385 if(dgstlen!=SHA_DIGEST_LENGTH) 00386 { 00387 CAMsg::printMsg(LOG_DEBUG, "Error: digest is %d long, should be %d\n", dgstlen, SHA_DIGEST_LENGTH); 00388 continue; 00389 } 00390 UINT32 tmpSiglen = 255; 00391 UINT8 tmpSig[255]; 00392 if(getDOMElementValue(elemSigValue,tmpSig,&tmpSiglen)!=E_SUCCESS) 00393 { 00394 CAMsg::printMsg(LOG_DEBUG, "Error: could not get signature value from XML\n"); 00395 continue; 00396 } 00397 if(CABase64::decode(tmpSig,tmpSiglen,tmpSig,&tmpSiglen)!=E_SUCCESS) 00398 { 00399 CAMsg::printMsg(LOG_DEBUG, "Error: could not decode signature value\n"); 00400 continue; 00401 } 00402 outlen = 5000; 00403 out = new UINT8[outlen]; 00404 if(DOM_Output::makeCanonical(elemSigInfo, out, &outlen) == E_SUCCESS) 00405 { 00406 if(sigVerifier->verify(out, outlen, tmpSig, tmpSiglen) == E_SUCCESS) 00407 { 00408 CAMsg::printMsg(LOG_DEBUG, "Signature verification successful!\n"); 00409 verified = true; 00410 break; 00411 } 00412 } 00413 CAMsg::printMsg(LOG_WARNING, "Signature verification not successful!\n"); 00414 delete[] out; 00415 out = NULL; 00416 continue; 00417 } 00418 if(verified) 00419 { 00420 //the signature could be verified, now check digestValue 00421 //first remove Signature-nodes from root and store them 00422 DOMNode* removedSignatures[MAX_SIGNATURE_ELEMENTS]; 00423 00424 for(UINT32 i=0; i<signatureElementsCount; i++) 00425 { 00426 removedSignatures[i] = root->removeChild(signatureElements[i]); 00427 if(removedSignatures[i] == NULL) 00428 { 00429 //TODO do what? Verification will most likely fail, so just log the error for the moment 00430 CAMsg::printMsg(LOG_ERR, "Error removing signature-element %d of %d from Root-Node\n", i+1, signatureElementsCount); 00431 } 00432 } 00433 00434 outlen = 5000; 00435 DOM_Output::makeCanonical(root, out, &outlen); 00436 00437 //append Signature-nodes again 00438 for(UINT32 i=0; i<signatureElementsCount; i++) 00439 { 00440 if(removedSignatures[i] != NULL) 00441 { 00442 root->appendChild(removedSignatures[i]); 00443 } 00444 } 00445 00446 UINT8 newDgst[SHA_DIGEST_LENGTH]; 00447 SHA1(out, outlen, newDgst); 00448 delete[] out; 00449 out = NULL; 00450 for(int i=0; i<SHA_DIGEST_LENGTH; i++) 00451 { 00452 if(newDgst[i] != dgst[i]) 00453 { 00454 CAMsg::printMsg(LOG_ERR, "Error checking XML-Signature DigestValue!\n"); 00455 return E_UNKNOWN; 00456 } 00457 } 00458 return E_SUCCESS; 00459 } 00460 CAMsg::printMsg(LOG_ERR, "XML-Signature could not be verified!\n"); 00461 return E_UNKNOWN; 00462 } 00464 SINT32 CAMultiSignature::sign(UINT8* in,UINT32 inlen,UINT8* sig,UINT32* siglen) 00465 { 00466 if(m_sigCount < 1) 00467 { 00468 return E_UNKNOWN; 00469 } 00470 return m_signatures->pSig->sign(in, inlen, sig, siglen); 00471 } 00472 00473 SINT32 CAMultiSignature::getSKI(UINT8* out, UINT32 outlen, const UINT8* a_ski) 00474 { 00475 UINT8* tmp = (UINT8*) hex_to_string((unsigned char*)a_ski, SHA_DIGEST_LENGTH); 00476 UINT32 len=outlen; 00477 if (CACertificate::removeColons(tmp, strlen((const char*)tmp), out, &len) != E_SUCCESS) 00478 { 00479 OPENSSL_free(tmp); 00480 return E_UNKNOWN; 00481 } 00482 OPENSSL_free(tmp); 00483 strtrim(out); 00484 return E_SUCCESS; 00485 } 00486 00487 SINT32 CAMultiSignature::getXORofSKIs(UINT8* out, UINT32 outlen) 00488 { 00489 return getSKI(out, outlen, m_xoredID); 00490 }
1.7.6.1