LTP GCOV extension - code coverage report
Current view: directory - src/base - pdf-stm-f-aesv2.c
Test: libgnupdf.info
Date: 2010-07-31 Instrumented lines: 89
Code covered: 89.9 % Executed lines: 80

       1                 : /* -*- mode: C -*-
       2                 :  *
       3                 :  *       File:         pdf-stm-f-aesv2.c
       4                 :  *       Date:         Sun Dec 14 20:13:53 2008
       5                 :  *
       6                 :  *       GNU PDF Library - AESV2 stream filter
       7                 :  *
       8                 :  */
       9                 : 
      10                 : /* Copyright (C) 2008, 2009 Free Software Foundation, Inc. */
      11                 : 
      12                 : /* This program is free software: you can redistribute it and/or modify
      13                 :  * it under the terms of the GNU General Public License as published by
      14                 :  * the Free Software Foundation, either version 3 of the License, or
      15                 :  * (at your option) any later version.
      16                 :  *
      17                 :  * This program is distributed in the hope that it will be useful,
      18                 :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      19                 :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      20                 :  * GNU General Public License for more details.
      21                 :  *
      22                 :  * You should have received a copy of the GNU General Public License
      23                 :  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
      24                 :  */
      25                 : 
      26                 : #include <config.h>
      27                 : 
      28                 : #include <stdlib.h>
      29                 : #include <string.h>
      30                 : 
      31                 : #include <pdf-stm-f-aesv2.h>
      32                 : #include <pdf-hash-helper.h>
      33                 : 
      34                 : #define AESV2_CACHE_SIZE 16
      35                 : 
      36                 : 
      37                 : /* Internal state */
      38                 : struct pdf_stm_f_aesv2_s
      39                 : {
      40                 :   pdf_crypt_cipher_t cipher;
      41                 :   pdf_buffer_t in_cache;
      42                 :   pdf_buffer_t out_cache;
      43                 : };
      44                 : typedef struct pdf_stm_f_aesv2_s * pdf_stm_f_aesv2_t;
      45                 : 
      46                 : 
      47                 : /* Encryption and decryption  */
      48                 : enum pdf_stm_f_aesv2_mode_e
      49                 :   {
      50                 :     PDF_STM_F_AESV2_MODE_ENCODE,
      51                 :     PDF_STM_F_AESV2_MODE_DECODE
      52                 :   };
      53                 : typedef enum pdf_stm_f_aesv2_mode_e pdf_stm_f_aesv2_mode_t;
      54                 : 
      55                 : 
      56                 : 
      57                 : static inline pdf_status_t
      58                 : pdf_stm_f_aesv2_init (pdf_hash_t params, void **state)
      59               3 : {
      60                 :   pdf_status_t ret;
      61                 :   pdf_stm_f_aesv2_t filter_state;
      62                 :   
      63               3 :   filter_state = pdf_alloc (sizeof (struct pdf_stm_f_aesv2_s));
      64                 :   
      65               3 :   if (filter_state == NULL)
      66                 :     {
      67               0 :       ret = PDF_ENOMEM;
      68                 :     }
      69               3 :   else if (state == NULL)
      70                 :     {
      71               0 :       pdf_dealloc (filter_state);
      72               0 :       ret = PDF_EBADDATA;
      73                 :     }
      74                 :   else
      75                 :     {
      76                 :       pdf_char_t *key;
      77                 :       pdf_size_t keysize;
      78                 :       pdf_crypt_cipher_t cipher;
      79                 :       
      80                 :       /* We demand all parameters are present */
      81               3 :       if ((( pdf_hash_key_p (params, "Key")     == PDF_TRUE))
      82                 :           && pdf_hash_key_p (params, "KeySize") == PDF_TRUE)
      83                 :         {
      84               3 :           pdf_hash_get_string (params, "Key", &key);
      85               3 :           pdf_hash_get_size (params, "KeySize", &keysize);
      86                 : 
      87               3 :           ret = pdf_crypt_cipher_new (PDF_CRYPT_CIPHER_ALGO_AESV2, &cipher);
      88               3 :           if (ret == PDF_OK)
      89                 :             {
      90               6 :               ret = pdf_crypt_cipher_setkey (cipher, key, keysize);
      91               3 :               if (ret == PDF_OK)
      92                 :                 {
      93               3 :                   filter_state->cipher = cipher;
      94                 :                   
      95                 :                   /* Initialize cache buffers */
      96               3 :                   filter_state->in_cache  = pdf_buffer_new (AESV2_CACHE_SIZE);
      97               3 :                   filter_state->out_cache = pdf_buffer_new (AESV2_CACHE_SIZE);
      98                 :                   
      99               3 :                   if (filter_state->in_cache == NULL || filter_state->out_cache == NULL)
     100                 :                     {
     101               0 :                       ret = PDF_ERROR;
     102                 :                     }
     103                 :                   else
     104                 :                     {
     105               3 :                       ret = PDF_OK;
     106               3 :                       *state = filter_state;
     107                 :                     }
     108                 :                 }
     109                 :             }
     110                 :         }
     111                 :       else
     112                 :         {
     113               0 :           ret = PDF_EBADDATA;
     114                 :         }
     115                 : 
     116               3 :       if (ret != PDF_OK)
     117                 :         {
     118               0 :           pdf_dealloc (filter_state);
     119                 :         }
     120                 :     }
     121                 :   
     122               3 :   return ret;
     123                 : }
     124                 : 
     125                 : 
     126                 : 
     127                 : 
     128                 : static inline pdf_status_t
     129                 : pdf_stm_f_aesv2_apply (pdf_stm_f_aesv2_mode_t mode,
     130                 :                        pdf_hash_t params, void *state, pdf_buffer_t in,
     131                 :                        pdf_buffer_t out, pdf_bool_t finish_p)
     132               9 : {
     133               9 :   pdf_stm_f_aesv2_t filter_state = state;
     134               9 :   pdf_crypt_cipher_t cipher   = filter_state->cipher;
     135               9 :   pdf_buffer_t in_cache   = filter_state->in_cache;
     136               9 :   pdf_buffer_t out_cache  = filter_state->out_cache;
     137                 :   
     138                 :   while(1)
     139                 :     {
     140                 :       pdf_size_t in_size;
     141                 :       pdf_size_t out_size;
     142                 :       pdf_size_t in_cache_size;
     143                 :       pdf_size_t out_cache_size;
     144                 :       pdf_size_t bytes_to_read;
     145                 :       pdf_size_t bytes_to_write;
     146                 : 
     147                 :       /* Read bytes from IN and fill IN_CACHE*/
     148              18 :       in_size = in->wp - in->rp;
     149              18 :       in_cache_size = in_cache->size - in_cache->wp;
     150              18 :       bytes_to_read = PDF_MIN (in_size, in_cache_size);
     151                 : 
     152              18 :       memcpy (in_cache->data + in_cache->wp,
     153                 :               in->data       + in->rp,
     154                 :               bytes_to_read);
     155                 : 
     156              18 :       in_cache->wp += bytes_to_read;
     157              18 :       in->rp       += bytes_to_read;
     158                 : 
     159                 : 
     160                 :       /* If we cannot fill all IN_CACHE...  */
     161              18 :       if (!pdf_buffer_full_p (in_cache))
     162                 :         {
     163               8 :           if (finish_p && mode == PDF_STM_F_AESV2_MODE_DECODE
     164                 :               && in_cache->wp > 0)
     165               0 :             return PDF_ERROR;
     166                 :           
     167                 :           /* ...pad the cache if we have reached EOD */
     168              10 :           if (finish_p
     169                 :               && !pdf_buffer_full_p (in_cache)
     170                 :               && mode == PDF_STM_F_AESV2_MODE_ENCODE)
     171                 :             {
     172                 :               pdf_size_t padding;
     173               2 :               padding = in_cache->size - in_cache->wp;
     174                 :           
     175               2 :               memset (in_cache->data + in_cache->wp,
     176                 :                       padding,
     177                 :                       padding);
     178                 :               
     179               2 :               in_cache->wp += padding;
     180                 :             }
     181                 :           else
     182                 :             {
     183               6 :               if (pdf_buffer_eob_p (out_cache))
     184               5 :                 return PDF_ENINPUT; /* ...ask more input */
     185                 :             }
     186                 :         }
     187                 : 
     188                 : 
     189                 :       /* If OUT_CACHE is empty and IN_CACHE is full, then it is ready
     190                 :          to be processed. */
     191              13 :       if (pdf_buffer_full_p (in_cache) && pdf_buffer_eob_p (out_cache))
     192                 :         {
     193              12 :           switch (mode)
     194                 :             {
     195                 :             case PDF_STM_F_AESV2_MODE_ENCODE:
     196               9 :               pdf_crypt_cipher_encrypt (cipher,
     197                 :                                         out_cache->data,
     198                 :                                         out_cache->size,
     199                 :                                         in_cache->data,
     200                 :                                         in_cache->size,
     201                 :                                         NULL);
     202                 :               break;
     203                 :               
     204                 :             case PDF_STM_F_AESV2_MODE_DECODE:
     205               3 :               pdf_crypt_cipher_decrypt (cipher,
     206                 :                                         out_cache->data,
     207                 :                                         out_cache->size,
     208                 :                                         in_cache->data,
     209                 :                                         in_cache->size,
     210                 :                                         NULL);
     211                 :               break;
     212                 : 
     213                 :             default: /* not reached */
     214                 :               break;
     215                 :             }
     216                 : 
     217                 :           /* Both cache are full now */
     218              12 :           pdf_buffer_rewind (in_cache);
     219              12 :           out_cache->wp = out_cache->size;
     220                 :         }
     221                 : 
     222                 : 
     223                 :       /* When we are decrypting data, we need know what block is the
     224                 :          last. If both IN and IN_CACHE are empty, then OUT_CACHE could
     225                 :          hold it. So, we ask more input to we make sure.*/
     226              13 :       if (mode == PDF_STM_F_AESV2_MODE_DECODE
     227                 :           && pdf_buffer_eob_p (in) && pdf_buffer_eob_p (in_cache))
     228                 :         {
     229                 :           /* When we know it is the last, remove the padding. */
     230               2 :           if (finish_p)
     231                 :             {
     232                 :               pdf_size_t padding;
     233               1 :               padding = out_cache->data[out_cache->size - 1];
     234                 : 
     235               1 :               if (padding > AESV2_CACHE_SIZE)
     236               0 :                 return PDF_ERROR;
     237                 : 
     238               1 :               out_cache->wp = out_cache->size - padding;
     239                 :             }
     240                 :           else
     241               1 :             return PDF_ENINPUT;
     242                 :         }
     243                 :           
     244                 : 
     245                 :       /* Finally, we fill the OUT buffer */
     246              12 :       out_size = out->size - out->wp;
     247              12 :       out_cache_size = out_cache->wp - out_cache->rp;
     248              12 :       bytes_to_write = PDF_MIN (out_size, out_cache_size);
     249                 : 
     250              12 :       memcpy (out->data + out->wp,
     251                 :               out_cache->data + out_cache->rp,
     252                 :               bytes_to_write);
     253                 : 
     254              12 :       out_cache->rp += bytes_to_write;
     255              12 :       out->wp       += bytes_to_write;
     256                 : 
     257                 : 
     258              12 :       if (finish_p)
     259                 :         {
     260               3 :           return PDF_EEOF;
     261                 :         }
     262               9 :       else if (pdf_buffer_full_p (out))
     263                 :         {
     264               0 :           return PDF_ENOUTPUT;
     265                 :         }
     266                 :       else
     267                 :         {
     268               9 :           pdf_buffer_rewind (out_cache);
     269                 :         }
     270               9 :     }
     271                 : }
     272                 : 
     273                 : 
     274                 : 
     275                 : static inline pdf_status_t
     276                 : pdf_stm_f_aesv2_dealloc_state (void *state)
     277               3 : {
     278               3 :   pdf_stm_f_aesv2_t filter_state = state;
     279               3 :   pdf_crypt_cipher_destroy (filter_state->cipher);
     280               3 :   pdf_buffer_destroy (filter_state->in_cache);
     281               3 :   pdf_buffer_destroy (filter_state->out_cache);
     282               3 :   pdf_dealloc (state);
     283               3 :   return PDF_OK;
     284                 : }
     285                 : 
     286                 : 
     287                 : 
     288                 : 
     289                 : /* Encode filter */
     290                 : 
     291                 : pdf_status_t
     292                 : pdf_stm_f_aesv2enc_init (pdf_hash_t params, void **state)
     293               2 : {
     294               2 :   return pdf_stm_f_aesv2_init (params, state);
     295                 : }
     296                 : 
     297                 : pdf_status_t
     298                 : pdf_stm_f_aesv2enc_apply (pdf_hash_t params, void *state, pdf_buffer_t in,
     299                 :                           pdf_buffer_t out, pdf_bool_t finish_p)
     300               6 : {
     301               6 :   return pdf_stm_f_aesv2_apply (PDF_STM_F_AESV2_MODE_ENCODE,
     302                 :                                 params, state, in, out, finish_p);
     303                 : }
     304                 : 
     305                 : pdf_status_t
     306                 : pdf_stm_f_aesv2enc_dealloc_state (void *state)
     307               2 : {
     308               2 :   return pdf_stm_f_aesv2_dealloc_state (state);
     309                 : }
     310                 : 
     311                 : 
     312                 : 
     313                 : /* Decode filter  */
     314                 : 
     315                 : pdf_status_t
     316                 : pdf_stm_f_aesv2dec_init (pdf_hash_t params, void **state)
     317               1 : {
     318               1 :   return pdf_stm_f_aesv2_init (params, state);
     319                 : }
     320                 : 
     321                 : 
     322                 : pdf_status_t
     323                 : pdf_stm_f_aesv2dec_apply (pdf_hash_t params, void *state, pdf_buffer_t in,
     324                 :                           pdf_buffer_t out, pdf_bool_t finish_p)
     325               3 : {
     326               3 :   return pdf_stm_f_aesv2_apply (PDF_STM_F_AESV2_MODE_DECODE,
     327                 :                                 params, state, in, out, finish_p);
     328                 : }
     329                 : 
     330                 : 
     331                 : pdf_status_t
     332                 : pdf_stm_f_aesv2dec_dealloc_state (void *state)
     333               1 : {
     334               1 :   return pdf_stm_f_aesv2_dealloc_state (state);
     335                 : }
     336                 : 
     337                 : 
     338                 : 
     339                 : /* End of pdf_stm_f_aesv2.c */

Generated by: LTP GCOV extension version 1.6