LCOV - code coverage report
Current view: top level - cipher - md.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 504 0.0 %
Date: 2016-12-15 12:59:22 Functions: 0 44 0.0 %

          Line data    Source code
       1             : /* md.c  -  message digest dispatcher
       2             :  * Copyright (C) 1998, 1999, 2002, 2003, 2006,
       3             :  *               2008 Free Software Foundation, Inc.
       4             :  * Copyright (C) 2013, 2014 g10 Code GmbH
       5             :  *
       6             :  * This file is part of Libgcrypt.
       7             :  *
       8             :  * Libgcrypt is free software; you can redistribute it and/or modify
       9             :  * it under the terms of the GNU Lesser general Public License as
      10             :  * published by the Free Software Foundation; either version 2.1 of
      11             :  * the License, or (at your option) any later version.
      12             :  *
      13             :  * Libgcrypt is distributed in the hope that it will be useful,
      14             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :  * GNU Lesser General Public License for more details.
      17             :  *
      18             :  * You should have received a copy of the GNU Lesser General Public
      19             :  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
      20             :  */
      21             : 
      22             : #include <config.h>
      23             : #include <stdio.h>
      24             : #include <stdlib.h>
      25             : #include <string.h>
      26             : #include <errno.h>
      27             : 
      28             : #include "g10lib.h"
      29             : #include "cipher.h"
      30             : 
      31             : 
      32             : /* This is the list of the digest implementations included in
      33             :    libgcrypt.  */
      34             : static gcry_md_spec_t *digest_list[] =
      35             :   {
      36             : #if USE_CRC
      37             :      &_gcry_digest_spec_crc32,
      38             :      &_gcry_digest_spec_crc32_rfc1510,
      39             :      &_gcry_digest_spec_crc24_rfc2440,
      40             : #endif
      41             : #if USE_SHA1
      42             :      &_gcry_digest_spec_sha1,
      43             : #endif
      44             : #if USE_SHA256
      45             :      &_gcry_digest_spec_sha256,
      46             :      &_gcry_digest_spec_sha224,
      47             : #endif
      48             : #if USE_SHA512
      49             :      &_gcry_digest_spec_sha512,
      50             :      &_gcry_digest_spec_sha384,
      51             : #endif
      52             : #if USE_SHA3
      53             :      &_gcry_digest_spec_sha3_224,
      54             :      &_gcry_digest_spec_sha3_256,
      55             :      &_gcry_digest_spec_sha3_384,
      56             :      &_gcry_digest_spec_sha3_512,
      57             :      &_gcry_digest_spec_shake128,
      58             :      &_gcry_digest_spec_shake256,
      59             : #endif
      60             : #ifdef USE_GOST_R_3411_94
      61             :      &_gcry_digest_spec_gost3411_94,
      62             :      &_gcry_digest_spec_gost3411_cp,
      63             : #endif
      64             : #ifdef USE_GOST_R_3411_12
      65             :      &_gcry_digest_spec_stribog_256,
      66             :      &_gcry_digest_spec_stribog_512,
      67             : #endif
      68             : #if USE_WHIRLPOOL
      69             :      &_gcry_digest_spec_whirlpool,
      70             : #endif
      71             : #if USE_RMD160
      72             :      &_gcry_digest_spec_rmd160,
      73             : #endif
      74             : #if USE_TIGER
      75             :      &_gcry_digest_spec_tiger,
      76             :      &_gcry_digest_spec_tiger1,
      77             :      &_gcry_digest_spec_tiger2,
      78             : #endif
      79             : #if USE_MD5
      80             :      &_gcry_digest_spec_md5,
      81             : #endif
      82             : #if USE_MD4
      83             :      &_gcry_digest_spec_md4,
      84             : #endif
      85             : #if USE_MD2
      86             :      &_gcry_digest_spec_md2,
      87             : #endif
      88             :     NULL
      89             :   };
      90             : 
      91             : 
      92             : typedef struct gcry_md_list
      93             : {
      94             :   gcry_md_spec_t *spec;
      95             :   struct gcry_md_list *next;
      96             :   size_t actual_struct_size;     /* Allocated size of this structure. */
      97             :   PROPERLY_ALIGNED_TYPE context;
      98             : } GcryDigestEntry;
      99             : 
     100             : /* This structure is put right after the gcry_md_hd_t buffer, so that
     101             :  * only one memory block is needed. */
     102             : struct gcry_md_context
     103             : {
     104             :   int  magic;
     105             :   size_t actual_handle_size;     /* Allocated size of this handle. */
     106             :   FILE  *debug;
     107             :   struct {
     108             :     unsigned int secure: 1;
     109             :     unsigned int finalized:1;
     110             :     unsigned int bugemu1:1;
     111             :     unsigned int hmac:1;
     112             :   } flags;
     113             :   GcryDigestEntry *list;
     114             : };
     115             : 
     116             : 
     117             : #define CTX_MAGIC_NORMAL 0x11071961
     118             : #define CTX_MAGIC_SECURE 0x16917011
     119             : 
     120             : static gcry_err_code_t md_enable (gcry_md_hd_t hd, int algo);
     121             : static void md_close (gcry_md_hd_t a);
     122             : static void md_write (gcry_md_hd_t a, const void *inbuf, size_t inlen);
     123             : static byte *md_read( gcry_md_hd_t a, int algo );
     124             : static int md_get_algo( gcry_md_hd_t a );
     125             : static int md_digest_length( int algo );
     126             : static void md_start_debug ( gcry_md_hd_t a, const char *suffix );
     127             : static void md_stop_debug ( gcry_md_hd_t a );
     128             : 
     129             : 
     130             : 
     131             : static int
     132           0 : map_algo (int algo)
     133             : {
     134           0 :   return algo;
     135             : }
     136             : 
     137             : 
     138             : /* Return the spec structure for the hash algorithm ALGO.  For an
     139             :    unknown algorithm NULL is returned.  */
     140             : static gcry_md_spec_t *
     141           0 : spec_from_algo (int algo)
     142             : {
     143             :   int idx;
     144             :   gcry_md_spec_t *spec;
     145             : 
     146           0 :   algo = map_algo (algo);
     147             : 
     148           0 :   for (idx = 0; (spec = digest_list[idx]); idx++)
     149           0 :     if (algo == spec->algo)
     150           0 :       return spec;
     151           0 :   return NULL;
     152             : }
     153             : 
     154             : 
     155             : /* Lookup a hash's spec by its name.  */
     156             : static gcry_md_spec_t *
     157           0 : spec_from_name (const char *name)
     158             : {
     159             :   gcry_md_spec_t *spec;
     160             :   int idx;
     161             : 
     162           0 :   for (idx=0; (spec = digest_list[idx]); idx++)
     163             :     {
     164           0 :       if (!stricmp (name, spec->name))
     165           0 :         return spec;
     166             :     }
     167             : 
     168           0 :   return NULL;
     169             : }
     170             : 
     171             : 
     172             : /* Lookup a hash's spec by its OID.  */
     173             : static gcry_md_spec_t *
     174           0 : spec_from_oid (const char *oid)
     175             : {
     176             :   gcry_md_spec_t *spec;
     177             :   gcry_md_oid_spec_t *oid_specs;
     178             :   int idx, j;
     179             : 
     180           0 :   for (idx=0; (spec = digest_list[idx]); idx++)
     181             :     {
     182           0 :       oid_specs = spec->oids;
     183           0 :       if (oid_specs)
     184             :         {
     185           0 :           for (j = 0; oid_specs[j].oidstring; j++)
     186           0 :             if (!stricmp (oid, oid_specs[j].oidstring))
     187           0 :               return spec;
     188             :         }
     189             :     }
     190             : 
     191           0 :   return NULL;
     192             : }
     193             : 
     194             : 
     195             : static gcry_md_spec_t *
     196           0 : search_oid (const char *oid, gcry_md_oid_spec_t *oid_spec)
     197             : {
     198             :   gcry_md_spec_t *spec;
     199             :   int i;
     200             : 
     201           0 :   if (!oid)
     202           0 :     return NULL;
     203             : 
     204           0 :   if (!strncmp (oid, "oid.", 4) || !strncmp (oid, "OID.", 4))
     205           0 :     oid += 4;
     206             : 
     207           0 :   spec = spec_from_oid (oid);
     208           0 :   if (spec && spec->oids)
     209             :     {
     210           0 :       for (i = 0; spec->oids[i].oidstring; i++)
     211           0 :         if (!stricmp (oid, spec->oids[i].oidstring))
     212             :           {
     213           0 :             if (oid_spec)
     214           0 :               *oid_spec = spec->oids[i];
     215           0 :             return spec;
     216             :           }
     217             :     }
     218             : 
     219           0 :   return NULL;
     220             : }
     221             : 
     222             : 
     223             : /****************
     224             :  * Map a string to the digest algo
     225             :  */
     226             : int
     227           0 : _gcry_md_map_name (const char *string)
     228             : {
     229             :   gcry_md_spec_t *spec;
     230             : 
     231           0 :   if (!string)
     232           0 :     return 0;
     233             : 
     234             :   /* If the string starts with a digit (optionally prefixed with
     235             :      either "OID." or "oid."), we first look into our table of ASN.1
     236             :      object identifiers to figure out the algorithm */
     237           0 :   spec = search_oid (string, NULL);
     238           0 :   if (spec)
     239           0 :     return spec->algo;
     240             : 
     241             :   /* Not found, search a matching digest name.  */
     242           0 :   spec = spec_from_name (string);
     243           0 :   if (spec)
     244           0 :     return spec->algo;
     245             : 
     246           0 :   return 0;
     247             : }
     248             : 
     249             : 
     250             : /****************
     251             :  * This function simply returns the name of the algorithm or some constant
     252             :  * string when there is no algo.  It will never return NULL.
     253             :  * Use  the macro gcry_md_test_algo() to check whether the algorithm
     254             :  * is valid.
     255             :  */
     256             : const char *
     257           0 : _gcry_md_algo_name (int algorithm)
     258             : {
     259             :   gcry_md_spec_t *spec;
     260             : 
     261           0 :   spec = spec_from_algo (algorithm);
     262           0 :   return spec ? spec->name : "?";
     263             : }
     264             : 
     265             : 
     266             : static gcry_err_code_t
     267           0 : check_digest_algo (int algorithm)
     268             : {
     269             :   gcry_md_spec_t *spec;
     270             : 
     271           0 :   spec = spec_from_algo (algorithm);
     272           0 :   if (spec && !spec->flags.disabled)
     273           0 :     return 0;
     274             : 
     275           0 :   return GPG_ERR_DIGEST_ALGO;
     276             : 
     277             : }
     278             : 
     279             : 
     280             : /****************
     281             :  * Open a message digest handle for use with algorithm ALGO.
     282             :  * More algorithms may be added by md_enable(). The initial algorithm
     283             :  * may be 0.
     284             :  */
     285             : static gcry_err_code_t
     286           0 : md_open (gcry_md_hd_t *h, int algo, unsigned int flags)
     287             : {
     288           0 :   gcry_err_code_t err = 0;
     289           0 :   int secure = !!(flags & GCRY_MD_FLAG_SECURE);
     290           0 :   int hmac =   !!(flags & GCRY_MD_FLAG_HMAC);
     291           0 :   int bufsize = secure ? 512 : 1024;
     292             :   struct gcry_md_context *ctx;
     293             :   gcry_md_hd_t hd;
     294             :   size_t n;
     295             : 
     296             :   /* Allocate a memory area to hold the caller visible buffer with it's
     297             :    * control information and the data required by this module. Set the
     298             :    * context pointer at the beginning to this area.
     299             :    * We have to use this strange scheme because we want to hide the
     300             :    * internal data but have a variable sized buffer.
     301             :    *
     302             :    *    +---+------+---........------+-------------+
     303             :    *    !ctx! bctl !  buffer         ! private     !
     304             :    *    +---+------+---........------+-------------+
     305             :    *      !                           ^
     306             :    *      !---------------------------!
     307             :    *
     308             :    * We have to make sure that private is well aligned.
     309             :    */
     310           0 :   n = sizeof (struct gcry_md_handle) + bufsize;
     311           0 :   n = ((n + sizeof (PROPERLY_ALIGNED_TYPE) - 1)
     312             :        / sizeof (PROPERLY_ALIGNED_TYPE)) * sizeof (PROPERLY_ALIGNED_TYPE);
     313             : 
     314             :   /* Allocate and set the Context pointer to the private data */
     315           0 :   if (secure)
     316           0 :     hd = xtrymalloc_secure (n + sizeof (struct gcry_md_context));
     317             :   else
     318           0 :     hd = xtrymalloc (n + sizeof (struct gcry_md_context));
     319             : 
     320           0 :   if (! hd)
     321           0 :     err = gpg_err_code_from_errno (errno);
     322             : 
     323           0 :   if (! err)
     324             :     {
     325           0 :       hd->ctx = ctx = (void *) ((char *) hd + n);
     326             :       /* Setup the globally visible data (bctl in the diagram).*/
     327           0 :       hd->bufsize = n - sizeof (struct gcry_md_handle) + 1;
     328           0 :       hd->bufpos = 0;
     329             : 
     330             :       /* Initialize the private data. */
     331           0 :       memset (hd->ctx, 0, sizeof *hd->ctx);
     332           0 :       ctx->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL;
     333           0 :       ctx->actual_handle_size = n + sizeof (struct gcry_md_context);
     334           0 :       ctx->flags.secure = secure;
     335           0 :       ctx->flags.hmac = hmac;
     336           0 :       ctx->flags.bugemu1 = !!(flags & GCRY_MD_FLAG_BUGEMU1);
     337             :     }
     338             : 
     339           0 :   if (! err)
     340             :     {
     341             :       /* Hmmm, should we really do that? - yes [-wk] */
     342           0 :       _gcry_fast_random_poll ();
     343             : 
     344           0 :       if (algo)
     345             :         {
     346           0 :           err = md_enable (hd, algo);
     347           0 :           if (err)
     348           0 :             md_close (hd);
     349             :         }
     350             :     }
     351             : 
     352           0 :   if (! err)
     353           0 :     *h = hd;
     354             : 
     355           0 :   return err;
     356             : }
     357             : 
     358             : /* Create a message digest object for algorithm ALGO.  FLAGS may be
     359             :    given as an bitwise OR of the gcry_md_flags values.  ALGO may be
     360             :    given as 0 if the algorithms to be used are later set using
     361             :    gcry_md_enable. H is guaranteed to be a valid handle or NULL on
     362             :    error.  */
     363             : gcry_err_code_t
     364           0 : _gcry_md_open (gcry_md_hd_t *h, int algo, unsigned int flags)
     365             : {
     366             :   gcry_err_code_t rc;
     367             :   gcry_md_hd_t hd;
     368             : 
     369           0 :   if ((flags & ~(GCRY_MD_FLAG_SECURE
     370             :                  | GCRY_MD_FLAG_HMAC
     371             :                  | GCRY_MD_FLAG_BUGEMU1)))
     372           0 :     rc = GPG_ERR_INV_ARG;
     373             :   else
     374           0 :     rc = md_open (&hd, algo, flags);
     375             : 
     376           0 :   *h = rc? NULL : hd;
     377           0 :   return rc;
     378             : }
     379             : 
     380             : 
     381             : 
     382             : static gcry_err_code_t
     383           0 : md_enable (gcry_md_hd_t hd, int algorithm)
     384             : {
     385           0 :   struct gcry_md_context *h = hd->ctx;
     386             :   gcry_md_spec_t *spec;
     387             :   GcryDigestEntry *entry;
     388           0 :   gcry_err_code_t err = 0;
     389             : 
     390           0 :   for (entry = h->list; entry; entry = entry->next)
     391           0 :     if (entry->spec->algo == algorithm)
     392           0 :       return 0; /* Already enabled */
     393             : 
     394           0 :   spec = spec_from_algo (algorithm);
     395           0 :   if (!spec)
     396             :     {
     397           0 :       log_debug ("md_enable: algorithm %d not available\n", algorithm);
     398           0 :       err = GPG_ERR_DIGEST_ALGO;
     399             :     }
     400             : 
     401             : 
     402           0 :   if (!err && algorithm == GCRY_MD_MD5 && fips_mode ())
     403             :     {
     404           0 :       _gcry_inactivate_fips_mode ("MD5 used");
     405           0 :       if (_gcry_enforced_fips_mode () )
     406             :         {
     407             :           /* We should never get to here because we do not register
     408             :              MD5 in enforced fips mode. But better throw an error.  */
     409           0 :           err = GPG_ERR_DIGEST_ALGO;
     410             :         }
     411             :     }
     412             : 
     413           0 :   if (!err && h->flags.hmac && spec->read == NULL)
     414             :     {
     415             :       /* Expandable output function cannot act as part of HMAC. */
     416           0 :       err = GPG_ERR_DIGEST_ALGO;
     417             :     }
     418             : 
     419           0 :   if (!err)
     420             :     {
     421           0 :       size_t size = (sizeof (*entry)
     422           0 :                      + spec->contextsize * (h->flags.hmac? 3 : 1)
     423             :                      - sizeof (entry->context));
     424             : 
     425             :       /* And allocate a new list entry. */
     426           0 :       if (h->flags.secure)
     427           0 :         entry = xtrymalloc_secure (size);
     428             :       else
     429           0 :         entry = xtrymalloc (size);
     430             : 
     431           0 :       if (! entry)
     432           0 :         err = gpg_err_code_from_errno (errno);
     433             :       else
     434             :         {
     435           0 :           entry->spec = spec;
     436           0 :           entry->next = h->list;
     437           0 :           entry->actual_struct_size = size;
     438           0 :           h->list = entry;
     439             : 
     440             :           /* And init this instance. */
     441           0 :           entry->spec->init (&entry->context.c,
     442           0 :                              h->flags.bugemu1? GCRY_MD_FLAG_BUGEMU1:0);
     443             :         }
     444             :     }
     445             : 
     446           0 :   return err;
     447             : }
     448             : 
     449             : 
     450             : gcry_err_code_t
     451           0 : _gcry_md_enable (gcry_md_hd_t hd, int algorithm)
     452             : {
     453           0 :   return md_enable (hd, algorithm);
     454             : }
     455             : 
     456             : 
     457             : static gcry_err_code_t
     458           0 : md_copy (gcry_md_hd_t ahd, gcry_md_hd_t *b_hd)
     459             : {
     460           0 :   gcry_err_code_t err = 0;
     461           0 :   struct gcry_md_context *a = ahd->ctx;
     462             :   struct gcry_md_context *b;
     463             :   GcryDigestEntry *ar, *br;
     464             :   gcry_md_hd_t bhd;
     465             :   size_t n;
     466             : 
     467           0 :   if (ahd->bufpos)
     468           0 :     md_write (ahd, NULL, 0);
     469             : 
     470           0 :   n = (char *) ahd->ctx - (char *) ahd;
     471           0 :   if (a->flags.secure)
     472           0 :     bhd = xtrymalloc_secure (n + sizeof (struct gcry_md_context));
     473             :   else
     474           0 :     bhd = xtrymalloc (n + sizeof (struct gcry_md_context));
     475             : 
     476           0 :   if (!bhd)
     477             :     {
     478           0 :       err = gpg_err_code_from_syserror ();
     479           0 :       goto leave;
     480             :     }
     481             : 
     482           0 :   bhd->ctx = b = (void *) ((char *) bhd + n);
     483             :   /* No need to copy the buffer due to the write above. */
     484           0 :   gcry_assert (ahd->bufsize == (n - sizeof (struct gcry_md_handle) + 1));
     485           0 :   bhd->bufsize = ahd->bufsize;
     486           0 :   bhd->bufpos = 0;
     487           0 :   gcry_assert (! ahd->bufpos);
     488           0 :   memcpy (b, a, sizeof *a);
     489           0 :   b->list = NULL;
     490           0 :   b->debug = NULL;
     491             : 
     492             :   /* Copy the complete list of algorithms.  The copied list is
     493             :      reversed, but that doesn't matter. */
     494           0 :   for (ar = a->list; ar; ar = ar->next)
     495             :     {
     496           0 :       if (a->flags.secure)
     497           0 :         br = xtrymalloc_secure (ar->actual_struct_size);
     498             :       else
     499           0 :         br = xtrymalloc (ar->actual_struct_size);
     500           0 :       if (!br)
     501             :         {
     502           0 :           err = gpg_err_code_from_syserror ();
     503           0 :           md_close (bhd);
     504           0 :           goto leave;
     505             :         }
     506             : 
     507           0 :       memcpy (br, ar, ar->actual_struct_size);
     508           0 :       br->next = b->list;
     509           0 :       b->list = br;
     510             :     }
     511             : 
     512           0 :   if (a->debug)
     513           0 :     md_start_debug (bhd, "unknown");
     514             : 
     515           0 :   *b_hd = bhd;
     516             : 
     517             :  leave:
     518           0 :   return err;
     519             : }
     520             : 
     521             : 
     522             : gcry_err_code_t
     523           0 : _gcry_md_copy (gcry_md_hd_t *handle, gcry_md_hd_t hd)
     524             : {
     525             :   gcry_err_code_t rc;
     526             : 
     527           0 :   rc = md_copy (hd, handle);
     528           0 :   if (rc)
     529           0 :     *handle = NULL;
     530           0 :   return rc;
     531             : }
     532             : 
     533             : 
     534             : /*
     535             :  * Reset all contexts and discard any buffered stuff.  This may be used
     536             :  * instead of a md_close(); md_open().
     537             :  */
     538             : void
     539           0 : _gcry_md_reset (gcry_md_hd_t a)
     540             : {
     541             :   GcryDigestEntry *r;
     542             : 
     543             :   /* Note: We allow this even in fips non operational mode.  */
     544             : 
     545           0 :   a->bufpos = a->ctx->flags.finalized = 0;
     546             : 
     547           0 :   if (a->ctx->flags.hmac)
     548           0 :     for (r = a->ctx->list; r; r = r->next)
     549             :       {
     550           0 :         memcpy (r->context.c, r->context.c + r->spec->contextsize,
     551           0 :                 r->spec->contextsize);
     552             :       }
     553             :   else
     554           0 :     for (r = a->ctx->list; r; r = r->next)
     555             :       {
     556           0 :         memset (r->context.c, 0, r->spec->contextsize);
     557           0 :         (*r->spec->init) (&r->context.c,
     558           0 :                           a->ctx->flags.bugemu1? GCRY_MD_FLAG_BUGEMU1:0);
     559             :       }
     560           0 : }
     561             : 
     562             : 
     563             : static void
     564           0 : md_close (gcry_md_hd_t a)
     565             : {
     566             :   GcryDigestEntry *r, *r2;
     567             : 
     568           0 :   if (! a)
     569           0 :     return;
     570           0 :   if (a->ctx->debug)
     571           0 :     md_stop_debug (a);
     572           0 :   for (r = a->ctx->list; r; r = r2)
     573             :     {
     574           0 :       r2 = r->next;
     575           0 :       wipememory (r, r->actual_struct_size);
     576           0 :       xfree (r);
     577             :     }
     578             : 
     579           0 :   wipememory (a, a->ctx->actual_handle_size);
     580           0 :   xfree(a);
     581             : }
     582             : 
     583             : 
     584             : void
     585           0 : _gcry_md_close (gcry_md_hd_t hd)
     586             : {
     587             :   /* Note: We allow this even in fips non operational mode.  */
     588           0 :   md_close (hd);
     589           0 : }
     590             : 
     591             : 
     592             : static void
     593           0 : md_write (gcry_md_hd_t a, const void *inbuf, size_t inlen)
     594             : {
     595             :   GcryDigestEntry *r;
     596             : 
     597           0 :   if (a->ctx->debug)
     598             :     {
     599           0 :       if (a->bufpos && fwrite (a->buf, a->bufpos, 1, a->ctx->debug) != 1)
     600           0 :         BUG();
     601           0 :       if (inlen && fwrite (inbuf, inlen, 1, a->ctx->debug) != 1)
     602           0 :         BUG();
     603             :     }
     604             : 
     605           0 :   for (r = a->ctx->list; r; r = r->next)
     606             :     {
     607           0 :       if (a->bufpos)
     608           0 :         (*r->spec->write) (&r->context.c, a->buf, a->bufpos);
     609           0 :       (*r->spec->write) (&r->context.c, inbuf, inlen);
     610             :     }
     611           0 :   a->bufpos = 0;
     612           0 : }
     613             : 
     614             : 
     615             : /* Note that this function may be used after finalize and read to keep
     616             :    on writing to the transform function so to mitigate timing
     617             :    attacks.  */
     618             : void
     619           0 : _gcry_md_write (gcry_md_hd_t hd, const void *inbuf, size_t inlen)
     620             : {
     621           0 :   md_write (hd, inbuf, inlen);
     622           0 : }
     623             : 
     624             : 
     625             : static void
     626           0 : md_final (gcry_md_hd_t a)
     627             : {
     628             :   GcryDigestEntry *r;
     629             : 
     630           0 :   if (a->ctx->flags.finalized)
     631           0 :     return;
     632             : 
     633           0 :   if (a->bufpos)
     634           0 :     md_write (a, NULL, 0);
     635             : 
     636           0 :   for (r = a->ctx->list; r; r = r->next)
     637           0 :     (*r->spec->final) (&r->context.c);
     638             : 
     639           0 :   a->ctx->flags.finalized = 1;
     640             : 
     641           0 :   if (!a->ctx->flags.hmac)
     642           0 :     return;
     643             : 
     644           0 :   for (r = a->ctx->list; r; r = r->next)
     645             :     {
     646             :       byte *p;
     647           0 :       size_t dlen = r->spec->mdlen;
     648             :       byte *hash;
     649             :       gcry_err_code_t err;
     650             : 
     651           0 :       if (r->spec->read == NULL)
     652           0 :         continue;
     653             : 
     654           0 :       p = r->spec->read (&r->context.c);
     655             : 
     656           0 :       if (a->ctx->flags.secure)
     657           0 :         hash = xtrymalloc_secure (dlen);
     658             :       else
     659           0 :         hash = xtrymalloc (dlen);
     660           0 :       if (!hash)
     661             :         {
     662           0 :           err = gpg_err_code_from_errno (errno);
     663           0 :           _gcry_fatal_error (err, NULL);
     664             :         }
     665             : 
     666           0 :       memcpy (hash, p, dlen);
     667           0 :       memcpy (r->context.c, r->context.c + r->spec->contextsize * 2,
     668           0 :               r->spec->contextsize);
     669           0 :       (*r->spec->write) (&r->context.c, hash, dlen);
     670           0 :       (*r->spec->final) (&r->context.c);
     671           0 :       xfree (hash);
     672             :     }
     673             : }
     674             : 
     675             : 
     676             : static gcry_err_code_t
     677           0 : prepare_macpads (gcry_md_hd_t a, const unsigned char *key, size_t keylen)
     678             : {
     679             :   GcryDigestEntry *r;
     680             : 
     681           0 :   if (!a->ctx->list)
     682           0 :     return GPG_ERR_DIGEST_ALGO; /* Might happen if no algo is enabled.  */
     683             : 
     684           0 :   if (!a->ctx->flags.hmac)
     685           0 :     return GPG_ERR_DIGEST_ALGO; /* Tried setkey for non-HMAC md. */
     686             : 
     687           0 :   for (r = a->ctx->list; r; r = r->next)
     688             :     {
     689             :       const unsigned char *k;
     690             :       size_t k_len;
     691           0 :       unsigned char *key_allocated = NULL;
     692             :       int macpad_Bsize;
     693             :       int i;
     694             : 
     695           0 :       switch (r->spec->algo)
     696             :         {
     697             :         case GCRY_MD_SHA3_224:
     698           0 :           macpad_Bsize = 1152 / 8;
     699           0 :           break;
     700             :         case GCRY_MD_SHA3_256:
     701           0 :           macpad_Bsize = 1088 / 8;
     702           0 :           break;
     703             :         case GCRY_MD_SHA3_384:
     704           0 :           macpad_Bsize = 832 / 8;
     705           0 :           break;
     706             :         case GCRY_MD_SHA3_512:
     707           0 :           macpad_Bsize = 576 / 8;
     708           0 :           break;
     709             :         case GCRY_MD_SHA384:
     710             :         case GCRY_MD_SHA512:
     711           0 :           macpad_Bsize = 128;
     712           0 :           break;
     713             :         case GCRY_MD_GOSTR3411_94:
     714             :         case GCRY_MD_GOSTR3411_CP:
     715           0 :           macpad_Bsize = 32;
     716           0 :           break;
     717             :         default:
     718           0 :           macpad_Bsize = 64;
     719           0 :           break;
     720             :         }
     721             : 
     722           0 :       if ( keylen > macpad_Bsize )
     723             :         {
     724           0 :           k = key_allocated = xtrymalloc_secure (r->spec->mdlen);
     725           0 :           if (!k)
     726           0 :             return gpg_err_code_from_errno (errno);
     727           0 :           _gcry_md_hash_buffer (r->spec->algo, key_allocated, key, keylen);
     728           0 :           k_len = r->spec->mdlen;
     729           0 :           gcry_assert ( k_len <= macpad_Bsize );
     730             :         }
     731             :       else
     732             :         {
     733           0 :           k = key;
     734           0 :           k_len = keylen;
     735             :         }
     736             : 
     737           0 :       (*r->spec->init) (&r->context.c,
     738           0 :                         a->ctx->flags.bugemu1? GCRY_MD_FLAG_BUGEMU1:0);
     739           0 :       a->bufpos = 0;
     740           0 :       for (i=0; i < k_len; i++ )
     741           0 :         _gcry_md_putc (a, k[i] ^ 0x36);
     742           0 :       for (; i < macpad_Bsize; i++ )
     743           0 :         _gcry_md_putc (a, 0x36);
     744           0 :       (*r->spec->write) (&r->context.c, a->buf, a->bufpos);
     745           0 :       memcpy (r->context.c + r->spec->contextsize, r->context.c,
     746           0 :               r->spec->contextsize);
     747             : 
     748           0 :       (*r->spec->init) (&r->context.c,
     749           0 :                         a->ctx->flags.bugemu1? GCRY_MD_FLAG_BUGEMU1:0);
     750           0 :       a->bufpos = 0;
     751           0 :       for (i=0; i < k_len; i++ )
     752           0 :         _gcry_md_putc (a, k[i] ^ 0x5c);
     753           0 :       for (; i < macpad_Bsize; i++ )
     754           0 :         _gcry_md_putc (a, 0x5c);
     755           0 :       (*r->spec->write) (&r->context.c, a->buf, a->bufpos);
     756           0 :       memcpy (r->context.c + r->spec->contextsize*2, r->context.c,
     757           0 :               r->spec->contextsize);
     758             : 
     759           0 :       xfree (key_allocated);
     760             :     }
     761             : 
     762           0 :   a->bufpos = 0;
     763           0 :   return 0;
     764             : }
     765             : 
     766             : 
     767             : gcry_err_code_t
     768           0 : _gcry_md_ctl (gcry_md_hd_t hd, int cmd, void *buffer, size_t buflen)
     769             : {
     770           0 :   gcry_err_code_t rc = 0;
     771             : 
     772             :   (void)buflen; /* Currently not used.  */
     773             : 
     774           0 :   switch (cmd)
     775             :     {
     776             :     case GCRYCTL_FINALIZE:
     777           0 :       md_final (hd);
     778           0 :       break;
     779             :     case GCRYCTL_START_DUMP:
     780           0 :       md_start_debug (hd, buffer);
     781           0 :       break;
     782             :     case GCRYCTL_STOP_DUMP:
     783           0 :       md_stop_debug ( hd );
     784           0 :       break;
     785             :     default:
     786           0 :       rc = GPG_ERR_INV_OP;
     787             :     }
     788           0 :   return rc;
     789             : }
     790             : 
     791             : 
     792             : gcry_err_code_t
     793           0 : _gcry_md_setkey (gcry_md_hd_t hd, const void *key, size_t keylen)
     794             : {
     795             :   gcry_err_code_t rc;
     796             : 
     797           0 :   rc = prepare_macpads (hd, key, keylen);
     798           0 :   if (!rc)
     799           0 :     _gcry_md_reset (hd);
     800             : 
     801           0 :   return rc;
     802             : }
     803             : 
     804             : 
     805             : /* The new debug interface.  If SUFFIX is a string it creates an debug
     806             :    file for the context HD.  IF suffix is NULL, the file is closed and
     807             :    debugging is stopped.  */
     808             : void
     809           0 : _gcry_md_debug (gcry_md_hd_t hd, const char *suffix)
     810             : {
     811           0 :   if (suffix)
     812           0 :     md_start_debug (hd, suffix);
     813             :   else
     814           0 :     md_stop_debug (hd);
     815           0 : }
     816             : 
     817             : 
     818             : /****************
     819             :  * If ALGO is null get the digest for the used algo (which should be
     820             :  * only one)
     821             :  */
     822             : static byte *
     823           0 : md_read( gcry_md_hd_t a, int algo )
     824             : {
     825           0 :   GcryDigestEntry *r = a->ctx->list;
     826             : 
     827           0 :   if (! algo)
     828             :     {
     829             :       /* Return the first algorithm */
     830           0 :       if (r)
     831             :         {
     832           0 :           if (r->next)
     833           0 :             log_debug ("more than one algorithm in md_read(0)\n");
     834           0 :           if (r->spec->read)
     835           0 :             return r->spec->read (&r->context.c);
     836             :         }
     837             :     }
     838             :   else
     839             :     {
     840           0 :       for (r = a->ctx->list; r; r = r->next)
     841           0 :         if (r->spec->algo == algo)
     842             :           {
     843           0 :             if (r->spec->read)
     844           0 :               return r->spec->read (&r->context.c);
     845           0 :             break;
     846             :           }
     847             :     }
     848             : 
     849           0 :   if (r && !r->spec->read)
     850           0 :     _gcry_fatal_error (GPG_ERR_DIGEST_ALGO,
     851             :                        "requested algo has no fixed digest length");
     852             :   else
     853           0 :     _gcry_fatal_error (GPG_ERR_DIGEST_ALGO, "requested algo not in md context");
     854             :   return NULL;
     855             : }
     856             : 
     857             : 
     858             : /*
     859             :  * Read out the complete digest, this function implictly finalizes
     860             :  * the hash.
     861             :  */
     862             : byte *
     863           0 : _gcry_md_read (gcry_md_hd_t hd, int algo)
     864             : {
     865             :   /* This function is expected to always return a digest, thus we
     866             :      can't return an error which we actually should do in
     867             :      non-operational state.  */
     868           0 :   _gcry_md_ctl (hd, GCRYCTL_FINALIZE, NULL, 0);
     869           0 :   return md_read (hd, algo);
     870             : }
     871             : 
     872             : 
     873             : /****************
     874             :  * If ALGO is null get the digest for the used algo (which should be
     875             :  * only one)
     876             :  */
     877             : static gcry_err_code_t
     878           0 : md_extract(gcry_md_hd_t a, int algo, void *out, size_t outlen)
     879             : {
     880           0 :   GcryDigestEntry *r = a->ctx->list;
     881             : 
     882           0 :   if (!algo)
     883             :     {
     884             :       /* Return the first algorithm */
     885           0 :       if (r && r->spec->extract)
     886             :         {
     887           0 :           if (r->next)
     888           0 :             log_debug ("more than one algorithm in md_extract(0)\n");
     889           0 :           r->spec->extract (&r->context.c, out, outlen);
     890           0 :           return 0;
     891             :         }
     892             :     }
     893             :   else
     894             :     {
     895           0 :       for (r = a->ctx->list; r; r = r->next)
     896           0 :         if (r->spec->algo == algo && r->spec->extract)
     897             :           {
     898           0 :             r->spec->extract (&r->context.c, out, outlen);
     899           0 :             return 0;
     900             :           }
     901             :     }
     902             : 
     903           0 :   return GPG_ERR_DIGEST_ALGO;
     904             : }
     905             : 
     906             : 
     907             : /*
     908             :  * Expand the output from XOF class digest, this function implictly finalizes
     909             :  * the hash.
     910             :  */
     911             : gcry_err_code_t
     912           0 : _gcry_md_extract (gcry_md_hd_t hd, int algo, void *out, size_t outlen)
     913             : {
     914           0 :   _gcry_md_ctl (hd, GCRYCTL_FINALIZE, NULL, 0);
     915           0 :   return md_extract (hd, algo, out, outlen);
     916             : }
     917             : 
     918             : 
     919             : /*
     920             :  * Read out an intermediate digest.  Not yet functional.
     921             :  */
     922             : gcry_err_code_t
     923           0 : _gcry_md_get (gcry_md_hd_t hd, int algo, byte *buffer, int buflen)
     924             : {
     925             :   (void)hd;
     926             :   (void)algo;
     927             :   (void)buffer;
     928             :   (void)buflen;
     929             : 
     930             :   /*md_digest ... */
     931           0 :   fips_signal_error ("unimplemented function called");
     932           0 :   return GPG_ERR_INTERNAL;
     933             : }
     934             : 
     935             : 
     936             : /*
     937             :  * Shortcut function to hash a buffer with a given algo. The only
     938             :  * guaranteed supported algorithms are RIPE-MD160 and SHA-1. The
     939             :  * supplied digest buffer must be large enough to store the resulting
     940             :  * hash.  No error is returned, the function will abort on an invalid
     941             :  * algo.  DISABLED_ALGOS are ignored here.  */
     942             : void
     943           0 : _gcry_md_hash_buffer (int algo, void *digest,
     944             :                       const void *buffer, size_t length)
     945             : {
     946           0 :   if (algo == GCRY_MD_SHA1)
     947           0 :     _gcry_sha1_hash_buffer (digest, buffer, length);
     948           0 :   else if (algo == GCRY_MD_RMD160 && !fips_mode () )
     949           0 :     _gcry_rmd160_hash_buffer (digest, buffer, length);
     950             :   else
     951             :     {
     952             :       /* For the others we do not have a fast function, so we use the
     953             :          normal functions. */
     954             :       gcry_md_hd_t h;
     955             :       gpg_err_code_t err;
     956             : 
     957           0 :       if (algo == GCRY_MD_MD5 && fips_mode ())
     958             :         {
     959           0 :           _gcry_inactivate_fips_mode ("MD5 used");
     960           0 :           if (_gcry_enforced_fips_mode () )
     961             :             {
     962             :               /* We should never get to here because we do not register
     963             :                  MD5 in enforced fips mode.  */
     964           0 :               _gcry_fips_noreturn ();
     965             :             }
     966             :         }
     967             : 
     968           0 :       err = md_open (&h, algo, 0);
     969           0 :       if (err)
     970           0 :         log_bug ("gcry_md_open failed for algo %d: %s",
     971             :                  algo, gpg_strerror (gcry_error(err)));
     972           0 :       md_write (h, (byte *) buffer, length);
     973           0 :       md_final (h);
     974           0 :       memcpy (digest, md_read (h, algo), md_digest_length (algo));
     975           0 :       md_close (h);
     976             :     }
     977           0 : }
     978             : 
     979             : 
     980             : /* Shortcut function to hash multiple buffers with a given algo.  In
     981             :    contrast to gcry_md_hash_buffer, this function returns an error on
     982             :    invalid arguments or on other problems; disabled algorithms are
     983             :    _not_ ignored but flagged as an error.
     984             : 
     985             :    The data to sign is taken from the array IOV which has IOVCNT items.
     986             : 
     987             :    The only supported flag in FLAGS is GCRY_MD_FLAG_HMAC which turns
     988             :    this function into a HMAC function; the first item in IOV is then
     989             :    used as the key.
     990             : 
     991             :    On success 0 is returned and resulting hash or HMAC is stored at
     992             :    DIGEST which must have been provided by the caller with an
     993             :    appropriate length.  */
     994             : gpg_err_code_t
     995           0 : _gcry_md_hash_buffers (int algo, unsigned int flags, void *digest,
     996             :                        const gcry_buffer_t *iov, int iovcnt)
     997             : {
     998             :   int hmac;
     999             : 
    1000           0 :   if (!iov || iovcnt < 0)
    1001           0 :     return GPG_ERR_INV_ARG;
    1002           0 :   if (flags & ~(GCRY_MD_FLAG_HMAC))
    1003           0 :     return GPG_ERR_INV_ARG;
    1004             : 
    1005           0 :   hmac = !!(flags & GCRY_MD_FLAG_HMAC);
    1006           0 :   if (hmac && iovcnt < 1)
    1007           0 :     return GPG_ERR_INV_ARG;
    1008             : 
    1009           0 :   if (algo == GCRY_MD_SHA1 && !hmac)
    1010           0 :     _gcry_sha1_hash_buffers (digest, iov, iovcnt);
    1011             :   else
    1012             :     {
    1013             :       /* For the others we do not have a fast function, so we use the
    1014             :          normal functions. */
    1015             :       gcry_md_hd_t h;
    1016             :       gpg_err_code_t rc;
    1017             :       int dlen;
    1018             : 
    1019           0 :       if (algo == GCRY_MD_MD5 && fips_mode ())
    1020             :         {
    1021           0 :           _gcry_inactivate_fips_mode ("MD5 used");
    1022           0 :           if (_gcry_enforced_fips_mode () )
    1023             :             {
    1024             :               /* We should never get to here because we do not register
    1025             :                  MD5 in enforced fips mode.  */
    1026           0 :               _gcry_fips_noreturn ();
    1027             :             }
    1028             :         }
    1029             : 
    1030             :       /* Detect SHAKE128 like algorithms which we can't use because
    1031             :        * our API does not allow for a variable length digest.  */
    1032           0 :       dlen = md_digest_length (algo);
    1033           0 :       if (!dlen)
    1034           0 :         return GPG_ERR_DIGEST_ALGO;
    1035             : 
    1036           0 :       rc = md_open (&h, algo, (hmac? GCRY_MD_FLAG_HMAC:0));
    1037           0 :       if (rc)
    1038           0 :         return rc;
    1039             : 
    1040           0 :       if (hmac)
    1041             :         {
    1042           0 :           rc = _gcry_md_setkey (h,
    1043           0 :                                 (const char*)iov[0].data + iov[0].off,
    1044             :                                 iov[0].len);
    1045           0 :           if (rc)
    1046             :             {
    1047           0 :               md_close (h);
    1048           0 :               return rc;
    1049             :             }
    1050           0 :           iov++; iovcnt--;
    1051             :         }
    1052           0 :       for (;iovcnt; iov++, iovcnt--)
    1053           0 :         md_write (h, (const char*)iov[0].data + iov[0].off, iov[0].len);
    1054           0 :       md_final (h);
    1055           0 :       memcpy (digest, md_read (h, algo), dlen);
    1056           0 :       md_close (h);
    1057             :     }
    1058             : 
    1059           0 :   return 0;
    1060             : }
    1061             : 
    1062             : 
    1063             : static int
    1064           0 : md_get_algo (gcry_md_hd_t a)
    1065             : {
    1066           0 :   GcryDigestEntry *r = a->ctx->list;
    1067             : 
    1068           0 :   if (r && r->next)
    1069             :     {
    1070           0 :       fips_signal_error ("possible usage error");
    1071           0 :       log_error ("WARNING: more than one algorithm in md_get_algo()\n");
    1072             :     }
    1073           0 :   return r ? r->spec->algo : 0;
    1074             : }
    1075             : 
    1076             : 
    1077             : int
    1078           0 : _gcry_md_get_algo (gcry_md_hd_t hd)
    1079             : {
    1080           0 :   return md_get_algo (hd);
    1081             : }
    1082             : 
    1083             : 
    1084             : /****************
    1085             :  * Return the length of the digest
    1086             :  */
    1087             : static int
    1088           0 : md_digest_length (int algorithm)
    1089             : {
    1090             :   gcry_md_spec_t *spec;
    1091             : 
    1092           0 :   spec = spec_from_algo (algorithm);
    1093           0 :   return spec? spec->mdlen : 0;
    1094             : }
    1095             : 
    1096             : 
    1097             : /****************
    1098             :  * Return the length of the digest in bytes.
    1099             :  * This function will return 0 in case of errors.
    1100             :  */
    1101             : unsigned int
    1102           0 : _gcry_md_get_algo_dlen (int algorithm)
    1103             : {
    1104           0 :   return md_digest_length (algorithm);
    1105             : }
    1106             : 
    1107             : 
    1108             : /* Hmmm: add a mode to enumerate the OIDs
    1109             :  *      to make g10/sig-check.c more portable */
    1110             : static const byte *
    1111           0 : md_asn_oid (int algorithm, size_t *asnlen, size_t *mdlen)
    1112             : {
    1113             :   gcry_md_spec_t *spec;
    1114           0 :   const byte *asnoid = NULL;
    1115             : 
    1116           0 :   spec = spec_from_algo (algorithm);
    1117           0 :   if (spec)
    1118             :     {
    1119           0 :       if (asnlen)
    1120           0 :         *asnlen = spec->asnlen;
    1121           0 :       if (mdlen)
    1122           0 :         *mdlen = spec->mdlen;
    1123           0 :       asnoid = spec->asnoid;
    1124             :     }
    1125             :   else
    1126           0 :     log_bug ("no ASN.1 OID for md algo %d\n", algorithm);
    1127             : 
    1128           0 :   return asnoid;
    1129             : }
    1130             : 
    1131             : 
    1132             : /****************
    1133             :  * Return information about the given cipher algorithm
    1134             :  * WHAT select the kind of information returned:
    1135             :  *  GCRYCTL_TEST_ALGO:
    1136             :  *      Returns 0 when the specified algorithm is available for use.
    1137             :  *      buffer and nbytes must be zero.
    1138             :  *  GCRYCTL_GET_ASNOID:
    1139             :  *      Return the ASNOID of the algorithm in buffer. if buffer is NULL, only
    1140             :  *      the required length is returned.
    1141             :  *  GCRYCTL_SELFTEST
    1142             :  *      Helper for the regression tests - shall not be used by applications.
    1143             :  *
    1144             :  * Note:  Because this function is in most cases used to return an
    1145             :  * integer value, we can make it easier for the caller to just look at
    1146             :  * the return value.  The caller will in all cases consult the value
    1147             :  * and thereby detecting whether a error occurred or not (i.e. while checking
    1148             :  * the block size)
    1149             :  */
    1150             : gcry_err_code_t
    1151           0 : _gcry_md_algo_info (int algo, int what, void *buffer, size_t *nbytes)
    1152             : {
    1153             :   gcry_err_code_t rc;
    1154             : 
    1155           0 :   switch (what)
    1156             :     {
    1157             :     case GCRYCTL_TEST_ALGO:
    1158           0 :       if (buffer || nbytes)
    1159           0 :         rc = GPG_ERR_INV_ARG;
    1160             :       else
    1161           0 :         rc = check_digest_algo (algo);
    1162           0 :       break;
    1163             : 
    1164             :     case GCRYCTL_GET_ASNOID:
    1165             :       /* We need to check that the algo is available because
    1166             :          md_asn_oid would otherwise raise an assertion. */
    1167           0 :       rc = check_digest_algo (algo);
    1168           0 :       if (!rc)
    1169             :         {
    1170             :           const char unsigned *asn;
    1171             :           size_t asnlen;
    1172             : 
    1173           0 :           asn = md_asn_oid (algo, &asnlen, NULL);
    1174           0 :           if (buffer && (*nbytes >= asnlen))
    1175             :             {
    1176           0 :               memcpy (buffer, asn, asnlen);
    1177           0 :               *nbytes = asnlen;
    1178             :             }
    1179           0 :           else if (!buffer && nbytes)
    1180           0 :             *nbytes = asnlen;
    1181             :           else
    1182             :             {
    1183           0 :               if (buffer)
    1184           0 :                 rc = GPG_ERR_TOO_SHORT;
    1185             :               else
    1186           0 :                 rc = GPG_ERR_INV_ARG;
    1187             :             }
    1188             :         }
    1189           0 :       break;
    1190             : 
    1191             :     case GCRYCTL_SELFTEST:
    1192             :       /* Helper function for the regression tests.  */
    1193           0 :       rc = gpg_err_code (_gcry_md_selftest (algo, nbytes? (int)*nbytes : 0,
    1194             :                                              NULL));
    1195           0 :       break;
    1196             : 
    1197             :     default:
    1198           0 :       rc = GPG_ERR_INV_OP;
    1199           0 :       break;
    1200             :   }
    1201             : 
    1202           0 :   return rc;
    1203             : }
    1204             : 
    1205             : 
    1206             : static void
    1207           0 : md_start_debug ( gcry_md_hd_t md, const char *suffix )
    1208             : {
    1209             :   static int idx=0;
    1210             :   char buf[50];
    1211             : 
    1212           0 :   if (fips_mode ())
    1213           0 :     return;
    1214             : 
    1215           0 :   if ( md->ctx->debug )
    1216             :     {
    1217           0 :       log_debug("Oops: md debug already started\n");
    1218           0 :       return;
    1219             :     }
    1220           0 :   idx++;
    1221           0 :   snprintf (buf, DIM(buf)-1, "dbgmd-%05d.%.10s", idx, suffix );
    1222           0 :   md->ctx->debug = fopen(buf, "w");
    1223           0 :   if ( !md->ctx->debug )
    1224           0 :     log_debug("md debug: can't open %s\n", buf );
    1225             : }
    1226             : 
    1227             : 
    1228             : static void
    1229           0 : md_stop_debug( gcry_md_hd_t md )
    1230             : {
    1231           0 :   if ( md->ctx->debug )
    1232             :     {
    1233           0 :       if ( md->bufpos )
    1234           0 :         md_write ( md, NULL, 0 );
    1235           0 :       fclose (md->ctx->debug);
    1236           0 :       md->ctx->debug = NULL;
    1237             :     }
    1238             : 
    1239             :   {  /* a kludge to pull in the __muldi3 for Solaris */
    1240           0 :     volatile u32 a = (u32)(uintptr_t)md;
    1241           0 :     volatile u64 b = 42;
    1242             :     volatile u64 c;
    1243           0 :     c = a * b;
    1244           0 :     (void)c;
    1245             :   }
    1246           0 : }
    1247             : 
    1248             : 
    1249             : 
    1250             : /*
    1251             :  * Return information about the digest handle.
    1252             :  *  GCRYCTL_IS_SECURE:
    1253             :  *      Returns 1 when the handle works on secured memory
    1254             :  *      otherwise 0 is returned.  There is no error return.
    1255             :  *  GCRYCTL_IS_ALGO_ENABLED:
    1256             :  *     Returns 1 if the algo is enabled for that handle.
    1257             :  *     The algo must be passed as the address of an int.
    1258             :  */
    1259             : gcry_err_code_t
    1260           0 : _gcry_md_info (gcry_md_hd_t h, int cmd, void *buffer, size_t *nbytes)
    1261             : {
    1262           0 :   gcry_err_code_t rc = 0;
    1263             : 
    1264           0 :   switch (cmd)
    1265             :     {
    1266             :     case GCRYCTL_IS_SECURE:
    1267           0 :       *nbytes = h->ctx->flags.secure;
    1268           0 :       break;
    1269             : 
    1270             :     case GCRYCTL_IS_ALGO_ENABLED:
    1271             :       {
    1272             :         GcryDigestEntry *r;
    1273             :         int algo;
    1274             : 
    1275           0 :         if ( !buffer || !nbytes || *nbytes != sizeof (int))
    1276           0 :           rc = GPG_ERR_INV_ARG;
    1277             :         else
    1278             :           {
    1279           0 :             algo = *(int*)buffer;
    1280             : 
    1281           0 :             *nbytes = 0;
    1282           0 :             for(r=h->ctx->list; r; r = r->next ) {
    1283           0 :               if (r->spec->algo == algo)
    1284             :                 {
    1285           0 :                   *nbytes = 1;
    1286           0 :                   break;
    1287             :                 }
    1288             :             }
    1289             :           }
    1290           0 :         break;
    1291             :       }
    1292             : 
    1293             :   default:
    1294           0 :     rc = GPG_ERR_INV_OP;
    1295             :   }
    1296             : 
    1297           0 :   return rc;
    1298             : }
    1299             : 
    1300             : 
    1301             : /* Explicitly initialize this module.  */
    1302             : gcry_err_code_t
    1303           0 : _gcry_md_init (void)
    1304             : {
    1305           0 :   if (fips_mode())
    1306             :     {
    1307             :       /* disable algorithms that are disallowed in fips */
    1308             :       int idx;
    1309             :       gcry_md_spec_t *spec;
    1310             : 
    1311           0 :       for (idx = 0; (spec = digest_list[idx]); idx++)
    1312           0 :         if (!spec->flags.fips)
    1313           0 :           spec->flags.disabled = 1;
    1314             :     }
    1315             : 
    1316           0 :   return 0;
    1317             : }
    1318             : 
    1319             : 
    1320             : int
    1321           0 : _gcry_md_is_secure (gcry_md_hd_t a)
    1322             : {
    1323             :   size_t value;
    1324             : 
    1325           0 :   if (_gcry_md_info (a, GCRYCTL_IS_SECURE, NULL, &value))
    1326           0 :     value = 1; /* It seems to be better to assume secure memory on
    1327             :                   error. */
    1328           0 :   return value;
    1329             : }
    1330             : 
    1331             : 
    1332             : int
    1333           0 : _gcry_md_is_enabled (gcry_md_hd_t a, int algo)
    1334             : {
    1335             :   size_t value;
    1336             : 
    1337           0 :   value = sizeof algo;
    1338           0 :   if (_gcry_md_info (a, GCRYCTL_IS_ALGO_ENABLED, &algo, &value))
    1339           0 :     value = 0;
    1340           0 :   return value;
    1341             : }
    1342             : 
    1343             : 
    1344             : /* Run the selftests for digest algorithm ALGO with optional reporting
    1345             :    function REPORT.  */
    1346             : gpg_error_t
    1347           0 : _gcry_md_selftest (int algo, int extended, selftest_report_func_t report)
    1348             : {
    1349           0 :   gcry_err_code_t ec = 0;
    1350             :   gcry_md_spec_t *spec;
    1351             : 
    1352           0 :   spec = spec_from_algo (algo);
    1353           0 :   if (spec && !spec->flags.disabled && spec->selftest)
    1354           0 :     ec = spec->selftest (algo, extended, report);
    1355             :   else
    1356             :     {
    1357           0 :       ec = (spec && spec->selftest) ? GPG_ERR_DIGEST_ALGO
    1358           0 :         /* */                       : GPG_ERR_NOT_IMPLEMENTED;
    1359           0 :       if (report)
    1360           0 :         report ("digest", algo, "module",
    1361           0 :                 (spec && !spec->flags.disabled)?
    1362             :                 "no selftest available" :
    1363           0 :                 spec? "algorithm disabled" : "algorithm not found");
    1364             :     }
    1365             : 
    1366           0 :   return gpg_error (ec);
    1367             : }

Generated by: LCOV version 1.12