"Fossies" - the Fresh Open Source Software Archive

Member "openssl-1.0.2q/crypto/aes/aes_ige.c" (20 Nov 2018, 11686 Bytes) of package /linux/misc/openssl-1.0.2q.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "aes_ige.c" see the Fossies "Dox" file reference documentation.

    1 /* crypto/aes/aes_ige.c */
    2 /* ====================================================================
    3  * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  *
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  *
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in
   14  *    the documentation and/or other materials provided with the
   15  *    distribution.
   16  *
   17  * 3. All advertising materials mentioning features or use of this
   18  *    software must display the following acknowledgment:
   19  *    "This product includes software developed by the OpenSSL Project
   20  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
   21  *
   22  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
   23  *    endorse or promote products derived from this software without
   24  *    prior written permission. For written permission, please contact
   25  *    openssl-core@openssl.org.
   26  *
   27  * 5. Products derived from this software may not be called "OpenSSL"
   28  *    nor may "OpenSSL" appear in their names without prior written
   29  *    permission of the OpenSSL Project.
   30  *
   31  * 6. Redistributions of any form whatsoever must retain the following
   32  *    acknowledgment:
   33  *    "This product includes software developed by the OpenSSL Project
   34  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
   35  *
   36  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
   37  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   38  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   39  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
   40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   42  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   43  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   44  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   45  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   46  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
   47  * OF THE POSSIBILITY OF SUCH DAMAGE.
   48  * ====================================================================
   49  *
   50  */
   51 
   52 #include "cryptlib.h"
   53 
   54 #include <openssl/aes.h>
   55 #include "aes_locl.h"
   56 
   57 #define N_WORDS (AES_BLOCK_SIZE / sizeof(unsigned long))
   58 typedef struct {
   59     unsigned long data[N_WORDS];
   60 } aes_block_t;
   61 
   62 /* XXX: probably some better way to do this */
   63 #if defined(__i386__) || defined(__x86_64__)
   64 # define UNALIGNED_MEMOPS_ARE_FAST 1
   65 #else
   66 # define UNALIGNED_MEMOPS_ARE_FAST 0
   67 #endif
   68 
   69 #if UNALIGNED_MEMOPS_ARE_FAST
   70 # define load_block(d, s)        (d) = *(const aes_block_t *)(s)
   71 # define store_block(d, s)       *(aes_block_t *)(d) = (s)
   72 #else
   73 # define load_block(d, s)        memcpy((d).data, (s), AES_BLOCK_SIZE)
   74 # define store_block(d, s)       memcpy((d), (s).data, AES_BLOCK_SIZE)
   75 #endif
   76 
   77 /* N.B. The IV for this mode is _twice_ the block size */
   78 
   79 void AES_ige_encrypt(const unsigned char *in, unsigned char *out,
   80                      size_t length, const AES_KEY *key,
   81                      unsigned char *ivec, const int enc)
   82 {
   83     size_t n;
   84     size_t len = length;
   85 
   86     OPENSSL_assert(in && out && key && ivec);
   87     OPENSSL_assert((AES_ENCRYPT == enc) || (AES_DECRYPT == enc));
   88     OPENSSL_assert((length % AES_BLOCK_SIZE) == 0);
   89 
   90     len = length / AES_BLOCK_SIZE;
   91 
   92     if (AES_ENCRYPT == enc) {
   93         if (in != out &&
   94             (UNALIGNED_MEMOPS_ARE_FAST
   95              || ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(long) ==
   96              0)) {
   97             aes_block_t *ivp = (aes_block_t *) ivec;
   98             aes_block_t *iv2p = (aes_block_t *) (ivec + AES_BLOCK_SIZE);
   99 
  100             while (len) {
  101                 aes_block_t *inp = (aes_block_t *) in;
  102                 aes_block_t *outp = (aes_block_t *) out;
  103 
  104                 for (n = 0; n < N_WORDS; ++n)
  105                     outp->data[n] = inp->data[n] ^ ivp->data[n];
  106                 AES_encrypt((unsigned char *)outp->data,
  107                             (unsigned char *)outp->data, key);
  108                 for (n = 0; n < N_WORDS; ++n)
  109                     outp->data[n] ^= iv2p->data[n];
  110                 ivp = outp;
  111                 iv2p = inp;
  112                 --len;
  113                 in += AES_BLOCK_SIZE;
  114                 out += AES_BLOCK_SIZE;
  115             }
  116             memcpy(ivec, ivp->data, AES_BLOCK_SIZE);
  117             memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE);
  118         } else {
  119             aes_block_t tmp, tmp2;
  120             aes_block_t iv;
  121             aes_block_t iv2;
  122 
  123             load_block(iv, ivec);
  124             load_block(iv2, ivec + AES_BLOCK_SIZE);
  125 
  126             while (len) {
  127                 load_block(tmp, in);
  128                 for (n = 0; n < N_WORDS; ++n)
  129                     tmp2.data[n] = tmp.data[n] ^ iv.data[n];
  130                 AES_encrypt((unsigned char *)tmp2.data,
  131                             (unsigned char *)tmp2.data, key);
  132                 for (n = 0; n < N_WORDS; ++n)
  133                     tmp2.data[n] ^= iv2.data[n];
  134                 store_block(out, tmp2);
  135                 iv = tmp2;
  136                 iv2 = tmp;
  137                 --len;
  138                 in += AES_BLOCK_SIZE;
  139                 out += AES_BLOCK_SIZE;
  140             }
  141             memcpy(ivec, iv.data, AES_BLOCK_SIZE);
  142             memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE);
  143         }
  144     } else {
  145         if (in != out &&
  146             (UNALIGNED_MEMOPS_ARE_FAST
  147              || ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(long) ==
  148              0)) {
  149             aes_block_t *ivp = (aes_block_t *) ivec;
  150             aes_block_t *iv2p = (aes_block_t *) (ivec + AES_BLOCK_SIZE);
  151 
  152             while (len) {
  153                 aes_block_t tmp;
  154                 aes_block_t *inp = (aes_block_t *) in;
  155                 aes_block_t *outp = (aes_block_t *) out;
  156 
  157                 for (n = 0; n < N_WORDS; ++n)
  158                     tmp.data[n] = inp->data[n] ^ iv2p->data[n];
  159                 AES_decrypt((unsigned char *)tmp.data,
  160                             (unsigned char *)outp->data, key);
  161                 for (n = 0; n < N_WORDS; ++n)
  162                     outp->data[n] ^= ivp->data[n];
  163                 ivp = inp;
  164                 iv2p = outp;
  165                 --len;
  166                 in += AES_BLOCK_SIZE;
  167                 out += AES_BLOCK_SIZE;
  168             }
  169             memcpy(ivec, ivp->data, AES_BLOCK_SIZE);
  170             memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE);
  171         } else {
  172             aes_block_t tmp, tmp2;
  173             aes_block_t iv;
  174             aes_block_t iv2;
  175 
  176             load_block(iv, ivec);
  177             load_block(iv2, ivec + AES_BLOCK_SIZE);
  178 
  179             while (len) {
  180                 load_block(tmp, in);
  181                 tmp2 = tmp;
  182                 for (n = 0; n < N_WORDS; ++n)
  183                     tmp.data[n] ^= iv2.data[n];
  184                 AES_decrypt((unsigned char *)tmp.data,
  185                             (unsigned char *)tmp.data, key);
  186                 for (n = 0; n < N_WORDS; ++n)
  187                     tmp.data[n] ^= iv.data[n];
  188                 store_block(out, tmp);
  189                 iv = tmp2;
  190                 iv2 = tmp;
  191                 --len;
  192                 in += AES_BLOCK_SIZE;
  193                 out += AES_BLOCK_SIZE;
  194             }
  195             memcpy(ivec, iv.data, AES_BLOCK_SIZE);
  196             memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE);
  197         }
  198     }
  199 }
  200 
  201 /*
  202  * Note that its effectively impossible to do biIGE in anything other
  203  * than a single pass, so no provision is made for chaining.
  204  */
  205 
  206 /* N.B. The IV for this mode is _four times_ the block size */
  207 
  208 void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out,
  209                         size_t length, const AES_KEY *key,
  210                         const AES_KEY *key2, const unsigned char *ivec,
  211                         const int enc)
  212 {
  213     size_t n;
  214     size_t len = length;
  215     unsigned char tmp[AES_BLOCK_SIZE];
  216     unsigned char tmp2[AES_BLOCK_SIZE];
  217     unsigned char tmp3[AES_BLOCK_SIZE];
  218     unsigned char prev[AES_BLOCK_SIZE];
  219     const unsigned char *iv;
  220     const unsigned char *iv2;
  221 
  222     OPENSSL_assert(in && out && key && ivec);
  223     OPENSSL_assert((AES_ENCRYPT == enc) || (AES_DECRYPT == enc));
  224     OPENSSL_assert((length % AES_BLOCK_SIZE) == 0);
  225 
  226     if (AES_ENCRYPT == enc) {
  227         /*
  228          * XXX: Do a separate case for when in != out (strictly should check
  229          * for overlap, too)
  230          */
  231 
  232         /* First the forward pass */
  233         iv = ivec;
  234         iv2 = ivec + AES_BLOCK_SIZE;
  235         while (len >= AES_BLOCK_SIZE) {
  236             for (n = 0; n < AES_BLOCK_SIZE; ++n)
  237                 out[n] = in[n] ^ iv[n];
  238             AES_encrypt(out, out, key);
  239             for (n = 0; n < AES_BLOCK_SIZE; ++n)
  240                 out[n] ^= iv2[n];
  241             iv = out;
  242             memcpy(prev, in, AES_BLOCK_SIZE);
  243             iv2 = prev;
  244             len -= AES_BLOCK_SIZE;
  245             in += AES_BLOCK_SIZE;
  246             out += AES_BLOCK_SIZE;
  247         }
  248 
  249         /* And now backwards */
  250         iv = ivec + AES_BLOCK_SIZE * 2;
  251         iv2 = ivec + AES_BLOCK_SIZE * 3;
  252         len = length;
  253         while (len >= AES_BLOCK_SIZE) {
  254             out -= AES_BLOCK_SIZE;
  255             /*
  256              * XXX: reduce copies by alternating between buffers
  257              */
  258             memcpy(tmp, out, AES_BLOCK_SIZE);
  259             for (n = 0; n < AES_BLOCK_SIZE; ++n)
  260                 out[n] ^= iv[n];
  261             /*
  262              * hexdump(stdout, "out ^ iv", out, AES_BLOCK_SIZE);
  263              */
  264             AES_encrypt(out, out, key);
  265             /*
  266              * hexdump(stdout,"enc", out, AES_BLOCK_SIZE);
  267              */
  268             /*
  269              * hexdump(stdout,"iv2", iv2, AES_BLOCK_SIZE);
  270              */
  271             for (n = 0; n < AES_BLOCK_SIZE; ++n)
  272                 out[n] ^= iv2[n];
  273             /*
  274              * hexdump(stdout,"out", out, AES_BLOCK_SIZE);
  275              */
  276             iv = out;
  277             memcpy(prev, tmp, AES_BLOCK_SIZE);
  278             iv2 = prev;
  279             len -= AES_BLOCK_SIZE;
  280         }
  281     } else {
  282         /* First backwards */
  283         iv = ivec + AES_BLOCK_SIZE * 2;
  284         iv2 = ivec + AES_BLOCK_SIZE * 3;
  285         in += length;
  286         out += length;
  287         while (len >= AES_BLOCK_SIZE) {
  288             in -= AES_BLOCK_SIZE;
  289             out -= AES_BLOCK_SIZE;
  290             memcpy(tmp, in, AES_BLOCK_SIZE);
  291             memcpy(tmp2, in, AES_BLOCK_SIZE);
  292             for (n = 0; n < AES_BLOCK_SIZE; ++n)
  293                 tmp[n] ^= iv2[n];
  294             AES_decrypt(tmp, out, key);
  295             for (n = 0; n < AES_BLOCK_SIZE; ++n)
  296                 out[n] ^= iv[n];
  297             memcpy(tmp3, tmp2, AES_BLOCK_SIZE);
  298             iv = tmp3;
  299             iv2 = out;
  300             len -= AES_BLOCK_SIZE;
  301         }
  302 
  303         /* And now forwards */
  304         iv = ivec;
  305         iv2 = ivec + AES_BLOCK_SIZE;
  306         len = length;
  307         while (len >= AES_BLOCK_SIZE) {
  308             memcpy(tmp, out, AES_BLOCK_SIZE);
  309             memcpy(tmp2, out, AES_BLOCK_SIZE);
  310             for (n = 0; n < AES_BLOCK_SIZE; ++n)
  311                 tmp[n] ^= iv2[n];
  312             AES_decrypt(tmp, out, key);
  313             for (n = 0; n < AES_BLOCK_SIZE; ++n)
  314                 out[n] ^= iv[n];
  315             memcpy(tmp3, tmp2, AES_BLOCK_SIZE);
  316             iv = tmp3;
  317             iv2 = out;
  318             len -= AES_BLOCK_SIZE;
  319             in += AES_BLOCK_SIZE;
  320             out += AES_BLOCK_SIZE;
  321         }
  322     }
  323 }