00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #ifdef __HAVE_MMSCRYPT__
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #include <errno.h>
00044 #include <string.h>
00045 #include <openssl/rand.h>
00046 #include <openssl/aes.h>
00047
00048 #include "mmstools/mmscrypt.h"
00049 #include "mmstools/mmsfile.h"
00050
00051 unsigned char* MMSCrypt::createUserKey(string keyfile) {
00052 MMSFile *file;
00053 unsigned char *userKey, *userKeyEnc;
00054 size_t numWritten = 0;
00055
00056
00057 RAND_set_rand_method(RAND_SSLeay());
00058 userKey = (unsigned char*)malloc(EVP_MAX_KEY_LENGTH + EVP_MAX_IV_LENGTH);
00059 if(!userKey) {
00060 return NULL;
00061 }
00062 RAND_bytes(userKey, EVP_MAX_KEY_LENGTH + EVP_MAX_IV_LENGTH);
00063 RAND_cleanup();
00064
00065 userKeyEnc = encrypt(userKey, EVP_MAX_KEY_LENGTH + EVP_MAX_IV_LENGTH, true);
00066
00067
00068 file = new MMSFile(keyfile, MMSFM_WRITE);
00069 file->writeBuffer((void*)userKeyEnc, &numWritten, 16, 1);
00070 delete(file);
00071
00072 return userKey;
00073 }
00074
00075 unsigned char* MMSCrypt::getUserKey(string keyfile) {
00076 unsigned char *userKey, *userKeyEnc;
00077 MMSFile *file;
00078 size_t numRead = 0;
00079
00080
00081
00082
00083 file = new MMSFile(keyfile);
00084 if((file->getLastError() != 0) &&
00085 (keyfile != MMSCRYPT_DEFAULT_KEY_FILENAME))
00086 file = new MMSFile(MMSCRYPT_DEFAULT_KEY_FILENAME);
00087
00088 switch(file->getLastError()) {
00089 case 0 :
00090 file->readBufferEx((void**)&userKeyEnc, &numRead);
00091 userKey = decrypt(userKeyEnc, EVP_MAX_KEY_LENGTH + EVP_MAX_IV_LENGTH, true);
00092 delete(file);
00093 break;
00094 case ENOENT :
00095 delete(file);
00096 userKey = createUserKey(file->getName());
00097 break;
00098 default :
00099 delete(file);
00100 throw MMSCryptError(0, "file " + keyfile + " could not be opened (" + strerror(file->getLastError()) + ")");
00101 }
00102
00103 return userKey;
00104 }
00105
00106 MMSCrypt::MMSCrypt(string keyfile) {
00107 unsigned char mmskey[] = {0x25, 0x04, 0x19, 0x79, 0xaf, 0xfe, 0x1a, 0x3d};
00108 unsigned char mmsiv[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
00109 unsigned char *userKey = NULL;
00110
00111
00112 EVP_CIPHER_CTX_init(&mmsCtx);
00113 EVP_EncryptInit_ex(&mmsCtx, EVP_aes_128_cbc(), 0, mmskey, mmsiv);
00114
00115
00116 userKey = getUserKey(keyfile);
00117 EVP_CIPHER_CTX_init(&userCtx);
00118 EVP_EncryptInit_ex(&userCtx, EVP_aes_128_cbc(), 0, &userKey[0], &userKey[EVP_MAX_KEY_LENGTH - 1]);
00119
00120
00121 free(userKey);
00122 }
00123
00124 MMSCrypt::~MMSCrypt() {
00125 EVP_CIPHER_CTX_cleanup(&mmsCtx);
00126 EVP_CIPHER_CTX_cleanup(&userCtx);
00127 }
00128
00129 unsigned char* MMSCrypt::encrypt(unsigned char *in, unsigned int size, bool useMMSCtx) {
00130 unsigned char *out;
00131 int inl, tmp, ol = 0;
00132 EVP_CIPHER_CTX *ctx;
00133
00134 ((size == 0) ? inl = strlen((char*)in) : inl = size);
00135 (useMMSCtx ? ctx = &mmsCtx : ctx = &userCtx);
00136
00137 if(!(out = (unsigned char*)malloc(inl + EVP_CIPHER_CTX_block_size(ctx))))
00138 throw MMSCryptError(0, "not enough memory available");
00139
00140 for(int i = 0; i < inl / 128; i++) {
00141 if(!EVP_EncryptUpdate(ctx, &out[ol], &tmp, &in[ol], 128)) {
00142 free(out);
00143 throw MMSCryptError(0, "error while encrypting data");
00144 }
00145 ol += tmp;
00146 }
00147
00148 if(inl % 128) {
00149 if(!EVP_EncryptUpdate(ctx, &out[ol], &tmp, &in[ol], inl % 128)) {
00150 free(out);
00151 throw MMSCryptError(0, "error while encrypting data");
00152 }
00153 ol += tmp;
00154 }
00155
00156 if(!EVP_EncryptFinal_ex(ctx, &out[ol], &tmp)) {
00157 free(out);
00158 throw MMSCryptError(0, "error while encrypting data");
00159 }
00160
00161 return out;
00162 }
00163
00164 unsigned char* MMSCrypt::decrypt(unsigned char *in, unsigned int size, bool useMMSCtx) {
00165 unsigned char *out;
00166 int inl, ol;
00167 EVP_CIPHER_CTX *ctx;
00168
00169 ((size == 0) ? inl = strlen((char*)in) : inl = size);
00170 (useMMSCtx ? ctx = &mmsCtx : ctx = &userCtx);
00171
00172 if(!(out = (unsigned char*)malloc(inl + EVP_CIPHER_CTX_block_size(ctx) + 1)))
00173 throw MMSCryptError(0, "not enough memory available");
00174
00175 EVP_DecryptUpdate(ctx, out, &ol, in, inl);
00176
00177
00178 if(!ol) {
00179 free(out);
00180 return 0;
00181 }
00182
00183
00184 out[ol] = 0;
00185 return out;
00186 }
00187
00188 #endif