Wiselib
|
00001 /*************************************************************************** 00002 ** This file is part of the generic algorithm library Wiselib. ** 00003 ** Copyright (C) 2008,2009 by the Wisebed (www.wisebed.eu) project. ** 00004 ** ** 00005 ** The Wiselib is free software: you can redistribute it and/or modify ** 00006 ** it under the terms of the GNU Lesser General Public License as ** 00007 ** published by the Free Software Foundation, either version 3 of the ** 00008 ** License, or (at your option) any later version. ** 00009 ** ** 00010 ** The Wiselib is distributed in the hope that it will be useful, ** 00011 ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** 00012 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** 00013 ** GNU Lesser General Public License for more details. ** 00014 ** ** 00015 ** You should have received a copy of the GNU Lesser General Public ** 00016 ** License along with the Wiselib. ** 00017 ** If not, see <http://www.gnu.org/licenses/>. ** 00018 ***************************************************************************/ 00019 00020 #ifndef __ALGORITHMS_CRYPTO_ECIESFP_H__ 00021 #define __ALGORITHMS_CRYPTO_ECIESFP_H__ 00022 00023 //hash length (case of sha-1 hash) 00024 #define HMAC_LEN 20 00025 00026 //max msg length according to radio 00027 //maximum payload size 116 bytes e.g for iSense radio 00028 00029 //case of 128-bit elliptic curve (34 + msg + HMAC_LEN) 00030 //#define MAX_M_LEN 62 00031 00032 //case of 160-bit elliptic curve (42 + msg + HMAC_LEN) 00033 #define MAX_M_LEN 54 00034 00035 //case of 192-bit elliptic curve (50 + msg + HMAC_LEN) 00036 //#define MAX_M_LEN 46 00037 00038 #include "algorithms/crypto/eccfp.h" 00039 #include "algorithms/crypto/pmp.h" 00040 #include "algorithms/crypto/sha1.h" 00041 #include <string.h> 00042 00043 namespace wiselib 00044 { 00055 template<typename OsModel_P> 00056 class ECIESFP 00057 { 00058 public: 00059 typedef OsModel_P OsModel; 00060 00063 ECIESFP(); 00064 ~ECIESFP(); 00066 00069 void enable( void ); 00070 void disable( void ); 00072 00076 int8_t encrypt(uint8_t * input, uint8_t * output, int8_t msg_length, Point *KeyA ); 00077 int8_t decrypt(uint8_t * input, uint8_t * output, int8_t msg_length, NN_DIGIT *KeyB); 00078 00079 //initialize parameter for private key generation 00080 void key_setup(uint8_t seed); 00081 00082 private: 00083 //objects for necessary classes 00084 ECCFP eccfp; 00085 PMP pmp; 00086 uint8_t seed1; 00087 }; 00088 00089 // ----------------------------------------------------------------------- 00090 template<typename OsModel_P> 00091 ECIESFP<OsModel_P>:: 00092 ECIESFP() 00093 {} 00094 // ----------------------------------------------------------------------- 00095 template<typename OsModel_P> 00096 ECIESFP<OsModel_P>:: 00097 ~ECIESFP() 00098 {} 00099 // ----------------------------------------------------------------------- 00100 template<typename OsModel_P> 00101 void 00102 ECIESFP<OsModel_P>:: 00103 enable( void ) 00104 { 00105 } 00106 // ----------------------------------------------------------------------- 00107 template<typename OsModel_P> 00108 void 00109 ECIESFP<OsModel_P>:: 00110 disable( void ) 00111 { 00112 } 00113 //---------------------------------------------------------------------------- 00114 template<typename OsModel_P> 00115 int8_t 00116 ECIESFP<OsModel_P>:: 00117 encrypt(uint8_t * input, uint8_t * output, int8_t msg_length, Point *KeyA ) 00118 { 00119 NN_DIGIT k[NUMWORDS]; 00120 uint8_t z[KEYDIGITS*NN_DIGIT_LEN +1]; 00121 00122 //clear points 00123 Point R, P; 00124 eccfp.p_clear(&P); 00125 eccfp.p_clear(&R); 00126 00127 int8_t octet_len; 00128 uint8_t K[MAX_M_LEN + HMAC_LEN]; 00129 int8_t i; 00130 00131 //generate private and public key 00132 eccfp.gen_private_key(k, seed1); 00133 eccfp.gen_public_key(&R, k); 00134 00135 //2. convert R to octet string 00136 octet_len = eccfp.point2octet(output, 2*(KEYDIGITS*NN_DIGIT_LEN + 1), &R, FALSE) + 1; 00137 00138 //3. derive shared secret z=P.x 00139 eccfp.c_mul(&P, KeyA, k); 00140 00141 if (eccfp.p_iszero(&P)) 00142 return -1; 00143 00144 //4. convert z= P.x to octet string Z 00145 pmp.Encode(z, KEYDIGITS * NN_DIGIT_LEN +1, P.x, NUMWORDS); 00146 00147 //5. use KDF to generate K of length enckeylen + mackeylen octets from z 00148 //enckeylen = message length, mackeylen = 20 00149 SHA1::KDF(K, msg_length + HMAC_LEN, z); 00150 00151 //6. encrypt the message 00152 for (i=0; i<msg_length; i++) 00153 { 00154 output[octet_len+i] = input[i] ^ K[i]; 00155 } 00156 00157 //7. generate mac D on the encrypted data + key 00158 SHA1::hmac_sha1(output + octet_len, msg_length, K + msg_length, HMAC_LEN, output + octet_len + msg_length); 00159 00160 //8. output C = R||EM||D 00161 return (octet_len + msg_length + HMAC_LEN); 00162 } 00163 00164 //--------------------------------------------------------------------------- 00165 template<typename OsModel_P> 00166 int8_t 00167 ECIESFP<OsModel_P>:: 00168 decrypt(uint8_t * input, uint8_t * output, int8_t msg_length, NN_DIGIT *KeyB) 00169 { 00170 //total length 00171 int8_t LEN = 2*(KEYDIGITS * NN_DIGIT_LEN +1) + msg_length + HMAC_LEN; 00172 00173 uint8_t z[KEYDIGITS*NN_DIGIT_LEN + 1]; 00174 00175 //initialize points 00176 Point R, P; 00177 eccfp.p_clear(&P); 00178 eccfp.p_clear(&R); 00179 00180 int8_t octet_len; 00181 uint8_t K[MAX_M_LEN + HMAC_LEN]; 00182 int8_t i; 00183 uint8_t hmac_tmp[HMAC_LEN]; 00184 00185 //1. parse R||EM||D and 00186 //2. get the point R 00187 octet_len = eccfp.octet2point(&R, input, 2*(KEYDIGITS * NN_DIGIT_LEN +1)) +1; 00188 00189 //3. check if R is valid 00190 if (eccfp.check_point(&R) != 1) 00191 return 3; 00192 00193 //4. use private key to generate shared secret z 00194 eccfp.c_mul(&P, &R, KeyB); 00195 00196 if (eccfp.p_iszero(&P)) 00197 return 4; 00198 00199 //5. convert z = P.x to octet string 00200 pmp.Encode(z, KEYDIGITS * NN_DIGIT_LEN + 1, P.x, NUMWORDS); 00201 00202 //6. use KDF to derive EK and MK 00203 SHA1::KDF(K, msg_length + HMAC_LEN, z); 00204 00205 //7. check D first 00206 if (msg_length < LEN - HMAC_LEN - octet_len) 00207 return 5; 00208 00209 SHA1::hmac_sha1(input + octet_len, msg_length, K + msg_length, HMAC_LEN, hmac_tmp); 00210 00211 for (i=0; i < HMAC_LEN; i++) 00212 { 00213 if (hmac_tmp[i] != input[octet_len + msg_length + i]) 00214 return 6; 00215 } 00216 00217 //8. decrypt 00218 for(i=0; i< msg_length; i++) 00219 { 00220 output[i] = input[octet_len + i] ^ K[i]; 00221 } 00222 00223 return msg_length; 00224 } 00225 00226 //------------------------------------------------------------------------------ 00227 template<typename OsModel_P> 00228 void 00229 ECIESFP<OsModel_P>:: 00230 key_setup(uint8_t seed) 00231 { 00232 //seed used for private key generation 00233 seed1 = seed; 00234 } 00235 00236 } //end of wiselib namespace 00237 00238 #endif