LCOV - code coverage report
Current view: top level - egg - egg-padding.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 86.8 % 136 118
Test Date: 2024-12-15 20:37:51 Functions: 100.0 % 9 9

            Line data    Source code
       1              : /*
       2              :  * gnome-keyring
       3              :  *
       4              :  * Copyright (C) 2008 Stefan Walter
       5              :  *
       6              :  * This program 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              :  * This program is distributed in the hope that it will be useful, but
      12              :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      13              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14              :  * 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
      18              :  * <http://www.gnu.org/licenses/>.
      19              :  */
      20              : 
      21              : #include "config.h"
      22              : 
      23              : #include "egg-padding.h"
      24              : 
      25              : #include <gcrypt.h>
      26              : 
      27              : #include "egg/egg-secure-memory.h"
      28              : 
      29              : /* ----------------------------------------------------------------------------
      30              :  * INTERNAL
      31              :  */
      32              : 
      33              : static void
      34            1 : fill_random_nonzero (guchar *data, gsize n_data)
      35              : {
      36              :         guchar *rnd;
      37              :         guint n_zero, i, j;
      38              : 
      39            1 :         gcry_randomize (data, n_data, GCRY_STRONG_RANDOM);
      40              : 
      41              :         /* Find any zeros in random data */
      42            1 :         n_zero = 0;
      43            4 :         for (i = 0; i < n_data; ++i) {
      44            3 :                 if (data[i] == 0x00)
      45            0 :                         ++n_zero;
      46              :         }
      47              : 
      48            1 :         while (n_zero > 0) {
      49            0 :                 rnd = gcry_random_bytes (n_zero, GCRY_STRONG_RANDOM);
      50            0 :                 n_zero = 0;
      51            0 :                 for (i = 0, j = 0; i < n_data; ++i) {
      52            0 :                         if (data[i] != 0x00)
      53            0 :                                 continue;
      54              : 
      55              :                         /* Use some of the replacement data */
      56            0 :                         data[i] = rnd[j];
      57            0 :                         ++j;
      58              : 
      59              :                         /* It's zero again :( */
      60            0 :                         if (data[i] == 0x00)
      61            0 :                                 n_zero++;
      62              :                 }
      63              : 
      64            0 :                 gcry_free (rnd);
      65              :         }
      66            1 : }
      67              : 
      68              : static gboolean
      69           10 : unpad_pkcs1 (guchar bt, EggAllocator alloc, gsize block, const guchar* padded,
      70              :              gsize n_padded, gpointer *raw, gsize *n_raw)
      71              : {
      72              :         const guchar *at;
      73              : 
      74           10 :         if (block && n_padded % block != 0)
      75            1 :                 return FALSE;
      76              : 
      77              :         /* Check the header */
      78            9 :         if (padded[0] != 0x00 || padded[1] != bt)
      79            2 :                 return FALSE;
      80              : 
      81              :         /* The first zero byte after the header */
      82            7 :         at = memchr (padded + 2, 0x00, n_padded - 2);
      83            7 :         if (!at)
      84            1 :                 return FALSE;
      85              : 
      86            6 :         if (alloc == NULL)
      87            6 :                 alloc = g_realloc;
      88              : 
      89            6 :         ++at;
      90            6 :         *n_raw = n_padded - (at - padded);
      91            6 :         if (raw) {
      92            3 :                 *raw = (alloc) (NULL, *n_raw + 1);
      93            3 :                 if (*raw == NULL)
      94            0 :                         return FALSE;
      95            3 :                 memcpy (*raw, at, *n_raw);
      96              : 
      97              :                 /* Convenience null terminate the result */
      98            3 :                 memset (((guchar*)*raw) + *n_raw, 0, 1);
      99              :         }
     100              : 
     101            6 :         return TRUE;
     102              : }
     103              : 
     104              : /* ----------------------------------------------------------------------------
     105              :  * PUBLIC
     106              :  */
     107              : 
     108              : gboolean
     109            4 : egg_padding_zero_pad (EggAllocator alloc, gsize block, gconstpointer raw,
     110              :                       gsize n_raw, gpointer *padded, gsize *n_padded)
     111              : {
     112              :         guchar *pad;
     113              :         gsize n_pad;
     114              : 
     115              :         /*
     116              :          * 0x00 0x00 0x00 ... 0x?? 0x?? 0x?? ...
     117              :          *   padding               data
     118              :          */
     119              : 
     120            4 :         g_return_val_if_fail (block != 0, FALSE);
     121              : 
     122            4 :         *n_padded = ((n_raw + (block - 1)) / block) * block;
     123            4 :         g_assert (n_raw <= *n_padded);
     124            4 :         n_pad = *n_padded - n_raw;
     125            4 :         g_assert (n_pad < block);
     126              : 
     127            4 :         if (alloc == NULL)
     128            4 :                 alloc = g_realloc;
     129              : 
     130            4 :         if (padded) {
     131            2 :                 *padded = pad = (alloc) (NULL, MAX (*n_padded, 1));
     132            2 :                 if (pad == NULL)
     133            0 :                         return FALSE;
     134            2 :                 memset (pad, 0x00, n_pad);
     135            2 :                 memcpy (pad + n_pad, raw, n_raw);
     136              :         }
     137              : 
     138            4 :         return TRUE;
     139              : }
     140              : 
     141              : gboolean
     142            6 : egg_padding_pkcs1_pad_01 (EggAllocator alloc, gsize block, gconstpointer raw,
     143              :                            gsize n_raw, gpointer *padded, gsize *n_padded)
     144              : {
     145              :         guchar *pad;
     146              :         gsize n_pad;
     147              : 
     148              :         /*
     149              :          * 0x00 0x01 0xFF 0xFF ... 0x00 0x?? 0x?? 0x?? ...
     150              :          *      type  padding              data
     151              :          */
     152              : 
     153            6 :         g_return_val_if_fail (block != 0, FALSE);
     154            6 :         g_return_val_if_fail (block > 3, FALSE);
     155              : 
     156            6 :         *n_padded = ((n_raw + 3 + (block - 1)) / block) * block;
     157            6 :         g_assert (n_raw <= *n_padded);
     158            6 :         n_pad = *n_padded - n_raw;
     159            6 :         g_assert (n_pad <= block);
     160            6 :         g_assert (n_pad >= 3);
     161              : 
     162            6 :         if (alloc == NULL)
     163            4 :                 alloc = g_realloc;
     164              : 
     165            6 :         if (padded) {
     166            4 :                 *padded = pad = (alloc) (NULL, MAX (*n_padded, 1));
     167            4 :                 if (pad == NULL)
     168            0 :                         return FALSE;
     169            4 :                 pad[0] = 0; /* Prefix */
     170            4 :                 pad[1] = 1; /* Block type */
     171            4 :                 memset (pad + 2, 0xFF, n_pad - 3);
     172            4 :                 pad[n_pad - 1] = 0;
     173            4 :                 memcpy (pad + n_pad, raw, n_raw);
     174              :         }
     175              : 
     176            6 :         return TRUE;
     177              : }
     178              : 
     179              : gboolean
     180            1 : egg_padding_pkcs1_pad_02 (EggAllocator alloc, gsize block, gconstpointer raw,
     181              :                            gsize n_raw, gpointer *padded, gsize *n_padded)
     182              : {
     183              :         guchar *pad;
     184              :         gsize n_pad;
     185              : 
     186              :         /*
     187              :          * 0x00 0x01 0x?? 0x?? ... 0x00 0x?? 0x?? 0x?? ...
     188              :          *      type  padding              data
     189              :          */
     190              : 
     191            1 :         g_return_val_if_fail (block != 0, FALSE);
     192            1 :         g_return_val_if_fail (block > 3, FALSE);
     193              : 
     194            1 :         *n_padded = ((n_raw + 3 + (block - 1)) / block) * block;
     195            1 :         g_assert (n_raw <= *n_padded);
     196            1 :         n_pad = *n_padded - n_raw;
     197            1 :         g_assert (n_pad <= block);
     198            1 :         g_assert (n_pad >= 3);
     199              : 
     200            1 :         if (alloc == NULL)
     201            1 :                 alloc = g_realloc;
     202              : 
     203            1 :         if (padded) {
     204            1 :                 *padded = pad = (alloc) (NULL, MAX (*n_padded, 1));
     205            1 :                 if (pad == NULL)
     206            0 :                         return FALSE;
     207            1 :                 pad[0] = 0; /* Prefix */
     208            1 :                 pad[1] = 2; /* Block type */
     209            1 :                 fill_random_nonzero (pad + 2, n_pad - 3);
     210            1 :                 pad[n_pad - 1] = 0;
     211            1 :                 memcpy (pad + n_pad, raw, n_raw);
     212              :         }
     213              : 
     214            1 :         return TRUE;
     215              : }
     216              : 
     217              : gboolean
     218            8 : egg_padding_pkcs1_unpad_01 (EggAllocator alloc, gsize block, gconstpointer padded,
     219              :                              gsize n_padded, gpointer *raw, gsize *n_raw)
     220              : {
     221            8 :         return unpad_pkcs1 (0x01, alloc, block, padded, n_padded, raw, n_raw);
     222              : }
     223              : 
     224              : gboolean
     225            2 : egg_padding_pkcs1_unpad_02 (EggAllocator alloc, gsize block, gconstpointer padded,
     226              :                              gsize n_padded, gpointer *raw, gsize *n_raw)
     227              : {
     228            2 :         return unpad_pkcs1 (0x02, alloc, block, padded, n_padded, raw, n_raw);
     229              : }
     230              : 
     231              : gboolean
     232            6 : egg_padding_pkcs7_pad (EggAllocator alloc, gsize block, gconstpointer raw,
     233              :                        gsize n_raw, gpointer *padded, gsize *n_padded)
     234              : {
     235              :         guchar *pad;
     236              :         gsize n_pad;
     237              : 
     238            6 :         g_return_val_if_fail (block != 0, FALSE);
     239            6 :         g_return_val_if_fail (block < 256, FALSE);
     240              : 
     241            6 :         *n_padded = ((n_raw + block) / block) * block;
     242            6 :         g_assert (n_raw < *n_padded);
     243            6 :         n_pad = *n_padded - n_raw;
     244            6 :         g_assert (n_pad > 0 && n_pad <= block);
     245              : 
     246            6 :         if (alloc == NULL)
     247            6 :                 alloc = g_realloc;
     248              : 
     249            6 :         if (padded) {
     250            3 :                 *padded = pad = (alloc) (NULL, MAX (*n_padded, 1));
     251            3 :                 if (pad == NULL)
     252            0 :                         return FALSE;
     253            3 :                 memcpy (pad, raw, n_raw);
     254            3 :                 memset (pad + n_raw, n_pad, n_pad);
     255              :         }
     256              : 
     257            6 :         return TRUE;
     258              : }
     259              : 
     260              : gboolean
     261           11 : egg_padding_pkcs7_unpad (EggAllocator alloc, gsize block, gconstpointer padded,
     262              :                          gsize n_padded, gpointer *raw, gsize *n_raw)
     263              : {
     264              :         const guchar *pad;
     265              :         gsize n_pad, i;
     266              : 
     267           11 :         if (n_padded == 0)
     268            0 :                 return FALSE;
     269              : 
     270           11 :         pad = padded;
     271           11 :         n_pad = pad[n_padded - 1];
     272              : 
     273              :         /* Validate the padding */
     274           11 :         if (n_pad == 0 || n_pad > 256)
     275            1 :                 return FALSE;
     276           10 :         if (n_pad > n_padded)
     277            1 :                 return FALSE;
     278            9 :         if (block && n_pad > block)
     279            1 :                 return FALSE;
     280           60 :         for (i = n_padded - n_pad; i < n_padded; ++i) {
     281           53 :                 if (pad[i] != n_pad)
     282            1 :                         return FALSE;
     283              :         }
     284              : 
     285            7 :         *n_raw = n_padded - n_pad;
     286              : 
     287            7 :         if (alloc == NULL)
     288            6 :                 alloc = g_realloc;
     289              : 
     290            7 :         if (raw) {
     291            4 :                 *raw = (alloc) (NULL, *n_raw + 1);
     292            4 :                 if (*raw == NULL)
     293            0 :                         return FALSE;
     294              : 
     295              :                 /* Output the result, null terminated */
     296            4 :                 memcpy (*raw, pad, *n_raw);
     297            4 :                 memset (((guchar*)*raw) + *n_raw, 0, 1);
     298              :         }
     299              : 
     300            7 :         return TRUE;
     301              : }
        

Generated by: LCOV version 2.0-1