00001
00002
00003
00004
00005
00006
00007
00008
00009 static const char rcsid[] __attribute__((used)) = "$Id: Crypt.cpp 1230 2014-11-16 02:32:01Z sella $";
00010
00011 #include "Crypt.h"
00012 #include "CommonMacro.h"
00013 #include "../Exception.h"
00014
00015 #ifndef SKIP_CRYPT
00016
00017 #include <mhash.h>
00018 #include <mutils/mhash.h>
00019 #include <string.h>
00020 #include <stdlib.h>
00021
00022
00023
00024 using namespace sella::util;
00025
00026 Crypt::Crypt(const char *algo, const char *mode, int keylen) : init(false), password(NULL), salt(NULL), key(NULL), iv(NULL), algo(algo), mode(mode) {
00027 time_t t;
00028
00029 td = mcrypt_module_open((char*) algo, NULL, (char*) mode, NULL);
00030
00031 if (mcrypt_enc_is_block_algorithm(td) == 1 && mcrypt_enc_is_block_mode(td) == 1) {
00032 THROW(Exception, "Crypt does not support block algorithm or block modes");
00033 }
00034
00035 setKeyLen(keylen);
00036
00037 time(&t);
00038 setFlipSeed((uint32_t) t);
00039
00040 setPassword(CRYPT_PASSWORD_DEF, CRYPT_SALT_DEF);
00041 }
00042
00043 Crypt::Crypt(const Crypt &other) :
00044 init(false),
00045 seed(other.seed),
00046 password(strdup(other.password)),
00047 salt(strdup(other.salt)),
00048 key((unsigned char *)malloc(other.keylen)),
00049 iv(NULL),
00050 keylen(other.keylen),
00051 algo(other.algo),
00052 mode(other.mode)
00053 {
00054 memcpy(this->key, other.key, this->keylen);
00055
00056 this->td = mcrypt_module_open((char*) this->algo.c_str(), NULL, (char*) this->mode.c_str(), NULL);
00057 }
00058
00059 Crypt::~Crypt() {
00060 clear();
00061
00062 mcrypt_module_close(td);
00063 }
00064
00065 Crypt& Crypt::operator=(const Crypt &other) throw () {
00066 if (this != &other) {
00067 clear();
00068
00069 this->init = false;
00070 this->seed = other.seed;
00071 this->password = strdup(other.password);
00072 this->salt = strdup(other.salt);
00073 this->iv = NULL;
00074 this->keylen = other.keylen;
00075 this->algo = other.algo;
00076 this->mode = other.mode;
00077
00078 key = (unsigned char *)malloc(this->keylen);
00079 memcpy(this->key, other.key, this->keylen);
00080
00081 this->td = mcrypt_module_open((char*) this->algo.c_str(), NULL, (char*) this->mode.c_str(), NULL);
00082 }
00083
00084 return *this;
00085 }
00086
00087 void Crypt::clear(void) {
00088 deinitialize();
00089
00090 SAFE_FREE(iv);
00091 SAFE_FREE(key);
00092 SAFE_FREE(salt);
00093 SAFE_FREE(password);
00094 }
00095
00096 void Crypt::setSeed(uint32_t seed) {
00097 this->seed = seed;
00098
00099 SAFE_FREE(iv);
00100 }
00101
00102 void Crypt::setFlipSeed(uint32_t seed, uint32_t pattern) {
00103 setSeed((~seed) ^ pattern);
00104 }
00105
00106 uint32_t Crypt::getSeed(void) const {
00107 return seed;
00108 }
00109
00110 bool Crypt::setPassword(const char *password, const char *salt) {
00111 KEYGEN data;
00112 int passlen, saltlen;
00113 unsigned char* key = NULL;
00114
00115 assert(password != NULL);
00116 assert(salt != NULL);
00117
00118 SAFE_FREE(this->password);
00119 SAFE_FREE(this->salt);
00120 SAFE_FREE(this->key);
00121
00122 if (password == NULL || salt == NULL) {
00123 goto error;
00124 }
00125
00126 if ((key = (unsigned char*) calloc(1, keylen)) == NULL) {
00127 goto error;
00128 }
00129
00130 if ((saltlen = mhash_get_keygen_salt_size(KEYGEN_MCRYPT)) == 0) {
00131 saltlen = strlen(salt);
00132 } else if (saltlen > (int) strlen(salt)) {
00133 saltlen = strlen(salt);
00134 }
00135
00136 data.hash_algorithm[0] = MHASH_MD5;
00137 data.count = 0;
00138 data.salt = (void*) salt;
00139 data.salt_size = saltlen;
00140 passlen = strlen(password);
00141
00142 if (mhash_keygen_ext(KEYGEN_MCRYPT, data, key, keylen, (unsigned char*) password, passlen) < 0) {
00143 goto error;
00144 }
00145
00146 this->key = key;
00147 this->password = strndup(password, passlen);
00148 this->salt = strndup(salt, saltlen);
00149
00150 #ifdef DUMP
00151 printf("key(%d): 0x", keylen);
00152 for (int i = 0; i < keylen; i++) {
00153 printf("%.2x", this->key[i]);
00154 }
00155 printf("\n");
00156 #endif
00157
00158 return true;
00159
00160 error:
00161 SAFE_FREE(key);
00162
00163 return false;
00164 }
00165
00166 const char* Crypt::getPassword(void) {
00167 return password;
00168 }
00169
00170 const unsigned char* Crypt::getKey(void) {
00171 return key;
00172 }
00173
00174 void Crypt::setKeyLen(int bits) {
00175 int maxlen = mcrypt_enc_get_key_size(td);
00176 keylen = bits / 8;
00177
00178 if (keylen > maxlen) {
00179 keylen = maxlen;
00180 } else if (keylen < 1) {
00181 keylen = CRYPT_KEYLEN_DEF;
00182 }
00183
00184
00185 if (password && salt) {
00186 char *tpassword = strdup(password);
00187 char *tsalt = strdup(salt);
00188
00189 setPassword(password, salt);
00190
00191 SAFE_FREE(tpassword);
00192 SAFE_FREE(tsalt);
00193 }
00194 }
00195
00196 int Crypt::getKeyLen(void) const {
00197 return (keylen * 8);
00198 }
00199
00200 bool Crypt::encrypt(char *plaintext, int len) {
00201 if (!plaintext || len < 1) {
00202 return false;
00203 }
00204
00205 if (!initialize()) {
00206 return false;
00207 }
00208
00209 return !mcrypt_generic(td, plaintext, len);
00210 }
00211
00212 bool Crypt::decrypt(char *ciphertext, int len) {
00213 if (!ciphertext || len < 1) {
00214 return false;
00215 }
00216
00217 if (!initialize()) {
00218 return false;
00219 }
00220
00221 return !mdecrypt_generic(td, ciphertext, len);
00222 }
00223
00224 bool Crypt::check(const char *ciphertext, int len) {
00225 bool retval;
00226 void *tmp;
00227
00228 if ((tmp = malloc(len)) == NULL) {
00229 return false;
00230 }
00231
00232 memcpy(tmp, ciphertext, len);
00233
00234 retval = decrypt((char*) tmp, len);
00235
00236 free(tmp);
00237
00238 return retval;
00239 }
00240
00241 bool Crypt::initialize(void) {
00242 if (!deinitialize()) {
00243 return false;
00244 }
00245
00246 if (iv == NULL) {
00247 if (!generateIV()) {
00248 return false;
00249 }
00250 }
00251
00252 if (mcrypt_generic_init(td, key, keylen, iv) >= 0) {
00253 init = true;
00254
00255 return true;
00256 }
00257
00258 return false;
00259 }
00260
00261 bool Crypt::deinitialize(void) {
00262 if (init) {
00263 init = false;
00264
00265 if (mcrypt_generic_deinit(td) < 0) {
00266 return false;
00267 }
00268 }
00269
00270 return true;
00271 }
00272
00273 bool Crypt::generateIV(void) {
00274 struct drand48_data state;
00275 long int result;
00276
00277 SAFE_FREE(iv);
00278
00279 int iv_size = mcrypt_enc_get_iv_size(td);
00280 if ((iv = (unsigned char*) malloc(iv_size)) == NULL) {
00281 return false;
00282 }
00283
00284 srand48_r(seed, &state);
00285 for (int i = 0; i < iv_size; i++) {
00286 lrand48_r(&state, &result);
00287 iv[i] = (unsigned char) result;
00288 }
00289
00290 #ifdef DUMP
00291 printf("iv(%d)[seed: %lu]: 0x", iv_size, seed);
00292 for (int i = 0; i < iv_size; i++) {
00293 printf("%.1x", iv[i]);
00294 }
00295 printf("\n");
00296 #endif
00297
00298 return true;
00299 }
00300
00301 #endif
00302
00303
00304
00305