root/maint/gnulib/lib/sha256-stream.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. shaxxx_stream
  2. sha256_stream
  3. sha224_stream

   1 /* sha256.c - Functions to compute SHA256 and SHA224 message digest of files or
   2    memory blocks according to the NIST specification FIPS-180-2.
   3 
   4    Copyright (C) 2005-2006, 2008-2021 Free Software Foundation, Inc.
   5 
   6    This file 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 the
   9    License, or (at your option) any later version.
  10 
  11    This file 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 License
  17    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
  18 
  19 /* Written by David Madore, considerably copypasting from
  20    Scott G. Miller's sha1.c
  21 */
  22 
  23 #include <config.h>
  24 
  25 /* Specification.  */
  26 #if HAVE_OPENSSL_SHA256
  27 # define GL_OPENSSL_INLINE _GL_EXTERN_INLINE
  28 #endif
  29 #include "sha256.h"
  30 
  31 #include <stdlib.h>
  32 
  33 #if USE_UNLOCKED_IO
  34 # include "unlocked-io.h"
  35 #endif
  36 
  37 #include "af_alg.h"
  38 
  39 #define BLOCKSIZE 32768
  40 #if BLOCKSIZE % 64 != 0
  41 # error "invalid BLOCKSIZE"
  42 #endif
  43 
  44 /* Compute message digest for bytes read from STREAM using algorithm ALG.
  45    Write the message digest into RESBLOCK, which contains HASHLEN bytes.
  46    The initial and finishing operations are INIT_CTX and FINISH_CTX.
  47    Return zero if and only if successful.  */
  48 static int
  49 shaxxx_stream (FILE *stream, char const *alg, void *resblock,
     /* [previous][next][first][last][top][bottom][index][help] */
  50                ssize_t hashlen, void (*init_ctx) (struct sha256_ctx *),
  51                void *(*finish_ctx) (struct sha256_ctx *, void *))
  52 {
  53   switch (afalg_stream (stream, alg, resblock, hashlen))
  54     {
  55     case 0: return 0;
  56     case -EIO: return 1;
  57     }
  58 
  59   char *buffer = malloc (BLOCKSIZE + 72);
  60   if (!buffer)
  61     return 1;
  62 
  63   struct sha256_ctx ctx;
  64   init_ctx (&ctx);
  65   size_t sum;
  66 
  67   /* Iterate over full file contents.  */
  68   while (1)
  69     {
  70       /* We read the file in blocks of BLOCKSIZE bytes.  One call of the
  71          computation function processes the whole buffer so that with the
  72          next round of the loop another block can be read.  */
  73       size_t n;
  74       sum = 0;
  75 
  76       /* Read block.  Take care for partial reads.  */
  77       while (1)
  78         {
  79           /* Either process a partial fread() from this loop,
  80              or the fread() in afalg_stream may have gotten EOF.
  81              We need to avoid a subsequent fread() as EOF may
  82              not be sticky.  For details of such systems, see:
  83              https://sourceware.org/bugzilla/show_bug.cgi?id=1190  */
  84           if (feof (stream))
  85             goto process_partial_block;
  86 
  87           n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
  88 
  89           sum += n;
  90 
  91           if (sum == BLOCKSIZE)
  92             break;
  93 
  94           if (n == 0)
  95             {
  96               /* Check for the error flag IFF N == 0, so that we don't
  97                  exit the loop after a partial read due to e.g., EAGAIN
  98                  or EWOULDBLOCK.  */
  99               if (ferror (stream))
 100                 {
 101                   free (buffer);
 102                   return 1;
 103                 }
 104               goto process_partial_block;
 105             }
 106         }
 107 
 108       /* Process buffer with BLOCKSIZE bytes.  Note that
 109                         BLOCKSIZE % 64 == 0
 110        */
 111       sha256_process_block (buffer, BLOCKSIZE, &ctx);
 112     }
 113 
 114  process_partial_block:;
 115 
 116   /* Process any remaining bytes.  */
 117   if (sum > 0)
 118     sha256_process_bytes (buffer, sum, &ctx);
 119 
 120   /* Construct result in desired memory.  */
 121   finish_ctx (&ctx, resblock);
 122   free (buffer);
 123   return 0;
 124 }
 125 
 126 int
 127 sha256_stream (FILE *stream, void *resblock)
     /* [previous][next][first][last][top][bottom][index][help] */
 128 {
 129   return shaxxx_stream (stream, "sha256", resblock, SHA256_DIGEST_SIZE,
 130                         sha256_init_ctx, sha256_finish_ctx);
 131 }
 132 
 133 int
 134 sha224_stream (FILE *stream, void *resblock)
     /* [previous][next][first][last][top][bottom][index][help] */
 135 {
 136   return shaxxx_stream (stream, "sha224", resblock, SHA224_DIGEST_SIZE,
 137                         sha224_init_ctx, sha224_finish_ctx);
 138 }
 139 
 140 /*
 141  * Hey Emacs!
 142  * Local Variables:
 143  * coding: utf-8
 144  * End:
 145  */

/* [previous][next][first][last][top][bottom][index][help] */