LCOV - code coverage report
Current view: top level - lib/util - data_blob.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 95 111 85.6 %
Date: 2024-06-13 04:01:37 Functions: 16 16 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    Easy management of byte-length data
       4             :    Copyright (C) Andrew Tridgell 2001
       5             :    Copyright (C) Andrew Bartlett 2001
       6             :    
       7             :    This program is free software; you can redistribute it and/or modify
       8             :    it under the terms of the GNU General Public License as published by
       9             :    the Free Software Foundation; either version 3 of the License, or
      10             :    (at your option) any later version.
      11             :    
      12             :    This program is distributed in the hope that it will be useful,
      13             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :    GNU General Public License for more details.
      16             :    
      17             :    You should have received a copy of the GNU General Public License
      18             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include "replace.h"
      22             : #include "attr.h"
      23             : #include "data_blob.h"
      24             : #include "lib/util/samba_util.h"
      25             : 
      26             : const DATA_BLOB data_blob_null = { NULL, 0 };
      27             : 
      28             : /**
      29             :  * @file
      30             :  * @brief Manipulation of arbitrary data blobs
      31             :  **/
      32             : 
      33             : /**
      34             :  construct a data blob, must be freed with data_blob_free()
      35             :  you can pass NULL for p and get a blank data blob
      36             : **/
      37     2102366 : _PUBLIC_ DATA_BLOB data_blob_named(const void *p, size_t length, const char *name)
      38             : {
      39     2102366 :         return data_blob_talloc_named(NULL, p, length, name);
      40             : }
      41             : 
      42             : /**
      43             :  construct a data blob, using supplied TALLOC_CTX
      44             : **/
      45   188105462 : _PUBLIC_ DATA_BLOB data_blob_talloc_named(TALLOC_CTX *mem_ctx, const void *p, size_t length, const char *name)
      46             : {
      47             :         DATA_BLOB ret;
      48             : 
      49   188105462 :         if (p == NULL && length == 0) {
      50     2108185 :                 ZERO_STRUCT(ret);
      51     2108185 :                 return ret;
      52             :         }
      53             : 
      54   185997277 :         if (p) {
      55    87275062 :                 ret.data = (uint8_t *)talloc_memdup(mem_ctx, p, length);
      56             :         } else {
      57    98722215 :                 ret.data = talloc_array(mem_ctx, uint8_t, length);
      58             :         }
      59   185997277 :         if (ret.data == NULL) {
      60           0 :                 ret.length = 0;
      61           0 :                 return ret;
      62             :         }
      63   185997277 :         talloc_set_name_const(ret.data, name);
      64   185997277 :         ret.length = length;
      65   185997277 :         return ret;
      66             : }
      67             : 
      68             : /**
      69             :  construct a zero data blob, using supplied TALLOC_CTX. 
      70             :  use this sparingly as it initialises data - better to initialise
      71             :  yourself if you want specific data in the blob
      72             : **/
      73      582983 : _PUBLIC_ DATA_BLOB data_blob_talloc_zero(TALLOC_CTX *mem_ctx, size_t length)
      74             : {
      75      582983 :         DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, length);
      76      582983 :         data_blob_clear(&blob);
      77      582983 :         return blob;
      78             : }
      79             : 
      80             : /**
      81             : free a data blob
      82             : **/
      83    84013274 : _PUBLIC_ void data_blob_free(DATA_BLOB *d)
      84             : {
      85    84013274 :         if (d) {
      86    84013259 :                 TALLOC_FREE(d->data);
      87    84013259 :                 d->length = 0;
      88             :         }
      89    84013274 : }
      90             : 
      91             : /**
      92             : clear a DATA_BLOB's contents
      93             : **/
      94      817930 : _PUBLIC_ void data_blob_clear(DATA_BLOB *d)
      95             : {
      96      817930 :         if (d->data) {
      97      792958 :                 memset_s(d->data, d->length, 0, d->length);
      98             :         }
      99      817930 : }
     100             : 
     101             : /**
     102             : free a data blob and clear its contents
     103             : **/
     104       88535 : _PUBLIC_ void data_blob_clear_free(DATA_BLOB *d)
     105             : {
     106       88535 :         data_blob_clear(d);
     107       88535 :         data_blob_free(d);
     108       88535 : }
     109             : 
     110             : 
     111             : /**
     112             : check if two data blobs are equal
     113             : **/
     114     6091786 : _PUBLIC_ int data_blob_cmp(const DATA_BLOB *d1, const DATA_BLOB *d2)
     115             : {
     116             :         int ret;
     117     6091786 :         if (d1->data == NULL && d2->data != NULL) {
     118           0 :                 return -1;
     119             :         }
     120     6091786 :         if (d1->data != NULL && d2->data == NULL) {
     121           0 :                 return 1;
     122             :         }
     123     6091786 :         if (d1->data == d2->data) {
     124       14523 :                 return d1->length - d2->length;
     125             :         }
     126     6077263 :         ret = memcmp(d1->data, d2->data, MIN(d1->length, d2->length));
     127     6077263 :         if (ret == 0) {
     128     3380503 :                 return d1->length - d2->length;
     129             :         }
     130     2696760 :         return ret;
     131             : }
     132             : 
     133             : /**
     134             : check if two data blobs are equal, where the time taken should not depend on the
     135             : contents of either blob.
     136             : **/
     137        1579 : _PUBLIC_ bool data_blob_equal_const_time(const DATA_BLOB *d1, const DATA_BLOB *d2)
     138             : {
     139             :         bool ret;
     140        1579 :         if (d1->data == NULL && d2->data != NULL) {
     141           0 :                 return false;
     142             :         }
     143        1579 :         if (d1->data != NULL && d2->data == NULL) {
     144           0 :                 return false;
     145             :         }
     146        1579 :         if (d1->length != d2->length) {
     147           0 :                 return false;
     148             :         }
     149        1579 :         if (d1->data == d2->data) {
     150           0 :                 return true;
     151             :         }
     152        1579 :         ret = mem_equal_const_time(d1->data, d2->data, d1->length);
     153        1579 :         return ret;
     154             : }
     155             : 
     156             : /**
     157             : print the data_blob as hex string
     158             : **/
     159     5943350 : _PUBLIC_ char *data_blob_hex_string_lower(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob)
     160             : {
     161             :         size_t i;
     162             :         char *hex_string;
     163             : 
     164     5943350 :         hex_string = talloc_array(mem_ctx, char, (blob->length*2)+1);
     165     5943350 :         if (!hex_string) {
     166           0 :                 return NULL;
     167             :         }
     168             : 
     169             :         /* this must be lowercase or w2k8 cannot join a samba domain,
     170             :            as this routine is used to encode extended DNs and windows
     171             :            only accepts lowercase hexadecimal numbers */
     172   104634802 :         for (i = 0; i < blob->length; i++)
     173    98691452 :                 slprintf(&hex_string[i*2], 3, "%02x", blob->data[i]);
     174             : 
     175     5943350 :         hex_string[(blob->length*2)] = '\0';
     176     5943350 :         return hex_string;
     177             : }
     178             : 
     179     6024780 : _PUBLIC_ char *data_blob_hex_string_upper(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob)
     180             : {
     181             :         size_t i;
     182             :         char *hex_string;
     183             : 
     184     6024780 :         hex_string = talloc_array(mem_ctx, char, (blob->length*2)+1);
     185     6024780 :         if (!hex_string) {
     186           0 :                 return NULL;
     187             :         }
     188             : 
     189   132778440 :         for (i = 0; i < blob->length; i++)
     190   126753660 :                 slprintf(&hex_string[i*2], 3, "%02X", blob->data[i]);
     191             : 
     192     6024780 :         hex_string[(blob->length*2)] = '\0';
     193     6024780 :         return hex_string;
     194             : }
     195             : 
     196             : /**
     197             :   useful for constructing data blobs in test suites, while
     198             :   avoiding const warnings
     199             : **/
     200    47191401 : _PUBLIC_ DATA_BLOB data_blob_string_const(const char *str)
     201             : {
     202             :         DATA_BLOB blob;
     203    47191401 :         blob.data = discard_const_p(uint8_t, str);
     204    47191401 :         blob.length = str ? strlen(str) : 0;
     205    47191401 :         return blob;
     206             : }
     207             : 
     208             : /**
     209             :   useful for constructing data blobs in test suites, while
     210             :   avoiding const warnings
     211             : **/
     212       62045 : _PUBLIC_ DATA_BLOB data_blob_string_const_null(const char *str)
     213             : {
     214             :         DATA_BLOB blob;
     215       62045 :         blob.data = discard_const_p(uint8_t, str);
     216       62045 :         blob.length = str ? strlen(str)+1 : 0;
     217       62045 :         return blob;
     218             : }
     219             : 
     220             : /**
     221             :  * Create a new data blob from const data 
     222             :  */
     223             : 
     224    22511856 : _PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length)
     225             : {
     226             :         DATA_BLOB blob;
     227    22511856 :         blob.data = discard_const_p(uint8_t, p);
     228    22511856 :         blob.length = length;
     229    22511856 :         return blob;
     230             : }
     231             : 
     232             : 
     233             : /**
     234             :   realloc a data_blob
     235             : **/
     236     2010732 : _PUBLIC_ bool data_blob_realloc(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, size_t length)
     237             : {
     238     2010732 :         uint8_t *tmp = talloc_realloc(mem_ctx, blob->data, uint8_t, length);
     239     2010732 :         if (tmp == NULL) {
     240           0 :                 return false;
     241             :         }
     242     2010732 :         blob->data = tmp;
     243     2010732 :         blob->length = length;
     244     2010732 :         return true;
     245             : }
     246             : 
     247             : 
     248             : /**
     249             :   append some data to a data blob
     250             : **/
     251      128995 : _PUBLIC_ bool data_blob_append(TALLOC_CTX *mem_ctx, DATA_BLOB *blob,
     252             :                                    const void *p, size_t length)
     253             : {
     254      128995 :         size_t old_len = blob->length;
     255      128995 :         size_t new_len = old_len + length;
     256             : 
     257      128995 :         if (length == 0) {
     258        2762 :                 return true;
     259             :         }
     260             : 
     261      126233 :         if (new_len < length || new_len < old_len) {
     262           0 :                 return false;
     263             :         }
     264             : 
     265      126233 :         if ((const uint8_t *)p + length < (const uint8_t *)p) {
     266           0 :                 return false;
     267             :         }
     268             :         
     269      126233 :         if (!data_blob_realloc(mem_ctx, blob, new_len)) {
     270           0 :                 return false;
     271             :         }
     272             : 
     273      126233 :         memcpy(blob->data + old_len, p, length);
     274      126233 :         return true;
     275             : }
     276             : 
     277             : /**
     278             :   pad the length of a data blob to a multiple of
     279             :   'pad'. 'pad' must be a power of two.
     280             : **/
     281       19010 : _PUBLIC_ bool data_blob_pad(TALLOC_CTX *mem_ctx, DATA_BLOB *blob,
     282             :                             size_t pad)
     283             : {
     284       19010 :         size_t old_len = blob->length;
     285       19010 :         size_t new_len = (old_len + pad - 1) & ~(pad - 1);
     286             : 
     287       19010 :         if (new_len < old_len) {
     288           0 :                 return false;
     289             :         }
     290             : 
     291       19010 :         if (!data_blob_realloc(mem_ctx, blob, new_len)) {
     292           0 :                 return false;
     293             :         }
     294             : 
     295       19010 :         memset(blob->data + old_len, 0, new_len - old_len);
     296       19010 :         return true;
     297             : }

Generated by: LCOV version 1.13