LCOV - code coverage report
Current view: top level - cipher - bufhelp.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 95 100 95.0 %
Date: 2017-03-02 16:44:37 Functions: 15 15 100.0 %

          Line data    Source code
       1             : /* bufhelp.h  -  Some buffer manipulation helpers
       2             :  * Copyright (C) 2012-2017 Jussi Kivilinna <jussi.kivilinna@iki.fi>
       3             :  *
       4             :  * This file is part of Libgcrypt.
       5             :  *
       6             :  * Libgcrypt is free software; you can redistribute it and/or modify
       7             :  * it under the terms of the GNU Lesser General Public License as
       8             :  * published by the Free Software Foundation; either version 2.1 of
       9             :  * the License, or (at your option) any later version.
      10             :  *
      11             :  * Libgcrypt is distributed in the hope that it will be useful,
      12             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :  * GNU Lesser General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU Lesser General Public
      17             :  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
      18             :  */
      19             : #ifndef GCRYPT_BUFHELP_H
      20             : #define GCRYPT_BUFHELP_H
      21             : 
      22             : 
      23             : #include "g10lib.h"
      24             : #include "bithelp.h"
      25             : 
      26             : 
      27             : #undef BUFHELP_UNALIGNED_ACCESS
      28             : #if defined(HAVE_GCC_ATTRIBUTE_PACKED) && \
      29             :     defined(HAVE_GCC_ATTRIBUTE_ALIGNED) && \
      30             :     defined(HAVE_GCC_ATTRIBUTE_MAY_ALIAS)
      31             : /* Compiler is supports attributes needed for automatically issuing unaligned
      32             :    memory access instructions.
      33             :  */
      34             : # define BUFHELP_UNALIGNED_ACCESS 1
      35             : #endif
      36             : 
      37             : 
      38             : #undef BUFHELP_FAST_UNALIGNED_ACCESS
      39             : #if defined(BUFHELP_UNALIGNED_ACCESS) && \
      40             :     (defined(__i386__) || defined(__x86_64__) || \
      41             :      (defined(__arm__) && defined(__ARM_FEATURE_UNALIGNED)) || \
      42             :      defined(__aarch64__))
      43             : /* These architectures are able of unaligned memory accesses and can
      44             :    handle those fast.
      45             :  */
      46             : # define BUFHELP_FAST_UNALIGNED_ACCESS 1
      47             : #endif
      48             : 
      49             : 
      50             : #ifdef BUFHELP_FAST_UNALIGNED_ACCESS
      51             : /* Define type with one-byte alignment on architectures with fast unaligned
      52             :    memory accesses.
      53             :  */
      54             : typedef struct bufhelp_int_s
      55             : {
      56             :   uintptr_t a;
      57             : } __attribute__((packed, aligned(1), may_alias)) bufhelp_int_t;
      58             : #else
      59             : /* Define type with default alignment for other architectures (unaligned
      60             :    accessed handled in per byte loops).
      61             :  */
      62             : #ifdef HAVE_GCC_ATTRIBUTE_MAY_ALIAS
      63             : typedef struct bufhelp_int_s
      64             : {
      65             :   uintptr_t a;
      66             : } __attribute__((may_alias)) bufhelp_int_t;
      67             : #else
      68             : typedef struct bufhelp_int_s
      69             : {
      70             :   uintptr_t a;
      71             : } bufhelp_int_t;
      72             : #endif
      73             : #endif
      74             : 
      75             : 
      76             : /* Optimized function for small buffer copying */
      77             : static inline void
      78    17848000 : buf_cpy(void *_dst, const void *_src, size_t len)
      79             : {
      80             : #if __GNUC__ >= 4 && (defined(__x86_64__) || defined(__i386__))
      81             :   /* For AMD64 and i386, memcpy is faster.  */
      82    17848000 :   memcpy(_dst, _src, len);
      83             : #else
      84             :   byte *dst = _dst;
      85             :   const byte *src = _src;
      86             :   bufhelp_int_t *ldst;
      87             :   const bufhelp_int_t *lsrc;
      88             : #ifndef BUFHELP_FAST_UNALIGNED_ACCESS
      89             :   const unsigned int longmask = sizeof(bufhelp_int_t) - 1;
      90             : 
      91             :   /* Skip fast processing if buffers are unaligned.  */
      92             :   if (UNLIKELY(((uintptr_t)dst | (uintptr_t)src) & longmask))
      93             :     goto do_bytes;
      94             : #endif
      95             : 
      96             :   ldst = (bufhelp_int_t *)(void *)dst;
      97             :   lsrc = (const bufhelp_int_t *)(const void *)src;
      98             : 
      99             :   for (; len >= sizeof(bufhelp_int_t); len -= sizeof(bufhelp_int_t))
     100             :     (ldst++)->a = (lsrc++)->a;
     101             : 
     102             :   dst = (byte *)ldst;
     103             :   src = (const byte *)lsrc;
     104             : 
     105             : #ifndef BUFHELP_FAST_UNALIGNED_ACCESS
     106             : do_bytes:
     107             : #endif
     108             :   /* Handle tail.  */
     109             :   for (; len; len--)
     110             :     *dst++ = *src++;
     111             : #endif /*__GNUC__ >= 4 && (__x86_64__ || __i386__)*/
     112    17848000 : }
     113             : 
     114             : 
     115             : /* Optimized function for buffer xoring */
     116             : static inline void
     117    45255156 : buf_xor(void *_dst, const void *_src1, const void *_src2, size_t len)
     118             : {
     119    45255156 :   byte *dst = _dst;
     120    45255156 :   const byte *src1 = _src1;
     121    45255156 :   const byte *src2 = _src2;
     122             :   bufhelp_int_t *ldst;
     123             :   const bufhelp_int_t *lsrc1, *lsrc2;
     124             : #ifndef BUFHELP_FAST_UNALIGNED_ACCESS
     125             :   const unsigned int longmask = sizeof(bufhelp_int_t) - 1;
     126             : 
     127             :   /* Skip fast processing if buffers are unaligned.  */
     128             :   if (UNLIKELY(((uintptr_t)dst | (uintptr_t)src1 | (uintptr_t)src2) & longmask))
     129             :     goto do_bytes;
     130             : #endif
     131             : 
     132    45255156 :   ldst = (bufhelp_int_t *)(void *)dst;
     133    45255156 :   lsrc1 = (const bufhelp_int_t *)(const void *)src1;
     134    45255156 :   lsrc2 = (const bufhelp_int_t *)(const void *)src2;
     135             : 
     136   133375314 :   for (; len >= sizeof(bufhelp_int_t); len -= sizeof(bufhelp_int_t))
     137    88120158 :     (ldst++)->a = (lsrc1++)->a ^ (lsrc2++)->a;
     138             : 
     139    45255156 :   dst = (byte *)ldst;
     140    45255156 :   src1 = (const byte *)lsrc1;
     141    45255156 :   src2 = (const byte *)lsrc2;
     142             : 
     143             : #ifndef BUFHELP_FAST_UNALIGNED_ACCESS
     144             : do_bytes:
     145             : #endif
     146             :   /* Handle tail.  */
     147    45891928 :   for (; len; len--)
     148      636772 :     *dst++ = *src1++ ^ *src2++;
     149    45255156 : }
     150             : 
     151             : 
     152             : /* Optimized function for in-place buffer xoring. */
     153             : static inline void
     154    44051998 : buf_xor_1(void *_dst, const void *_src, size_t len)
     155             : {
     156    44051998 :   byte *dst = _dst;
     157    44051998 :   const byte *src = _src;
     158             :   bufhelp_int_t *ldst;
     159             :   const bufhelp_int_t *lsrc;
     160             : #ifndef BUFHELP_FAST_UNALIGNED_ACCESS
     161             :   const unsigned int longmask = sizeof(bufhelp_int_t) - 1;
     162             : 
     163             :   /* Skip fast processing if buffers are unaligned.  */
     164             :   if (UNLIKELY(((uintptr_t)dst | (uintptr_t)src) & longmask))
     165             :     goto do_bytes;
     166             : #endif
     167             : 
     168    44051998 :   ldst = (bufhelp_int_t *)(void *)dst;
     169    44051998 :   lsrc = (const bufhelp_int_t *)(const void *)src;
     170             : 
     171   132155994 :   for (; len >= sizeof(bufhelp_int_t); len -= sizeof(bufhelp_int_t))
     172    88103996 :     (ldst++)->a ^= (lsrc++)->a;
     173             : 
     174    44051998 :   dst = (byte *)ldst;
     175    44051998 :   src = (const byte *)lsrc;
     176             : 
     177             : #ifndef BUFHELP_FAST_UNALIGNED_ACCESS
     178             : do_bytes:
     179             : #endif
     180             :   /* Handle tail.  */
     181    44051998 :   for (; len; len--)
     182           0 :     *dst++ ^= *src++;
     183    44051998 : }
     184             : 
     185             : 
     186             : /* Optimized function for buffer xoring with two destination buffers.  Used
     187             :    mainly by CFB mode encryption.  */
     188             : static inline void
     189     5817765 : buf_xor_2dst(void *_dst1, void *_dst2, const void *_src, size_t len)
     190             : {
     191     5817765 :   byte *dst1 = _dst1;
     192     5817765 :   byte *dst2 = _dst2;
     193     5817765 :   const byte *src = _src;
     194             :   bufhelp_int_t *ldst1, *ldst2;
     195             :   const bufhelp_int_t *lsrc;
     196             : #ifndef BUFHELP_FAST_UNALIGNED_ACCESS
     197             :   const unsigned int longmask = sizeof(bufhelp_int_t) - 1;
     198             : 
     199             :   /* Skip fast processing if buffers are unaligned.  */
     200             :   if (UNLIKELY(((uintptr_t)src | (uintptr_t)dst1 | (uintptr_t)dst2) & longmask))
     201             :     goto do_bytes;
     202             : #endif
     203             : 
     204     5817765 :   ldst1 = (bufhelp_int_t *)(void *)dst1;
     205     5817765 :   ldst2 = (bufhelp_int_t *)(void *)dst2;
     206     5817765 :   lsrc = (const bufhelp_int_t *)(const void *)src;
     207             : 
     208    14164867 :   for (; len >= sizeof(bufhelp_int_t); len -= sizeof(bufhelp_int_t))
     209     8347102 :     (ldst1++)->a = ((ldst2++)->a ^= (lsrc++)->a);
     210             : 
     211     5817765 :   dst1 = (byte *)ldst1;
     212     5817765 :   dst2 = (byte *)ldst2;
     213     5817765 :   src = (const byte *)lsrc;
     214             : 
     215             : #ifndef BUFHELP_FAST_UNALIGNED_ACCESS
     216             : do_bytes:
     217             : #endif
     218             :   /* Handle tail.  */
     219     5817765 :   for (; len; len--)
     220           0 :     *dst1++ = (*dst2++ ^= *src++);
     221     5817765 : }
     222             : 
     223             : 
     224             : /* Optimized function for combined buffer xoring and copying.  Used by mainly
     225             :    CBC mode decryption.  */
     226             : static inline void
     227     1995844 : buf_xor_n_copy_2(void *_dst_xor, const void *_src_xor, void *_srcdst_cpy,
     228             :                  const void *_src_cpy, size_t len)
     229             : {
     230     1995844 :   byte *dst_xor = _dst_xor;
     231     1995844 :   byte *srcdst_cpy = _srcdst_cpy;
     232     1995844 :   const byte *src_xor = _src_xor;
     233     1995844 :   const byte *src_cpy = _src_cpy;
     234             :   byte temp;
     235             :   bufhelp_int_t *ldst_xor, *lsrcdst_cpy;
     236             :   const bufhelp_int_t *lsrc_cpy, *lsrc_xor;
     237             :   uintptr_t ltemp;
     238             : #ifndef BUFHELP_FAST_UNALIGNED_ACCESS
     239             :   const unsigned int longmask = sizeof(bufhelp_int_t) - 1;
     240             : 
     241             :   /* Skip fast processing if buffers are unaligned.  */
     242             :   if (UNLIKELY(((uintptr_t)src_cpy | (uintptr_t)src_xor | (uintptr_t)dst_xor |
     243             :        (uintptr_t)srcdst_cpy) & longmask))
     244             :     goto do_bytes;
     245             : #endif
     246             : 
     247     1995844 :   ldst_xor = (bufhelp_int_t *)(void *)dst_xor;
     248     1995844 :   lsrc_xor = (const bufhelp_int_t *)(void *)src_xor;
     249     1995844 :   lsrcdst_cpy = (bufhelp_int_t *)(void *)srcdst_cpy;
     250     1995844 :   lsrc_cpy = (const bufhelp_int_t *)(const void *)src_cpy;
     251             : 
     252     4351872 :   for (; len >= sizeof(bufhelp_int_t); len -= sizeof(bufhelp_int_t))
     253             :     {
     254     2356028 :       ltemp = (lsrc_cpy++)->a;
     255     2356028 :       (ldst_xor++)->a = (lsrcdst_cpy)->a ^ (lsrc_xor++)->a;
     256     2356028 :       (lsrcdst_cpy++)->a = ltemp;
     257             :     }
     258             : 
     259     1995844 :   dst_xor = (byte *)ldst_xor;
     260     1995844 :   src_xor = (const byte *)lsrc_xor;
     261     1995844 :   srcdst_cpy = (byte *)lsrcdst_cpy;
     262     1995844 :   src_cpy = (const byte *)lsrc_cpy;
     263             : 
     264             : #ifndef BUFHELP_FAST_UNALIGNED_ACCESS
     265             : do_bytes:
     266             : #endif
     267             :   /* Handle tail.  */
     268     1995844 :   for (; len; len--)
     269             :     {
     270           0 :       temp = *src_cpy++;
     271           0 :       *dst_xor++ = *srcdst_cpy ^ *src_xor++;
     272           0 :       *srcdst_cpy++ = temp;
     273             :     }
     274     1995844 : }
     275             : 
     276             : 
     277             : /* Optimized function for combined buffer xoring and copying.  Used by mainly
     278             :    CFB mode decryption.  */
     279             : static inline void
     280     1863715 : buf_xor_n_copy(void *_dst_xor, void *_srcdst_cpy, const void *_src, size_t len)
     281             : {
     282     1863715 :   buf_xor_n_copy_2(_dst_xor, _src, _srcdst_cpy, _src, len);
     283     1863715 : }
     284             : 
     285             : 
     286             : /* Constant-time compare of two buffers.  Returns 1 if buffers are equal,
     287             :    and 0 if buffers differ.  */
     288             : static inline int
     289       44670 : buf_eq_const(const void *_a, const void *_b, size_t len)
     290             : {
     291       44670 :   const byte *a = _a;
     292       44670 :   const byte *b = _b;
     293             :   size_t diff, i;
     294             : 
     295             :   /* Constant-time compare. */
     296      572030 :   for (i = 0, diff = 0; i < len; i++)
     297      527360 :     diff -= !!(a[i] - b[i]);
     298             : 
     299       44670 :   return !diff;
     300             : }
     301             : 
     302             : 
     303             : #ifndef BUFHELP_UNALIGNED_ACCESS
     304             : 
     305             : /* Functions for loading and storing unaligned u32 values of different
     306             :    endianness.  */
     307             : static inline u32 buf_get_be32(const void *_buf)
     308             : {
     309             :   const byte *in = _buf;
     310             :   return ((u32)in[0] << 24) | ((u32)in[1] << 16) | \
     311             :          ((u32)in[2] << 8) | (u32)in[3];
     312             : }
     313             : 
     314             : static inline u32 buf_get_le32(const void *_buf)
     315             : {
     316             :   const byte *in = _buf;
     317             :   return ((u32)in[3] << 24) | ((u32)in[2] << 16) | \
     318             :          ((u32)in[1] << 8) | (u32)in[0];
     319             : }
     320             : 
     321             : static inline void buf_put_be32(void *_buf, u32 val)
     322             : {
     323             :   byte *out = _buf;
     324             :   out[0] = val >> 24;
     325             :   out[1] = val >> 16;
     326             :   out[2] = val >> 8;
     327             :   out[3] = val;
     328             : }
     329             : 
     330             : static inline void buf_put_le32(void *_buf, u32 val)
     331             : {
     332             :   byte *out = _buf;
     333             :   out[3] = val >> 24;
     334             :   out[2] = val >> 16;
     335             :   out[1] = val >> 8;
     336             :   out[0] = val;
     337             : }
     338             : 
     339             : 
     340             : /* Functions for loading and storing unaligned u64 values of different
     341             :    endianness.  */
     342             : static inline u64 buf_get_be64(const void *_buf)
     343             : {
     344             :   const byte *in = _buf;
     345             :   return ((u64)in[0] << 56) | ((u64)in[1] << 48) | \
     346             :          ((u64)in[2] << 40) | ((u64)in[3] << 32) | \
     347             :          ((u64)in[4] << 24) | ((u64)in[5] << 16) | \
     348             :          ((u64)in[6] << 8) | (u64)in[7];
     349             : }
     350             : 
     351             : static inline u64 buf_get_le64(const void *_buf)
     352             : {
     353             :   const byte *in = _buf;
     354             :   return ((u64)in[7] << 56) | ((u64)in[6] << 48) | \
     355             :          ((u64)in[5] << 40) | ((u64)in[4] << 32) | \
     356             :          ((u64)in[3] << 24) | ((u64)in[2] << 16) | \
     357             :          ((u64)in[1] << 8) | (u64)in[0];
     358             : }
     359             : 
     360             : static inline void buf_put_be64(void *_buf, u64 val)
     361             : {
     362             :   byte *out = _buf;
     363             :   out[0] = val >> 56;
     364             :   out[1] = val >> 48;
     365             :   out[2] = val >> 40;
     366             :   out[3] = val >> 32;
     367             :   out[4] = val >> 24;
     368             :   out[5] = val >> 16;
     369             :   out[6] = val >> 8;
     370             :   out[7] = val;
     371             : }
     372             : 
     373             : static inline void buf_put_le64(void *_buf, u64 val)
     374             : {
     375             :   byte *out = _buf;
     376             :   out[7] = val >> 56;
     377             :   out[6] = val >> 48;
     378             :   out[5] = val >> 40;
     379             :   out[4] = val >> 32;
     380             :   out[3] = val >> 24;
     381             :   out[2] = val >> 16;
     382             :   out[1] = val >> 8;
     383             :   out[0] = val;
     384             : }
     385             : 
     386             : #else /*BUFHELP_UNALIGNED_ACCESS*/
     387             : 
     388             : typedef struct bufhelp_u32_s
     389             : {
     390             :   u32 a;
     391             : } __attribute__((packed, aligned(1), may_alias)) bufhelp_u32_t;
     392             : 
     393             : /* Functions for loading and storing unaligned u32 values of different
     394             :    endianness.  */
     395    96865912 : static inline u32 buf_get_be32(const void *_buf)
     396             : {
     397    96865912 :   return be_bswap32(((const bufhelp_u32_t *)_buf)->a);
     398             : }
     399             : 
     400    65130436 : static inline u32 buf_get_le32(const void *_buf)
     401             : {
     402    65130436 :   return le_bswap32(((const bufhelp_u32_t *)_buf)->a);
     403             : }
     404             : 
     405    95477453 : static inline void buf_put_be32(void *_buf, u32 val)
     406             : {
     407    95477453 :   bufhelp_u32_t *out = _buf;
     408    95477453 :   out->a = be_bswap32(val);
     409    95477453 : }
     410             : 
     411    34586482 : static inline void buf_put_le32(void *_buf, u32 val)
     412             : {
     413    34586482 :   bufhelp_u32_t *out = _buf;
     414    34586482 :   out->a = le_bswap32(val);
     415    34586482 : }
     416             : 
     417             : 
     418             : typedef struct bufhelp_u64_s
     419             : {
     420             :   u64 a;
     421             : } __attribute__((packed, aligned(1), may_alias)) bufhelp_u64_t;
     422             : 
     423             : /* Functions for loading and storing unaligned u64 values of different
     424             :    endianness.  */
     425     2904328 : static inline u64 buf_get_be64(const void *_buf)
     426             : {
     427     2904328 :   return be_bswap64(((const bufhelp_u64_t *)_buf)->a);
     428             : }
     429             : 
     430    30008774 : static inline u64 buf_get_le64(const void *_buf)
     431             : {
     432    30008774 :   return le_bswap64(((const bufhelp_u64_t *)_buf)->a);
     433             : }
     434             : 
     435     3018277 : static inline void buf_put_be64(void *_buf, u64 val)
     436             : {
     437     3018277 :   bufhelp_u64_t *out = _buf;
     438     3018277 :   out->a = be_bswap64(val);
     439     3018277 : }
     440             : 
     441     7465188 : static inline void buf_put_le64(void *_buf, u64 val)
     442             : {
     443     7465188 :   bufhelp_u64_t *out = _buf;
     444     7465188 :   out->a = le_bswap64(val);
     445     7465188 : }
     446             : 
     447             : 
     448             : #endif /*BUFHELP_UNALIGNED_ACCESS*/
     449             : 
     450             : #endif /*GCRYPT_BUFHELP_H*/

Generated by: LCOV version 1.13