00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
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=NULL;
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
00152
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)
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);
00215 tmp+=X509_CERTIFICATE_TAGNAME_LEN;
00216 i=i2d_X509(m_pCert,&tmp);
00217 if(i==0)
00218 return E_UNKNOWN;
00219 CABase64::encode( buff+X509_CERTIFICATE_TAGNAME_LEN,i,
00220 buff+X509_CERTIFICATE_TAGNAME_LEN,bufflen);
00221 memcpy( buff+X509_CERTIFICATE_TAGNAME_LEN+*bufflen,
00222 "</X509Certificate>",X509_CERTIFICATE_TAGNAME_LEN+1);
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)
00232 {
00233 elemRoot=createDOMElement(doc,"X509Certificate");
00234 UINT8 buff[2048];
00235 UINT8* tmp=buff;
00236 int i=i2d_X509(m_pCert,&tmp);
00237 UINT32 bufflen=2048;
00238 CABase64::encode(buff,i,buff,&bufflen);
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
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)
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
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
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)
00414 {
00415 if(a_cert == NULL || a_cert->m_pCert == NULL || m_pCert == NULL)
00416 {
00417 return E_UNKNOWN;
00418 }
00419
00420 if(!isValid())
00421 {
00422 CAMsg::printMsg(LOG_ERR, "Verification Error: Certificate is not valid!\n");
00423 return E_UNKNOWN;
00424 }
00425
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
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
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
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
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()
00470 {
00471 if(X509_cmp_current_time(X509_get_notBefore(m_pCert)) == -1
00472 && X509_cmp_current_time(X509_get_notAfter(m_pCert)) == 1)
00473 {
00474 return true;
00475 }
00476
00477 time_t now = time(NULL);
00478 tm* time = new tm;
00479 time = gmtime_r(&now, time);
00480 if(time->tm_mon < 2)
00481 {
00482 time->tm_mon = time->tm_mon+10;
00483 time->tm_year = time->tm_year-1;
00484 }
00485 else
00486 {
00487 time->tm_mon = time->tm_mon-2;
00488 }
00489 time_t ttiq = mktime(time);
00490 delete time;
00491 time = NULL;
00492 if(X509_cmp_time(X509_get_notBefore(m_pCert), &ttiq) == -1
00493 && X509_cmp_time(X509_get_notAfter(m_pCert), &ttiq) == 1)
00494 {
00495 CAMsg::printMsg(LOG_WARNING, "Certificate is only valid within grace period of two months!\n");
00496 return true;
00497 }
00498 return false;
00499 }
00500
00501 #endif //ONLY_LOCAL_PROXY
00502