Logo
  • Main Page
  • Related Pages
  • Modules
  • Classes
  • Files

mmscrypt.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2005-2007 Stefan Schwarzer, Jens Schneider,             *
00003  *                           Matthias Hardt, Guido Madaus                  *
00004  *                                                                         *
00005  *   Copyright (C) 2007-2008 BerLinux Solutions GbR                        *
00006  *                           Stefan Schwarzer & Guido Madaus               *
00007  *                                                                         *
00008  *   Copyright (C) 2009-2013 BerLinux Solutions GmbH                       *
00009  *                                                                         *
00010  *   Authors:                                                              *
00011  *      Stefan Schwarzer   <stefan.schwarzer@diskohq.org>,                 *
00012  *      Matthias Hardt     <matthias.hardt@diskohq.org>,                   *
00013  *      Jens Schneider     <jens.schneider@diskohq.org>,                   *
00014  *      Guido Madaus       <guido.madaus@diskohq.org>,                     *
00015  *      Patrick Helterhoff <patrick.helterhoff@diskohq.org>,               *
00016  *      René Bählkow       <rene.baehlkow@diskohq.org>                     *
00017  *                                                                         *
00018  *   This library is free software; you can redistribute it and/or         *
00019  *   modify it under the terms of the GNU Lesser General Public            *
00020  *   License version 2.1 as published by the Free Software Foundation.     *
00021  *                                                                         *
00022  *   This library is distributed in the hope that it will be useful,       *
00023  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00024  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00025  *   Lesser General Public License for more details.                       *
00026  *                                                                         *
00027  *   You should have received a copy of the GNU Lesser General Public      *
00028  *   License along with this library; if not, write to the                 *
00029  *   Free Software Foundation, Inc.,                                       *
00030  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
00031  **************************************************************************/
00032 
00033 #ifdef __HAVE_MMSCRYPT__
00034 
00035 /**
00036  * @file mmscrypt.cpp
00037  *
00038  * Implementation of MMSCrypt class.
00039  *
00040  * @ingroup mmstools
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     /* generate random key */
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     /* write key to file */
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     /* try to open keyfile for reading                   */
00081     /* if it fails and the filename differs from default */
00082     /* try the default file                              */
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     /* initialise our private cipher context */
00112     EVP_CIPHER_CTX_init(&mmsCtx);
00113     EVP_EncryptInit_ex(&mmsCtx, EVP_aes_128_cbc(), 0, mmskey, mmsiv);
00114 
00115     /* initialise user cipher context */
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     /* free memory */
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     /* nothing to decrypt */
00178     if(!ol) {
00179         free(out);
00180         return 0;
00181     }
00182 
00183     /* null-terminate output */
00184     out[ol] = 0;
00185     return out;
00186 }
00187 
00188 #endif /* __HAVE_MMSCRYPT__ */

Generated by doxygen