LCOV - code coverage report
Current view: top level - lib - asn1.c (source / functions) Hit Total Coverage
Test: GNU Generic Security Service Lines: 104 123 84.6 %
Date: 2010-05-20 Functions: 6 6 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 44 64 68.8 %

           Branch data     Line data    Source code
       1                 :            : /* asn1.c --- Wrapper around pseudo-ASN.1 token format.
       2                 :            :  * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010  Simon Josefsson
       3                 :            :  *
       4                 :            :  * This file is part of the Generic Security Service (GSS).
       5                 :            :  *
       6                 :            :  * GSS is free software; you can redistribute it and/or modify it
       7                 :            :  * under the terms of the GNU General Public License as published by
       8                 :            :  * the Free Software Foundation; either version 3 of the License, or
       9                 :            :  * (at your option) any later version.
      10                 :            :  *
      11                 :            :  * GSS is distributed in the hope that it will be useful, but WITHOUT
      12                 :            :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
      13                 :            :  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
      14                 :            :  * License for more details.
      15                 :            :  *
      16                 :            :  * You should have received a copy of the GNU General Public License
      17                 :            :  * along with GSS; if not, see http://www.gnu.org/licenses or write to
      18                 :            :  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth
      19                 :            :  * Floor, Boston, MA 02110-1301, USA.
      20                 :            :  *
      21                 :            :  */
      22                 :            : 
      23                 :            : #include "internal.h"
      24                 :            : 
      25                 :            : /*
      26                 :            :  * The following two functions borrowed from libtasn.1, under LGPL.
      27                 :            :  * Copyright (C) 2002 Fabio Fiorina.
      28                 :            :  */
      29                 :            : static void
      30                 :         40 : _gss_asn1_length_der (size_t len, unsigned char *ans, size_t * ans_len)
      31                 :            : {
      32                 :            :   size_t k;
      33                 :            :   unsigned char temp[sizeof (len)];
      34                 :            : 
      35         [ +  + ]:         40 :   if (len < 128)
      36                 :            :     {
      37         [ +  + ]:         34 :       if (ans != NULL)
      38                 :         17 :         ans[0] = (unsigned char) len;
      39                 :         34 :       *ans_len = 1;
      40                 :            :     }
      41                 :            :   else
      42                 :            :     {
      43                 :          6 :       k = 0;
      44                 :            : 
      45         [ +  + ]:         18 :       while (len)
      46                 :            :         {
      47                 :         12 :           temp[k++] = len & 0xFF;
      48                 :         12 :           len = len >> 8;
      49                 :            :         }
      50                 :            : 
      51                 :          6 :       *ans_len = k + 1;
      52                 :            : 
      53         [ +  + ]:          6 :       if (ans != NULL)
      54                 :            :         {
      55                 :          3 :           ans[0] = ((unsigned char) k & 0x7F) + 128;
      56         [ +  + ]:          9 :           while (k--)
      57                 :          6 :             ans[*ans_len - 1 - k] = temp[k];
      58                 :            :         }
      59                 :            :     }
      60                 :         40 : }
      61                 :            : 
      62                 :            : static size_t
      63                 :         22 : _gss_asn1_get_length_der (const char *der, size_t der_len, size_t * len)
      64                 :            : {
      65                 :            :   size_t ans;
      66                 :            :   size_t k, punt;
      67                 :            : 
      68                 :         22 :   *len = 0;
      69         [ -  + ]:         22 :   if (der_len <= 0)
      70                 :          0 :     return 0;
      71                 :            : 
      72         [ +  + ]:         22 :   if (!(der[0] & 128))
      73                 :            :     {
      74                 :            :       /* short form */
      75                 :         19 :       *len = 1;
      76                 :         19 :       return (unsigned char) der[0];
      77                 :            :     }
      78                 :            :   else
      79                 :            :     {
      80                 :            :       /* Long form */
      81                 :          3 :       k = (unsigned char) der[0] & 0x7F;
      82                 :          3 :       punt = 1;
      83         [ +  - ]:          3 :       if (k)
      84                 :            :         {                       /* definite length method */
      85                 :          3 :           ans = 0;
      86 [ +  + ][ +  - ]:          9 :           while (punt <= k && punt < der_len)
      87                 :            :             {
      88                 :          6 :               size_t last = ans;
      89                 :            : 
      90                 :          6 :               ans = ans * 256 + (unsigned char) der[punt++];
      91         [ -  + ]:          6 :               if (ans < last)
      92                 :            :                 /* we wrapped around, no bignum support... */
      93                 :          0 :                 return -2;
      94                 :            :             }
      95                 :            :         }
      96                 :            :       else
      97                 :            :         {                       /* indefinite length method */
      98                 :          0 :           ans = -1;
      99                 :            :         }
     100                 :            : 
     101                 :          3 :       *len = punt;
     102                 :         22 :       return ans;
     103                 :            :     }
     104                 :            : }
     105                 :            : 
     106                 :            : OM_uint32
     107                 :         10 : _gss_encapsulate_token_prefix (const char *prefix, size_t prefixlen,
     108                 :            :                                const char *in, size_t inlen,
     109                 :            :                                const char *oid, OM_uint32 oidlen,
     110                 :            :                                void **out, size_t * outlen)
     111                 :            : {
     112                 :            :   size_t oidlenlen;
     113                 :            :   size_t asn1len, asn1lenlen;
     114                 :            :   unsigned char *p;
     115                 :            : 
     116         [ +  + ]:         10 :   if (prefix == NULL)
     117                 :          4 :     prefixlen = 0;
     118                 :            : 
     119                 :         10 :   _gss_asn1_length_der (oidlen, NULL, &oidlenlen);
     120                 :         10 :   asn1len = 1 + oidlenlen + oidlen + prefixlen + inlen;
     121                 :         10 :   _gss_asn1_length_der (asn1len, NULL, &asn1lenlen);
     122                 :            : 
     123                 :         10 :   *outlen = 1 + asn1lenlen + asn1len;
     124                 :         10 :   p = *out = malloc (*outlen);
     125         [ -  + ]:         10 :   if (!p)
     126                 :          0 :     return -1;
     127                 :            : 
     128                 :         10 :   *p++ = '\x60';
     129                 :         10 :   _gss_asn1_length_der (asn1len, p, &asn1lenlen);
     130                 :         10 :   p += asn1lenlen;
     131                 :         10 :   *p++ = '\x06';
     132                 :         10 :   _gss_asn1_length_der (oidlen, p, &oidlenlen);
     133                 :         10 :   p += oidlenlen;
     134                 :         10 :   memcpy (p, oid, oidlen);
     135                 :         10 :   p += oidlen;
     136         [ +  + ]:         10 :   if (prefixlen > 0)
     137                 :            :     {
     138                 :          6 :       memcpy (p, prefix, prefixlen);
     139                 :          6 :       p += prefixlen;
     140                 :            :     }
     141                 :         10 :   memcpy (p, in, inlen);
     142                 :            : 
     143                 :         10 :   return 0;
     144                 :            : }
     145                 :            : 
     146                 :            : /**
     147                 :            :  * gss_encapsulate_token:
     148                 :            :  * @input_token: (buffer, opaque, read) Buffer with GSS-API context token data.
     149                 :            :  * @token_oid: (Object ID, read) Object identifier of token.
     150                 :            :  * @output_token: (buffer, opaque, modify) Encapsulated token data;
     151                 :            :  *   caller must release with gss_release_buffer().
     152                 :            :  *
     153                 :            :  * Add the mechanism-independent token header to GSS-API context token
     154                 :            :  * data.
     155                 :            :  *
     156                 :            :  * Returns:
     157                 :            :  *
     158                 :            :  * `GSS_S_COMPLETE`: Indicates successful completion, and that output
     159                 :            :  * parameters holds correct information.
     160                 :            :  *
     161                 :            :  * `GSS_S_FAILURE`: Indicates that encapsulation failed for reasons
     162                 :            :  * unspecified at the GSS-API level.
     163                 :            :  **/
     164                 :            : extern OM_uint32
     165                 :          4 : gss_encapsulate_token (const gss_buffer_t input_token,
     166                 :            :                        const gss_OID token_oid, gss_buffer_t output_token)
     167                 :            : {
     168                 :            :   int rc;
     169                 :            : 
     170         [ -  + ]:          4 :   if (!input_token)
     171                 :          0 :     return GSS_S_CALL_INACCESSIBLE_READ;
     172         [ -  + ]:          4 :   if (!token_oid)
     173                 :          0 :     return GSS_S_CALL_INACCESSIBLE_READ;
     174         [ -  + ]:          4 :   if (!output_token)
     175                 :          0 :     return GSS_S_CALL_INACCESSIBLE_WRITE;
     176                 :            : 
     177                 :          4 :   rc = _gss_encapsulate_token_prefix (NULL, 0,
     178                 :          4 :                                       input_token->value,
     179                 :            :                                       input_token->length,
     180                 :          4 :                                       token_oid->elements,
     181                 :            :                                       token_oid->length,
     182                 :            :                                       &output_token->value,
     183                 :            :                                       &output_token->length);
     184         [ -  + ]:          4 :   if (rc != 0)
     185                 :          0 :     return GSS_S_FAILURE;
     186                 :            : 
     187                 :          4 :   return GSS_S_COMPLETE;
     188                 :            : }
     189                 :            : 
     190                 :            : static int
     191                 :         11 : _gss_decapsulate_token (const char *in, size_t inlen,
     192                 :            :                         char **oid, size_t * oidlen,
     193                 :            :                         char **out, size_t * outlen)
     194                 :            : {
     195                 :            :   size_t i;
     196                 :            :   size_t asn1lenlen;
     197                 :            : 
     198         [ -  + ]:         11 :   if (inlen-- == 0)
     199                 :          0 :     return -1;
     200         [ -  + ]:         11 :   if (*in++ != '\x60')
     201                 :          0 :     return -1;
     202                 :            : 
     203                 :         11 :   i = inlen;
     204                 :         11 :   asn1lenlen = _gss_asn1_get_length_der (in, inlen, &i);
     205         [ -  + ]:         11 :   if (inlen < i)
     206                 :          0 :     return -1;
     207                 :            : 
     208                 :         11 :   inlen -= i;
     209                 :         11 :   in += i;
     210                 :            : 
     211         [ -  + ]:         11 :   if (inlen != asn1lenlen)
     212                 :          0 :     return -1;
     213                 :            : 
     214         [ -  + ]:         11 :   if (inlen-- == 0)
     215                 :          0 :     return -1;
     216         [ -  + ]:         11 :   if (*in++ != '\x06')
     217                 :          0 :     return -1;
     218                 :            : 
     219                 :         11 :   i = inlen;
     220                 :         11 :   asn1lenlen = _gss_asn1_get_length_der (in, inlen, &i);
     221         [ -  + ]:         11 :   if (inlen < i)
     222                 :          0 :     return -1;
     223                 :            : 
     224                 :         11 :   inlen -= i;
     225                 :         11 :   in += i;
     226                 :            : 
     227         [ +  + ]:         11 :   if (inlen < asn1lenlen)
     228                 :          1 :     return -1;
     229                 :            : 
     230                 :         10 :   *oidlen = asn1lenlen;
     231                 :         10 :   *oid = (char *) in;
     232                 :            : 
     233                 :         10 :   inlen -= asn1lenlen;
     234                 :         10 :   in += asn1lenlen;
     235                 :            : 
     236                 :         10 :   *outlen = inlen;
     237                 :         10 :   *out = (char *) in;
     238                 :            : 
     239                 :         11 :   return 0;
     240                 :            : }
     241                 :            : 
     242                 :            : /**
     243                 :            :  * gss_decapsulate_token:
     244                 :            :  * @input_token: (buffer, opaque, read) Buffer with GSS-API context token.
     245                 :            :  * @token_oid: (Object ID, read) Expected object identifier of token.
     246                 :            :  * @output_token: (buffer, opaque, modify) Decapsulated token data;
     247                 :            :  *   caller must release with gss_release_buffer().
     248                 :            :  *
     249                 :            :  * Remove the mechanism-independent token header from an initial
     250                 :            :  * GSS-API context token.
     251                 :            :  *
     252                 :            :  * Return value:
     253                 :            :  *
     254                 :            :  * `GSS_S_COMPLETE`: Indicates successful completion, and that output
     255                 :            :  * parameters holds correct information.
     256                 :            :  *
     257                 :            :  * `GSS_S_DEFECTIVE_TOKEN`: Means that the token failed consistency
     258                 :            :  * checks (e.g., OID mismatch or ASN.1 DER length errors).
     259                 :            :  *
     260                 :            :  * `GSS_S_FAILURE`: Indicates that decapsulation failed for reasons
     261                 :            :  * unspecified at the GSS-API level.
     262                 :            :  **/
     263                 :            : OM_uint32
     264                 :         11 : gss_decapsulate_token (const gss_buffer_t input_token,
     265                 :            :                        const gss_OID token_oid, gss_buffer_t output_token)
     266                 :            : {
     267                 :            :   gss_OID_desc tmpoid;
     268                 :         11 :   char *oid = NULL, *out = NULL;
     269                 :         11 :   size_t oidlen = 0, outlen = 0;
     270                 :            : 
     271         [ -  + ]:         11 :   if (!input_token)
     272                 :          0 :     return GSS_S_CALL_INACCESSIBLE_READ;
     273         [ -  + ]:         11 :   if (!token_oid)
     274                 :          0 :     return GSS_S_CALL_INACCESSIBLE_READ;
     275         [ -  + ]:         11 :   if (!output_token)
     276                 :          0 :     return GSS_S_CALL_INACCESSIBLE_WRITE;
     277                 :            : 
     278         [ +  + ]:         11 :   if (_gss_decapsulate_token ((char *) input_token->value,
     279                 :            :                               input_token->length,
     280                 :            :                               &oid, &oidlen, &out, &outlen) != 0)
     281                 :          1 :     return GSS_S_DEFECTIVE_TOKEN;
     282                 :            : 
     283                 :         10 :   tmpoid.length = oidlen;
     284                 :         10 :   tmpoid.elements = oid;
     285                 :            : 
     286         [ +  + ]:         10 :   if (!gss_oid_equal (token_oid, &tmpoid))
     287                 :          1 :     return GSS_S_DEFECTIVE_TOKEN;
     288                 :            : 
     289                 :          9 :   output_token->length = outlen;
     290                 :          9 :   output_token->value = malloc (outlen);
     291         [ -  + ]:          9 :   if (!output_token->value)
     292                 :          0 :     return GSS_S_FAILURE;
     293                 :            : 
     294                 :          9 :   memcpy (output_token->value, out, outlen);
     295                 :            : 
     296                 :         11 :   return GSS_S_COMPLETE;
     297                 :            : }

Generated by: LCOV version 1.8