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   m_pGCMCtxEnc = new gcm_ctx_64k;
00323   m_pGCMCtxDec = new gcm_ctx_64k;
00324   gcm_init_64k(m_pGCMCtxEnc, keySend, 128);
00325   gcm_init_64k(m_pGCMCtxDec, keyRecv, 128);
00326 }
00327 
00328 SINT32 CASymCipher::encryptMessage(const UINT8* in, UINT32 inlen, UINT8* out)
00329   {
00330     //m_pcsEnc->lock();
00331     m_pEncMsgIV[2] = htonl(m_nEncMsgCounter);
00332     m_nEncMsgCounter++;
00333     gcm_encrypt_64k(m_pGCMCtxEnc, m_pEncMsgIV, in, inlen, out, (UINT32*)(out + inlen));
00334     //m_pcsEnc->unlock();
00335     return E_SUCCESS;
00336   }
00337 
00338 SINT32 CASymCipher::decryptMessage(const UINT8* in, UINT32 inlen, UINT8* out, bool integrityCheck) 
00339   {
00340     SINT32 ret = E_UNKNOWN;
00341     //m_pcsDec->lock();
00342     m_pDecMsgIV[2] = htonl(m_nDecMsgCounter);
00343     if (integrityCheck)
00344       {
00345         m_nDecMsgCounter++;
00346         ret = ::gcm_decrypt_64k(m_pGCMCtxDec, m_pDecMsgIV, in, inlen - 16, in + inlen - 16, out);
00347       }
00348     else
00349       {
00350         ret = ::gcm_decrypt_64k(m_pGCMCtxDec, m_pDecMsgIV, in, inlen, out);
00351       }
00352     //m_pcsDec->unlock();
00353     if(ret==0)
00354       return E_UNKNOWN;
00355     return E_SUCCESS;
00356   }