|
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 #include "StdAfx.h" 00030 #ifndef ONLY_LOCAL_PROXY 00031 #include "CACertificate.hpp" 00032 #include "CABase64.hpp" 00033 #include "CAUtil.hpp" 00034 #include "CAMsg.hpp" 00035 00036 UINT8 * CACertificate::m_spXmlElementName =0; 00037 00038 CACertificate::CACertificate() 00039 { 00040 m_pCert = NULL; 00041 m_pSKI = NULL; 00042 m_pAKI = NULL; 00043 } 00044 00045 CACertificate::CACertificate(X509* x) 00046 { 00047 m_pCert = x; 00048 m_pSKI = NULL; 00049 m_pAKI = NULL; 00050 if(m_pCert != NULL) 00051 { 00052 m_pSKI = (ASN1_OCTET_STRING*) X509_get_ext_d2i(m_pCert, NID_subject_key_identifier, NULL, NULL); 00053 m_pAKI = (AUTHORITY_KEYID*) X509_get_ext_d2i (m_pCert, NID_authority_key_identifier, NULL, NULL); 00054 } 00055 } 00056 00057 CACertificate* CACertificate::decode(const DOMNode* n,UINT32 type,const char* passwd) 00058 { 00059 const DOMNode* node=n; 00060 switch(type) 00061 { 00062 case CERT_PKCS12: 00063 while(node!=NULL) 00064 { 00065 if(equals(node->getNodeName(),"X509PKCS12")) 00066 { 00067 UINT32 strLen=4096; 00068 UINT8* tmpStr=new UINT8[strLen]; 00069 CACertificate* cert=NULL; 00070 if(getDOMElementValue(node,tmpStr,&strLen)!=E_SUCCESS) 00071 { 00072 delete[] tmpStr; 00073 tmpStr = NULL; 00074 return NULL; 00075 } 00076 UINT32 decLen=4096; 00077 UINT8* decBuff=new UINT8[decLen]; 00078 SINT32 ret=CABase64::decode((UINT8*)tmpStr,strLen,decBuff,&decLen); 00079 delete[] tmpStr; 00080 tmpStr = NULL; 00081 if(ret==E_SUCCESS) 00082 { 00083 cert=decode(decBuff,decLen,CERT_PKCS12,passwd); 00084 } 00085 delete[] decBuff; 00086 decBuff = NULL; 00087 return cert; 00088 } 00089 node=node->getNextSibling(); 00090 } 00091 break; 00092 case CERT_X509CERTIFICATE: 00093 while(node!=NULL) 00094 { 00095 if(equals(node->getNodeName(),"X509Certificate")) 00096 { 00097 UINT32 strLen=4096; 00098 UINT8* tmpStr=new UINT8[strLen]; 00099 CACertificate* cert=NULL; 00100 if(getDOMElementValue(node,tmpStr,&strLen)!=E_SUCCESS) 00101 { 00102 delete[] tmpStr; 00103 tmpStr = NULL; 00104 return NULL; 00105 } 00106 UINT32 decLen=4096; 00107 UINT8* decBuff=new UINT8[decLen]; 00108 SINT32 ret=CABase64::decode((UINT8*)tmpStr,strLen,decBuff,&decLen); 00109 delete[] tmpStr; 00110 tmpStr = NULL; 00111 if(ret==E_SUCCESS) 00112 { 00113 cert=decode(decBuff,decLen,CERT_DER); 00114 } 00115 delete[] decBuff; 00116 decBuff = NULL; 00117 return cert; 00118 } 00119 node=node->getNextSibling(); 00120 } 00121 00122 } 00123 return NULL; 00124 } 00125 00126 CACertificate* CACertificate::decode(const UINT8* const buff,UINT32 bufflen,UINT32 type,const char* const passwd) 00127 { 00128 if(buff==NULL) 00129 return NULL; 00130 X509* tmpCert=NULL; 00131 EVP_PKEY* tmpKey=NULL; 00132 SINT32 ret=-1; 00133 const UINT8* tmp=buff; 00134 switch(type) 00135 { 00136 case CERT_DER: 00137 tmp=buff; 00138 #if OPENSSL_VERSION_NUMBER > 0x009070CfL 00139 tmpCert=d2i_X509(NULL,&tmp,bufflen); 00140 #else 00141 tmpCert=d2i_X509(NULL,(UINT8**)&tmp,bufflen); 00142 #endif 00143 break; 00144 case CERT_PKCS12: 00145 PKCS12* tmpPKCS12; 00146 #if OPENSSL_VERSION_NUMBER > 0x009070CfL 00147 tmpPKCS12=d2i_PKCS12(NULL,&tmp,bufflen); 00148 #else 00149 tmpPKCS12=d2i_PKCS12(NULL,(UINT8**)&tmp,bufflen); 00150 #endif 00151 /*Note: Basically we are not interested in the private keys here - but still we need cannot supply 00152 *NULL for that parameter, as OpenSSL 1.0.0. would not work in that case*/ 00153 ret=PKCS12_parse(tmpPKCS12,passwd,&tmpKey,&tmpCert,NULL); 00154 PKCS12_free(tmpPKCS12); 00155 EVP_PKEY_free(tmpKey); 00156 if(ret!=1) 00157 { 00158 return NULL; 00159 } 00160 break; 00161 case CERT_XML_X509CERTIFICATE: 00162 XERCES_CPP_NAMESPACE::DOMDocument* doc=parseDOMDocument(buff,bufflen); 00163 if(doc == NULL) 00164 { 00165 return NULL; 00166 } 00167 DOMElement* root=doc->getDocumentElement(); 00168 if(root==NULL||!equals(root->getNodeName(),"X509Certificate")) 00169 { 00170 return NULL; 00171 } 00172 UINT8* tmpBuff=new UINT8[bufflen]; 00173 UINT32 tmpBuffSize=bufflen; 00174 if(getDOMElementValue(root,tmpBuff,&tmpBuffSize)==E_SUCCESS) 00175 { 00176 ret=CABase64::decode(tmpBuff,tmpBuffSize,tmpBuff,&tmpBuffSize); 00177 } 00178 tmp=tmpBuff; 00179 if(ret==E_SUCCESS) 00180 { 00181 #if OPENSSL_VERSION_NUMBER > 0x009070CfL 00182 tmpCert=d2i_X509(NULL,&tmp,tmpBuffSize); 00183 #else 00184 tmpCert=d2i_X509(NULL,(UINT8**)&tmp,tmpBuffSize); 00185 #endif 00186 } 00187 delete[] tmpBuff; 00188 tmpBuff = NULL; 00189 break; 00190 } 00191 if(tmpCert == NULL) 00192 { 00193 return NULL; 00194 } 00195 return new CACertificate(tmpCert); 00196 } 00197 00198 SINT32 CACertificate::encode(UINT8* buff,UINT32* bufflen,UINT32 type) const 00199 { 00200 if(m_pCert==NULL||buff==NULL||bufflen==NULL) 00201 return E_UNKNOWN; 00202 int i=0; 00203 UINT8* tmp=buff; 00204 switch(type) 00205 { 00206 case CERT_DER: 00207 i=i2d_X509(m_pCert,&tmp); 00208 if(i==0) 00209 return E_UNKNOWN; 00210 *bufflen=i; 00211 break; 00212 case CERT_XML_X509CERTIFICATE: 00213 #define X509_CERTIFICATE_TAGNAME_LEN 17 00214 memcpy(buff,"<X509Certificate>",X509_CERTIFICATE_TAGNAME_LEN); //we start with '<X509Certificate>' 00215 tmp+=X509_CERTIFICATE_TAGNAME_LEN; 00216 i=i2d_X509(m_pCert,&tmp); //now we need DER 00217 if(i==0) 00218 return E_UNKNOWN; 00219 CABase64::encode( buff+X509_CERTIFICATE_TAGNAME_LEN,i, 00220 buff+X509_CERTIFICATE_TAGNAME_LEN,bufflen); //now we have it converted to Base64 00221 memcpy( buff+X509_CERTIFICATE_TAGNAME_LEN+*bufflen, 00222 "</X509Certificate>",X509_CERTIFICATE_TAGNAME_LEN+1); //we end it with '</X509Certificate>' 00223 *bufflen+=2*X509_CERTIFICATE_TAGNAME_LEN+1; 00224 break; 00225 default: 00226 return E_UNKNOWN; 00227 } 00228 return E_SUCCESS; 00229 } 00230 00231 SINT32 CACertificate::encode(DOMElement* & elemRoot,XERCES_CPP_NAMESPACE::DOMDocument* doc) const 00232 { 00233 elemRoot=createDOMElement(doc,"X509Certificate"); 00234 UINT8 buff[2048]; //TODO: Very bad --> looks like easy buffer overflow... [donn't care at the moment...] 00235 UINT8* tmp=buff; 00236 int i=i2d_X509(m_pCert,&tmp); //now we need DER 00237 UINT32 bufflen=2048; 00238 CABase64::encode(buff,i,buff,&bufflen); //now we have it converted to Base64 00239 buff[bufflen]=0; 00240 setDOMElementValue(elemRoot,buff); 00241 return E_SUCCESS; 00242 } 00243 00252 SINT32 CACertificate::getSubjectKeyIdentifier(UINT8* r_ski, UINT32 *r_skiLen) 00253 { 00254 if (m_pSKI == NULL) 00255 { 00256 #ifdef DEBUG 00257 CAMsg::printMsg( LOG_ERR, "Unable to get SKI from Certificate, trying to recover\n"); 00258 #endif 00259 setSubjectKeyIdentifier(); 00260 if(m_pSKI == NULL) 00261 { 00262 CAMsg::printMsg( LOG_ERR, "Unable to retrieve 1SKI from Certificate\n"); 00263 return E_UNKNOWN; 00264 } 00265 #ifdef DEBUG 00266 else 00267 { 00268 CAMsg::printMsg( LOG_ERR, "Recovery SUCCESSFUL!\n"); 00269 } 00270 #endif 00271 } 00272 // Get the ASCII string format of the subject key identifier 00273 UINT8* cSki = (UINT8*)i2s_ASN1_OCTET_STRING( NULL, m_pSKI ); 00274 if ( cSki==NULL ) 00275 { 00276 CAMsg::printMsg( LOG_ERR, "Unable to convert SKI\n"); 00277 return E_UNKNOWN; 00278 } 00279 #ifdef DEBUG 00280 CAMsg::printMsg( LOG_ERR, "getSubjectKeyIdentifier: SKI is %s\n", cSki); 00281 #endif 00282 removeColons(cSki, strlen((const char*)cSki), r_ski, r_skiLen); 00283 OPENSSL_free(cSki); 00284 return E_SUCCESS; 00285 } 00286 00287 SINT32 CACertificate::getAuthorityKeyIdentifier(UINT8* r_aki, UINT32* r_akiLen) const 00288 { 00289 if(m_pAKI == NULL) 00290 { 00291 return E_UNKNOWN; 00292 } 00293 00294 ASN1_OCTET_STRING* pKeyID = NULL; 00295 pKeyID = m_pAKI->keyid; 00296 if(pKeyID == NULL) 00297 { 00298 return E_UNKNOWN; 00299 } 00300 00301 // Get the ASCII string format of the authority key identifier 00302 UINT8* cKeyID = (UINT8*)i2s_ASN1_OCTET_STRING(NULL, pKeyID); 00303 if (cKeyID == NULL) 00304 { 00305 return E_UNKNOWN; 00306 } 00307 removeColons(cKeyID, strlen((const char*)cKeyID), r_aki, r_akiLen); 00308 OPENSSL_free(cKeyID); 00309 return E_SUCCESS; 00310 } 00311 00324 SINT32 CACertificate::removeColons(const UINT8* a_cSkid, UINT32 a_cSkidLen, UINT8 *&r_ski, UINT32 *r_skiLen) 00325 { 00326 UINT32 i = 0, j = 0; 00327 UINT32 tmp = (2*a_cSkidLen)/3 + 2; 00328 if(*r_skiLen < tmp) 00329 { 00330 CAMsg::printMsg( LOG_ERR, "CACertificate::removeColons: Unable to copy SKI to target array, size must at least be %i but is only %i!\n", tmp, *r_skiLen); 00331 return E_UNKNOWN; 00332 } 00333 for(i = 0; i < a_cSkidLen; i++) 00334 { 00335 if(i % 3 == 2) { 00336 j++; 00337 continue; 00338 } 00339 r_ski[i-j] = a_cSkid[i]; 00340 } 00341 r_ski[i-j] = 0; 00342 *r_skiLen = i-j; 00343 return E_SUCCESS; 00344 } 00345 00352 SINT32 CACertificate::setSubjectKeyIdentifier() 00353 { 00354 UINT32 len = 0; 00355 UINT8 sha_hash[SHA_DIGEST_LENGTH]; 00356 X509_pubkey_digest(m_pCert, EVP_sha1(), sha_hash, &len); 00357 return setSubjectKeyIdentifier( sha_hash, len ); 00358 } 00359 00368 SINT32 CACertificate::setSubjectKeyIdentifier( UINT8* a_value, UINT32 a_valueLen ) 00369 { 00370 SINT32 ret = E_UNKNOWN; 00371 ASN1_OCTET_STRING* skid = NULL; 00372 00373 skid = ASN1_OCTET_STRING_new(); 00374 if(NULL == skid) goto end; 00375 00376 ASN1_OCTET_STRING_set(skid, a_value, a_valueLen); 00377 if( X509_add1_ext_i2d(m_pCert, NID_subject_key_identifier, skid, false, X509V3_ADD_REPLACE) == 1) 00378 { 00379 m_pSKI = skid; 00380 ret = E_SUCCESS; 00381 } 00382 00383 end: 00384 //ASN1_OCTET_STRING_free(skid); 00385 return ret; 00386 } 00387 00388 SINT32 CACertificate::getRawSubjectKeyIdentifier(UINT8* r_ski, UINT32* r_skiLen) 00389 { 00390 if (m_pSKI == NULL) 00391 { 00392 setSubjectKeyIdentifier(); 00393 if(m_pSKI == NULL) 00394 { 00395 CAMsg::printMsg( LOG_ERR, "Unable to retrieve raw SKI from Certificate\n"); 00396 return E_UNKNOWN; 00397 } 00398 00399 } 00400 if(*r_skiLen < (UINT32) m_pSKI->length) 00401 { 00402 CAMsg::printMsg( LOG_ERR, "Unable to copy SKI to target array, size must at least be %i but is only %i!\n", m_pSKI->length, r_skiLen ); 00403 return E_UNKNOWN; 00404 } 00405 *r_skiLen = m_pSKI->length; 00406 for(SINT32 i=0; i<m_pSKI->length; i++) 00407 { 00408 r_ski[i] = m_pSKI->data[i]; 00409 } 00410 return E_SUCCESS; 00411 } 00412 00413 SINT32 CACertificate::verify(const CACertificate* a_cert) const 00414 { 00415 if(a_cert == NULL || a_cert->m_pCert == NULL || m_pCert == NULL) 00416 { 00417 return E_UNKNOWN; 00418 } 00419 //check validity 00420 if(!isValid()) 00421 { 00422 CAMsg::printMsg(LOG_ERR, "Verification Error: Certificate is not valid!\n"); 00423 return E_UNKNOWN; 00424 } 00425 //namechaining... 00426 if(X509_NAME_cmp(X509_get_issuer_name(m_pCert), X509_get_subject_name(a_cert->m_pCert)) != 0) 00427 { 00428 CAMsg::printMsg(LOG_ERR, "Verification Error: Names do not match!\n"); 00429 return E_UNKNOWN; 00430 } 00431 //keychaining... (only if available) 00432 if(m_pAKI != NULL && a_cert->m_pSKI != NULL) 00433 { 00434 if(ASN1_OCTET_STRING_cmp(m_pAKI->keyid, a_cert->m_pSKI) != 0) 00435 { 00436 CAMsg::printMsg(LOG_ERR, "Verification Error: Key Identifiers do not match!\n"); 00437 return E_UNKNOWN; 00438 } 00439 } 00440 //get public key 00441 EVP_PKEY* pubKey = X509_get_pubkey(a_cert->m_pCert); 00442 if(pubKey == NULL) 00443 { 00444 CAMsg::printMsg(LOG_ERR, "Verification Error: Public Key is NULL!\n"); 00445 return E_UNKNOWN; 00446 } 00447 //check if public key and signature algorithm match -> does not work because of openssl bug! 00448 //SINT32 sigType = X509_get_signature_type(m_pCert); 00449 /*SINT32 sigType = OBJ_obj2nid((m_pCert)->sig_alg->algorithm); 00450 SINT32 keyType = EVP_PKEY_type(pubKey->type); 00451 CAMsg::printMsg(LOG_DEBUG, "sigType is %d and keyType is %d\n", sigType, keyType); 00452 if((sigType != (NID_dsaWithSHA1 || NID_sha1WithRSAEncryption ||NID_ecdsa_with_SHA1)) 00453 && keyType != EVP_PKEY_DSA) || 00454 (sigType == NID_sha1WithRSAEncryption && keyType != EVP_PKEY_RSA) || 00455 (sigType == NID_ecdsa_with_SHA1 && keyType != EVP_PKEY_EC)) 00456 { 00457 CAMsg::printMsg(LOG_ERR, "Verification Error: Signature Algorithm does not match!\n"); 00458 //return E_UNKNOWN; 00459 }*/ 00460 if(X509_verify(m_pCert, pubKey) == 1) 00461 { 00462 CAMsg::printMsg(LOG_DEBUG, "Successfully verified certificate.\n"); 00463 return E_SUCCESS; 00464 } 00465 CAMsg::printMsg(LOG_ERR, "Verification Error: Signature is not correct!\n"); 00466 return E_UNKNOWN; 00467 } 00468 00469 bool CACertificate::isValid() const 00470 { 00471 ASN1_TIME* pValidNotBefore=X509_get_notBefore(m_pCert); 00472 ASN1_TIME* pValidNotAfter=X509_get_notAfter(m_pCert); 00473 if(X509_cmp_current_time( pValidNotBefore) <0 00474 && X509_cmp_current_time(pValidNotAfter) >0) 00475 { 00476 return true; 00477 } 00478 //check if certificate is valid within grace period of two months 00479 time_t now = time(NULL); //get current time; 00480 tm* time = new tm; 00481 time = gmtime_r(&now, time); //convert time to modifiable format 00482 if(time->tm_mon < 2) //go back two months in time 00483 { 00484 time->tm_mon = time->tm_mon+10; 00485 time->tm_year = time->tm_year-1; 00486 } 00487 else 00488 { 00489 time->tm_mon = time->tm_mon-2; 00490 } 00491 time_t ttiq = mktime(time); //convert time back to time_t and check again 00492 delete time; 00493 time = NULL; 00494 if(X509_cmp_time( pValidNotBefore, &ttiq) <0 00495 && X509_cmp_time(pValidNotAfter, &ttiq) >0) 00496 { 00497 CAMsg::printMsg(LOG_WARNING, "Certificate is only valid within grace period of two months!\n"); 00498 return true; 00499 } 00500 return false; 00501 } 00502 00503 #endif //ONLY_LOCAL_PROXY 00504
1.7.6.1