Mixe for Privacy and Anonymity in the Internet
CASymCipher.cpp
Go to the documentation of this file.
00001 /*
00002 Copyright (c) 2000, The JAP-Team
00003 All rights reserved.
00004 Redistribution and use in source and binary forms, with or without modification,
00005 are permitted provided that the following conditions are met:
00006 
00007   - Redistributions of source code must retain the above copyright notice,
00008     this list of conditions and the following disclaimer.
00009 
00010   - Redistributions in binary form must reproduce the above copyright notice,
00011     this list of conditions and the following disclaimer in the documentation and/or
00012     other materials provided with the distribution.
00013 
00014   - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors
00015     may be used to endorse or promote products derived from this software without specific
00016     prior written permission.
00017 
00018 
00019 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
00020 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
00021 AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS
00022 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00023 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
00024 OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
00025 IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
00027 */
00028 #include "StdAfx.h"
00029 #include "CASymCipher.hpp"
00030 //AES
00031 
00036 SINT32 CASymCipher::setKey(const UINT8* key)
00037 {
00038   return setKey(key,true);
00039 }
00040 
00046 SINT32 CASymCipher::setKey(const UINT8* key,bool bEncrypt)
00047 {
00048 #ifdef INTEL_IPP_CRYPTO
00049   ippsRijndael128Init(key, IppsRijndaelKey128,m_keyAES1);
00050   ippsRijndael128Init(key, IppsRijndaelKey128,m_keyAES2);
00051 #else
00052   if(bEncrypt)
00053     {
00054       AES_set_encrypt_key(key,128,m_keyAES1);
00055       AES_set_encrypt_key(key,128,m_keyAES2);
00056     }
00057   else
00058     {
00059       AES_set_decrypt_key(key,128,m_keyAES1);
00060       AES_set_decrypt_key(key,128,m_keyAES2);
00061     }
00062 #endif
00063   memset(m_iv1,0,16);
00064   memset(m_iv2,0,16);
00065   m_bKeySet=true;
00066   return E_SUCCESS;
00067 }
00068 
00069 SINT32 CASymCipher::setKeys(const UINT8* key,UINT32 keysize)
00070 {
00071   if(keysize==KEY_SIZE)
00072     {
00073       return setKey(key);
00074     }
00075   else if(keysize==2*KEY_SIZE)
00076     {
00077 #ifdef INTEL_IPP_CRYPTO
00078       ippsRijndael128Init(key, IppsRijndaelKey128,m_keyAES1);
00079       ippsRijndael128Init(key+KEY_SIZE, IppsRijndaelKey128,m_keyAES2);
00080 #else
00081       AES_set_encrypt_key(key,128,m_keyAES1);
00082       AES_set_encrypt_key(key+KEY_SIZE,128,m_keyAES2);
00083 #endif
00084       memset(m_iv1,0,16);
00085       memset(m_iv2,0,16);
00086       m_bKeySet=true;
00087       return E_SUCCESS;
00088     }
00089   return E_UNKNOWN;
00090 }
00091 
00104 SINT32 CASymCipher::crypt1(const UINT8* in,UINT8* out,UINT32 len)
00105 {
00106 #ifdef INTEL_IPP_CRYPTO
00107   UINT32 k=len&0xFFFFFFF0;
00108   ippsRijndael128EncryptOFB(in,out,k,16, m_keyAES1,m_iv1);
00109 //        if((len%16)!=0)
00110 //          {
00111   ippsRijndael128EncryptOFB(in+k,out+k,len%16,len%16, m_keyAES1,m_iv1);
00112 //          }
00113   return E_SUCCESS;
00114 #endif
00115   UINT32 i=0;
00116   while(i+15<len)
00117     {
00118 #ifdef INTEL_IPP_CRYPTO
00119       ippsRijndael128EncryptECB(m_iv1,m_iv1,KEY_SIZE, m_keyAES1, IppsCPPaddingNONE);
00120 #else
00121       AES_encrypt(m_iv1,m_iv1,m_keyAES1);
00122 #endif
00123       out[i]=in[i]^m_iv1[0];
00124       i++;
00125       out[i]=in[i]^m_iv1[1];
00126       i++;
00127       out[i]=in[i]^m_iv1[2];
00128       i++;
00129       out[i]=in[i]^m_iv1[3];
00130       i++;
00131       out[i]=in[i]^m_iv1[4];
00132       i++;
00133       out[i]=in[i]^m_iv1[5];
00134       i++;
00135       out[i]=in[i]^m_iv1[6];
00136       i++;
00137       out[i]=in[i]^m_iv1[7];
00138       i++;
00139       out[i]=in[i]^m_iv1[8];
00140       i++;
00141       out[i]=in[i]^m_iv1[9];
00142       i++;
00143       out[i]=in[i]^m_iv1[10];
00144       i++;
00145       out[i]=in[i]^m_iv1[11];
00146       i++;
00147       out[i]=in[i]^m_iv1[12];
00148       i++;
00149       out[i]=in[i]^m_iv1[13];
00150       i++;
00151       out[i]=in[i]^m_iv1[14];
00152       i++;
00153       out[i]=in[i]^m_iv1[15];
00154       i++;
00155     }
00156   if(i<len) //In this case len-i<16 !
00157     {
00158 #ifdef INTEL_IPP_CRYPTO
00159       ippsRijndael128EncryptECB(m_iv1,m_iv1,KEY_SIZE, m_keyAES1, IppsCPPaddingNONE);
00160 #else
00161       AES_encrypt(m_iv1,m_iv1,m_keyAES1);
00162 #endif
00163       len-=i;
00164       for(UINT32 k=0; k<len; k++)
00165         {
00166           out[i]=in[i]^m_iv1[k];
00167           i++;
00168         }
00169     }
00170   return E_SUCCESS;
00171 }
00172 
00180 SINT32 CASymCipher::crypt2(const UINT8* in,UINT8* out,UINT32 len)
00181 {
00182   UINT32 i=0;
00183   while(i+15<len)
00184     {
00185 #ifdef INTEL_IPP_CRYPTO
00186       ippsRijndael128EncryptECB(m_iv1,m_iv1,KEY_SIZE, m_keyAES2, IppsCPPaddingNONE);
00187 #else
00188       AES_encrypt(m_iv2,m_iv2,m_keyAES2);
00189 #endif
00190       out[i]=in[i]^m_iv2[0];
00191       i++;
00192       out[i]=in[i]^m_iv2[1];
00193       i++;
00194       out[i]=in[i]^m_iv2[2];
00195       i++;
00196       out[i]=in[i]^m_iv2[3];
00197       i++;
00198       out[i]=in[i]^m_iv2[4];
00199       i++;
00200       out[i]=in[i]^m_iv2[5];
00201       i++;
00202       out[i]=in[i]^m_iv2[6];
00203       i++;
00204       out[i]=in[i]^m_iv2[7];
00205       i++;
00206       out[i]=in[i]^m_iv2[8];
00207       i++;
00208       out[i]=in[i]^m_iv2[9];
00209       i++;
00210       out[i]=in[i]^m_iv2[10];
00211       i++;
00212       out[i]=in[i]^m_iv2[11];
00213       i++;
00214       out[i]=in[i]^m_iv2[12];
00215       i++;
00216       out[i]=in[i]^m_iv2[13];
00217       i++;
00218       out[i]=in[i]^m_iv2[14];
00219       i++;
00220       out[i]=in[i]^m_iv2[15];
00221       i++;
00222     }
00223   if(i<len)
00224     {
00225 #ifdef INTEL_IPP_CRYPTO
00226       ippsRijndael128EncryptECB(m_iv1,m_iv1,KEY_SIZE, m_keyAES2, IppsCPPaddingNONE);
00227 #else
00228       AES_encrypt(m_iv2,m_iv2,m_keyAES2);
00229 #endif
00230       len-=i;
00231       for(UINT32 k=0; k<len; k++)
00232         {
00233           out[i]=in[i]^m_iv2[k];
00234           i++;
00235         }
00236     }
00237   return E_SUCCESS;
00238 }
00239 
00249 SINT32 CASymCipher::decrypt1CBCwithPKCS7(const UINT8* in,UINT8* out,UINT32* len)
00250 {
00251   if(in==NULL||out==NULL||len==NULL||*len==0)
00252     return E_UNKNOWN;
00253 #ifdef INTEL_IPP_CRYPTO
00254 #else
00255   AES_cbc_encrypt(in,out,*len,m_keyAES1,m_iv1,AES_DECRYPT);
00256   //Now remove padding
00257   UINT32 pad=out[*len-1];
00258   if(pad>16||pad>*len)
00259     return E_UNKNOWN;
00260   for(UINT32 i=*len-pad; i<*len-1; i++)
00261     if(out[i]!=pad)
00262       return E_UNKNOWN;
00263   *len-=pad;
00264 #endif
00265   return E_SUCCESS;
00266 }
00267 
00277 SINT32 CASymCipher::encrypt1CBCwithPKCS7(const UINT8* in,UINT32 inlen,UINT8* out,UINT32* len)
00278 {
00279 #ifdef INTEL_IPP_CRYPTO
00280 #else
00281   UINT32 padlen=16-(inlen%16);
00282   if(inlen+padlen>(*len))
00283     {
00284       return E_SPACE;
00285     }
00286   UINT8* tmp=new UINT8[inlen+padlen];
00287   memcpy(tmp,in,inlen);
00288   for(UINT32 i=inlen; i<inlen+padlen; i++)
00289     {
00290       tmp[i]=(UINT8)padlen;
00291     }
00292   AES_cbc_encrypt(tmp,out,inlen+padlen,m_keyAES1,m_iv1,AES_ENCRYPT);
00293   delete[] tmp;
00294   tmp = NULL;
00295   *len=inlen+padlen;
00296 #endif
00297   return E_SUCCESS;
00298 }
00299 
00300 SINT32 CASymCipher::testSpeed()
00301 {
00302   const UINT32 runs=1000000;
00303   CASymCipher* pCipher=new CASymCipher();
00304   UINT8 key[16];
00305   UINT8* inBuff=new UINT8[1024];
00306   getRandom(key,16);
00307   getRandom(inBuff,1024);
00308   pCipher->setKey(key);
00309   UINT64 start,end;
00310   getcurrentTimeMillis(start);
00311   for(UINT32 i=0; i<runs; i++)
00312     {
00313       pCipher->crypt1(inBuff,inBuff,1023);
00314     }
00315   getcurrentTimeMillis(end);
00316   UINT32 d=diff64(end,start);
00317   printf("CASymCiper::testSpeed() takes %u ms for %u * 1023 Bytes!\n",d,runs);
00318   return E_SUCCESS;
00319 }
00320 
00321 void CASymCipher::setGCMKeys(UINT8* keyRecv, UINT8* keySend)
00322 {
00323 
00324 #ifndef USE_OPENSSL_GCM
00325   m_pGCMCtxEnc = new gcm_ctx_64k;
00326   m_pGCMCtxDec = new gcm_ctx_64k;
00327 #else
00328   //Note the have to provide *some* key (OpenSSL API enforced --> so the use the variables we have anyway..)
00329   // The Key will be overriden by a call to setKeyGCM in any case!
00330   AES_set_encrypt_key(m_iv1,128,m_keyAES1);
00331   m_pGCMCtxEnc = CRYPTO_gcm128_new(m_keyAES1,(block128_f)AES_encrypt);
00332   m_pGCMCtxDec = CRYPTO_gcm128_new(m_keyAES1,(block128_f)AES_encrypt);
00333 #endif
00334 
00335 
00336 
00337 #ifndef USE_OPENSSL_GCM
00338   if(m_pGCMCtxDec!=NULL)
00339     delete m_pGCMCtxDec;
00340   if(m_pGCMCtxEnc!=NULL)
00341     delete m_pGCMCtxEnc;
00342 
00343   m_pGCMCtxEnc = new gcm_ctx_64k;
00344   m_pGCMCtxDec = new gcm_ctx_64k;
00345   gcm_init_64k(m_pGCMCtxEnc, keySend, 128);
00346   gcm_init_64k(m_pGCMCtxDec, keyRecv, 128);
00347 #else
00348   AES_set_encrypt_key(keyRecv,128,m_keyAES1);
00349   AES_set_encrypt_key(keySend,128,m_keyAES2);
00350   CRYPTO_gcm128_release(m_pGCMCtxEnc);
00351   CRYPTO_gcm128_release(m_pGCMCtxDec);
00352   m_pGCMCtxEnc=CRYPTO_gcm128_new(m_keyAES2,(block128_f)AES_encrypt);
00353   m_pGCMCtxDec=CRYPTO_gcm128_new(m_keyAES1,(block128_f)AES_encrypt);
00354 #endif
00355   //reset IV
00356   m_nEncMsgCounter = 0;
00357   memset(m_pEncMsgIV, 0, 12);
00358   m_nDecMsgCounter = 0;
00359   memset(m_pDecMsgIV, 0, 12);
00360 }
00361 
00362 SINT32 CASymCipher::encryptMessage(const UINT8* const in, UINT32 inlen, UINT8* out)
00363 {
00364   //m_pcsEnc->lock();
00365   m_pEncMsgIV[2] = htonl(m_nEncMsgCounter);
00366   m_nEncMsgCounter++;
00367 #ifndef USE_OPENSSL_GCM
00368   gcm_encrypt_64k(m_pGCMCtxEnc, m_pEncMsgIV, in, inlen, out, (UINT32*)(out + inlen));
00369 #else
00370   CRYPTO_gcm128_setiv(m_pGCMCtxEnc,(UINT8*)m_pEncMsgIV,12);
00371   CRYPTO_gcm128_encrypt(m_pGCMCtxEnc,in,out,inlen);
00372   CRYPTO_gcm128_tag(m_pGCMCtxEnc,out+inlen,16);
00373 #endif
00374   //m_pcsEnc->unlock();
00375   return E_SUCCESS;
00376 }
00377 
00378 SINT32 CASymCipher::decryptMessage(const UINT8* in, UINT32 inlen, UINT8* out, bool integrityCheck)
00379 {
00380   SINT32 ret = E_UNKNOWN;
00381   //m_pcsDec->lock();
00382   m_pDecMsgIV[2] = htonl(m_nDecMsgCounter);
00383   if (integrityCheck)
00384     {
00385       m_nDecMsgCounter++;
00386 #ifndef USE_OPENSSL_GCM
00387       ret = ::gcm_decrypt_64k(m_pGCMCtxDec, m_pDecMsgIV, in, inlen - 16, in + inlen - 16, out);
00388 #else
00389       CRYPTO_gcm128_setiv(m_pGCMCtxDec,(UINT8*)m_pDecMsgIV,12);
00390       CRYPTO_gcm128_decrypt(m_pGCMCtxDec,in,out,inlen-16);
00391       ret=CRYPTO_gcm128_finish(m_pGCMCtxDec,in + inlen - 16,16);
00392 #endif
00393     }
00394   else
00395     {
00396 #ifndef USE_OPENSSL_GCM
00397       ret = ::gcm_decrypt_64k(m_pGCMCtxDec, m_pDecMsgIV, in, inlen, out);
00398 #else
00399       CRYPTO_gcm128_setiv(m_pGCMCtxDec,(UINT8*)m_pDecMsgIV,12);
00400       ret=CRYPTO_gcm128_decrypt(m_pGCMCtxDec,in,out,inlen);
00401 #endif
00402     }
00403   //m_pcsDec->unlock();
00404 #ifndef USE_OPENSSL_GCM
00405   if(ret==0)
00406 #else
00407   if(ret!=0)
00408 #endif
00409     return E_UNKNOWN;
00410   return E_SUCCESS;
00411 }