AES CBC and CFB performance tune-up from HEAD.
authorAndy Polyakov <appro@openssl.org>
Thu, 30 Dec 2004 22:57:19 +0000 (22:57 +0000)
committerAndy Polyakov <appro@openssl.org>
Thu, 30 Dec 2004 22:57:19 +0000 (22:57 +0000)
crypto/aes/aes_cbc.c
crypto/aes/aes_cfb.c

index 1222a21002c1add66fcfbf5fe57c84475838102b..f909aaf47a19a1be0da7267206f3d7497432b393 100644 (file)
@@ -66,6 +66,7 @@ void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
        unsigned long n;
        unsigned long len = length;
        unsigned char tmp[AES_BLOCK_SIZE];
+       const unsigned char *iv = ivec;
 
        assert(in && out && key && ivec);
        assert((AES_ENCRYPT == enc)||(AES_DECRYPT == enc));
@@ -73,22 +74,39 @@ void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
        if (AES_ENCRYPT == enc) {
                while (len >= AES_BLOCK_SIZE) {
                        for(n=0; n < AES_BLOCK_SIZE; ++n)
-                               tmp[n] = in[n] ^ ivec[n];
-                       AES_encrypt(tmp, out, key);
-                       memcpy(ivec, out, AES_BLOCK_SIZE);
+                               out[n] = in[n] ^ iv[n];
+                       AES_encrypt(out, out, key);
+                       iv = out;
                        len -= AES_BLOCK_SIZE;
                        in += AES_BLOCK_SIZE;
                        out += AES_BLOCK_SIZE;
                }
                if (len) {
                        for(n=0; n < len; ++n)
-                               tmp[n] = in[n] ^ ivec[n];
+                               out[n] = in[n] ^ iv[n];
                        for(n=len; n < AES_BLOCK_SIZE; ++n)
-                               tmp[n] = ivec[n];
-                       AES_encrypt(tmp, tmp, key);
-                       memcpy(out, tmp, AES_BLOCK_SIZE);
-                       memcpy(ivec, tmp, AES_BLOCK_SIZE);
-               }                       
+                               out[n] = iv[n];
+                       AES_encrypt(out, out, key);
+                       iv = out;
+               }
+               memcpy(ivec,iv,AES_BLOCK_SIZE);
+       } else if (in != out) {
+               while (len >= AES_BLOCK_SIZE) {
+                       AES_decrypt(in, out, key);
+                       for(n=0; n < AES_BLOCK_SIZE; ++n)
+                               out[n] ^= iv[n];
+                       iv = in;
+                       len -= AES_BLOCK_SIZE;
+                       in  += AES_BLOCK_SIZE;
+                       out += AES_BLOCK_SIZE;
+               }
+               if (len) {
+                       AES_decrypt(in,tmp,key);
+                       for(n=0; n < len; ++n)
+                               out[n] = tmp[n] ^ iv[n];
+                       iv = in;
+               }
+               memcpy(ivec,iv,AES_BLOCK_SIZE);
        } else {
                while (len >= AES_BLOCK_SIZE) {
                        memcpy(tmp, in, AES_BLOCK_SIZE);
@@ -106,6 +124,6 @@ void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
                        for(n=0; n < len; ++n)
                                out[n] = tmp[n] ^ ivec[n];
                        memcpy(ivec, tmp, AES_BLOCK_SIZE);
-               }                       
+               }
        }
 }
index ab42cd5ecd242c70d41f7e9e2d599343ba252df0..49f0411010c371a0285ca22280a7f1ff1f609fb4 100644 (file)
@@ -158,61 +158,35 @@ void AES_cfb128_encrypt(const unsigned char *in, unsigned char *out,
 
 /* This expects a single block of size nbits for both in and out. Note that
    it corrupts any extra bits in the last byte of out */
-/* Untested, once it is working, it will be optimised */
 void AES_cfbr_encrypt_block(const unsigned char *in,unsigned char *out,
                            const int nbits,const AES_KEY *key,
                            unsigned char *ivec,const int enc)
     {
-    int n;
+    int n,rem,num;
     unsigned char ovec[AES_BLOCK_SIZE*2];
 
-    assert(in && out && key && ivec);
-    if(enc)
-       {
-       /* construct the new IV */
-       AES_encrypt(ivec,ovec,key);
-       /* encrypt the input */
-       for(n=0 ; n < (nbits+7)/8 ; ++n)
-           out[n]=in[n]^ovec[n];
-       /* fill in the first half of the new IV with the current IV */
-       memcpy(ovec,ivec,AES_BLOCK_SIZE);
-       /* and put the ciphertext in the second half */
-       memcpy(ovec+AES_BLOCK_SIZE,out,(nbits+7)/8);
-       /* shift ovec left most of the bits... */
-       memmove(ovec,ovec+nbits/8,AES_BLOCK_SIZE+(nbits%8 ? 1 : 0));
-       /* now the remaining bits */
-       if(nbits%8 != 0)
-           for(n=0 ; n < AES_BLOCK_SIZE ; ++n)
-               {
-               ovec[n]<<=nbits%8;
-               ovec[n]|=ovec[n+1]>>(8-nbits%8);
-               }
-       /* finally, move it back into place */
-       memcpy(ivec,ovec,AES_BLOCK_SIZE);
-       }
-    else
-       {
-       /* construct the new IV in the first half of ovec */
-       AES_encrypt(ivec,ovec,key);
-       /* decrypt the input */
-       for(n=0 ; n < (nbits+7)/8 ; ++n)
-           out[n]=in[n]^ovec[n];
+    if (nbits<=0 || nbits>128) return;
+
        /* fill in the first half of the new IV with the current IV */
        memcpy(ovec,ivec,AES_BLOCK_SIZE);
-       /* append the ciphertext */
-       memcpy(ovec+AES_BLOCK_SIZE,in,(nbits+7)/8);
-       /* shift ovec left most of the bits... */
-       memmove(ovec,ovec+nbits/8,AES_BLOCK_SIZE+(nbits%8 ? 1 : 0));
-       /* now the remaining bits */
-       if(nbits%8 != 0)
+       /* construct the new IV */
+       AES_encrypt(ivec,ivec,key);
+       num = (nbits+7)/8;
+       if (enc)        /* encrypt the input */
+           for(n=0 ; n < num ; ++n)
+               out[n] = (ovec[AES_BLOCK_SIZE+n] = in[n] ^ ivec[n]);
+       else            /* decrypt the input */
+           for(n=0 ; n < num ; ++n)
+               out[n] = (ovec[AES_BLOCK_SIZE+n] = in[n]) ^ ivec[n];
+       /* shift ovec left... */
+       rem = nbits%8;
+       num = nbits/8;
+       if(rem==0)
+           memcpy(ivec,ovec+num,AES_BLOCK_SIZE);
+       else
            for(n=0 ; n < AES_BLOCK_SIZE ; ++n)
-               {
-               ovec[n]<<=nbits%8;
-               ovec[n]|=ovec[n+1]>>(8-nbits%8);
-               }
-       /* finally, move it back into place */
-       memcpy(ivec,ovec,AES_BLOCK_SIZE);
-       }
+               ivec[n] = ovec[n+num]<<rem | ovec[n+num+1]>>(8-rem);
+
     /* it is not necessary to cleanse ovec, since the IV is not secret */
     }