LCOV - code coverage report
Current view: top level - src - data-identify.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 196 0.0 %
Date: 2016-09-12 13:07:23 Functions: 0 6 0.0 %

          Line data    Source code
       1             : /* data-identify.c - Try to identify the data
       2             :    Copyright (C) 2013, 2016 g10 Code GmbH
       3             : 
       4             :    This file is part of GPGME.
       5             : 
       6             :    GPGME is free software; you can redistribute it and/or modify it
       7             :    under the terms of the GNU Lesser General Public License as
       8             :    published by the Free Software Foundation; either version 2.1 of
       9             :    the License, or (at your option) any later version.
      10             : 
      11             :    GPGME is distributed in the hope that it will be useful, but
      12             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :    Lesser General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU Lesser General Public
      17             :    License along with this program; if not, see <http://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : #if HAVE_CONFIG_H
      21             : # include <config.h>
      22             : #endif
      23             : 
      24             : #include <stdlib.h>
      25             : #include <string.h>
      26             : 
      27             : #include "gpgme.h"
      28             : #include "data.h"
      29             : #include "util.h"
      30             : #include "parsetlv.h"
      31             : 
      32             : 
      33             : /* The size of the sample data we take for detection.  */
      34             : #define SAMPLE_SIZE 2048
      35             : 
      36             : 
      37             : /* OpenPGP packet types.  */
      38             : enum
      39             :   {
      40             :     PKT_NONE          = 0,
      41             :     PKT_PUBKEY_ENC    = 1,  /* Public key encrypted packet. */
      42             :     PKT_SIGNATURE     = 2,  /* Secret key encrypted packet. */
      43             :     PKT_SYMKEY_ENC    = 3,  /* Session key packet. */
      44             :     PKT_ONEPASS_SIG   = 4,  /* One pass sig packet. */
      45             :     PKT_SECRET_KEY    = 5,  /* Secret key. */
      46             :     PKT_PUBLIC_KEY    = 6,  /* Public key. */
      47             :     PKT_SECRET_SUBKEY = 7,  /* Secret subkey. */
      48             :     PKT_COMPRESSED    = 8,  /* Compressed data packet. */
      49             :     PKT_ENCRYPTED     = 9,  /* Conventional encrypted data. */
      50             :     PKT_MARKER        = 10, /* Marker packet. */
      51             :     PKT_PLAINTEXT     = 11, /* Literal data packet. */
      52             :     PKT_RING_TRUST    = 12, /* Keyring trust packet. */
      53             :     PKT_USER_ID       = 13, /* User id packet. */
      54             :     PKT_PUBLIC_SUBKEY = 14, /* Public subkey. */
      55             :     PKT_OLD_COMMENT   = 16, /* Comment packet from an OpenPGP draft. */
      56             :     PKT_ATTRIBUTE     = 17, /* PGP's attribute packet. */
      57             :     PKT_ENCRYPTED_MDC = 18, /* Integrity protected encrypted data. */
      58             :     PKT_MDC           = 19, /* Manipulation detection code packet. */
      59             :   };
      60             : 
      61             : 
      62             : static inline unsigned long
      63           0 : buf32_to_ulong (const void *buffer)
      64             : {
      65           0 :   const unsigned char *p = buffer;
      66             : 
      67           0 :   return (((unsigned long)p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
      68             : }
      69             : 
      70             : 
      71             : /* Parse the next openpgp packet.  This function assumes a valid
      72             :  * OpenPGP packet at the address pointed to by BUFPTR which has a
      73             :  * maximum length as stored at BUFLEN.  Return the header information
      74             :  * of that packet and advance the pointer stored at BUFPTR to the next
      75             :  * packet; also adjust the length stored at BUFLEN to match the
      76             :  * remaining bytes. If there are no more packets, store NULL at
      77             :  * BUFPTR.  Return an non-zero error code on failure or the following
      78             :  * data on success:
      79             :  *
      80             :  *  R_PKTTYPE = The packet type.
      81             :  *  R_NTOTAL  = The total number of bytes of this packet
      82             :  *
      83             :  * If GPG_ERR_TRUNCATED is returned, a packet type is anyway stored at
      84             :  * R_PKTTYPE but R_NOTAL won't have a usable value,
      85             :  */
      86             : static gpg_error_t
      87           0 : next_openpgp_packet (unsigned char const **bufptr, size_t *buflen,
      88             :                      int *r_pkttype, size_t *r_ntotal)
      89             : {
      90           0 :   const unsigned char *buf = *bufptr;
      91           0 :   size_t len = *buflen;
      92             :   int c, ctb, pkttype;
      93             :   unsigned long pktlen;
      94             : 
      95           0 :   if (!len)
      96           0 :     return gpg_error (GPG_ERR_NO_DATA);
      97             : 
      98             :   /* First some blacklisting.  */
      99           0 :   if (len >= 4 && !memcmp (buf, "\x89PNG", 4))
     100           0 :     return gpg_error (GPG_ERR_INV_PACKET); /* This is a PNG file.  */
     101             : 
     102             :   /* Start parsing.  */
     103           0 :   ctb = *buf++; len--;
     104           0 :   if ( !(ctb & 0x80) )
     105           0 :     return gpg_error (GPG_ERR_INV_PACKET); /* Invalid CTB. */
     106             : 
     107           0 :   if ((ctb & 0x40))  /* New style (OpenPGP) CTB.  */
     108             :     {
     109           0 :       pkttype = (ctb & 0x3f);
     110           0 :       if (!len)
     111           0 :         return gpg_error (GPG_ERR_INV_PACKET); /* No 1st length byte. */
     112           0 :       c = *buf++; len--;
     113           0 :       if ( c < 192 )
     114           0 :         pktlen = c;
     115           0 :       else if ( c < 224 )
     116             :         {
     117           0 :           pktlen = (c - 192) * 256;
     118           0 :           if (!len)
     119           0 :             return gpg_error (GPG_ERR_INV_PACKET); /* No 2nd length byte. */
     120           0 :           c = *buf++; len--;
     121           0 :           pktlen += c + 192;
     122             :         }
     123           0 :       else if (c == 255)
     124             :         {
     125           0 :           if (len < 4)
     126           0 :             return gpg_error (GPG_ERR_INV_PACKET); /* No length bytes. */
     127           0 :           pktlen = buf32_to_ulong (buf);
     128           0 :           buf += 4;
     129           0 :           len -= 4;
     130             :         }
     131             :       else /* Partial length encoding. */
     132             :         {
     133           0 :           pktlen = 0;
     134             :         }
     135             :     }
     136             :   else /* Old style CTB.  */
     137             :     {
     138             :       int lenbytes;
     139             : 
     140           0 :       pktlen = 0;
     141           0 :       pkttype = (ctb>>2)&0xf;
     142           0 :       lenbytes = ((ctb&3)==3)? 0 : (1<<(ctb & 3));
     143           0 :       if (len < lenbytes)
     144           0 :         return gpg_error (GPG_ERR_INV_PACKET); /* Not enough length bytes.  */
     145           0 :       for (; lenbytes; lenbytes--)
     146             :         {
     147           0 :           pktlen <<= 8;
     148           0 :           pktlen |= *buf++; len--;
     149             :         }
     150             :     }
     151             : 
     152             :   /* Do some basic sanity check.  */
     153           0 :   switch (pkttype)
     154             :     {
     155             :     case PKT_PUBKEY_ENC:
     156             :     case PKT_SIGNATURE:
     157             :     case PKT_SYMKEY_ENC:
     158             :     case PKT_ONEPASS_SIG:
     159             :     case PKT_SECRET_KEY:
     160             :     case PKT_PUBLIC_KEY:
     161             :     case PKT_SECRET_SUBKEY:
     162             :     case PKT_COMPRESSED:
     163             :     case PKT_ENCRYPTED:
     164             :     case PKT_MARKER:
     165             :     case PKT_PLAINTEXT:
     166             :     case PKT_RING_TRUST:
     167             :     case PKT_USER_ID:
     168             :     case PKT_PUBLIC_SUBKEY:
     169             :     case PKT_OLD_COMMENT:
     170             :     case PKT_ATTRIBUTE:
     171             :     case PKT_ENCRYPTED_MDC:
     172             :     case PKT_MDC:
     173           0 :       break; /* Okay these are allowed packets. */
     174             :     default:
     175           0 :       return gpg_error (GPG_ERR_UNEXPECTED);
     176             :     }
     177             : 
     178           0 :   if (pktlen > len)
     179             :     {
     180             :       /* Packet length header too long.  This is possible because we
     181             :        * may have only a truncated image.  */
     182           0 :       *r_pkttype = pkttype;
     183           0 :       *r_ntotal = 0;
     184           0 :       *bufptr = NULL;
     185           0 :       return gpg_error (GPG_ERR_TRUNCATED);
     186             :     }
     187             : 
     188           0 :   *r_pkttype = pkttype;
     189           0 :   *r_ntotal = (buf - *bufptr) + pktlen;
     190             : 
     191           0 :   *bufptr = buf + pktlen;
     192           0 :   *buflen = len - pktlen;
     193           0 :   if (!*buflen)
     194           0 :     *bufptr = NULL;
     195             : 
     196           0 :   return 0;
     197             : }
     198             : 
     199             : 
     200             : /* Detection of PGP binary data.  This function parses an OpenPGP
     201             :  * message.  This parser is robust enough to work on a truncated
     202             :  * version.  Returns a GPGME_DATA_TYPE_.  */
     203             : static gpgme_data_type_t
     204           0 : pgp_binary_detection (const void *image_arg, size_t imagelen)
     205             : {
     206           0 :   gpg_error_t err = 0;
     207           0 :   const unsigned char *image = image_arg;
     208             :   size_t n;
     209             :   int pkttype;
     210           0 :   int anypacket = 0;
     211           0 :   int allsignatures = 0;
     212             : 
     213           0 :   while (!err && image)
     214             :     {
     215           0 :       err = next_openpgp_packet (&image, &imagelen, &pkttype, &n);
     216           0 :       if (gpg_err_code (err) == GPG_ERR_TRUNCATED)
     217             :         ;
     218           0 :       else if (err)
     219           0 :         break;
     220             : 
     221             :       /* Skip all leading marker packets.  */
     222           0 :       if (!anypacket && pkttype == PKT_MARKER)
     223           0 :         continue;
     224             : 
     225           0 :       if (pkttype == PKT_SIGNATURE)
     226             :         {
     227           0 :           if (!anypacket)
     228           0 :             allsignatures = 1;
     229             :         }
     230             :       else
     231           0 :         allsignatures = 0;
     232             : 
     233           0 :       switch (pkttype)
     234             :         {
     235             :         case PKT_SIGNATURE:
     236           0 :           break;  /* We decide later.  */
     237             : 
     238             :         case PKT_PLAINTEXT:
     239             :           /* Old style signature format: {sig}+,plaintext */
     240           0 :           if (allsignatures)
     241           0 :             return GPGME_DATA_TYPE_PGP_SIGNED;
     242           0 :           break;
     243             : 
     244             :         case PKT_ONEPASS_SIG:
     245           0 :           return GPGME_DATA_TYPE_PGP_SIGNED;
     246             : 
     247             :         case PKT_SECRET_KEY:
     248             :         case PKT_PUBLIC_KEY:
     249           0 :           return GPGME_DATA_TYPE_PGP_KEY;
     250             : 
     251             :         case PKT_SECRET_SUBKEY:
     252             :         case PKT_PUBLIC_SUBKEY:
     253           0 :           return GPGME_DATA_TYPE_PGP_OTHER;
     254             :         case PKT_PUBKEY_ENC:
     255             :         case PKT_SYMKEY_ENC:
     256           0 :           return GPGME_DATA_TYPE_PGP_ENCRYPTED;
     257             : 
     258             :         case PKT_COMPRESSED:
     259             :           /* If this is the first packet we assume that that a signed
     260             :            * packet follows.  We do not want to uncompress it here due
     261             :            * to the need of a lot of code and the potentail DoS. */
     262           0 :           if (!anypacket)
     263           0 :             return GPGME_DATA_TYPE_PGP_SIGNED;
     264           0 :           return GPGME_DATA_TYPE_PGP_OTHER;
     265             : 
     266             :         default:
     267           0 :           return GPGME_DATA_TYPE_PGP_OTHER;
     268             :         }
     269           0 :       anypacket = 1;
     270             :     }
     271             : 
     272           0 :   if (allsignatures)
     273           0 :     return  GPGME_DATA_TYPE_PGP_SIGNATURE;
     274             : 
     275           0 :   return GPGME_DATA_TYPE_UNKNOWN;
     276             : }
     277             : 
     278             : 
     279             : /* This is probably an armored "PGP MESSAGE" which can encode
     280             :  * different PGP data types.  STRING is modified after a call to this
     281             :  * fucntion. */
     282             : static gpgme_data_type_t
     283           0 : inspect_pgp_message (char *string)
     284             : {
     285             :   struct b64state state;
     286             :   size_t nbytes;
     287             : 
     288           0 :   if (_gpgme_b64dec_start (&state, ""))
     289           0 :     return GPGME_DATA_TYPE_INVALID; /* oops */
     290             : 
     291           0 :   if (_gpgme_b64dec_proc (&state, string, strlen (string), &nbytes))
     292             :     {
     293           0 :       _gpgme_b64dec_finish (&state);
     294           0 :       return GPGME_DATA_TYPE_UNKNOWN; /* bad encoding etc. */
     295             :     }
     296           0 :   _gpgme_b64dec_finish (&state);
     297           0 :   string[nbytes] = 0; /* Better append a Nul. */
     298             : 
     299           0 :   return pgp_binary_detection (string, nbytes);
     300             : }
     301             : 
     302             : 
     303             : /* Note that DATA may be binary but a final nul is required so that
     304             :    string operations will find a terminator.
     305             : 
     306             :    Returns: GPGME_DATA_TYPE_xxxx */
     307             : static gpgme_data_type_t
     308           0 : basic_detection (char *data, size_t datalen)
     309             : {
     310             :   tlvinfo_t ti;
     311             :   const char *s;
     312             :   size_t n;
     313           0 :   int maybe_p12 = 0;
     314             : 
     315           0 :   if (datalen < 24) /* Object is probably too short for detection.  */
     316           0 :     return GPGME_DATA_TYPE_UNKNOWN;
     317             : 
     318             :   /* This is a common example of a CMS object - it is obvious that we
     319             :      only need to read a few bytes to get to the OID:
     320             :   30 82 0B 59 06 09 2A 86 48 86 F7 0D 01 07 02 A0 82 0B 4A 30 82 0B 46 02
     321             :   ----------- ++++++++++++++++++++++++++++++++
     322             :   SEQUENCE    OID (signedData)
     323             :   (2 byte len)
     324             : 
     325             :     A PKCS#12 message is:
     326             : 
     327             :   30 82 08 59 02 01 03 30 82 08 1F 06 09 2A 86 48 86 F7 0D 01 07 01 A0 82
     328             :   ----------- ++++++++ ----------- ++++++++++++++++++++++++++++++++
     329             :   SEQUENCE    INTEGER  SEQUENCE    OID (data)
     330             : 
     331             :     A X.509 certificate is:
     332             : 
     333             :   30 82 05 B8 30 82 04 A0 A0 03 02 01 02 02 07 15 46 A0 BF 30 07 39 30 0D
     334             :   ----------- +++++++++++ ----- ++++++++ --------------------------
     335             :   SEQUENCE    SEQUENCE    [0]   INTEGER  INTEGER                    SEQU
     336             :               (tbs)            (version) (s/n)                      (Algo)
     337             : 
     338             :     Thus we need to read at least 22 bytes, we add 2 bytes to cope with
     339             :     length headers stored with 4 bytes.
     340             :   */
     341             : 
     342             : 
     343           0 :   s = data;
     344           0 :   n = datalen;
     345             : 
     346           0 :   if (parse_tlv (&s, &n, &ti))
     347           0 :     goto try_pgp; /* Not properly BER encoded.  */
     348           0 :   if (!(ti.cls == ASN1_CLASS_UNIVERSAL && ti.tag == ASN1_TAG_SEQUENCE
     349           0 :         && ti.is_cons))
     350             :     goto try_pgp; /* A CMS object always starts with a sequence.  */
     351             : 
     352           0 :   if (parse_tlv (&s, &n, &ti))
     353           0 :     goto try_pgp; /* Not properly BER encoded.  */
     354           0 :   if (ti.cls == ASN1_CLASS_UNIVERSAL && ti.tag == ASN1_TAG_SEQUENCE
     355           0 :       && ti.is_cons && n >= ti.length)
     356             :     {
     357           0 :       if (parse_tlv (&s, &n, &ti))
     358           0 :         goto try_pgp;
     359           0 :       if (!(ti.cls == ASN1_CLASS_CONTEXT && ti.tag == 0
     360           0 :             && ti.is_cons && ti.length == 3 && n >= ti.length))
     361             :         goto try_pgp;
     362             : 
     363           0 :       if (parse_tlv (&s, &n, &ti))
     364           0 :         goto try_pgp;
     365           0 :       if (!(ti.cls == ASN1_CLASS_UNIVERSAL && ti.tag == ASN1_TAG_INTEGER
     366           0 :             && !ti.is_cons && ti.length == 1 && n && (*s == 1 || *s == 2)))
     367             :         goto try_pgp;
     368           0 :       s++;
     369           0 :       n--;
     370           0 :       if (!(ti.cls == ASN1_CLASS_UNIVERSAL && ti.tag == ASN1_TAG_INTEGER
     371           0 :             && !ti.is_cons))
     372             :         goto try_pgp;
     373             :       /* Because the now following S/N may be larger than the sample
     374             :          data we have, we stop parsing here and don't check for the
     375             :          algorithm ID.  */
     376           0 :       return GPGME_DATA_TYPE_X509_CERT;
     377             :     }
     378           0 :   if (ti.cls == ASN1_CLASS_UNIVERSAL && ti.tag == ASN1_TAG_INTEGER
     379           0 :       && !ti.is_cons && ti.length == 1 && n && *s == 3)
     380             :     {
     381           0 :       maybe_p12 = 1;
     382           0 :       s++;
     383           0 :       n--;
     384           0 :       if (parse_tlv (&s, &n, &ti))
     385           0 :         goto try_pgp;
     386           0 :       if (!(ti.cls == ASN1_CLASS_UNIVERSAL && ti.tag == ASN1_TAG_SEQUENCE
     387           0 :             && ti.is_cons))
     388             :         goto try_pgp;
     389           0 :       if (parse_tlv (&s, &n, &ti))
     390           0 :         goto try_pgp;
     391             :     }
     392           0 :   if (ti.cls == ASN1_CLASS_UNIVERSAL && ti.tag == ASN1_TAG_OBJECT_ID
     393           0 :       && !ti.is_cons && ti.length && n >= ti.length)
     394             :     {
     395           0 :       if (ti.length == 9)
     396             :         {
     397           0 :           if (!memcmp (s, "\x2A\x86\x48\x86\xF7\x0D\x01\x07\x01", 9))
     398             :             {
     399             :               /* Data.  */
     400           0 :               return (maybe_p12 ? GPGME_DATA_TYPE_PKCS12
     401             :                       /*     */ : GPGME_DATA_TYPE_CMS_OTHER);
     402             :             }
     403           0 :           if (!memcmp (s, "\x2A\x86\x48\x86\xF7\x0D\x01\x07\x02", 9))
     404             :             {
     405             :               /* Signed Data.  */
     406           0 :               return (maybe_p12 ? GPGME_DATA_TYPE_PKCS12
     407             :                       /*     */ : GPGME_DATA_TYPE_CMS_SIGNED);
     408             :             }
     409           0 :           if (!memcmp (s, "\x2A\x86\x48\x86\xF7\x0D\x01\x07\x03", 9))
     410           0 :             return GPGME_DATA_TYPE_CMS_ENCRYPTED; /* Enveloped Data.  */
     411           0 :           if (!memcmp (s, "\x2A\x86\x48\x86\xF7\x0D\x01\x07\x05", 9))
     412           0 :             return GPGME_DATA_TYPE_CMS_OTHER; /* Digested Data.  */
     413           0 :           if (!memcmp (s, "\x2A\x86\x48\x86\xF7\x0D\x01\x07\x06", 9))
     414           0 :             return GPGME_DATA_TYPE_CMS_OTHER; /* Encrypted Data.  */
     415             :         }
     416           0 :       else if (ti.length == 11)
     417             :         {
     418           0 :           if (!memcmp (s, "\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x01\x02", 11))
     419           0 :             return GPGME_DATA_TYPE_CMS_OTHER; /* Auth Data.  */
     420             :         }
     421             :     }
     422             : 
     423             : 
     424             :  try_pgp:
     425             :   /* Check whether this might be a non-armored PGP message.  We need
     426             :      to do this before checking for armor lines, so that we don't get
     427             :      fooled by armored messages inside a signed binary PGP message.  */
     428           0 :   if ((data[0] & 0x80))
     429             :     {
     430             :       /* That might be a binary PGP message.  At least it is not plain
     431             :          ASCII.  Of course this might be certain lead-in text of
     432             :          armored CMS messages.  However, I am not sure whether this is
     433             :          at all defined and in any case it is uncommon.  Thus we don't
     434             :          do any further plausibility checks but stupidly assume no CMS
     435             :          armored data will follow.  */
     436           0 :       return pgp_binary_detection (data, datalen);
     437             :     }
     438             : 
     439             :   /* Now check whether there are armor lines.  */
     440           0 :   for (s = data; s && *s; s = (*s=='\n')?(s+1):((s=strchr (s,'\n'))?(s+1):s))
     441             :     {
     442           0 :       if (!strncmp (s, "-----BEGIN ", 11))
     443             :         {
     444           0 :           if (!strncmp (s+11, "SIGNED ", 7))
     445           0 :             return GPGME_DATA_TYPE_CMS_SIGNED;
     446           0 :           if (!strncmp (s+11, "ENCRYPTED ", 10))
     447           0 :             return GPGME_DATA_TYPE_CMS_ENCRYPTED;
     448           0 :           if (!strncmp (s+11, "PGP ", 4))
     449             :             {
     450           0 :               if (!strncmp (s+15, "SIGNATURE", 9))
     451           0 :                 return GPGME_DATA_TYPE_PGP_SIGNATURE;
     452           0 :               if (!strncmp (s+15, "SIGNED MESSAGE", 14))
     453           0 :                 return GPGME_DATA_TYPE_PGP_SIGNED;
     454           0 :               if (!strncmp (s+15, "PUBLIC KEY BLOCK", 16))
     455           0 :                 return GPGME_DATA_TYPE_PGP_KEY;
     456           0 :               if (!strncmp (s+15, "PRIVATE KEY BLOCK", 17))
     457           0 :                 return GPGME_DATA_TYPE_PGP_KEY;
     458           0 :               if (!strncmp (s+15, "SECRET KEY BLOCK", 16))
     459           0 :                 return GPGME_DATA_TYPE_PGP_KEY;
     460           0 :               if (!strncmp (s+15, "ARMORED FILE", 12))
     461           0 :                 return GPGME_DATA_TYPE_UNKNOWN;
     462             : 
     463           0 :               return inspect_pgp_message (data);
     464             :             }
     465           0 :           if (!strncmp (s+11, "CERTIFICATE", 11))
     466           0 :             return GPGME_DATA_TYPE_X509_CERT;
     467           0 :           if (!strncmp (s+11, "PKCS12", 6))
     468           0 :             return GPGME_DATA_TYPE_PKCS12;
     469           0 :           return GPGME_DATA_TYPE_CMS_OTHER; /* Not PGP, thus we assume CMS.  */
     470             :         }
     471             :     }
     472             : 
     473           0 :   return GPGME_DATA_TYPE_UNKNOWN;
     474             : }
     475             : 
     476             : 
     477             : /* Try to detect the type of the data.  Note that this function works
     478             :    only on seekable data objects.  The function tries to reset the
     479             :    file pointer but there is no guarantee that it will work.
     480             : 
     481             :    FIXME: We may want to add internal buffering so that this function
     482             :    can be implemented for allmost all kind of data objects.
     483             :  */
     484             : gpgme_data_type_t
     485           0 : gpgme_data_identify (gpgme_data_t dh, int reserved)
     486             : {
     487             :   gpgme_data_type_t result;
     488             :   char *sample;
     489             :   int n;
     490             :   gpgme_off_t off;
     491             : 
     492             :   /* Check whether we can seek the data object.  */
     493           0 :   off = gpgme_data_seek (dh, 0, SEEK_CUR);
     494           0 :   if (off == (gpgme_off_t)(-1))
     495           0 :     return GPGME_DATA_TYPE_INVALID;
     496             : 
     497             :   /* Allocate a buffer and read the data. */
     498           0 :   sample = malloc (SAMPLE_SIZE);
     499           0 :   if (!sample)
     500           0 :     return GPGME_DATA_TYPE_INVALID; /* Ooops.  */
     501           0 :   n = gpgme_data_read (dh, sample, SAMPLE_SIZE - 1);
     502           0 :   if (n < 0)
     503             :     {
     504           0 :       free (sample);
     505           0 :       return GPGME_DATA_TYPE_INVALID; /* Ooops.  */
     506             :     }
     507           0 :   sample[n] = 0;  /* (Required for our string functions.)  */
     508             : 
     509           0 :   result = basic_detection (sample, n);
     510           0 :   free (sample);
     511           0 :   gpgme_data_seek (dh, off, SEEK_SET);
     512             : 
     513           0 :   return result;
     514             : }

Generated by: LCOV version 1.11