root/WizardsToolkit/trunk/utilities/decipher.c

Revision 339, 30.5 KB (checked in by cristy, 6 weeks ago)
Line 
1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3%                                                                             %
4%                                                                             %
5%                                                                             %
6%            DDDD   EEEEE   CCCC  IIIII  PPPP   H   H  EEEEE  RRRR            %
7%            D   D  E      C        I    P   P  H   H  E      R   R           %
8%            D   D  EEE    C        I    PPPP   HHHHH  EEE    RRRR            %
9%            D   D  E      C        I    P      H   H  E      R R             %
10%            DDDD   EEEEE   CCCC  IIIII  P      H   H  EEEEE  R  R            %
11%                                                                             %
12%                                                                             %
13%                        Convert Ciphertext to Plaintext                      %
14%                                                                             %
15%                              Software Design                                %
16%                                John Cristy                                  %
17%                                January 2008                                 %
18%                                                                             %
19%                                                                             %
20%  Copyright 1999-2009 ImageMagick Studio LLC, a non-profit organization      %
21%  dedicated to making software imaging solutions freely available.           %
22%                                                                             %
23%  You may not use this file except in compliance with the License.  You may  %
24%  obtain a copy of the License at                                            %
25%                                                                             %
26%    http://www.wizards-toolkit.org/script/license.php                        %
27%                                                                             %
28%  Unless required by applicable law or agreed to in writing, software        %
29%  distributed under the License is distributed on an "AS IS" BASIS,          %
30%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31%  See the License for the specific language governing permissions and        %
32%  limitations under the License.                                             %
33%                                                                             %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37*/
38
39/*
40  Include declarations.
41*/
42#include <stdio.h>
43#include <stdlib.h>
44#include <string.h>
45#include <time.h>
46#include "wizard/studio.h"
47#include "wizard/WizardsToolkit.h"
48#include "wizard/blob-private.h"
49#include "wizard/exception-private.h"
50#if defined(WIZARDSTOOLKIT_HAVE_UTIME)
51#if defined(WIZARDSTOOLKIT_HAVE_UTIME_H)
52#include <utime.h>
53#else
54#include <sys/utime.h>
55#endif
56#endif
57#if defined(__WINDOWS__)
58#include <windows.h>
59#endif
60#include "content.h"
61#include "utility_.h"
62
63/*
64  Forward declaraction.
65*/
66static WizardBooleanType
67  DecipherContent(ContentInfo *,const char *,const char *,
68    const WizardBooleanType,ExceptionInfo *);
69
70/*
71%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
72%                                                                             %
73%                                                                             %
74%                                                                             %
75+   D e c i p h e r C o m m a n d                                             %
76%                                                                             %
77%                                                                             %
78%                                                                             %
79%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
80%
81%  DecipherCommand() reads ciphertext from a file and converts it to plaintext.
82%
83%  The format of the DecipherCommand method is:
84%
85%      WizardBooleanType DecipherCommand(int argc,char **argv,
86%        ExceptionInfo *exception)
87%
88%  A description of each parameter follows:
89%
90%    o argc: The number of elements in the argument vector.
91%
92%    o argv: A text array containing the command line arguments.
93%
94%    o exception: Return any errors or warnings in this structure.
95%
96*/
97
98static void DecipherUsage(void)
99{
100  static const char
101    *options[]=
102    {
103      "-authenticate method authenticate with this method: Secret or Public",
104      "-chunksize bytes     number of bytes in a chunk",
105      "-cipher type         cipher to decipher content",
106      "-(de)compress        automagically (de)compress BZIP and ZIP files",
107      "-debug events        display copious debugging information",
108      "-entropy type        increase content entropy",
109      "-help                print program options",
110      "-hmac hash           ensure message integrity with this hash",
111      "-key hash            strengthen the key with this hash",
112      "-key-length value    cipher key length in bits: 256, 512, 1024, or 2048",
113      "-keyring filename    add private key to this keyring",
114      "-level value         entropy level: 1 (less entropy) to 9 (more entropy)",
115      "-list type           print a list of supported option arguments",
116      "-log format          format of debugging information",
117      "-mode type           mode of deciphering",
118      "-passphrase filename get the passphrase from this file",
119      "-properties filename get cipher properties from this file",
120      "-random hash         strengthen random data with this hash",
121      "-true-random         strengthen deciphering with true random numbers",
122      "-verbose             print detailed information about the secure content",
123      "-version             print version information",
124      (char *) NULL
125    };
126
127  const char
128    **p;
129
130  (void) fprintf(stdout,"Version: %s\n",GetWizardVersion(
131    (unsigned long *) NULL));
132  (void) fprintf(stdout,"Copyright: %s\n\n",GetWizardCopyright());
133  (void) fprintf(stdout,"Usage: %s [options ...] ciphertext "
134    "plaintext\n",GetClientName());
135  (void) fprintf(stdout,"\nWhere options include:\n");
136  for (p=options; *p != (char *) NULL; p++)
137    (void) fprintf(stdout,"  %s\n",*p);
138  exit(0);
139}
140
141static double StringToDouble(const char *string,const double interval)
142{
143  char
144    *q;
145
146  double
147    scale,
148    value;
149
150  assert(string != (char *) NULL);
151  value=strtod(string,&q);
152  scale=1000.0;
153  if ((*q != '\0') && (tolower((int) ((unsigned char) *(q+1))) == 'i'))
154    scale=1024.0;
155  switch (tolower((int) ((unsigned char) *q)))
156  {
157    case '%': value*=pow(scale,0)*interval/100.0; break;
158    case 'k': value*=pow(scale,1); break;
159    case 'm': value*=pow(scale,2); break;
160    case 'g': value*=pow(scale,3); break;
161    case 't': value*=pow(scale,4); break;
162    case 'p': value*=pow(scale,5); break;
163    case 'e': value*=pow(scale,6); break;
164    case 'z': value*=pow(scale,7); break;
165    case 'y': value*=pow(scale,8); break;
166    defaultbreak;
167  }
168  return(value);
169}
170
171WizardExport WizardBooleanType DecipherCommand(int argc,char **argv,
172  ExceptionInfo *exception)
173{
174#define DestroyCipher() \
175{ \
176  content_info=DestroyContentInfo(content_info); \
177  for (i=0; i < (long) argc; i++) \
178    argv[i]=DestroyString(argv[i]); \
179  argv=(char **) RelinquishWizardMemory(argv); \
180}
181#define ThrowCipherException(asperity,tag,context) \
182{ \
183  (void) ThrowWizardException(exception,GetWizardModule(),asperity,tag, \
184    context); \
185  DestroyCipher(); \
186  return(WizardFalse); \
187}
188#define ThrowInvalidArgumentException(option,argument) \
189{ \
190  (void) ThrowWizardException(exception,GetWizardModule(),OptionError, \
191    "invalid argument: `%s': %s",argument,option); \
192  DestroyCipher(); \
193  return(WizardFalse); \
194}
195
196  const char
197    *cipher_filename,
198    *option,
199    *plain_filename;
200
201  ContentInfo
202    *content_info;
203
204  long
205    type;
206
207  register long
208    i;
209
210  WizardBooleanType
211    compress,
212    status,
213    verbose;
214
215  /*
216    Parse command-line options.
217  */
218  if (argc == 2)
219    {
220      option=argv[1];
221      if ((LocaleCompare("version",option+1) == 0) ||
222          (LocaleCompare("-version",option+1) == 0))
223        {
224          (void) fprintf(stdout,"Version: %s\n",GetWizardVersion(
225            (unsigned long *) NULL));
226          (void) fprintf(stdout,"Copyright: %s\n\n",GetWizardCopyright());
227          return(WizardTrue);
228        }
229    }
230  if (argc < 3)
231    DecipherUsage();
232  status=ExpandFilenames(&argc,&argv);
233  content_info=AcquireContentInfo();
234  if (status == WizardFalse)
235    ThrowCipherException(ResourceError,"memory allocation failed: `%s'",
236      strerror(errno));
237  plain_filename=(const char *) NULL;
238  cipher_filename=(const char *) NULL;
239  verbose=WizardFalse;
240  compress=WizardTrue;
241  for (i=1; i < (long) argc; i++)
242  {
243    option=argv[i];
244    if (IsWizardOption(option) == WizardFalse)
245      {
246        if (plain_filename == (char *) NULL)
247          plain_filename=option;
248        else
249          if (cipher_filename == (char *) NULL)
250            cipher_filename=option;
251          else
252            DecipherUsage();
253        continue;
254      }
255    switch (*(option+1))
256    {
257      case '(':
258      {
259        if (LocaleCompare(option+1,"(de)compress") == 0)
260          {
261            compress=(*option == '-') ? WizardTrue : WizardFalse;
262            break;
263          }
264        ThrowCipherException(OptionFatalError,"unrecognized option: `%s'",
265          option);
266        break;
267      }
268      case 'a':
269      {
270        if (LocaleCompare("authenticate",option+1) == 0)
271          {
272            long
273               method;
274
275            if (*option == '+')
276              break;
277            i++;
278            if (i == (long) argc)
279              ThrowCipherException(OptionError,"missing authentication method: "
280                "`%s'",option);
281            method=ParseWizardOption(WizardAuthenticateOptions,WizardFalse,
282              argv[i]);
283            if (method < 0)
284              ThrowCipherException(OptionFatalError,"unrecognized "
285                "authentication method: `%s'",argv[i]);
286            content_info->authenticate_method=(AuthenticateMethod) method;
287            if (method == PublicAuthenticateMethod)
288              ThrowCipherException(OptionFatalError,"Public authentication "
289                "method not available yet: `%s'",argv[i]);
290            break;
291          }
292        ThrowCipherException(OptionFatalError,"unrecognized option: `%s'",
293          option);
294        break;
295      }
296      case 'c':
297      {
298        if (LocaleCompare("cipher",option+1) == 0)
299          {
300            if (*option == '+')
301              break;
302            i++;
303            if (i == (long) argc)
304              ThrowCipherException(OptionError,"missing cipher type: `%s'",
305                option);
306            type=ParseWizardOption(WizardCipherOptions,WizardFalse,argv[i]);
307            if (type < 0)
308              ThrowCipherException(OptionFatalError,"unrecognized cipher "
309                "type: `%s'",argv[i]);
310            content_info->cipher=(CipherType) type;
311            break;
312          }
313        if (LocaleCompare(option,"-chunksize") == 0)
314          {
315            char
316              *p;
317
318            if (*option == '+')
319              break;
320            i++;
321            if (i == (long) argc)
322              ThrowCipherException(OptionError,"missing chunk size: `%s'",
323                option);
324            (void) strtod(argv[i],&p);
325            if (p == argv[i])
326              ThrowInvalidArgumentException(option,argv[i]);
327            content_info->chunksize=(size_t) StringToDouble(argv[i],100.0);
328            break;
329          }
330        ThrowCipherException(OptionFatalError,"unrecognized option: `%s'",
331          option);
332        break;
333      }
334      case 'd':
335      {
336        if (LocaleCompare(option,"-debug") == 0)
337          {
338            LogEventType
339              event_mask;
340
341            i++;
342            if (i == (long) argc)
343              ThrowCipherException(OptionError,"missing log event mask: `%s'",
344                option);
345            event_mask=SetLogEventMask(argv[i]);
346            if (event_mask == UndefinedEvents)
347              ThrowCipherException(OptionFatalError,"unrecognized log event "
348                "type: `%s'",argv[i]);
349            break;
350          }
351        ThrowCipherException(OptionFatalError,"unrecognized option: `%s'",
352          option);
353        break;
354      }
355      case 'e':
356      {
357        if (LocaleCompare("entropy",option+1) == 0)
358          {
359            if (*option == '+')
360              break;
361            i++;
362            if (i == (long) argc)
363              ThrowCipherException(OptionError,"missing entropy type: `%s'",
364                option);
365            type=ParseWizardOption(WizardEntropyOptions,WizardFalse,argv[i]);
366            if (type < 0)
367              ThrowCipherException(OptionFatalError,"unrecognized entropy "
368                "type: `%s'",argv[i]);
369            content_info->entropy=(EntropyType) type;
370            break;
371          }
372        ThrowCipherException(OptionFatalError,"unrecognized option: `%s'",
373          option);
374        break;
375      }
376      case 'h':
377      {
378        if (LocaleCompare("hmac",option+1) == 0)
379          {
380            long
381              type;
382
383            if (*option == '+')
384              break;
385            i++;
386            if (i == (long) argc)
387              ThrowCipherException(OptionError,"missing HMAC hash: `%s'",
388                option);
389            type=ParseWizardOption(WizardHashOptions,WizardFalse,argv[i]);
390            if (type < 0)
391              ThrowCipherException(OptionFatalError,"unrecognized HMAC hash: "
392                "`%s'",argv[i]);
393            content_info->hmac=(HashType) type;
394            break;
395          }
396        if ((LocaleCompare("help",option+1) == 0) ||
397            (LocaleCompare("-help",option+1) == 0))
398          DecipherUsage();
399        ThrowCipherException(OptionFatalError,"unrecognized option: `%s'",
400          option);
401        break;
402      }
403      case 'k':
404      {
405        if (LocaleCompare("key",option+1) == 0)
406          {
407            long
408              type;
409
410            if (*option == '+')
411              break;
412            i++;
413            if (i == (long) argc)
414              ThrowCipherException(OptionError,"missing key hash: `%s'",option);
415            type=ParseWizardOption(WizardHashOptions,WizardFalse,argv[i]);
416            if (type < 0)
417              ThrowCipherException(OptionFatalError,"unrecognized key hash: "
418                "`%s'",argv[i]);
419            content_info->key_hash=(HashType) type;
420            break;
421          }
422        if (LocaleCompare("key-length",option+1) == 0)
423          {
424            if (*option == '+')
425              break;
426            i++;
427            if (i == (long) argc)
428              ThrowCipherException(OptionError,"missing key length: `%s'",
429                option);
430            content_info->key_length=(unsigned int) strtod(option,(char **)
431              NULL);
432            break;
433          }
434        if (LocaleCompare("keyring",option+1) == 0)
435          {
436            if (*option == '+')
437              break;
438            i++;
439            if (i == (long) argc)
440              ThrowCipherException(OptionError,"missing keyring filename: `%s'",
441                option);
442            content_info->keyring=ConstantString(argv[i]);
443            break;
444          }
445        ThrowCipherException(OptionFatalError,"unrecognized option: `%s'",
446          option);
447        break;
448      }
449      case 'l':
450      {
451        if (LocaleCompare(option,"-level") == 0)
452          {
453            if (*option == '+')
454              break;
455            i++;
456            if (i == (long) argc)
457              ThrowCipherException(OptionError,"missing entropy level: `%s'",
458                option);
459            type=ParseWizardOption(WizardEntropyLevelOptions,WizardFalse,
460              argv[i]);
461            if (type < 0)
462              ThrowCipherException(OptionFatalError,"unrecognized entropy "
463                "level: `%s'",argv[i]);
464            content_info->level=(unsigned int) type;
465            break;
466          }
467        if (LocaleCompare(option,"-list") == 0)
468          {
469            long
470              list;
471
472            if (*option == '+')
473              break;
474            i++;
475            if (i == (long) argc)
476              ThrowCipherException(OptionError,"missing list type: `%s'",
477                option);
478            if (LocaleCompare(argv[i],"configure") == 0)
479              {
480                (void) ListConfigureInfo((FILE *) NULL,exception);
481                Exit(0);
482              }
483            list=ParseWizardOption(WizardListOptions,WizardFalse,argv[i]);
484            if (list < 0)
485              ThrowCipherException(OptionFatalError,"unrecognized list type: "
486                "`%s'",argv[i]);
487            (void) ListWizardOptions((FILE *) NULL,(WizardOption) list,
488              exception);
489            Exit(0);
490            break;
491          }
492        if (LocaleCompare("log",option+1) == 0)
493          {
494            if (*option == '+')
495              break;
496            i++;
497            if ((i == (long) argc) ||
498                (strchr(argv[i],'%') == (char *) NULL))
499              ThrowCipherException(OptionFatalError,"missing argument: `%s'",
500                option);
501            break;
502          }
503        ThrowCipherException(OptionFatalError,"unrecognized option: `%s'",
504          option);
505        break;
506      }
507      case 'm':
508      {
509        if (LocaleCompare("mode",option+1) == 0)
510          {
511            long
512              type;
513
514            if (*option == '+')
515              break;
516            i++;
517            if (i == (long) argc)
518              ThrowCipherException(OptionError,"missing cipher mode: `%s'",
519                option);
520            type=ParseWizardOption(WizardModeOptions,WizardFalse,argv[i]);
521            if (type < 0)
522              ThrowCipherException(OptionFatalError,"unrecognized cipher "
523                "mode: `%s'",argv[i]);
524            content_info->mode=(CipherMode) type;
525            break;
526          }
527        ThrowCipherException(OptionFatalError,"unrecognized option: `%s'",
528          option);
529        break;
530      }
531      case 'p':
532      {
533        if (LocaleCompare("passphrase",option+1) == 0)
534          {
535            if (*option == '+')
536              break;
537            i++;
538            if (i == (long) argc)
539              ThrowCipherException(OptionError,"missing passphrase filename: "
540                "`%s'",option);
541            content_info->passphrase=ConstantString(argv[i]);
542            break;
543          }
544        if (LocaleCompare("properties",option+1) == 0)
545          {
546            if (*option == '+')
547              break;
548            i++;
549            if (i == (long) argc)
550              ThrowCipherException(OptionError,"missing properties filename: "
551                "`%s'",option);
552            content_info->properties=ConstantString(argv[i]);
553            break;
554          }
555        ThrowCipherException(OptionFatalError,"unrecognized option: `%s'",
556          option);
557        break;
558      }
559      case 't':
560      {
561        if (LocaleCompare(option+1,"true-random") == 0)
562          {
563            SetRandomTrueRandom(*option == '-' ? WizardTrue : WizardFalse);
564            break;
565          }
566        ThrowCipherException(OptionFatalError,"unrecognized option: `%s'",
567          option);
568        break;
569      }
570      case 'v':
571      {
572        if (LocaleCompare(option+1,"verbose") == 0)
573          {
574            verbose=(*option == '-') ? WizardTrue : WizardFalse;
575            break;
576          }
577        if (LocaleCompare(option,"-version") == 0)
578          {
579            (void) fprintf(stdout,"Version: %s\n",GetWizardVersion(
580              (unsigned long *) NULL));
581            (void) fprintf(stdout,"Copyright: %s\n\n",GetWizardCopyright());
582            exit(0);
583          }
584        ThrowCipherException(OptionFatalError,"unrecognized option: `%s'",
585          option);
586        break;
587      }
588      default:
589      {
590        ThrowCipherException(OptionFatalError,"unrecognized option: `%s'",
591          option);
592        break;
593      }
594    }
595  }
596  /*
597    Decipher content.
598  */
599  if ((plain_filename == (char *) NULL) ||
600      (cipher_filename == (char *) NULL))
601    DecipherUsage();
602  content_info->content=ConstantString(plain_filename);
603  status=DecipherContent(content_info,plain_filename,cipher_filename,compress,
604    exception);
605  if ((status != WizardFalse) && (verbose != WizardFalse))
606    (void) PrintCipherProperties(content_info,stdout);
607  /*
608    Free resources.
609  */
610  DestroyCipher();
611  return(status);
612}
613
614/*
615%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
616%                                                                             %
617%                                                                             %
618%                                                                             %
619%   D e c i p h e r C o n t e n t                                             %
620%                                                                             %
621%                                                                             %
622%                                                                             %
623%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
624%
625%  DecipherContent() reads ciphertext from a file and writes it as plaintext.
626%
627%  The format of the DecipherContent method is:
628%
629%      WizardBooleanType DecipherContent(ContentInfo *content_info,
630%        const char *cipher_filename,const char *plain_filename,
631%        const WizardBooleanType compress,ExceptionInfo *exception)
632%
633%  A description of each parameter follows:
634%
635%    o content_info: the cipher options.
636%
637%    o cipher_filename: the ciphertext filename.
638%
639%    o plain_filename: the plaintext filename.
640%
641%    o compress: automagically (de)compress BZIP and ZIP files.
642%
643%    o exception: return any exceptions in this structure.
644%
645*/
646static WizardBooleanType DecipherContent(ContentInfo *content_info,
647  const char *cipher_filename,const char *plain_filename,
648  const WizardBooleanType compress,ExceptionInfo *exception)
649{
650#define ThrowDecipherContentException(asperity,tag,context) \
651{ \
652  (void) ThrowWizardException(exception,GetWizardModule(),asperity, \
653    tag,context,strerror(errno)); \
654  return(WizardFalse); \
655}
656
657  char
658    message[MaxTextExtent];
659
660  EntropyType
661    entropy;
662
663  size_t
664    length,
665    pad;
666
667  ssize_t
668    count;
669
670  StringInfo
671    *ciphertext,
672    *hmac,
673    *plaintext;
674
675  unsigned long
676    blocksize,
677    chunk;
678
679  WizardBooleanType
680    status;
681
682  /*
683    Open plaintext and ciphertext content files.
684  */
685  content_info->cipherblob=OpenBlob(cipher_filename,ReadBinaryBlobMode,compress,
686    exception);
687  if (content_info->cipherblob == (BlobInfo *) NULL)
688    return(WizardFalse);
689  content_info->plainblob=OpenBlob(plain_filename,WriteBinaryBlobMode,compress,
690    exception);
691  if (content_info->plainblob == (BlobInfo *) NULL)
692    return(WizardFalse);
693  /*
694    Decipher plaintext.
695  */
696  if (content_info->properties == (char *) NULL)
697    status=GetContentInfo(content_info,content_info->cipherblob,exception);
698  else
699    {
700      BlobInfo
701        *properties;
702
703      /*
704        Cipher properties are stored separately from the content.
705      */
706      properties=OpenBlob(content_info->properties,ReadBinaryBlobMode,
707        WizardTrue,exception);
708      if (properties == (BlobInfo *) NULL)
709        return(WizardFalse);
710      status=GetContentInfo(content_info,properties,exception);
711      if (CloseBlob(properties) == WizardTrue)
712        ThrowFileException(exception,FileError,content_info->properties);
713      properties=DestroyBlob(properties);
714    }
715  if (status == WizardFalse)
716    return(WizardFalse);
717  content_info->authenticate_info=AcquireAuthenticateInfo(
718    content_info->authenticate_method,content_info->keyring,
719    content_info->key_hash);
720  SetAuthenticateKeyLength(content_info->authenticate_info,
721    content_info->key_length);
722  if (content_info->id != (char *) NULL)
723    {
724      StringInfo
725        *id;
726
727      /*
728        Set key id.
729      */
730      id=HexStringToStringInfo(content_info->id);
731      SetAuthenticateId(content_info->authenticate_info,id);
732      id=DestroyStringInfo(id);
733    }
734  if (content_info->passphrase != (char *) NULL)
735    SetAuthenticatePassphrase(content_info->authenticate_info,
736      content_info->passphrase);
737  status=AuthenticateKey(content_info->authenticate_info,exception);
738  if (status == WizardFalse)
739    ThrowDecipherContentException(ResourceError,"authentication failed: `%s': "
740      "`%s'",cipher_filename);
741  content_info->cipher_info=AcquireCipherInfo(content_info->cipher,
742    content_info->mode);
743  SetCipherKey(content_info->cipher_info,GetAuthenticateKey(
744    content_info->authenticate_info));
745  if (content_info->nonce != (char *) NULL)
746    {
747      StringInfo
748        *nonce;
749
750      /*
751        Set cipher nonce.
752      */
753      nonce=HexStringToStringInfo(content_info->nonce);
754      SetCipherNonce(content_info->cipher_info,nonce);
755      nonce=DestroyStringInfo(nonce);
756    }
757  hmac=(StringInfo *) NULL;
758  if (content_info->hmac != NoHash)
759    {
760      content_info->hmac_info=AcquireHMACInfo(content_info->hmac);
761      hmac=AcquireStringInfo(GetHMACDigestsize(content_info->hmac_info));
762    }
763  entropy=content_info->entropy;
764  if (content_info->entropy != NoEntropy)
765    content_info->entropy_info=AcquireEntropyInfo(content_info->entropy,
766      content_info->level);
767  blocksize=GetCipherBlocksize(content_info->cipher_info);
768  pad=blocksize-content_info->chunksize % blocksize;
769  if (pad == blocksize)
770    pad=0;
771  ciphertext=AcquireStringInfo(content_info->chunksize);
772  for (chunk=0; ; chunk++)
773  {
774    if (content_info->hmac != NoHash)
775      {
776        length=GetStringInfoLength(hmac);
777        count=ReadBlobChunk(content_info->cipherblob,length,GetStringInfoDatum(
778          hmac));
779        if (count <= 0)
780          break;
781      }
782    if (content_info->entropy != NoEntropy)
783      entropy=(EntropyType) ReadBlobByte(content_info->cipherblob);
784    length=content_info->chunksize;
785    if (content_info->mode != CFBMode)
786      length+=pad;
787    SetStringInfoLength(ciphertext,length);
788    count=ReadBlobChunk(content_info->cipherblob,length,GetStringInfoDatum(
789      ciphertext));
790    if (count <= 0)
791      break;
792    length=(size_t) count;
793    SetStringInfoLength(ciphertext,length);
794    plaintext=DecipherCipher(content_info->cipher_info,ciphertext);
795    if ((content_info->mode != CFBMode) &&
796        ((pad != 0) || (EOFBlob(content_info->cipherblob) != WizardFalse)))
797      length-=GetStringInfoDatum(plaintext)[length-1]+1;
798    SetStringInfoLength(plaintext,length);
799    if (entropy != NoEntropy)
800      {
801        status=RestoreEntropy(content_info->entropy_info,length,plaintext,
802          exception);
803        if (status == WizardFalse)
804          ThrowDecipherContentException(FileError,"unable to restore entropy "
805            "`%s': `%s'",cipher_filename);
806        SetStringInfo(plaintext,GetEntropyChaos(content_info->entropy_info));
807      }
808    if (content_info->hmac != NoHash)
809      {
810        ConstructHMAC(content_info->hmac_info,GetAuthenticateKey(
811          content_info->authenticate_info),plaintext);
812        if (CompareStringInfo(hmac,GetHMACDigest(content_info->hmac_info)) != 0)
813          {
814            (void) FormatWizardString(message,MaxTextExtent,"corrupt cipher "
815              "chunk #%lu `%s'",chunk,cipher_filename);
816            ThrowDecipherContentException(FileError,"%s: `%s'",message);
817          }
818      }
819    count=WriteBlobChunk(content_info->plainblob,length,GetStringInfoDatum(
820      plaintext));
821    if (count != (ssize_t) length)
822      ThrowDecipherContentException(FileError,"unable to write plaintext "
823        "`%s': `%s'",cipher_filename);
824  }
825  if (CloseBlob(content_info->cipherblob) != WizardFalse)
826    ThrowFileException(exception,FileError,content_info->content);
827  if (CloseBlob(content_info->plainblob) != WizardFalse)
828    ThrowFileException(exception,FileError,content_info->content);
829#if defined(WIZARDSTOOLKIT_HAVE_UTIME)
830  {
831    struct utimbuf
832      properties;
833
834    properties.actime=content_info->modify_date;
835    properties.modtime=content_info->modify_date;
836    if (utime(plain_filename,&properties) < 0)
837      ThrowFileException(exception,FileError,plain_filename);
838  }
839#endif
840  ciphertext=DestroyStringInfo(ciphertext);
841  if (content_info->hmac != NoHash)
842    hmac=DestroyStringInfo(hmac);
843  return(WizardTrue);
844}
845
846/*
847%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
848%                                                                             %
849%                                                                             %
850%                                                                             %
851%  M a i n                                                                    %
852%                                                                             %
853%                                                                             %
854%                                                                             %
855%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
856%
857%
858*/
859int main(int argc,char **argv)
860{
861  char
862    *option;
863
864  double
865    elapsed_time,
866    user_time;
867
868  ExceptionInfo
869    *exception;
870
871  register long
872    i;
873
874  TimerInfo
875    *timer;
876
877  unsigned int
878    iterations;
879
880  WizardBooleanType
881    regard_warnings,
882    status;
883
884  WizardsToolkitGenesis(*argv);
885  exception=AcquireExceptionInfo();
886  iterations=1;
887  status=WizardTrue;
888  regard_warnings=WizardFalse;
889  for (i=1; i < (long) (argc-1); i++)
890  {
891    option=argv[i];
892    if ((strlen(option) == 1) || ((*option != '-') && (*option != '+')))
893      continue;
894    if (LocaleCompare("bench",option+1) == 0)
895      iterations=(unsigned int) atol(argv[++i]);
896    if (LocaleCompare("debug",option+1) == 0)
897      (void) SetLogEventMask(argv[++i]);
898    if (LocaleCompare("regard-warnings",option+1) == 0)
899      regard_warnings=WizardTrue;
900  }
901  timer=(TimerInfo *) NULL;
902  if (iterations > 1)
903    timer=AcquireTimerInfo();
904  for (i=0; i < (long) iterations; i++)
905  {
906    status=DecipherCommand(argc,argv,exception);
907    if ((status == WizardFalse) ||
908        (GetExceptionSeverity(exception) != UndefinedException))
909      {
910        if ((GetExceptionSeverity(exception) < ErrorException) &&
911            (regard_warnings == WizardFalse))
912          status=WizardTrue;
913        CatchException(exception);
914      }
915  }
916  if (iterations > 1)
917    {
918      elapsed_time=GetElapsedTime(timer);
919      user_time=GetUserTime(timer);
920      (void) fprintf(stderr,"Performance: %ui %gips %0.3fu %ld:%02ld.%03ld\n",
921        iterations,1.0*iterations/elapsed_time,user_time,(long)
922        (elapsed_time/60.0+0.5),(long) floor(fmod(elapsed_time,60.0)),
923        (long) (1000.0*(elapsed_time-floor(elapsed_time))+0.5));
924      timer=DestroyTimerInfo(timer);
925    }
926  exception=DestroyExceptionInfo(exception);
927  WizardsToolkitTerminus();
928  return(status == WizardFalse ? 1 : 0);
929}
Note: See TracBrowser for help on using the browser.