<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1"> <title>Crypto++: seckey.h Source File</title> <link href="doxygen.css" rel="stylesheet" type="text/css"> </head><body> <!-- Generated by Doxygen 1.3.7 --> <div class="qindex"><a class="qindex" href="index.html">Main Page</a> | <a class="qindex" href="namespaces.html">Namespace List</a> | <a class="qindex" href="hierarchy.html">Class Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical List</a> | <a class="qindex" href="annotated.html">Class List</a> | <a class="qindex" href="files.html">File List</a> | <a class="qindex" href="namespacemembers.html">Namespace Members</a> | <a class="qindex" href="functions.html">Class Members</a> | <a class="qindex" href="globals.html">File Members</a></div> <h1>seckey.h</h1><pre class="fragment"><div>00001 <span class="comment">// seckey.h - written and placed in the public domain by Wei Dai</span> 00002 00003 <span class="comment">// This file contains helper classes/functions for implementing secret key algorithms.</span> 00004 00005 <span class="preprocessor">#ifndef CRYPTOPP_SECKEY_H</span> 00006 <span class="preprocessor"></span><span class="preprocessor">#define CRYPTOPP_SECKEY_H</span> 00007 <span class="preprocessor"></span> 00008 <span class="preprocessor">#include "<a class="code" href="cryptlib_8h.html">cryptlib.h</a>"</span> 00009 <span class="preprocessor">#include "misc.h"</span> 00010 <span class="preprocessor">#include "<a class="code" href="simple_8h.html">simple.h</a>"</span> 00011 00012 NAMESPACE_BEGIN(CryptoPP) 00013 00014 inline CipherDir ReverseCipherDir(CipherDir dir) 00015 { 00016 <span class="keywordflow">return</span> (dir == ENCRYPTION) ? DECRYPTION : ENCRYPTION; 00017 } 00018 <span class="comment"></span> 00019 <span class="comment">//! to be inherited by block ciphers with fixed block size</span> 00020 <span class="comment"></span><span class="keyword">template</span> <<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> N> <a name="l00021"></a><a class="code" href="class_fixed_block_size.html">00021</a> <span class="keyword">class </span><a class="code" href="class_fixed_block_size.html">FixedBlockSize</a> 00022 { 00023 <span class="keyword">public</span>: 00024 <span class="keyword">enum</span> {BLOCKSIZE = N}; 00025 }; 00026 00027 <span class="comment">// ************** rounds ***************</span> 00028 <span class="comment"></span> 00029 <span class="comment">//! to be inherited by ciphers with fixed number of rounds</span> 00030 <span class="comment"></span><span class="keyword">template</span> <<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> R> <a name="l00031"></a><a class="code" href="class_fixed_rounds.html">00031</a> <span class="keyword">class </span><a class="code" href="class_fixed_rounds.html">FixedRounds</a> 00032 { 00033 <span class="keyword">public</span>: 00034 <span class="keyword">enum</span> {ROUNDS = R}; 00035 00036 <span class="keyword">protected</span>: 00037 <span class="keyword">template</span> <<span class="keyword">class</span> T> 00038 <span class="keyword">static</span> <span class="keyword">inline</span> <span class="keywordtype">void</span> CheckedSetKey(T *obj, <a class="code" href="cryptlib_8h.html#a11">CipherDir</a> dir, <span class="keyword">const</span> byte *key, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> length, <span class="keyword">const</span> <a class="code" href="class_name_value_pairs.html">NameValuePairs</a> &param) 00039 { 00040 obj->ThrowIfInvalidKeyLength(length); 00041 <span class="keywordtype">int</span> rounds = param.<a class="code" href="class_name_value_pairs.html#_x_t_r___d_ha43">GetIntValueWithDefault</a>(<span class="stringliteral">"Rounds"</span>, ROUNDS); 00042 <span class="keywordflow">if</span> (rounds != ROUNDS) 00043 <span class="keywordflow">throw</span> <a class="code" href="class_invalid_rounds.html">InvalidRounds</a>(obj->StaticAlgorithmName(), rounds); 00044 obj->UncheckedSetKey(dir, key, length); 00045 } 00046 }; 00047 <span class="comment"></span> 00048 <span class="comment">//! to be inherited by ciphers with variable number of rounds</span> 00049 <span class="comment"></span><span class="keyword">template</span> <<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> D, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> N=1, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> M=INT_MAX> <span class="comment">// use INT_MAX here because enums are treated as signed ints</span> <a name="l00050"></a><a class="code" href="class_variable_rounds.html">00050</a> <span class="keyword">class </span><a class="code" href="class_variable_rounds.html">VariableRounds</a> 00051 { 00052 <span class="keyword">public</span>: 00053 <span class="keyword">enum</span> {DEFAULT_ROUNDS = D, MIN_ROUNDS = N, MAX_ROUNDS = M}; 00054 <span class="keyword">static</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> StaticGetDefaultRounds(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> keylength) {<span class="keywordflow">return</span> DEFAULT_ROUNDS;} 00055 00056 <span class="keyword">protected</span>: 00057 <span class="keyword">static</span> <span class="keyword">inline</span> <span class="keywordtype">void</span> AssertValidRounds(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> rounds) 00058 { 00059 assert(rounds >= (<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span>)MIN_ROUNDS && rounds <= (<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span>)MAX_ROUNDS); 00060 } 00061 00062 <span class="keyword">template</span> <<span class="keyword">class</span> T> 00063 <span class="keyword">static</span> <span class="keyword">inline</span> <span class="keywordtype">void</span> CheckedSetKey(T *obj, <a class="code" href="cryptlib_8h.html#a11">CipherDir</a> dir, <span class="keyword">const</span> byte *key, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> length, <span class="keyword">const</span> <a class="code" href="class_name_value_pairs.html">NameValuePairs</a> &param) 00064 { 00065 obj->ThrowIfInvalidKeyLength(length); 00066 <span class="keywordtype">int</span> rounds = param.<a class="code" href="class_name_value_pairs.html#_x_t_r___d_ha43">GetIntValueWithDefault</a>(<span class="stringliteral">"Rounds"</span>, obj->StaticGetDefaultRounds(length)); 00067 <span class="keywordflow">if</span> (rounds < (int)MIN_ROUNDS || rounds > (<span class="keywordtype">int</span>)MAX_ROUNDS) 00068 <span class="keywordflow">throw</span> <a class="code" href="class_invalid_rounds.html">InvalidRounds</a>(obj->AlgorithmName(), rounds); 00069 obj->UncheckedSetKey(dir, key, length, rounds); 00070 } 00071 }; 00072 00073 <span class="comment">// ************** key length ***************</span> 00074 <span class="comment"></span> 00075 <span class="comment">//! to be inherited by keyed algorithms with fixed key length</span> 00076 <span class="comment"></span><span class="keyword">template</span> <<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> N, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> IV_REQ = SimpleKeyingInterface::NOT_RESYNCHRONIZABLE> <a name="l00077"></a><a class="code" href="class_fixed_key_length.html">00077</a> <span class="keyword">class </span><a class="code" href="class_fixed_key_length.html">FixedKeyLength</a> 00078 { 00079 <span class="keyword">public</span>: 00080 <span class="keyword">enum</span> {KEYLENGTH=N, MIN_KEYLENGTH=N, MAX_KEYLENGTH=N, DEFAULT_KEYLENGTH=N}; 00081 <span class="keyword">enum</span> {IV_REQUIREMENT = IV_REQ}; 00082 <span class="keyword">static</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> StaticGetValidKeyLength(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span>) {<span class="keywordflow">return</span> KEYLENGTH;} 00083 }; 00084 <span class="comment"></span> 00085 <span class="comment">/// support query of variable key length, template parameters are default, min, max, multiple (default multiple 1)</span> 00086 <span class="comment"></span><span class="keyword">template</span> <<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> D, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> N, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> M, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> Q = 1, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> IV_REQ = SimpleKeyingInterface::NOT_RESYNCHRONIZABLE> <a name="l00087"></a><a class="code" href="class_variable_key_length.html">00087</a> <span class="keyword">class </span><a class="code" href="class_variable_key_length.html">VariableKeyLength</a> 00088 { 00089 <span class="comment">// make these private to avoid Doxygen documenting them in all derived classes</span> 00090 CRYPTOPP_COMPILE_ASSERT(Q > 0); 00091 CRYPTOPP_COMPILE_ASSERT(N % Q == 0); 00092 CRYPTOPP_COMPILE_ASSERT(M % Q == 0); 00093 CRYPTOPP_COMPILE_ASSERT(N < M); 00094 CRYPTOPP_COMPILE_ASSERT(D >= N && M >= D); 00095 00096 <span class="keyword">public</span>: 00097 <span class="keyword">enum</span> {MIN_KEYLENGTH=N, MAX_KEYLENGTH=M, DEFAULT_KEYLENGTH=D, KEYLENGTH_MULTIPLE=Q}; 00098 <span class="keyword">enum</span> {IV_REQUIREMENT = IV_REQ}; 00099 <span class="keyword">static</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> StaticGetValidKeyLength(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> n) 00100 { 00101 <span class="keywordflow">if</span> (n < (<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span>)MIN_KEYLENGTH) 00102 <span class="keywordflow">return</span> MIN_KEYLENGTH; 00103 <span class="keywordflow">else</span> <span class="keywordflow">if</span> (n > (<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span>)MAX_KEYLENGTH) 00104 <span class="keywordflow">return</span> (<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span>)MAX_KEYLENGTH; 00105 <span class="keywordflow">else</span> 00106 { 00107 n += KEYLENGTH_MULTIPLE-1; 00108 <span class="keywordflow">return</span> n - n%KEYLENGTH_MULTIPLE; 00109 } 00110 } 00111 }; 00112 <span class="comment"></span> 00113 <span class="comment">/// support query of key length that's the same as another class</span> 00114 <span class="comment"></span><span class="keyword">template</span> <<span class="keyword">class</span> T> <a name="l00115"></a><a class="code" href="class_same_key_length_as.html">00115</a> <span class="keyword">class </span><a class="code" href="class_same_key_length_as.html">SameKeyLengthAs</a> 00116 { 00117 <span class="keyword">public</span>: 00118 <span class="keyword">enum</span> {MIN_KEYLENGTH=T::MIN_KEYLENGTH, MAX_KEYLENGTH=T::MAX_KEYLENGTH, DEFAULT_KEYLENGTH=T::DEFAULT_KEYLENGTH}; 00119 <span class="keyword">enum</span> {IV_REQUIREMENT = T::IV_REQUIREMENT}; 00120 <span class="keyword">static</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> StaticGetValidKeyLength(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> keylength) 00121 {<span class="keywordflow">return</span> T::StaticGetValidKeyLength(keylength);} 00122 }; 00123 00124 <span class="comment">// ************** implementation helper for SimpledKeyed ***************</span> 00125 00126 <span class="keyword">template</span> <<span class="keyword">class</span> T> 00127 <span class="keyword">static</span> <span class="keyword">inline</span> <span class="keywordtype">void</span> CheckedSetKey(T *obj, Empty empty, <span class="keyword">const</span> byte *key, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> length, <span class="keyword">const</span> <a class="code" href="class_name_value_pairs.html">NameValuePairs</a> &param) 00128 { 00129 obj->ThrowIfInvalidKeyLength(length); 00130 obj->UncheckedSetKey(key, length); 00131 } 00132 00133 <span class="keyword">template</span> <<span class="keyword">class</span> T> 00134 <span class="keyword">static</span> <span class="keyword">inline</span> <span class="keywordtype">void</span> CheckedSetKey(T *obj, CipherDir dir, <span class="keyword">const</span> byte *key, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> length, <span class="keyword">const</span> <a class="code" href="class_name_value_pairs.html">NameValuePairs</a> &param) 00135 { 00136 obj->ThrowIfInvalidKeyLength(length); 00137 obj->UncheckedSetKey(dir, key, length); 00138 } 00139 <span class="comment"></span> 00140 <span class="comment">//! _</span> 00141 <span class="comment"></span><span class="keyword">template</span> <<span class="keyword">class</span> BASE, <span class="keyword">class</span> INFO = BASE> <a name="l00142"></a><a class="code" href="class_simple_keying_interface_impl.html">00142</a> <span class="keyword">class </span>CRYPTOPP_NO_VTABLE SimpleKeyingInterfaceImpl : <span class="keyword">public</span> BASE 00143 { 00144 <span class="keyword">public</span>: 00145 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> MinKeyLength()<span class="keyword"> const </span>{<span class="keywordflow">return</span> INFO::MIN_KEYLENGTH;} 00146 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> MaxKeyLength()<span class="keyword"> const </span>{<span class="keywordflow">return</span> (<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span>)INFO::MAX_KEYLENGTH;} 00147 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> DefaultKeyLength()<span class="keyword"> const </span>{<span class="keywordflow">return</span> INFO::DEFAULT_KEYLENGTH;} 00148 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> GetValidKeyLength(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> n)<span class="keyword"> const </span>{<span class="keywordflow">return</span> INFO::StaticGetValidKeyLength(n);} 00149 <span class="keyword">typename</span> BASE::IV_Requirement IVRequirement()<span class="keyword"> const </span>{<span class="keywordflow">return</span> (<span class="keyword">typename</span> BASE::IV_Requirement)INFO::IV_REQUIREMENT;} 00150 00151 <span class="keyword">protected</span>: 00152 <span class="keywordtype">void</span> AssertValidKeyLength(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> length) {assert(GetValidKeyLength(length) == length);} 00153 }; 00154 00155 <span class="keyword">template</span> <<span class="keyword">class</span> INFO, <span class="keyword">class</span> BASE = BlockCipher> 00156 <span class="keyword">class </span>CRYPTOPP_NO_VTABLE BlockCipherImpl : <span class="keyword">public</span> <a class="code" href="class_algorithm_impl.html">AlgorithmImpl</a><SimpleKeyingInterfaceImpl<TwoBases<BASE, INFO> > > 00157 { 00158 <span class="keyword">public</span>: 00159 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> BlockSize()<span class="keyword"> const </span>{<span class="keywordflow">return</span> this->BLOCKSIZE;} 00160 }; 00161 <span class="comment"></span> 00162 <span class="comment">//! _</span> 00163 <span class="comment"></span><span class="keyword">template</span> <CipherDir DIR, <span class="keyword">class</span> BASE> <a name="l00164"></a><a class="code" href="class_block_cipher_final.html">00164</a> <span class="keyword">class </span><a class="code" href="class_block_cipher_final.html">BlockCipherFinal</a> : <span class="keyword">public</span> <a class="code" href="class_clonable_impl.html">ClonableImpl</a><BlockCipherFinal<DIR, BASE>, BASE> 00165 { 00166 <span class="keyword">public</span>: 00167 <a class="code" href="class_block_cipher_final.html">BlockCipherFinal</a>() {} 00168 <a class="code" href="class_block_cipher_final.html">BlockCipherFinal</a>(<span class="keyword">const</span> byte *key) 00169 {SetKey(key, this->DEFAULT_KEYLENGTH);} 00170 <a class="code" href="class_block_cipher_final.html">BlockCipherFinal</a>(<span class="keyword">const</span> byte *key, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> length) 00171 {SetKey(key, length);} 00172 <a class="code" href="class_block_cipher_final.html">BlockCipherFinal</a>(<span class="keyword">const</span> byte *key, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> length, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> rounds) 00173 {this->SetKeyWithRounds(key, length, rounds);} 00174 00175 <span class="keywordtype">bool</span> IsForwardTransformation()<span class="keyword"> const </span>{<span class="keywordflow">return</span> DIR == ENCRYPTION;} 00176 00177 <span class="keywordtype">void</span> SetKey(<span class="keyword">const</span> byte *key, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> length, <span class="keyword">const</span> <a class="code" href="class_name_value_pairs.html">NameValuePairs</a> &param = g_nullNameValuePairs) 00178 { 00179 CheckedSetKey(<span class="keyword">this</span>, DIR, key, length, param); 00180 } 00181 }; 00182 <span class="comment"></span> 00183 <span class="comment">//! _</span> 00184 <span class="comment"></span><span class="keyword">template</span> <<span class="keyword">class</span> BASE, <span class="keyword">class</span> INFO = BASE> <a name="l00185"></a><a class="code" href="class_message_authentication_code_impl.html">00185</a> <span class="keyword">class </span><a class="code" href="class_message_authentication_code_impl.html">MessageAuthenticationCodeImpl</a> : <span class="keyword">public</span> <a class="code" href="class_algorithm_impl.html">AlgorithmImpl</a><SimpleKeyingInterfaceImpl<BASE, INFO>, INFO> 00186 { 00187 <span class="keyword">public</span>: 00188 <span class="keywordtype">void</span> SetKey(<span class="keyword">const</span> byte *key, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> length, <span class="keyword">const</span> <a class="code" href="class_name_value_pairs.html">NameValuePairs</a> &params = g_nullNameValuePairs) 00189 { 00190 CheckedSetKey(<span class="keyword">this</span>, Empty(), key, length, params); 00191 } 00192 }; 00193 <span class="comment"></span> 00194 <span class="comment">//! _</span> 00195 <span class="comment"></span><span class="keyword">template</span> <<span class="keyword">class</span> BASE> <a name="l00196"></a><a class="code" href="class_message_authentication_code_final.html">00196</a> <span class="keyword">class </span><a class="code" href="class_message_authentication_code_final.html">MessageAuthenticationCodeFinal</a> : <span class="keyword">public</span> <a class="code" href="class_clonable_impl.html">ClonableImpl</a><MessageAuthenticationCodeFinal<BASE>, MessageAuthenticationCodeImpl<BASE> > 00197 { 00198 <span class="keyword">public</span>: 00199 <a class="code" href="class_message_authentication_code_final.html">MessageAuthenticationCodeFinal</a>() {} 00200 <a class="code" href="class_message_authentication_code_final.html">MessageAuthenticationCodeFinal</a>(<span class="keyword">const</span> byte *key) 00201 {SetKey(key, this->DEFAULT_KEYLENGTH);} 00202 <a class="code" href="class_message_authentication_code_final.html">MessageAuthenticationCodeFinal</a>(<span class="keyword">const</span> byte *key, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> length) 00203 {this->SetKey(key, length);} 00204 }; 00205 00206 <span class="comment">// ************** documentation ***************</span> 00207 <span class="comment"></span> 00208 <span class="comment">//! These objects usually should not be used directly. See CipherModeDocumentation instead.</span> 00209 <span class="comment"></span><span class="comment">/*! Each class derived from this one defines two types, Encryption and Decryption, </span> 00210 <span class="comment"> both of which implement the BlockCipher interface. */</span> <a name="l00211"></a><a class="code" href="struct_block_cipher_documentation.html">00211</a> <span class="keyword">struct </span><a class="code" href="struct_block_cipher_documentation.html">BlockCipherDocumentation</a> 00212 {<span class="comment"></span> 00213 <span class="comment"> //! implements the BlockCipher interface</span> <a name="l00214"></a><a class="code" href="struct_block_cipher_documentation.html#_r_c2w9">00214</a> <span class="comment"></span> <span class="keyword">typedef</span> <a class="code" href="class_block_cipher.html">BlockCipher</a> <a class="code" href="class_block_cipher.html">Encryption</a>;<span class="comment"></span> 00215 <span class="comment"> //! implements the BlockCipher interface</span> <a name="l00216"></a><a class="code" href="struct_block_cipher_documentation.html#_r_c2w10">00216</a> <span class="comment"></span> <span class="keyword">typedef</span> <a class="code" href="class_block_cipher.html">BlockCipher</a> <a class="code" href="class_block_cipher.html">Decryption</a>; 00217 }; 00218 <span class="comment"></span> 00219 <span class="comment">/*! \brief Each class derived from this one defines two types, Encryption and Decryption, </span> 00220 <span class="comment"> both of which implement the SymmetricCipher interface. Two types of classes derive</span> 00221 <span class="comment"> from this class: stream ciphers and block cipher modes. Stream ciphers can be used</span> 00222 <span class="comment"> alone, cipher mode classes need to be used with a block cipher. See CipherModeDocumentation</span> 00223 <span class="comment"> for more for information about using cipher modes and block ciphers. */</span> <a name="l00224"></a><a class="code" href="struct_symmetric_cipher_documentation.html">00224</a> <span class="keyword">struct </span><a class="code" href="struct_symmetric_cipher_documentation.html">SymmetricCipherDocumentation</a> 00225 {<span class="comment"></span> 00226 <span class="comment"> //! implements the SymmetricCipher interface</span> <a name="l00227"></a><a class="code" href="struct_symmetric_cipher_documentation.html#_symmetric_cipher_documentationw0">00227</a> <span class="comment"></span> <span class="keyword">typedef</span> <a class="code" href="class_symmetric_cipher.html">SymmetricCipher</a> <a class="code" href="class_symmetric_cipher.html">Encryption</a>;<span class="comment"></span> 00228 <span class="comment"> //! implements the SymmetricCipher interface</span> <a name="l00229"></a><a class="code" href="struct_symmetric_cipher_documentation.html#_symmetric_cipher_documentationw1">00229</a> <span class="comment"></span> <span class="keyword">typedef</span> <a class="code" href="class_symmetric_cipher.html">SymmetricCipher</a> <a class="code" href="class_symmetric_cipher.html">Decryption</a>; 00230 }; 00231 00232 NAMESPACE_END 00233 00234 <span class="preprocessor">#endif</span> </div></pre><hr size="1"><address style="align: right;"><small>Generated on Sun Nov 7 08:23:59 2004 for Crypto++ by <a href="http://www.doxygen.org/index.html"> <img src="doxygen.png" alt="doxygen" align="middle" border=0 ></a> 1.3.7 </small></address> </body> </html>