Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members

pana_security_assoc.cxx

00001 /* BEGIN_COPYRIGHT                                                        */
00002 /*                                                                        */
00003 /* Open Diameter: Open-source software for the Diameter and               */
00004 /*                Diameter related protocols                              */
00005 /*                                                                        */
00006 /* Copyright (C) 2002-2004 Open Diameter Project                          */
00007 /*                                                                        */
00008 /* This library is free software; you can redistribute it and/or modify   */
00009 /* it under the terms of the GNU Lesser General Public License as         */
00010 /* published by the Free Software Foundation; either version 2.1 of the   */
00011 /* License, or (at your option) any later version.                        */
00012 /*                                                                        */
00013 /* This library is distributed in the hope that it will be useful,        */
00014 /* but WITHOUT ANY WARRANTY; without even the implied warranty of         */
00015 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU      */
00016 /* Lesser General Public License for more details.                        */
00017 /*                                                                        */
00018 /* You should have received a copy of the GNU Lesser General Public       */
00019 /* License along with this library; if not, write to the Free Software    */
00020 /* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307    */
00021 /* USA.                                                                   */
00022 /*                                                                        */
00023 /* In addition, when you copy and redistribute some or the entire part of */
00024 /* the source code of this software with or without modification, you     */
00025 /* MUST include this copyright notice in each copy.                       */
00026 /*                                                                        */
00027 /* If you make any changes that are appeared to be useful, please send    */
00028 /* sources that include the changed part to                               */
00029 /* diameter-developers@lists.sourceforge.net so that we can reflect your  */
00030 /* changes to one unified version of this software.                       */
00031 /*                                                                        */
00032 /* END_COPYRIGHT                                                          */
00033 
00034 #include "pana_sha1.h"
00035 #include "pana_security_assoc.h"
00036 #include "pana_exceptions.h"
00037 #include "pana_memory_manager.h"
00038 
00039 #define PANA_SA_DEBUG   0
00040 
00041 diameter_octetstring_t &PANA_MacKey::MacKey(diameter_octetstring_t &msk,
00042                                             ACE_UINT32 ISN_pac,
00043                                             ACE_UINT32 ISN_paa)
00044 {
00045     /*
00046        The PANA_MAC_Key is used to integrity protect PANA messages and 
00047        derived from the MSK in the following way: 
00048     
00049           PANA_MAC_KEY = The first N-bit of 
00050                          HMAC_SHA1(MSK, ISN_pac | ISN_paa | Session-ID) 
00051 
00052        where the value of N depends on the integrity protection  algorithm 
00053        in use, i.e., N=128 for HMAC-MD5 and N=160 for HMAC-SHA1. 
00054     
00055        The length of MSK MUST be N-bit or longer.  See section 4.1.6 for 
00056        the detailed usage of the PANA_MAC_Key. 
00057     */
00058     PANA_Sha1 sha1;
00059     sha1.Update((unsigned char*)msk.data(), msk.size());
00060     sha1.Update((unsigned char*)&ISN_pac, sizeof(ISN_pac));
00061     sha1.Update((unsigned char*)&ISN_paa, sizeof(ISN_paa));
00062     sha1.Final();
00063 
00064     char sbuf[PANA_MACGEN_HMACSIZE];
00065     ACE_OS::memset(sbuf, 0x0, sizeof(sbuf));
00066     sha1.GetHash((unsigned char*)sbuf);
00067 
00068     m_MacKey.assign((char*)(sbuf), sizeof(sbuf));
00069 
00070 #if PANA_SA_DEBUG
00071     printf("EAP key: %d\n", msk.size());
00072     for (int i=0; i<msk.size(); i++) {
00073         printf("%02X ", ((char*)msk.data())[i]);
00074     }
00075     printf("\n");
00076 #endif
00077     
00078     return (m_MacKey);
00079 }
00080 
00081 void PANA_SecurityAssociation::GenerateMacValue(AAAMessageBlock *panaPDU,
00082                                                 diameter_octetstring_t &macValue)
00083 {
00084     /*
00085        A PANA message can contain a MAC (Message Authentication Code) AVP 
00086        for cryptographically protecting the message. 
00087     
00088        When a MAC AVP is included in a PANA message, the value field of the 
00089        MAC AVP is calculated by using the PANA_MAC_Key in the following 
00090        way: 
00091     
00092            MAC AVP value = HMAC_SHA1(PANA_MAC_Key, PANA_PDU) 
00093     
00094        where PANA_PDU is the PANA message including the PANA header, with 
00095        the MAC AVP value field first initialized to 0.  
00096     */
00097     PANA_Sha1 sha1;
00098     sha1.Update((unsigned char*)m_MacKey.data(), m_MacKey.size());
00099     sha1.Update((unsigned char*)panaPDU->base(), panaPDU->length());
00100     sha1.Final();
00101 
00102     char sbuf[PANA_MACGEN_HMACSIZE];
00103     ACE_OS::memset(sbuf, 0x0, sizeof(sbuf));
00104     sha1.GetHash((unsigned char*)sbuf);
00105     macValue.assign((char*)sbuf, sizeof(sbuf));
00106 
00107 #if PANA_SA_DEBUG
00108     printf("Master key: %d\n", m_MacKey.size());
00109     for (int i=0; i<m_MacKey.size(); i++) {
00110         printf("%02X ", ((char*)m_MacKey.data())[i]);
00111     }
00112     printf("\n");
00113     
00114     printf("PDU: %d\n", panaPDU->length());
00115     for (int i=0; i<panaPDU->length(); i++) {
00116         printf("%02X ", ((char*)panaPDU->base())[i]);
00117     }
00118     printf("\n");
00119 
00120     printf("MAC Value: %d\n", macValue.size());
00121     for (int i=0; i<macValue.size(); i++) {
00122         printf("%02X ", ((char*)macValue.data())[i]);
00123     }
00124     printf("\n");
00125 #endif
00126 }
00127 
00128 bool PANA_SecurityAssociation::AddMacValue(PANA_Message &msg)
00129 {
00130     AAAAvpContainerManager cm;
00131     AAAAvpContainerEntryManager em;
00132 
00133     AAAAvpContainer *c_macAvp = cm.acquire("Mac-Avp");
00134     AAAAvpContainerEntry *e = em.acquire(AAA_AVPDataType(AAA_AVP_MAC_TYPE));
00135     PANA_TVData_t &macAvp = e->dataRef(Type2Type<PANA_TVData_t>());
00136     c_macAvp->add(e);
00137 
00138     msg.avpList().add(c_macAvp);
00139 
00140     // init this to zero so we can compute true MAC
00141     char sbuf[PANA_MACGEN_HMACSIZE];
00142     ACE_OS::memset(sbuf, 0x0, sizeof(sbuf));
00143     macAvp.value.assign(sbuf, sizeof(sbuf));
00144     macAvp.type = PANA_MACGEN_HMACSHA1;
00145 
00146     PANA_MessageBuffer *rawBuf = PANA_MESSAGE_POOL()->malloc();
00147 
00148     PANA_HeaderParser hp;
00149     AAADictionaryOption opt(PARSE_STRICT, PANA_DICT_PROTOCOL_ID);
00150     hp.setRawData(reinterpret_cast<AAAMessageBlock*>(rawBuf));
00151     hp.setAppData(static_cast<PANA_MsgHeader*>(&msg));
00152     hp.setDictData(&opt);
00153 
00154     hp.parseAppToRaw();
00155 
00156     // Parse the payload
00157     PANA_PayloadParser pp;
00158     pp.setRawData(reinterpret_cast<AAAMessageBlock*>(rawBuf));
00159     pp.setAppData(&(msg.avpList()));
00160     pp.setDictData(msg.getDictHandle());
00161 
00162     pp.parseAppToRaw();
00163 
00164     // Re-do the header again to set the length
00165     msg.length(rawBuf->wr_ptr() - rawBuf->base());
00166     hp.parseAppToRaw();
00167 
00168     // generate mac value
00169     GenerateMacValue((AAAMessageBlock*)rawBuf, macAvp.value);
00170     PANA_MESSAGE_POOL()->free(rawBuf);
00171     msg.avpList().reset();
00172     return (true);
00173 }
00174 
00175 bool PANA_SecurityAssociation::ValidateMacValue(PANA_Message &msg)
00176 {
00177     try {
00178         if (m_MSK.size() == 0) {
00179             throw (PANA_Exception(PANA_Exception::FAILED, 
00180                                   "Warning: No MSK installed"));
00181         }
00182 
00183         AAAAvpContainer* c_macAvp = msg.avpList().search("Mac-Avp");
00184         if (c_macAvp == 0) {
00185             throw (PANA_Exception(PANA_Exception::FAILED, 
00186                                   "No MAC value found in the message"));
00187         }
00188         PANA_TVData_t &macAvp = (*c_macAvp)[0]->dataRef(Type2Type<PANA_TVData_t>());
00189 
00190         // verify type
00191         if (macAvp.type != PANA_MACGEN_HMACSHA1) {
00192             throw (PANA_Exception(PANA_Exception::FAILED, 
00193                                   "Warning: MAC algorithm not supported"));
00194         }
00195 
00196         // temporarily save the MAC value and insert 0 mac
00197         diameter_octetstring_t mvalue;
00198         mvalue.assign(macAvp.value.data(), macAvp.value.size());
00199 
00200 #if PANA_SA_DEBUG        
00201         printf("AVP Value: %d\n", mvalue.size());
00202         for (int i=0; i<mvalue.size(); i++) {
00203             printf("%02X ", ((char*)mvalue.data())[i]);
00204         }
00205         printf("\n");
00206 #endif
00207 
00208         // reset to zero
00209         char sbuf[PANA_MACGEN_HMACSIZE];
00210         ACE_OS::memset(sbuf, 0x0, sizeof(sbuf));
00211         macAvp.value.assign(sbuf, sizeof(sbuf));
00212         macAvp.type = PANA_MACGEN_HMACSHA1;
00213 
00214         PANA_MessageBuffer *aBuffer = PANA_MESSAGE_POOL()->malloc();
00215         msg.avpList().reset();
00216 
00217         // parse the message 
00218         PANA_HeaderParser hp;
00219         AAADictionaryOption opt(PARSE_STRICT, PANA_DICT_PROTOCOL_ID);
00220         hp.setRawData(reinterpret_cast<AAAMessageBlock*>(aBuffer));
00221         hp.setAppData(static_cast<PANA_MsgHeader*>(&msg));
00222         hp.setDictData(&opt);
00223 
00224         hp.parseAppToRaw();
00225 
00226         // Parse the payload
00227         PANA_PayloadParser pp;
00228         pp.setRawData(reinterpret_cast<AAAMessageBlock*>(aBuffer));
00229         pp.setAppData(&(msg.avpList()));
00230         pp.setDictData(msg.getDictHandle());
00231 
00232         pp.parseAppToRaw();
00233 
00234         // Re-do the header again to set the length
00235         msg.length(aBuffer->wr_ptr() - aBuffer->base());
00236         hp.parseAppToRaw();
00237 
00238         GenerateMacValue((AAAMessageBlock*)aBuffer, macAvp.value);
00239         
00240         // do comparison
00241         if (! (macAvp.value == mvalue)) {
00242             ACE_DEBUG((LM_ERROR, "(%P|%t) MAC value is invalid\n"));
00243         }
00244 
00245         PANA_MESSAGE_POOL()->free(aBuffer);
00246         return (true);
00247     }
00248     catch (AAAErrorStatus st) {
00249         ACE_DEBUG((LM_ERROR, "(%P|%t) Parsing error is session transmitter\n"));
00250     }  
00251     catch (PANA_Exception &e) {
00252         ACE_DEBUG((LM_ERROR, "(%P|%t) %s\n", e.description().data()));
00253     }
00254 
00255     return (false);
00256 }

Generated on Fri Jun 25 19:18:30 2004 for PANA by doxygen 1.3.5