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 // $Id: eap_archie_crypto.hxx,v 1.4 2004/06/17 21:13:36 yohba Exp $ 00034 00035 // EAP-Archie cryptographic functions. 00036 // Written by Yoshihiro Ohba (yohba@tari.toshiba.com) 00037 00038 #ifndef __EAP_ARCHIE_CRYPTO_HXX__ 00039 #define __EAP_ARCHIE_CRYPTO_HXX__ 00040 00041 #include <openssl/aes.h> 00042 #include <string.h> 00043 00044 /* From draft-jwalker-eap-archie-01.txt: 00045 00046 3.1. AES-CBC-MAC-128 and AES-CBC-MAC-96 00047 00048 This section reviews the definition of the AES-CBC-MAC. 00049 00050 Let K denote an AES key, and let AES-Encrypt denote the AES encrypt 00051 primitive. The AES-CBC-MAC-128 of a string S is defined using the 00052 following steps: 00053 00054 a. Let L denote the length of S in octets. Let L' = L + p, where p 00055 is the unique integer 0 <= p < 16 needed so that L' is a 00056 multiple of 16. 00057 b. Let n = L'/16, and partition S into substrings, such that 00058 S = S[1] S[2] ... S[n-1] S'[n], with S[1], S[2], ..., S[n-1] 00059 consisting of 16 octets each and S'[n] consisting of 16 octets 00060 if p is 0 and 16-p octets otherwise. Let S[n] = S'[n]0^p, where 00061 0^p denotes p octets of zero pad. 00062 c. Set IV to 16 zero octets. 00063 d. For i = 1 to n do 00064 IV = AES-Encrypt(K, S[i] XOR IV) 00065 e. Return IV. 00066 00067 The EAP-Archie protocol uses a variant of AES-CBC-MAC-128 called 00068 AES-CBC-MAC-96. This variant differs from the AES-CBC-MAC-128 00069 described above in only step e, which it replaces by: 00070 00071 e'. Return the first 12 octets of IV. 00072 00073 Note that any padding added in step b is used to compute the MAC value 00074 only, and is never sent as part of an EAP-Archie message. 00075 */ 00076 00078 class EapCryptoAES_CBC_MAC 00079 { 00080 public: 00081 enum MAC_LengthType { 00082 MAC_Length96, 00083 MAC_Length128 00084 }; 00091 void operator()(std::string& in, std::string& out, 00092 std::string& sharedSecret, MAC_LengthType lengthType) 00093 { 00094 // Number of 16-octet blocks. 00095 int L = (int)in.size(); 00096 int n = (L - 1) / 16 + 1; 00097 00098 AES_KEY key; 00099 AES_set_encrypt_key((const unsigned char*)sharedSecret.data(), 128, &key); 00100 00101 std::string tmp(16*n, '\0'); 00102 tmp.replace(0, in.size(), in); 00103 00104 unsigned char IV[16]; 00105 ACE_OS::memset(IV, 0, sizeof IV); 00106 00107 for (int i=0; i<n; i++) 00108 { 00109 const char* S = tmp.data() + 16*i; 00110 // Calculate XOR. 00111 for (int j=0; j<16; j++) { IV[j] ^= S[j]; } 00112 AES_encrypt((const unsigned char*)IV, IV, &key); 00113 } 00114 out.assign((char*)IV, (lengthType == MAC_Length96) ? 12 : 16); 00115 } 00116 }; 00117 00118 /* From draft-jwalker-eap-archie-01.txt: 00119 00120 3.2. The Archie-PRF 00121 00122 This section defines the Archie-PRF function. 00123 00124 Let K denote a key, and let Length denote the number of octets 00125 desired. The Archie-PRF of a string S is defined by the following 00126 steps: 00127 00128 a. Output is initialized to the null string. 00129 b. For i = 1 to (Length+15)/16 do 00130 Output = Output | AES-CBC-MAC-128(K, i | S | Length) 00131 c. Return first Length octets of Output 00132 00133 In step b, the loop index i and the Length are encoded as 32-bit 00134 big-Endian unsigned integers. 00135 00136 */ 00137 00139 class EapCryptoArchiePRF 00140 { 00141 public: 00142 void operator()(std::string& in, std::string& out, std::string& sharedSecret, 00143 ACE_UINT32 length) 00144 { 00145 out.assign(""); 00146 std::string tmp; 00147 ACE_UINT32 lengthNBO = ntohl(length); // representation of length 00148 // in networkbyte order. 00149 for (ACE_UINT32 i=1; i <= (length+15)/16; i++) 00150 { 00151 ACE_UINT32 iNBO = ntohl(i); // representation of i in network 00152 // byte order. 00153 tmp.assign((char*)&iNBO, sizeof iNBO); 00154 tmp.append(in); 00155 tmp.append((char*)&lengthNBO, sizeof lengthNBO); 00156 EapCryptoAES_CBC_MAC mac; 00157 mac(tmp, tmp, sharedSecret, EapCryptoAES_CBC_MAC::MAC_Length128); 00158 out.append(tmp); 00159 } 00160 out.resize(length); 00161 } 00162 }; 00163 00164 #endif