LCOV - code coverage report
Current view: top level - builds/gnutls/coverage/gnutls-git/lib - str.c (source / functions) Hit Total Coverage
Test: GnuTLS-3.6.14 Code Coverage Lines: 388 502 77.3 %
Date: 2020-10-30 04:50:48 Functions: 37 40 92.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2002-2012 Free Software Foundation, Inc.
       3             :  * Copyright (C) 2016-2017 Red Hat, Inc.
       4             :  *
       5             :  * Author: Nikos Mavrogiannopoulos
       6             :  *
       7             :  * This file is part of GnuTLS.
       8             :  *
       9             :  * The GnuTLS is free software; you can redistribute it and/or
      10             :  * modify it under the terms of the GNU Lesser General Public License
      11             :  * as published by the Free Software Foundation; either version 2.1 of
      12             :  * the License, or (at your option) any later version.
      13             :  *
      14             :  * This library is distributed in the hope that it will be useful, but
      15             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      17             :  * Lesser General Public License for more details.
      18             :  *
      19             :  * You should have received a copy of the GNU Lesser General Public License
      20             :  * along with this program.  If not, see <https://www.gnu.org/licenses/>
      21             :  *
      22             :  */
      23             : 
      24             : #include "gnutls_int.h"
      25             : #include "errors.h"
      26             : #include <num.h>
      27             : #include "str.h"
      28             : #include <stdarg.h>
      29             : #include <c-ctype.h>
      30             : #include <intprops.h>
      31             : #include <nettle/base64.h>
      32             : #include "extras/hex.h"
      33             : 
      34             : /* These functions are like strcat, strcpy. They only
      35             :  * do bound checking (they shouldn't cause buffer overruns),
      36             :  * and they always produce null terminated strings.
      37             :  *
      38             :  * They should be used only with null terminated strings.
      39             :  */
      40     1026710 : void _gnutls_str_cat(char *dest, size_t dest_tot_size, const char *src)
      41             : {
      42     1026710 :         size_t str_size = strlen(src);
      43     1026710 :         size_t dest_size = strlen(dest);
      44             : 
      45     1026710 :         if (dest_tot_size - dest_size > str_size) {
      46     1026710 :                 strcat(dest, src);
      47             :         } else {
      48           0 :                 if (dest_tot_size - dest_size > 0) {
      49           0 :                         strncat(dest, src,
      50             :                                 (dest_tot_size - dest_size) - 1);
      51           0 :                         dest[dest_tot_size - 1] = 0;
      52             :                 }
      53             :         }
      54     1026710 : }
      55             : 
      56      983166 : void _gnutls_str_cpy(char *dest, size_t dest_tot_size, const char *src)
      57             : {
      58      983166 :         size_t str_size = strlen(src);
      59             : 
      60      983166 :         if (dest_tot_size > str_size) {
      61      983166 :                 strcpy(dest, src);
      62             :         } else {
      63           0 :                 if (dest_tot_size > 0) {
      64           0 :                         memcpy(dest, src, (dest_tot_size) - 1);
      65           0 :                         dest[dest_tot_size - 1] = 0;
      66             :                 }
      67             :         }
      68      983166 : }
      69             : 
      70      654374 : void _gnutls_buffer_init(gnutls_buffer_st * str)
      71             : {
      72      654374 :         str->data = str->allocd = NULL;
      73      654374 :         str->max_length = 0;
      74      654374 :         str->length = 0;
      75      654374 : }
      76             : 
      77      538237 : void _gnutls_buffer_clear(gnutls_buffer_st * str)
      78             : {
      79      538237 :         if (str == NULL || str->allocd == NULL)
      80             :                 return;
      81      222951 :         gnutls_free(str->allocd);
      82             : 
      83      222951 :         str->data = NULL;
      84      222951 :         str->max_length = 0;
      85      222951 :         str->length = 0;
      86             : }
      87             : 
      88             : #define MIN_CHUNK 1024
      89             : 
      90      333344 : static void align_allocd_with_data(gnutls_buffer_st * dest)
      91             : {
      92      333344 :         assert(dest->allocd != NULL);
      93      333344 :         assert(dest->data != NULL);
      94      333344 :         if (dest->length)
      95       19808 :                 memmove(dest->allocd, dest->data, dest->length);
      96      333344 :         dest->data = dest->allocd;
      97      333344 : }
      98             : 
      99             : /**
     100             :  * gnutls_buffer_append_data:
     101             :  * @dest: the buffer to append to
     102             :  * @data: the data
     103             :  * @data_size: the size of @data
     104             :  *
     105             :  * Appends the provided @data to the destination buffer.
     106             :  *
     107             :  * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
     108             :  *
     109             :  * Since: 3.4.0
     110             :  **/
     111             : int
     112     4823650 : gnutls_buffer_append_data(gnutls_buffer_t dest, const void *data,
     113             :                            size_t data_size)
     114             : {
     115     4823650 :         size_t const tot_len = data_size + dest->length;
     116     4823650 :         size_t const unused = MEMSUB(dest->data, dest->allocd);
     117             : 
     118     4823650 :         if (unlikely(dest->data != NULL && dest->allocd == NULL))
     119           0 :                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
     120             : 
     121     4823650 :         if (data_size == 0)
     122             :                 return 0;
     123             : 
     124     4798160 :         if (unlikely(sizeof(size_t) == 4 &&
     125             :             INT_ADD_OVERFLOW (((ssize_t)MAX(data_size, MIN_CHUNK)), ((ssize_t)dest->length)))) {
     126             :                 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
     127             :         }
     128             : 
     129     4798160 :         if (dest->max_length >= tot_len) {
     130             : 
     131     4530770 :                 if (dest->max_length - unused <= tot_len) {
     132        3934 :                         align_allocd_with_data(dest);
     133             :                 }
     134             :         } else {
     135      267390 :                 size_t const new_len =
     136      267390 :                     MAX(data_size, MIN_CHUNK) + MAX(dest->max_length,
     137             :                                                     MIN_CHUNK);
     138             : 
     139      267390 :                 dest->allocd = gnutls_realloc_fast(dest->allocd, new_len);
     140      267390 :                 if (dest->allocd == NULL) {
     141           0 :                         gnutls_assert();
     142           0 :                         return GNUTLS_E_MEMORY_ERROR;
     143             :                 }
     144      267390 :                 dest->max_length = new_len;
     145      267390 :                 dest->data = dest->allocd + unused;
     146             : 
     147      267390 :                 align_allocd_with_data(dest);
     148             :         }
     149     4798160 :         assert(dest->data != NULL);
     150             : 
     151     4798160 :         memcpy(&dest->data[dest->length], data, data_size);
     152     4798160 :         dest->length = tot_len;
     153             : 
     154     4798160 :         return 0;
     155             : }
     156             : 
     157       64146 : int _gnutls_buffer_resize(gnutls_buffer_st * dest, size_t new_size)
     158             : {
     159       64146 :         if (unlikely(dest->data != NULL && dest->allocd == NULL))
     160           0 :                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
     161             : 
     162       64146 :         if (dest->max_length >= new_size) {
     163        2126 :                 size_t unused = MEMSUB(dest->data, dest->allocd);
     164        2126 :                 if (dest->max_length - unused <= new_size) {
     165           0 :                         align_allocd_with_data(dest);
     166             :                 }
     167             : 
     168        2126 :                 return 0;
     169             :         } else {
     170       62020 :                 size_t unused = MEMSUB(dest->data, dest->allocd);
     171       62020 :                 size_t alloc_len =
     172       62020 :                     MAX(new_size, MIN_CHUNK) + MAX(dest->max_length,
     173             :                                                    MIN_CHUNK);
     174             : 
     175      124040 :                 dest->allocd =
     176       62020 :                     gnutls_realloc_fast(dest->allocd, alloc_len);
     177       62020 :                 if (dest->allocd == NULL) {
     178           0 :                         gnutls_assert();
     179           0 :                         return GNUTLS_E_MEMORY_ERROR;
     180             :                 }
     181       62020 :                 dest->max_length = alloc_len;
     182       62020 :                 dest->data = dest->allocd + unused;
     183             : 
     184       62020 :                 align_allocd_with_data(dest);
     185             : 
     186       62020 :                 return 0;
     187             :         }
     188             : }
     189             : 
     190             : /* Appends the provided string. The null termination byte is appended
     191             :  * but not included in length.
     192             :  */
     193     1064360 : int _gnutls_buffer_append_str(gnutls_buffer_st * dest, const char *src)
     194             : {
     195     1064360 :         int ret;
     196     1064360 :         ret = _gnutls_buffer_append_data(dest, src, strlen(src) + 1);
     197     1064360 :         if (ret >= 0)
     198     1064360 :                 dest->length--;
     199             : 
     200     1064360 :         return ret;
     201             : }
     202             : 
     203             : /* returns data from a string in a constant buffer.
     204             :  * The data will NOT be valid if buffer is released or
     205             :  * data are appended in the buffer.
     206             :  */
     207             : void
     208       12983 : _gnutls_buffer_pop_datum(gnutls_buffer_st * str, gnutls_datum_t * data,
     209             :                          size_t req_size)
     210             : {
     211       12983 :         if (str->length == 0) {
     212           0 :                 data->data = NULL;
     213           0 :                 data->size = 0;
     214           0 :                 return;
     215             :         }
     216             : 
     217       12983 :         if (req_size > str->length)
     218           0 :                 req_size = str->length;
     219             : 
     220       12983 :         data->data = str->data;
     221       12983 :         data->size = req_size;
     222             : 
     223       12983 :         str->data += req_size;
     224       12983 :         str->length -= req_size;
     225             : 
     226             :         /* if string becomes empty start from beginning */
     227       12983 :         if (str->length == 0) {
     228         679 :                 str->data = str->allocd;
     229             :         }
     230             : 
     231             :         return;
     232             : }
     233             : 
     234             : /* converts the buffer to a datum if possible. After this call
     235             :  * (failed or not) the buffer should be considered deinitialized.
     236             :  */
     237       33283 : int _gnutls_buffer_to_datum(gnutls_buffer_st * str, gnutls_datum_t * data, unsigned is_str)
     238             : {
     239       33283 :         int ret;
     240             : 
     241       33283 :         if (str->length == 0) {
     242          20 :                 data->data = NULL;
     243          20 :                 data->size = 0;
     244          20 :                 ret = 0;
     245          20 :                 goto fail;
     246             :         }
     247             : 
     248       33263 :         if (is_str) {
     249       19789 :                 ret = _gnutls_buffer_append_data(str, "\x00", 1);
     250       19789 :                 if (ret < 0) {
     251           0 :                         gnutls_assert();
     252           0 :                         goto fail;
     253             :                 }
     254             :         }
     255             : 
     256       33263 :         if (str->allocd != str->data) {
     257           0 :                 data->data = gnutls_malloc(str->length);
     258           0 :                 if (data->data == NULL) {
     259           0 :                         gnutls_assert();
     260           0 :                         ret = GNUTLS_E_MEMORY_ERROR;
     261           0 :                         goto fail;
     262             :                 }
     263           0 :                 memcpy(data->data, str->data, str->length);
     264           0 :                 data->size = str->length;
     265           0 :                 _gnutls_buffer_clear(str);
     266             :         } else {
     267       33263 :                 data->data = str->data;
     268       33263 :                 data->size = str->length;
     269       33263 :                 _gnutls_buffer_init(str);
     270             :         }
     271             : 
     272       33263 :         if (is_str) {
     273       19789 :                 data->size--;
     274             :         }
     275             : 
     276             :         return 0;
     277          20 :  fail:
     278          20 :         _gnutls_buffer_clear(str);
     279          20 :         return ret;
     280             : }
     281             : 
     282             : /* returns data from a string in a constant buffer. Will
     283             :  * fail with GNUTLS_E_PARSING_ERROR, if the string has not enough data.
     284             :  */
     285             : int
     286        7430 : _gnutls_buffer_pop_data(gnutls_buffer_st * str, void *data,
     287             :                         size_t req_size)
     288             : {
     289        7430 :         gnutls_datum_t tdata;
     290             : 
     291        7430 :         _gnutls_buffer_pop_datum(str, &tdata, req_size);
     292        7430 :         if (tdata.data == NULL || tdata.size != req_size) {
     293             :                 return GNUTLS_E_PARSING_ERROR;
     294             :         }
     295             : 
     296        7430 :         memcpy(data, tdata.data, tdata.size);
     297             : 
     298        7430 :         return 0;
     299             : }
     300             : 
     301             : int
     302      803732 : _gnutls_buffer_append_printf(gnutls_buffer_st * dest, const char *fmt, ...)
     303             : {
     304      803732 :         va_list args;
     305      803732 :         int len;
     306      803732 :         char *str = NULL;
     307             : 
     308      803732 :         va_start(args, fmt);
     309      803732 :         len = vasprintf(&str, fmt, args);
     310      803732 :         va_end(args);
     311             : 
     312      803732 :         if (len < 0 || !str)
     313             :                 return -1;
     314             : 
     315      803732 :         len = _gnutls_buffer_append_str(dest, str);
     316             : 
     317      803732 :         free(str);
     318             : 
     319      803732 :         return len;
     320             : }
     321             : 
     322             : static int
     323           3 : _gnutls_buffer_insert_data(gnutls_buffer_st * dest, int pos,
     324             :                            const void *str, size_t str_size)
     325             : {
     326           3 :         size_t orig_length = dest->length;
     327           3 :         int ret;
     328             : 
     329           3 :         ret = _gnutls_buffer_resize(dest, dest->length + str_size);  /* resize to make space */
     330           3 :         if (ret < 0)
     331             :                 return ret;
     332             : 
     333           3 :         assert(dest->data != NULL);
     334             : 
     335           3 :         memmove(&dest->data[pos + str_size], &dest->data[pos],
     336             :                 orig_length - pos);
     337             : 
     338           3 :         memcpy(&dest->data[pos], str, str_size);
     339           3 :         dest->length += str_size;
     340             : 
     341           3 :         return 0;
     342             : }
     343             : 
     344             : static void
     345           3 : _gnutls_buffer_delete_data(gnutls_buffer_st * dest, int pos,
     346             :                            size_t str_size)
     347             : {
     348           3 :         memmove(&dest->data[pos], &dest->data[pos + str_size],
     349           3 :                 dest->length - pos - str_size);
     350             : 
     351           3 :         dest->length -= str_size;
     352             : 
     353           3 :         return;
     354             : }
     355             : 
     356             : 
     357             : int
     358           0 : _gnutls_buffer_append_escape(gnutls_buffer_st * dest, const void *data,
     359             :                              size_t data_size, const char *invalid_chars)
     360             : {
     361           0 :         int rv = -1;
     362           0 :         char t[5];
     363           0 :         unsigned int pos = dest->length;
     364             : 
     365           0 :         rv = _gnutls_buffer_append_data(dest, data, data_size);
     366           0 :         if (rv < 0)
     367           0 :                 return gnutls_assert_val(rv);
     368             : 
     369           0 :         while (pos < dest->length) {
     370             : 
     371           0 :                 if (dest->data[pos] == '\\'
     372           0 :                         || strchr(invalid_chars, dest->data[pos])
     373           0 :                         || !c_isgraph(dest->data[pos])) {
     374             : 
     375           0 :                         snprintf(t, sizeof(t), "%%%.2X",
     376             :                                  (unsigned int) dest->data[pos]);
     377             : 
     378           0 :                         _gnutls_buffer_delete_data(dest, pos, 1);
     379             : 
     380           0 :                         if (_gnutls_buffer_insert_data(dest, pos, t, 3) < 0) {
     381           0 :                                 rv = -1;
     382           0 :                                 goto cleanup;
     383             :                         }
     384           0 :                         pos += 3;
     385             :                 } else
     386           0 :                         pos++;
     387             :         }
     388             : 
     389             :         rv = 0;
     390             : 
     391             :       cleanup:
     392             :         return rv;
     393             : }
     394             : 
     395           8 : int _gnutls_buffer_unescape(gnutls_buffer_st * dest)
     396             : {
     397           8 :         int rv = -1;
     398           8 :         unsigned int pos = 0;
     399             : 
     400          77 :         while (pos < dest->length) {
     401          69 :                 if (dest->data[pos] == '%') {
     402           6 :                         if (pos + 1 < dest->length && dest->data[pos + 1] == '%') {
     403             :                                 // %% -> %
     404           0 :                                 _gnutls_buffer_delete_data(dest, pos, 1);
     405           6 :                         } else if (pos + 2 < dest->length && c_isxdigit(dest->data[pos + 1]) && c_isxdigit(dest->data[pos + 2])) {
     406           3 :                                 unsigned char x;
     407             : 
     408           3 :                                 hex_decode((char *) dest->data + pos + 1, 2, &x, 1);
     409             : 
     410           3 :                                 _gnutls_buffer_delete_data(dest, pos, 3);
     411           3 :                                 _gnutls_buffer_insert_data(dest, pos, &x, 1);
     412             :                         }
     413             :                 }
     414          69 :                 pos++;
     415             :         }
     416             : 
     417           8 :         rv = 0;
     418             : 
     419           8 :         return rv;
     420             : }
     421             : 
     422             : 
     423             : /* Converts the given string (old) to hex. A buffer must be provided
     424             :  * to hold the new hex string. The new string will be null terminated.
     425             :  * If the buffer does not have enough space to hold the string, a
     426             :  * truncated hex string is returned (always null terminated).
     427             :  */
     428        8359 : char *_gnutls_bin2hex(const void *_old, size_t oldlen,
     429             :                       char *buffer, size_t buffer_size,
     430             :                       const char *separator)
     431             : {
     432        8359 :         unsigned int i, j;
     433        8359 :         const uint8_t *old = _old;
     434        8359 :         int step = 2;
     435        8359 :         const char empty[] = "";
     436             : 
     437        8359 :         if (separator != NULL && separator[0] != 0)
     438             :                 step = 3;
     439             :         else
     440        8334 :                 separator = empty;
     441             : 
     442        8359 :         if (buffer_size < 3) {
     443           0 :                 gnutls_assert();
     444           0 :                 return NULL;
     445             :         }
     446             : 
     447        8359 :         i = j = 0;
     448        8359 :         sprintf(&buffer[j], "%.2x", old[i]);
     449        8359 :         j += 2;
     450        8359 :         i++;
     451             : 
     452      267041 :         for (; i < oldlen && j + step < buffer_size; j += step) {
     453      258682 :                 sprintf(&buffer[j], "%s%.2x", separator, old[i]);
     454      258682 :                 i++;
     455             :         }
     456        8359 :         buffer[j] = '\0';
     457             : 
     458        8359 :         return buffer;
     459             : }
     460             : 
     461             : /**
     462             :  * gnutls_hex2bin:
     463             :  * @hex_data: string with data in hex format
     464             :  * @hex_size: size of hex data
     465             :  * @bin_data: output array with binary data
     466             :  * @bin_size: when calling should hold maximum size of @bin_data,
     467             :  *          on return will hold actual length of @bin_data.
     468             :  *
     469             :  * Convert a buffer with hex data to binary data. This function
     470             :  * unlike gnutls_hex_decode() can parse hex data with separators
     471             :  * between numbers. That is, it ignores any non-hex characters.
     472             :  *
     473             :  * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
     474             :  *
     475             :  * Since: 2.4.0
     476             :  **/
     477             : int
     478          16 : gnutls_hex2bin(const char *hex_data,
     479             :                size_t hex_size, void *bin_data, size_t * bin_size)
     480             : {
     481          16 :         return _gnutls_hex2bin(hex_data, hex_size, (void *) bin_data,
     482             :                                bin_size);
     483             : }
     484             : 
     485             : int
     486          17 : _gnutls_hex2bin(const char *hex_data, size_t hex_size, uint8_t * bin_data,
     487             :                 size_t * bin_size)
     488             : {
     489          17 :         unsigned int i, j;
     490          17 :         uint8_t hex2_data[3];
     491          17 :         unsigned long val;
     492             : 
     493          17 :         hex2_data[2] = 0;
     494             : 
     495         780 :         for (i = j = 0; i < hex_size;) {
     496         764 :                 if (!isxdigit(hex_data[i])) {   /* skip non-hex such as the ':' in 00:FF */
     497         279 :                         i++;
     498         279 :                         continue;
     499             :                 }
     500         485 :                 if (j >= *bin_size) {
     501           0 :                         gnutls_assert();
     502           0 :                         return GNUTLS_E_SHORT_MEMORY_BUFFER;
     503             :                 }
     504             : 
     505         485 :                 if (i+1 >= hex_size)
     506           1 :                         return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
     507             : 
     508         484 :                 hex2_data[0] = hex_data[i];
     509         484 :                 hex2_data[1] = hex_data[i + 1];
     510         484 :                 i += 2;
     511             : 
     512         484 :                 val = strtoul((char *) hex2_data, NULL, 16);
     513         484 :                 if (val == ULONG_MAX) {
     514           0 :                         gnutls_assert();
     515           0 :                         return GNUTLS_E_PARSING_ERROR;
     516             :                 }
     517         484 :                 bin_data[j] = val;
     518         484 :                 j++;
     519             :         }
     520          16 :         *bin_size = j;
     521             : 
     522          16 :         return 0;
     523             : }
     524             : 
     525             : /**
     526             :  * gnutls_hex_decode2:
     527             :  * @hex_data: contain the encoded data
     528             :  * @result: the result in an allocated string
     529             :  *
     530             :  * This function will decode the given encoded data, using the hex
     531             :  * encoding used by PSK password files.
     532             :  *
     533             :  * Returns: %GNUTLS_E_PARSING_ERROR on invalid hex data, or 0 on success.
     534             :  **/
     535             : int
     536        7742 : gnutls_hex_decode2(const gnutls_datum_t * hex_data, gnutls_datum_t *result)
     537             : {
     538        7742 :         int ret;
     539        7742 :         int size = hex_data_size(hex_data->size);
     540             : 
     541        7742 :         result->data = gnutls_malloc(size);
     542        7742 :         if (result->data == NULL) {
     543           0 :                 gnutls_assert();
     544           0 :                 return GNUTLS_E_MEMORY_ERROR;
     545             :         }
     546             : 
     547        7742 :         result->size = size;
     548        7742 :         ret = hex_decode((char *) hex_data->data, hex_data->size,
     549             :                          result->data, result->size);
     550        7742 :         if (ret == 0) {
     551         134 :                 gnutls_assert();
     552         134 :                 gnutls_free(result->data);
     553         134 :                 return GNUTLS_E_PARSING_ERROR;
     554             :         }
     555             : 
     556             :         return 0;
     557             : }
     558             : 
     559             : /**
     560             :  * gnutls_hex_decode:
     561             :  * @hex_data: contain the encoded data
     562             :  * @result: the place where decoded data will be copied
     563             :  * @result_size: holds the size of the result
     564             :  *
     565             :  * This function will decode the given encoded data, using the hex
     566             :  * encoding used by PSK password files.
     567             :  *
     568             :  * Initially @result_size must hold the maximum size available in
     569             :  * @result, and on return it will contain the number of bytes written.
     570             :  *
     571             :  * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the buffer given is not
     572             :  *   long enough, %GNUTLS_E_PARSING_ERROR on invalid hex data, or 0 on success.
     573             :  **/
     574             : int
     575         349 : gnutls_hex_decode(const gnutls_datum_t * hex_data, void *result,
     576             :                   size_t * result_size)
     577             : {
     578         349 :         int ret;
     579         349 :         size_t size = hex_data_size(hex_data->size);
     580             : 
     581         349 :         if (*result_size < size) {
     582           0 :                 gnutls_assert();
     583           0 :                 return GNUTLS_E_SHORT_MEMORY_BUFFER;
     584             :         }
     585             : 
     586         349 :         ret = hex_decode((char *) hex_data->data, hex_data->size,
     587             :                          result, size);
     588         349 :         if (ret == 0) {
     589           0 :                 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
     590             :         }
     591         349 :         *result_size = size;
     592             : 
     593         349 :         return 0;
     594             : }
     595             : 
     596             : /**
     597             :  * gnutls_hex_encode:
     598             :  * @data: contain the raw data
     599             :  * @result: the place where hex data will be copied
     600             :  * @result_size: holds the size of the result
     601             :  *
     602             :  * This function will convert the given data to printable data, using
     603             :  * the hex encoding, as used in the PSK password files.
     604             :  *
     605             :  * Note that the size of the result includes the null terminator.
     606             :  *
     607             :  * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the buffer given is not
     608             :  * long enough, or 0 on success.
     609             :  **/
     610             : int
     611        3955 : gnutls_hex_encode(const gnutls_datum_t * data, char *result,
     612             :                   size_t * result_size)
     613             : {
     614        3955 :         int ret;
     615        3955 :         size_t size = hex_str_size(data->size);
     616             : 
     617        3955 :         if (*result_size < size) {
     618           0 :                 gnutls_assert();
     619           0 :                 return GNUTLS_E_SHORT_MEMORY_BUFFER;
     620             :         }
     621             : 
     622        3955 :         ret = hex_encode(data->data, data->size, result, *result_size);
     623        3955 :         if (ret == 0) {
     624           0 :                 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
     625             :         }
     626             : 
     627        3955 :         *result_size = size;
     628             : 
     629        3955 :         return 0;
     630             : }
     631             : 
     632             : /**
     633             :  * gnutls_hex_encode2:
     634             :  * @data: contain the raw data
     635             :  * @result: the result in an allocated string
     636             :  *
     637             :  * This function will convert the given data to printable data, using
     638             :  * the hex encoding, as used in the PSK password files.
     639             :  *
     640             :  * Note that the size of the result does NOT include the null terminator.
     641             :  *
     642             :  * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
     643             :  **/
     644             : int
     645        1686 : gnutls_hex_encode2(const gnutls_datum_t * data, gnutls_datum_t *result)
     646             : {
     647        1686 :         int ret;
     648        1686 :         int size = hex_str_size(data->size);
     649             : 
     650        1686 :         result->data = gnutls_malloc(size);
     651        1686 :         if (result->data == NULL) {
     652           0 :                 gnutls_assert();
     653           0 :                 return GNUTLS_E_MEMORY_ERROR;
     654             :         }
     655             : 
     656        1686 :         ret = hex_encode((char*)data->data, data->size, (char*)result->data, size);
     657        1686 :         if (ret == 0) {
     658           0 :                 gnutls_free(result->data);
     659           0 :                 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
     660             :         }
     661             : 
     662        1686 :         result->size = size-1;
     663             : 
     664        1686 :         return 0;
     665             : }
     666             : 
     667             : static int
     668           0 : hostname_compare_raw(const char *certname,
     669             :                          size_t certnamesize, const char *hostname)
     670             : {
     671           0 :         if (certnamesize == strlen(hostname) && memcmp(hostname, certname, certnamesize) == 0)
     672           0 :                 return 1;
     673             :         return 0;
     674             : }
     675             : 
     676             : static int
     677         446 : hostname_compare_ascii(const char *certname,
     678             :                          size_t certnamesize, const char *hostname)
     679             : {
     680         446 :         for (;
     681        3282 :              *certname && *hostname
     682        8484 :              && c_toupper(*certname) == c_toupper(*hostname);
     683        2836 :              certname++, hostname++, certnamesize--);
     684             : 
     685             :         /* the strings are the same */
     686         446 :         if (certnamesize == 0 && *hostname == '\0')
     687         237 :                 return 1;
     688             : 
     689             :         return 0;
     690             : }
     691             : 
     692             : /* compare hostname against certificate, taking account of wildcards
     693             :  * return 1 on success or 0 on error
     694             :  *
     695             :  * note: certnamesize is required as X509 certs can contain embedded NULs in
     696             :  * the strings such as CN or subjectAltName.
     697             :  *
     698             :  * Wildcards are taken into account only if they are the leftmost
     699             :  * component, and if the string is ascii only (partial advice from rfc6125)
     700             :  *
     701             :  */
     702             : int
     703         353 : _gnutls_hostname_compare(const char *certname,
     704             :                          size_t certnamesize, const char *hostname, unsigned vflags)
     705             : {
     706         353 :         char *p;
     707         353 :         unsigned i;
     708             : 
     709        4565 :         for (i=0;i<certnamesize;i++) {
     710        4212 :                 if (c_isprint(certname[i]) == 0)
     711           0 :                         return hostname_compare_raw(certname, certnamesize, hostname);
     712             :         }
     713             : 
     714         353 :         if (*certname == '*' && !(vflags & GNUTLS_VERIFY_DO_NOT_ALLOW_WILDCARDS)) {
     715             :                 /* a wildcard certificate */
     716             : 
     717             :                 /* ensure that we have at least two domain components after
     718             :                  * the wildcard. */
     719          19 :                 p = strrchr(certname, '.');
     720          19 :                 if (p == NULL || strchr(certname, '.') == p || p[1] == 0) {
     721             :                         return 0;
     722             :                 }
     723             : 
     724          16 :                 certname++;
     725          16 :                 certnamesize--;
     726             : 
     727         208 :                 while (1) {
     728         112 :                         if (hostname_compare_ascii(certname, certnamesize, hostname))
     729             :                                 return 1;
     730             : 
     731             :                         /* wildcards are only allowed to match a single domain
     732             :                            component or component fragment */
     733         108 :                         if (*hostname == '\0' || *hostname == '.')
     734             :                                 break;
     735          96 :                         hostname++;
     736             :                 }
     737             : 
     738             :                 return 0;
     739             :         } else {
     740         334 :                 return hostname_compare_ascii(certname, certnamesize, hostname);
     741             :         }
     742             : }
     743             : 
     744             : int
     745     2241960 : _gnutls_buffer_append_prefix(gnutls_buffer_st * buf, int pfx_size,
     746             :                              size_t data_size)
     747             : {
     748     2241960 :         uint8_t ss[4];
     749             : 
     750     2241960 :         if (pfx_size == 32) {
     751      344214 :                 _gnutls_write_uint32(data_size, ss);
     752      344214 :                 pfx_size = 4;
     753     1897740 :         } else if (pfx_size == 24) {
     754       42457 :                 _gnutls_write_uint24(data_size, ss);
     755       42457 :                 pfx_size = 3;
     756     1855290 :         } else if (pfx_size == 16) {
     757     1514810 :                 _gnutls_write_uint16(data_size, ss);
     758     1514810 :                 pfx_size = 2;
     759      340481 :         } else if (pfx_size == 8) {
     760      340481 :                 ss[0] = data_size;
     761      340481 :                 pfx_size = 1;
     762             :         } else
     763           0 :                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
     764             : 
     765     2241960 :         return _gnutls_buffer_append_data(buf, ss, pfx_size);
     766             : }
     767             : 
     768             : /* Reads an uint32 number from the buffer. If check is non zero it will also check whether
     769             :  * the number read, is less than the data in the buffer
     770             :  */
     771             : int
     772       61787 : _gnutls_buffer_pop_prefix32(gnutls_buffer_st * buf, size_t * data_size,
     773             :                             int check)
     774             : {
     775       61787 :         size_t size;
     776             : 
     777       61787 :         if (buf->length < 4) {
     778           0 :                 gnutls_assert();
     779           0 :                 return GNUTLS_E_PARSING_ERROR;
     780             :         }
     781             : 
     782       61787 :         size = _gnutls_read_uint32(buf->data);
     783       61787 :         if (check && size > buf->length - 4) {
     784           0 :                 gnutls_assert();
     785           0 :                 return GNUTLS_E_PARSING_ERROR;
     786             :         }
     787             : 
     788       61787 :         buf->data += 4;
     789       61787 :         buf->length -= 4;
     790             : 
     791       61787 :         *data_size = size;
     792             : 
     793       61787 :         return 0;
     794             : }
     795             : 
     796         331 : int _gnutls_buffer_pop_prefix8(gnutls_buffer_st *buf, uint8_t *data, int check)
     797             : {
     798         331 :         if (buf->length < 1) {
     799           0 :                 gnutls_assert();
     800           0 :                 return GNUTLS_E_PARSING_ERROR;
     801             :         }
     802             : 
     803         331 :         *data = buf->data[0];
     804             : 
     805         331 :         if (check && *data > buf->length - 1) {
     806           0 :                 gnutls_assert();
     807           0 :                 return GNUTLS_E_PARSING_ERROR;
     808             :         }
     809             : 
     810         331 :         buf->data++;
     811         331 :         buf->length--;
     812             : 
     813         331 :         return 0;
     814             : }
     815             : 
     816             : int
     817           0 : _gnutls_buffer_pop_prefix24(gnutls_buffer_st * buf, size_t * data_size,
     818             :                             int check)
     819             : {
     820           0 :         size_t size;
     821             : 
     822           0 :         if (buf->length < 3) {
     823           0 :                 gnutls_assert();
     824           0 :                 return GNUTLS_E_PARSING_ERROR;
     825             :         }
     826             : 
     827           0 :         size = _gnutls_read_uint24(buf->data);
     828           0 :         if (check && size > buf->length - 3) {
     829           0 :                 gnutls_assert();
     830           0 :                 return GNUTLS_E_PARSING_ERROR;
     831             :         }
     832             : 
     833           0 :         buf->data += 3;
     834           0 :         buf->length -= 3;
     835             : 
     836           0 :         *data_size = size;
     837             : 
     838           0 :         return 0;
     839             : }
     840             : 
     841             : int
     842        4904 : _gnutls_buffer_pop_datum_prefix32(gnutls_buffer_st * buf,
     843             :                                   gnutls_datum_t * data)
     844             : {
     845        4904 :         size_t size;
     846        4904 :         int ret;
     847             : 
     848        4904 :         ret = _gnutls_buffer_pop_prefix32(buf, &size, 1);
     849        4904 :         if (ret < 0) {
     850           0 :                 gnutls_assert();
     851           0 :                 return ret;
     852             :         }
     853             : 
     854        4904 :         if (size > 0) {
     855         455 :                 size_t osize = size;
     856         455 :                 _gnutls_buffer_pop_datum(buf, data, size);
     857         455 :                 if (osize != data->size) {
     858           0 :                         gnutls_assert();
     859           0 :                         return GNUTLS_E_PARSING_ERROR;
     860             :                 }
     861             :         } else {
     862        4449 :                 data->size = 0;
     863        4449 :                 data->data = NULL;
     864             :         }
     865             : 
     866             :         return 0;
     867             : }
     868             : 
     869             : int
     870         971 : _gnutls_buffer_pop_datum_prefix16(gnutls_buffer_st * buf,
     871             :                                   gnutls_datum_t * data)
     872             : {
     873         971 :         size_t size;
     874             : 
     875         971 :         if (buf->length < 2) {
     876           0 :                 gnutls_assert();
     877           0 :                 return GNUTLS_E_PARSING_ERROR;
     878             :         }
     879             : 
     880         971 :         size = _gnutls_read_uint16(buf->data);
     881             : 
     882         971 :         buf->data += 2;
     883         971 :         buf->length -= 2;
     884             : 
     885         971 :         if (size > 0) {
     886         971 :                 size_t osize = size;
     887         971 :                 _gnutls_buffer_pop_datum(buf, data, size);
     888         971 :                 if (osize != data->size) {
     889           0 :                         gnutls_assert();
     890           0 :                         return GNUTLS_E_PARSING_ERROR;
     891             :                 }
     892             :         } else {
     893           0 :                 data->size = 0;
     894           0 :                 data->data = NULL;
     895             :         }
     896             : 
     897             :         return 0;
     898             : }
     899             : 
     900             : int
     901        4145 : _gnutls_buffer_pop_datum_prefix8(gnutls_buffer_st * buf,
     902             :                                  gnutls_datum_t * data)
     903             : {
     904        4145 :         size_t size;
     905             : 
     906        4145 :         if (buf->length < 1) {
     907           0 :                 gnutls_assert();
     908           0 :                 return GNUTLS_E_PARSING_ERROR;
     909             :         }
     910             : 
     911        4145 :         size = buf->data[0];
     912             : 
     913        4145 :         buf->data++;
     914        4145 :         buf->length--;
     915             : 
     916        4145 :         if (size > 0) {
     917        4121 :                 size_t osize = size;
     918        4121 :                 _gnutls_buffer_pop_datum(buf, data, size);
     919        4121 :                 if (osize != data->size) {
     920           0 :                         gnutls_assert();
     921           0 :                         return GNUTLS_E_PARSING_ERROR;
     922             :                 }
     923             :         } else {
     924          24 :                 data->size = 0;
     925          24 :                 data->data = NULL;
     926             :         }
     927             : 
     928             :         return 0;
     929             : }
     930             : 
     931             : int
     932      365480 : _gnutls_buffer_append_data_prefix(gnutls_buffer_st * buf,
     933             :                                   int pfx_size, const void *data,
     934             :                                   size_t data_size)
     935             : {
     936      365480 :         int ret;
     937             : 
     938      365480 :         ret = _gnutls_buffer_append_prefix(buf, pfx_size, data_size);
     939      365480 :         if (ret < 0)
     940           0 :                 return gnutls_assert_val(ret);
     941             : 
     942      365480 :         if (data_size > 0) {
     943      280904 :                 ret = _gnutls_buffer_append_data(buf, data, data_size);
     944      280904 :                 if (ret < 0)
     945           0 :                         return gnutls_assert_val(ret);
     946             :         }
     947             : 
     948             :         return 0;
     949             : }
     950             : 
     951        7007 : int _gnutls_buffer_append_mpi(gnutls_buffer_st * buf, int pfx_size,
     952             :                               bigint_t mpi, int lz)
     953             : {
     954        7007 :         gnutls_datum_t dd;
     955        7007 :         int ret;
     956             : 
     957        7007 :         if (lz)
     958           0 :                 ret = _gnutls_mpi_dprint_lz(mpi, &dd);
     959             :         else
     960        7007 :                 ret = _gnutls_mpi_dprint(mpi, &dd);
     961             : 
     962        7007 :         if (ret < 0)
     963           0 :                 return gnutls_assert_val(ret);
     964             : 
     965        7007 :         ret =
     966       14014 :             _gnutls_buffer_append_data_prefix(buf, pfx_size, dd.data,
     967        7007 :                                               dd.size);
     968             : 
     969        7007 :         _gnutls_free_datum(&dd);
     970             : 
     971        7007 :         return ret;
     972             : }
     973             : 
     974             : /* Appends an MPI of fixed-size in bytes left-padded with zeros if necessary */
     975        1726 : int _gnutls_buffer_append_fixed_mpi(gnutls_buffer_st * buf,
     976             :                                     bigint_t mpi, unsigned size)
     977             : {
     978        1726 :         gnutls_datum_t dd;
     979        1726 :         unsigned pad, i;
     980        1726 :         int ret;
     981             : 
     982        1726 :         ret = _gnutls_mpi_dprint(mpi, &dd);
     983        1726 :         if (ret < 0)
     984           0 :                 return gnutls_assert_val(ret);
     985             : 
     986        1726 :         if (size < dd.size) {
     987           0 :                 ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
     988           0 :                 goto cleanup;
     989             :         }
     990             : 
     991        1726 :         pad = size - dd.size;
     992        1732 :         for (i=0;i<pad;i++) {
     993           6 :                 ret =
     994           6 :                     _gnutls_buffer_append_data(buf, "\x00", 1);
     995           6 :                 if (ret < 0) {
     996           0 :                         gnutls_assert();
     997           0 :                         goto cleanup;
     998             :                 }
     999             :         }
    1000             : 
    1001             :         /* append the rest */
    1002        1726 :         ret =
    1003        1726 :             _gnutls_buffer_append_data(buf, dd.data, dd.size);
    1004             : 
    1005        1726 :  cleanup:
    1006        1726 :         _gnutls_free_datum(&dd);
    1007        1726 :         return ret;
    1008             : }
    1009             : 
    1010             : void
    1011       20463 : _gnutls_buffer_hexprint(gnutls_buffer_st * str,
    1012             :                         const void *_data, size_t len)
    1013             : {
    1014       20463 :         size_t j;
    1015       20463 :         const unsigned char *data = _data;
    1016             : 
    1017       20463 :         if (len == 0)
    1018           7 :                 _gnutls_buffer_append_str(str, "00");
    1019             :         else {
    1020      376475 :                 for (j = 0; j < len; j++)
    1021      356019 :                         _gnutls_buffer_append_printf(str, "%.2x",
    1022      356019 :                                                      (unsigned) data[j]);
    1023             :         }
    1024       20463 : }
    1025             : 
    1026             : int
    1027        1885 : _gnutls_buffer_base64print(gnutls_buffer_st * str,
    1028             :                            const void *_data, size_t len)
    1029             : {
    1030        1885 :         const unsigned char *data = _data;
    1031        1885 :         unsigned b64len = BASE64_ENCODE_RAW_LENGTH(len);
    1032        1885 :         int ret;
    1033             : 
    1034        1885 :         ret = _gnutls_buffer_resize(str, str->length+b64len+1);
    1035        1885 :         if (ret < 0) {
    1036           0 :                 return gnutls_assert_val(ret);
    1037             :         }
    1038             : 
    1039        1885 :         base64_encode_raw((void*)&str->data[str->length], len, data);
    1040        1885 :         str->length += b64len;
    1041        1885 :         str->data[str->length] = 0;
    1042             : 
    1043        1885 :         return 0;
    1044             : }
    1045             : 
    1046             : void
    1047        2700 : _gnutls_buffer_hexdump(gnutls_buffer_st * str, const void *_data,
    1048             :                        size_t len, const char *spc)
    1049             : {
    1050        2700 :         size_t j;
    1051        2700 :         const unsigned char *data = _data;
    1052             : 
    1053        2700 :         if (spc)
    1054        2700 :                 _gnutls_buffer_append_str(str, spc);
    1055      368710 :         for (j = 0; j < len; j++) {
    1056      366010 :                 if (((j + 1) % 16) == 0) {
    1057       22664 :                         _gnutls_buffer_append_printf(str, "%.2x\n",
    1058       22664 :                                                      (unsigned) data[j]);
    1059       22664 :                         if (spc && j != (len - 1))
    1060       21388 :                                 _gnutls_buffer_append_str(str, spc);
    1061      343346 :                 } else if (j == (len - 1))
    1062        1422 :                         _gnutls_buffer_append_printf(str, "%.2x",
    1063        1422 :                                                      (unsigned) data[j]);
    1064             :                 else
    1065      341924 :                         _gnutls_buffer_append_printf(str, "%.2x:",
    1066      341924 :                                                      (unsigned) data[j]);
    1067             :         }
    1068        2700 :         if ((j % 16) != 0)
    1069        1422 :                 _gnutls_buffer_append_str(str, "\n");
    1070        2700 : }
    1071             : 
    1072             : void
    1073         758 : _gnutls_buffer_asciiprint(gnutls_buffer_st * str,
    1074             :                           const char *data, size_t len)
    1075             : {
    1076         758 :         size_t j;
    1077             : 
    1078       30037 :         for (j = 0; j < len; j++)
    1079       29279 :                 if (c_isprint(data[j]))
    1080       16298 :                         _gnutls_buffer_append_printf(str, "%c",
    1081       16298 :                                                      (unsigned char)
    1082             :                                                      data[j]);
    1083             :                 else
    1084       12981 :                         _gnutls_buffer_append_printf(str, ".");
    1085         758 : }

Generated by: LCOV version 1.14