1 2 /*-------------------------------------------------------------*/ 3 /*************************************************************** 4 * A netwib_buf is the standard memory storage used in netwib. * 5 * * 6 * A netwib_buf points to an array (static or malloced) which * 7 * starts at 'first' and finishes at 'last'. * 8 * The memory contains user data between 'begin' and 'end'. * 9 * --------------------------------------------------- * 10 * | | data | | * 11 * |F| |B| |E| |L * 12 * --------------------------------------------------- * 13 * First Begin End Last * 14 * 0 x y totalsize * 15 * * 16 * Data between 'first and begin', and data between 'end and * 17 * last' may be corrupted when working on the buffer. To avoid * 18 * this, use netwib_buf_init_ext_buf and work on the new buffer* 19 ***************************************************************/ 20 21 /*-------------------------------------------------------------*/ 22 typedef struct { 23 netwib_uint32 flags; /* see below */ 24 netwib_data totalptr; /* ptr to first */ 25 netwib_uint32 totalsize; /* last - first */ 26 netwib_uint32 beginoffset; /* begin - first */ 27 netwib_uint32 endoffset; /* end - first */ 28 } netwib_buf; 29 typedef const netwib_buf netwib_constbuf; 30 31 /*-------------------------------------------------------------*/ 32 /*************************************************************** 33 * Field "flags" is a bit field indicating some information * 34 * about a netwib_buf. * 35 ***************************************************************/ 36 37 /* If totalptr points : 38 0x0001 : to an allocated memory 39 ~0x0001 : to an external array (stack array or array which 40 does not need to be freed) 41 Those two modes corresponds to the two ways to initialize a 42 netwib_buf : 43 - netwib_buf_init_malloc : it internally allocates memory 44 and eventually reallocate it if more is needed. At the 45 end, function netwib_buf_close must be called to free 46 memory. 47 - netwib_buf_init_ext_xyz : buffer does not contain memory, 48 but points on an external array. At the end, function 49 netwib_buf_close does not need to be called to free 50 memory (no closing function is needed). 51 This flag should not be directly modified by user. 52 */ 53 #define NETWIB_BUF_FLAGS_ALLOC 0x00000001u 54 55 /* In the following case : 56 - flag NETWIB_BUF_FLAGS_ALLOC is unset, and 57 - there is no sufficient space in the array 58 we can : 59 0x0002 : allocate memory and store array content in it 60 (the array is no more used) 61 ~0x0002 : return a space limitation error 62 This flag is very useful to optimize code. When we know in 63 most cases our code will need 80 bytes, we use an array 64 of 80 bytes. In the rare cases where it is not sufficient, 65 an allocated pointer is created. Like this for most 66 frequently encountered cases, there is no need to allocate. 67 Once allocated, it works like if it was allocated from beginning. 68 Once allocated, the external array is no more used. 69 Once allocated, flag NETWIB_BUF_FLAGS_ALLOC is automatically 70 set. 71 If array size is greater than 2k, it's not really advantageous 72 to use this flag, because copying 2k needs almost the same time 73 as a malloc and free. 74 This is generally used with netwib_buf_init_ext_arrayempty. 75 This flag defaults to false. It has to be explicitly set 76 by user. 77 */ 78 #define NETWIB_BUF_FLAGS_CANALLOC 0x00000002u 79 80 /* If functions are : 81 0x0004 : allowed to slide data (shrunk space between First 82 and Begin), when there is no sufficient space 83 between End and Last for appending 84 ~0x0004 : not allowed to slide 85 This flag defaults to false. It has to be explicitly set 86 by user. 87 */ 88 #define NETWIB_BUF_FLAGS_CANSLIDE 0x00000004u 89 90 /* Sometimes, a buffer contains sensitive data such as a password, 91 so we want to do a memset on this data when it is no more needed. 92 This flags says that buffer contains sensitive data. Buffer will 93 be wiped with memset(.0.) during: 94 netwib_buf_close(), 95 netwib__buf_reinit(), 96 netwib__buf_erase(), 97 netwib_bufpool_buf_close(), 98 netwib_bufpool_close(), 99 and all functions using above ones. 100 It is developer's task to set this flag each time a buffer may 101 contain sensitive data. 102 Netwib supports a feature to transfer this flag (also known as 103 tainting in other languages). For example, when a sensitive 104 buffer is copied to another buffer, this one also becomes 105 sensitive. 106 Once buffer is closed, the flag is unset, so user has to set 107 it each time sensitive data is initialized. The closing 108 functions are: 109 netwib_buf_close(), 110 netwib_bufpool_buf_close(), 111 netwib_bufpool_close(). 112 WARNING: 113 This feature was conceived for PASSWORDS or cryptographic KEYS 114 stored in a netwib_buf. It cannot help for other types such 115 as a netwib_string, a netwib_ring or a netwib_ip. 116 This feature was conceived for buffer manipulation functions, 117 such as netwib_buf_append_buf, and not in functions unrelated 118 to passwords or keys, such as netwib_pkt_... or 119 netwib_sniff_... When a function supports this feature, it is 120 indicated in its help comment before the prototype (.h file). 121 Perhaps one day, I will expand this feature to erase other kind 122 of data, but this is not the case currently. 123 To sum up, don't expect this feature to be the Solution for 124 your sensitive data management, but only a small step towards it. 125 END OF WARNING. 126 This flag defaults to false. It has to be explicitly set 127 by user. 128 */ 129 #define NETWIB_BUF_FLAGS_SENSITIVE 0x00000008u 130 /* data is sensitive, but readonly (such as a password stored 131 in a static string which cannot be wiped, but can be 132 transfered when buffer is copied) 133 */ 134 #define NETWIB_BUF_FLAGS_SENSITIVE_READONLY 0x00000010u 135 /* to transfer the sensitive flag to the second buffer */ 136 #define netwib__buf_transfersensitive(pbuf1,pbuf2) { if ((pbuf1) != NULL && (pbuf2) != NULL) { if ((pbuf1)->flags & NETWIB_BUF_FLAGS_SENSITIVE) { (pbuf2)->flags |= NETWIB_BUF_FLAGS_SENSITIVE; } } } 137 /* to wipe a local array used in parallel of a buffer */ 138 #define netwib__localarray_wipe(arr) netwib_c_memset((arr),0,sizeof(arr)) 139 #define netwib__localarray_ifbuf_wipe(pbuf,arr) { if ((pbuf) != NULL && ((pbuf)->flags & NETWIB_BUF_FLAGS_SENSITIVE)) netwib__localarray_wipe(arr); } 140 141 /* number of used bits */ 142 #define NETWIB_BUF_FLAGS_USEDBITS 5 143 144 /*-------------------------------------------------------------*/ 145 /*************************************************************** 146 * Type netwib_bufext is exactly the same as netwib_buf. It * 147 * permits to easily determine which kind of buffer is needed * 148 * by a function : * 149 * - Functions having an output parameter of type netwib_buf * 150 * must be called with the buffer previously initialized : * 151 * they will append data to it * 152 * - Functions having an output parameter of type * 153 * netwib_bufext will initialize it. * 154 * Example : * 155 * An IP4 packet might contain an IP4 option. There is no * 156 * need to allocate/copy data for this option, because it is * 157 * simply contained in the input packet (at offset * 158 * 20==sizeof(ip4hdr)). So in this case a netwib_bufext is * 159 * used. * 160 ***************************************************************/ 161 typedef netwib_buf netwib_bufext; 162 163 /*-------------------------------------------------------------*/ 164 /* Name : netwib_buf_init_malloc 165 Description : 166 Initialize a buf. Its memory dynamically grows. 167 Input parameter(s) : 168 allocsize : allocated size. If 0, a 169 default value is used. 170 Input/output parameter(s) : 171 Output parameter(s) : 172 *pbuf : netwib_buf initialized 173 Normal return values : 174 NETWIB_ERR_OK : ok 175 */ 176 netwib_err netwib_buf_init_malloc(netwib_uint32 allocs, 177 netwib_buf *pbuf); 178 #define netwib_buf_init_mallocdefault(pbuf) netwib_buf_init_malloc(1024,pbuf) 179 180 /*-------------------------------------------------------------*/ 181 /* Name : netwib_buf_init_ext_array 182 Description : 183 Initialize a buf. Its memory corresponds to an external 184 fixed size array. 185 Input parameter(s) : 186 array : external array 187 arraysize : external array size 188 beginoffset : offset of begin in this array 189 endoffset : offset of end in this array 190 Input/output parameter(s) : 191 Output parameter(s) : 192 *pbuf : netwib_bufext initialized 193 Normal return values : 194 NETWIB_ERR_OK : ok 195 */ 196 netwib_err netwib_buf_init_ext_array(netwib_constptr array, 197 netwib_uint32 arraysize, 198 netwib_uint32 beginoffset, 199 netwib_uint32 endoffset, 200 netwib_bufext *pbuf); 201 #define netwib_buf_init_ext_arrayempty(array,arraysize,pbuf) netwib_buf_init_ext_array(array,arraysize,0,0,pbuf) 202 #define netwib_buf_init_ext_arrayfilled(array,arraysize,pbuf) netwib_buf_init_ext_array(array,arraysize,0,arraysize,pbuf) 203 #define netwib_buf_init_ext_arraysizeofempty(array,pbuf) netwib_buf_init_ext_arrayempty(array,sizeof(array),pbuf) 204 #define netwib_buf_init_ext_arraysizeoffilled(array,pbuf) netwib_buf_init_ext_arrayfilled(array,sizeof(array),pbuf) 205 /* A buffer containing no data */ 206 #define netwib_buf_init_ext_empty(pbuf) netwib_buf_init_ext_array(NULL,0,0,0,pbuf) 207 208 /*-------------------------------------------------------------*/ 209 /* Name : netwib_buf_init_ext_storagearray 210 Description : 211 Initialize a buf. Its memory corresponds to an external 212 fixed size array or to nothing. When data is added, it may 213 be allocated. A call to netwib_buf_close() will have to be done. 214 Input parameter(s) : 215 array : external array 216 arraysize : external array size 217 beginoffset : offset of begin in this array 218 endoffset : offset of end in this array 219 Input/output parameter(s) : 220 Output parameter(s) : 221 *pbuf : netwib_bufext initialized 222 Normal return values : 223 NETWIB_ERR_OK : ok 224 */ 225 netwib_err netwib_buf_init_ext_storagearray(netwib_constptr array, 226 netwib_uint32 arraysize, 227 netwib_bufext *pbuf); 228 /* An empty buffer, allocated on first append */ 229 #define netwib_buf_init_ext_storage(pbuf) netwib_buf_init_ext_storagearray(NULL,0,pbuf) 230 /* An empty array, allocated if not sufficiently big */ 231 #define netwib_buf_init_ext_storagearraysizeof(array,pbuf) netwib_buf_init_ext_storagearray(array,sizeof(array),pbuf) 232 233 /*-------------------------------------------------------------*/ 234 /* Name : netwib_buf_init_ext_buf 235 Description : 236 Initialize a buf. Its memory corresponds to an external 237 buffer. 238 Input parameter(s) : 239 *pbuf : netwib_buf containing data 240 Input/output parameter(s) : 241 Output parameter(s) : 242 *pbuf : netwib_bufext initialized 243 Normal return values : 244 NETWIB_ERR_OK : ok 245 This function supports NETWIB_BUF_FLAGS_SENSITIVE. 246 */ 247 netwib_err netwib_buf_init_ext_buf(netwib_constbuf *pbufin, 248 netwib_bufext *pbuf); 249 250 /*-------------------------------------------------------------*/ 251 /* Name : netwib_buf_init_ext_string 252 Description : 253 Initialize a buf. Its memory corresponds to an external 254 preset string. 255 Input parameter(s) : 256 str : external string 257 Input/output parameter(s) : 258 Output parameter(s) : 259 *pbuf : netwib_bufext initialized 260 Normal return values : 261 NETWIB_ERR_OK : ok 262 */ 263 netwib_err netwib_buf_init_ext_string(netwib_conststring str, 264 netwib_bufext *pbuf); 265 266 /*-------------------------------------------------------------*/ 267 /* Name : netwib_buf_append_xyz 268 Description : 269 Add data to a buf. 270 Input parameter(s) : 271 data : data to add 272 datasize : size of data to add 273 str : string to add 274 c : character to add 275 Input/output parameter(s) : 276 *pbuf : netwib_buf updated 277 Output parameter(s) : 278 Normal return values : 279 NETWIB_ERR_OK : ok 280 The netwib_buf_append_buf function supports NETWIB_BUF_FLAGS_SENSITIVE. 281 */ 282 netwib_err netwib_buf_append_data(netwib_constdata data, 283 netwib_uint32 datasize, 284 netwib_buf *pbuf); 285 netwib_err netwib_buf_append_string(netwib_conststring str, 286 netwib_buf *pbuf); 287 netwib_err netwib_buf_append_buf(netwib_constbuf *pbuftoappend, 288 netwib_buf *pbuf); 289 netwib_err netwib_buf_append_byte(netwib_byte b, 290 netwib_buf *pbuf); 291 292 /*-------------------------------------------------------------*/ 293 /* Name : netwib_buf_prepend_buf 294 Description : 295 Prepend data to a buf. 296 Input parameter(s) : 297 Input/output parameter(s) : 298 *pbuf : netwib_buf updated 299 Output parameter(s) : 300 Normal return values : 301 NETWIB_ERR_OK : ok 302 Note : 303 Parameter canslide has no effect on this function (this is 304 logical). 305 This function supports NETWIB_BUF_FLAGS_SENSITIVE. 306 */ 307 netwib_err netwib_buf_prepend_buf(netwib_constbuf *pbuftoprepend, 308 netwib_buf *pbuf); 309 310 /*-------------------------------------------------------------*/ 311 /* Name : netwib_buf_ref_string 312 Description : 313 Get pointers to data stored in buf (between begin and end). 314 If buffer internal storage does not end with '\0', 315 a new one is added. So, we can have NETWIB_ERR_DATANOSPACE 316 if there is no room for the '\0'. 317 Input parameter(s) : 318 *pbuf : buffer 319 Input/output parameter(s) : 320 Output parameter(s) : 321 *pstr : pointer to start of string 322 Normal return values : 323 NETWIB_ERR_OK : ok 324 NETWIB_ERR_DATANOSPACE : no room for the '\0' 325 */ 326 netwib_err netwib_buf_ref_string(netwib_buf *pbuf, 327 netwib_string *pstr); 328 329 /*-------------------------------------------------------------*/ 330 /* Name : netwib_constbuf_ref_string 331 Description : 332 Some as netwib_buf_ref_string except it does not modify 333 the buffer to add the '\0'. 334 Input parameter(s) : 335 *pbuf : buffer 336 Input/output parameter(s) : 337 Output parameter(s) : 338 *pstr : pointer to start of string 339 Normal return values : 340 NETWIB_ERR_OK : ok 341 NETWIB_ERR_DATANOSPACE : the char after endoffset is not a '\0' 342 */ 343 netwib_err netwib_constbuf_ref_string(netwib_constbuf *pbuf, 344 netwib_string *pstr); 345 /* to use at begin of a function to manage a local buffer */ 346 #define netwib__constbuf_ref_string(pbuf, str, bufstorage, func) { netwib_err bufstorageret; bufstorageret = netwib_constbuf_ref_string(pbuf, &str); if (bufstorageret != NETWIB_ERR_OK) { if (bufstorageret == NETWIB_ERR_DATANOSPACE) { netwib_data bufstoragearray[512]; netwib_buf bufstorage; netwib_er(netwib_buf_init_ext_storagearraysizeof(bufstoragearray, &bufstorage)); netwib_er(netwib_buf_append_buf(pbuf, &bufstorage)); netwib_er(netwib_buf_append_byte(0, &bufstorage)); bufstorage.endoffset--; bufstorageret = func; netwib_er(netwib_buf_close(&bufstorage)); } return(bufstorageret); } } 347 348 /*-------------------------------------------------------------*/ 349 /* Name : netwib_buf_wantspace 350 Description : 351 Request space in a buffer (from end to last). 352 When buffer is initialized as malloced memory, it is 353 possible to obtain unlimited space. Otherwise, we cannot 354 obtain more space than array size (unless flag 355 NETWIB_BUF_FLAGS_CANALLOC is set). 356 Input parameter(s) : 357 wantedspace : wanted space 358 Input/output parameter(s) : 359 *pbuf : buffer 360 Output parameter(s) : 361 *pdata : pointer to end (endoffset) 362 Normal return values : 363 NETWIB_ERR_OK : ok 364 NETWIB_ERR_DATANOSPACE : there is less than wantedspace 365 */ 366 netwib_err netwib_buf_wantspace(netwib_buf *pbuf, 367 netwib_uint32 wantedspace, 368 netwib_data *pdata); 369 370 /*-------------------------------------------------------------*/ 371 /* Name : netwib_buf_wishspace 372 Description : 373 Request space in a buffer (from end to last). 374 When buffer is initialized as malloced memory, it is 375 possible to obtain unlimited space. Otherwise, we cannot 376 obtain more space than array size (unless flag 377 NETWIB_BUF_FLAGS_CANALLOC is set). 378 Input parameter(s) : 379 wantedspace : wanted space 380 Input/output parameter(s) : 381 *pbuf : buffer 382 Output parameter(s) : 383 *pdata : pointer to end (endoffset) 384 *pobtainedspace : obtained space (from end to last) 385 Normal return values : 386 NETWIB_ERR_OK : ok 387 */ 388 netwib_err netwib_buf_wishspace(netwib_buf *pbuf, 389 netwib_uint32 wantedspace, 390 netwib_data *pdata, 391 netwib_uint32 *pobtainedspace); 392 393 /*-------------------------------------------------------------*/ 394 /* Name : netwib_buf_cmp 395 Description : 396 Compare two netwib_buf. 397 Input parameter(s) : 398 *pbuf1 : netwib_buf to compare with buf2 399 *pbuf2 : netwib_buf to compare with buf1 400 Input/output parameter(s) : 401 Output parameter(s) : 402 *pcmp : 403 NETWIB_CMP_LT : buf1<buf2 404 NETWIB_CMP_EQ : if buf1 and buf2 are equal 405 NETWIB_CMP_GT : buf1>buf2 406 Normal return values : 407 NETWIB_ERR_OK : ok 408 */ 409 netwib_err netwib_buf_cmp(netwib_constbuf *pbuf1, 410 netwib_constbuf *pbuf2, 411 netwib_cmp *pcmp); 412 /* ignore case */ 413 netwib_err netwib_buf_casecmp(netwib_constbuf *pbuf1, 414 netwib_constbuf *pbuf2, 415 netwib_cmp *pcmp); 416 /* compare to a string */ 417 netwib_err netwib_buf_cmp_string(netwib_constbuf *pbuf1, 418 netwib_conststring string2, 419 netwib_cmp *pcmp); 420 netwib_err netwib_buf_casecmp_string(netwib_constbuf *pbuf1, 421 netwib_conststring string2, 422 netwib_cmp *pcmp); 423 424 /*-------------------------------------------------------------*/ 425 /* Name : netwib_buf_shift 426 Description : 427 Shift data in a buf. 428 Input parameter(s) : 429 offset : offset 430 truncbegend : truncate on begin/end edges (otherwise, 431 truncate only on first/last edges) 432 Input/output parameter(s) : 433 *pbuf : netwib_buf updated 434 Output parameter(s) : 435 Normal return values : 436 NETWIB_ERR_OK : ok 437 Examples : 438 buf contains " data " 439 shift(buf,-1,0) => " data " 440 shift(buf,-1,1) => " ata " (d is truncated) 441 shift(buf,+1,0) => " data " 442 shift(buf,+4,0) => " data" (if buffer is malloced) 443 shift(buf,+4,0) => " da" (if buffer is external) 444 shift(buf,+1,1) => " dat " (a is truncated) 445 Note : 446 Flag NETWIB_BUF_FLAGS_CANSLIDE has no effect on this 447 function (this is logical). 448 */ 449 netwib_err netwib_buf_shift(netwib_buf *pbuf, 450 netwib_int32 offset, 451 netwib_bool truncbegend); 452 453 /*-------------------------------------------------------------*/ 454 /* Name : netwib_buf_close 455 Description : 456 Close buf, eventually freeing data it contains. 457 Input parameter(s) : 458 Input/output parameter(s) : 459 *pbuf : buffer closed 460 Output parameter(s) : 461 Normal return values : 462 NETWIB_ERR_OK : ok 463 Note : 464 This function is only needed for a buffer initialized 465 with netwib_buf_init_malloc, or if flag 466 NETWIB_BUF_FLAGS_CANALLOC is set. 467 */ 468 netwib_err netwib_buf_close(netwib_buf *pbuf); 469 470 /*-------------------------------------------------------------*/ 471 /* Frequently needed defines */ 472 #define netwib__buf_reinit(pbuf) { (pbuf)->beginoffset = 0; (pbuf)->endoffset = 0; if (((pbuf)->flags & NETWIB_BUF_FLAGS_SENSITIVE) && !((pbuf)->flags & NETWIB_BUF_FLAGS_SENSITIVE_READONLY)) { netwib_c_memset((pbuf)->totalptr, 0, (pbuf)->totalsize); } } 473 #define netwib__buf_erase(pbuf) { if (((pbuf)->flags & NETWIB_BUF_FLAGS_SENSITIVE) && !((pbuf)->flags & NETWIB_BUF_FLAGS_SENSITIVE_READONLY)) { netwib_c_memset((pbuf)->totalptr+(pbuf)->beginoffset, 0, (pbuf)->endoffset-(pbuf)->beginoffset); } (pbuf)->endoffset = (pbuf)->beginoffset; } 474 #define netwib__buf_ref_data_ptr(pbuf) ((pbuf)->totalptr + (pbuf)->beginoffset) 475 #define netwib__buf_ref_data_size(pbuf) ((pbuf)->endoffset -(pbuf)->beginoffset) 476 #define netwib__buf_ref_data_sizenull(pbuf) ((pbuf)!=NULL?netwib__buf_ref_data_size(pbuf):0) 477 478