Coverage Report

Created: 2025-12-12 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/xmlsec/src/buffer.c
Line
Count
Source
1
/*
2
 * XML Security Library (http://www.aleksey.com/xmlsec).
3
 *
4
 *
5
 * This is free software; see the Copyright file in the source
6
 * distribution for precise wording.
7
 *
8
 * Copyright (C) 2002-2024 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved.
9
 */
10
/**
11
 * SECTION:buffer
12
 * @Short_description:Binary memory buffer functions.
13
 * @Stability: Stable
14
 *
15
 */
16
17
#include "globals.h"
18
19
#include <stdlib.h>
20
#include <string.h>
21
#include <ctype.h>
22
23
#include <libxml/tree.h>
24
25
#include <xmlsec/xmlsec.h>
26
#include <xmlsec/xmltree.h>
27
#include <xmlsec/base64.h>
28
#include <xmlsec/buffer.h>
29
#include <xmlsec/errors.h>
30
31
#include "cast_helpers.h"
32
33
/*****************************************************************************
34
 *
35
 * xmlSecBuffer
36
 *
37
 ****************************************************************************/
38
static xmlSecAllocMode gAllocMode = xmlSecAllocModeDouble;
39
static xmlSecSize gInitialSize = 1024;
40
41
/**
42
 * xmlSecBufferSetDefaultAllocMode:
43
 * @defAllocMode:       the new default buffer allocation mode.
44
 * @defInitialSize:     the new default buffer minimal intial size.
45
 *
46
 * Sets new global default allocation mode and minimal intial size.
47
 */
48
void
49
0
xmlSecBufferSetDefaultAllocMode(xmlSecAllocMode defAllocMode, xmlSecSize defInitialSize) {
50
0
    xmlSecAssert(defInitialSize > 0);
51
52
0
    gAllocMode = defAllocMode;
53
0
    gInitialSize = defInitialSize;
54
0
}
55
56
/**
57
 * xmlSecBufferCreate:
58
 * @size:               the intial size.
59
 *
60
 * Allocates and initializes new memory buffer with given size.
61
 * Caller is responsible for calling #xmlSecBufferDestroy function
62
 * to free the buffer.
63
 *
64
 * Returns: pointer to newly allocated buffer or NULL if an error occurs.
65
 */
66
xmlSecBufferPtr
67
18.9k
xmlSecBufferCreate(xmlSecSize size) {
68
18.9k
    xmlSecBufferPtr buf;
69
18.9k
    int ret;
70
71
18.9k
    buf = (xmlSecBufferPtr)xmlMalloc(sizeof(xmlSecBuffer));
72
18.9k
    if(buf == NULL) {
73
0
        xmlSecMallocError(sizeof(xmlSecBuffer), NULL);
74
0
        return(NULL);
75
0
    }
76
77
18.9k
    ret = xmlSecBufferInitialize(buf, size);
78
18.9k
    if(ret < 0) {
79
0
        xmlSecInternalError2("xmlSecBufferInitialize", NULL, "size=" XMLSEC_SIZE_FMT, size);
80
0
        xmlSecBufferDestroy(buf);
81
0
        return(NULL);
82
0
    }
83
18.9k
    return(buf);
84
18.9k
}
85
86
/**
87
 * xmlSecBufferDestroy:
88
 * @buf:                the pointer to buffer object.
89
 *
90
 * Destroys buffer object created with #xmlSecBufferCreate function.
91
 */
92
void
93
18.9k
xmlSecBufferDestroy(xmlSecBufferPtr buf) {
94
18.9k
    xmlSecAssert(buf != NULL);
95
96
18.9k
    xmlSecBufferFinalize(buf);
97
18.9k
    xmlFree(buf);
98
18.9k
}
99
100
/**
101
 * xmlSecBufferInitialize:
102
 * @buf:                the pointer to buffer object.
103
 * @size:               the initial buffer size.
104
 *
105
 * Initializes buffer object @buf. Caller is responsible for calling
106
 * #xmlSecBufferFinalize function to free allocated resources.
107
 *
108
 * Returns: 0 on success or a negative value if an error occurs.
109
 */
110
int
111
18.9k
xmlSecBufferInitialize(xmlSecBufferPtr buf, xmlSecSize size) {
112
18.9k
    xmlSecAssert2(buf != NULL, -1);
113
114
18.9k
    buf->data = NULL;
115
18.9k
    buf->size = buf->maxSize = 0;
116
18.9k
    buf->allocMode = gAllocMode;
117
118
18.9k
    return(xmlSecBufferSetMaxSize(buf, size));
119
18.9k
}
120
121
/**
122
 * xmlSecBufferFinalize:
123
 * @buf:                the pointer to buffer object.
124
 *
125
 * Frees allocated resource for a buffer initialized with #xmlSecBufferInitialize
126
 * function.
127
 */
128
void
129
18.9k
xmlSecBufferFinalize(xmlSecBufferPtr buf) {
130
18.9k
    xmlSecAssert(buf != NULL);
131
132
18.9k
    xmlSecBufferEmpty(buf);
133
134
18.9k
    if(buf->data != 0) {
135
18.9k
        xmlFree(buf->data);
136
18.9k
    }
137
18.9k
    buf->data = NULL;
138
18.9k
    buf->size = buf->maxSize = 0;
139
18.9k
}
140
141
/**
142
 * xmlSecBufferEmpty:
143
 * @buf:                the pointer to buffer object.
144
 *
145
 * Empties the buffer.
146
 */
147
void
148
37.9k
xmlSecBufferEmpty(xmlSecBufferPtr buf) {
149
37.9k
    xmlSecAssert(buf != NULL);
150
151
37.9k
    if(buf->data != 0) {
152
37.9k
        xmlSecAssert(buf->maxSize > 0);
153
37.9k
        memset(buf->data, 0, buf->maxSize);
154
37.9k
    }
155
37.9k
    buf->size = 0;
156
37.9k
}
157
158
/**
159
 * xmlSecBufferIsEmpty:
160
 * @buf:                the pointer to buffer object.
161
 *
162
 * Checks if the @buf is empty (@buf is null or @buf's data is null or @buf's size is zero).
163
 *
164
 * Returns: 1 if buffer is empty or 0 otherwise.
165
 */
166
int
167
0
xmlSecBufferIsEmpty(xmlSecBufferPtr buf) {
168
0
    return (((buf == NULL) || (buf->data == NULL) || (buf->size <= 0)) ? 1 : 0);
169
0
}
170
171
/**
172
 * xmlSecBufferGetData:
173
 * @buf:                the pointer to buffer object.
174
 *
175
 * Gets pointer to buffer's data.
176
 *
177
 * Returns: pointer to buffer's data.
178
 */
179
xmlSecByte*
180
18.9k
xmlSecBufferGetData(xmlSecBufferPtr buf) {
181
18.9k
    xmlSecAssert2(buf != NULL, NULL);
182
183
18.9k
    return(buf->data);
184
18.9k
}
185
186
/**
187
 * xmlSecBufferSetData:
188
 * @buf:                the pointer to buffer object.
189
 * @data:               the data.
190
 * @size:               the data size.
191
 *
192
 * Sets the value of the buffer to @data.
193
 *
194
 * Returns: 0 on success or a negative value if an error occurs.
195
 */
196
int
197
18.9k
xmlSecBufferSetData(xmlSecBufferPtr buf, const xmlSecByte* data, xmlSecSize size) {
198
18.9k
    int ret;
199
200
18.9k
    xmlSecAssert2(buf != NULL, -1);
201
202
18.9k
    xmlSecBufferEmpty(buf);
203
18.9k
    if(size > 0) {
204
18.9k
        xmlSecAssert2(data != NULL, -1);
205
206
18.9k
        ret = xmlSecBufferSetMaxSize(buf, size);
207
18.9k
        if(ret < 0) {
208
0
            xmlSecInternalError2("xmlSecBufferSetMaxSize", NULL, "size=" XMLSEC_SIZE_FMT, size);
209
0
            return(-1);
210
0
        }
211
212
18.9k
        memcpy(buf->data, data, size);
213
18.9k
    }
214
215
18.9k
    buf->size = size;
216
18.9k
    return(0);
217
18.9k
}
218
219
/**
220
 * xmlSecBufferGetSize:
221
 * @buf:                the pointer to buffer object.
222
 *
223
 * Gets the current buffer data size.
224
 *
225
 * Returns: the current data size.
226
 */
227
xmlSecSize
228
18.9k
xmlSecBufferGetSize(xmlSecBufferPtr buf) {
229
18.9k
    xmlSecAssert2(buf != NULL, 0);
230
231
18.9k
    return(buf->size);
232
18.9k
}
233
234
/**
235
 * xmlSecBufferSetSize:
236
 * @buf:                the pointer to buffer object.
237
 * @size:               the new data size.
238
 *
239
 * Sets new buffer data size. If necessary, buffer grows to
240
 * have at least @size bytes.
241
 *
242
 * Returns: 0 on success or a negative value if an error occurs.
243
 */
244
int
245
0
xmlSecBufferSetSize(xmlSecBufferPtr buf, xmlSecSize size) {
246
0
    int ret;
247
248
0
    xmlSecAssert2(buf != NULL, -1);
249
250
0
    ret = xmlSecBufferSetMaxSize(buf, size);
251
0
    if(ret < 0) {
252
0
        xmlSecInternalError2("xmlSecBufferSetMaxSize", NULL, "size=" XMLSEC_SIZE_FMT, size);
253
0
        return(-1);
254
0
    }
255
256
257
0
    buf->size = size;
258
0
    return(0);
259
0
}
260
261
/**
262
 * xmlSecBufferGetMaxSize:
263
 * @buf:                the pointer to buffer object.
264
 *
265
 * Gets the maximum (allocated) buffer size.
266
 *
267
 * Returns: the maximum (allocated) buffer size.
268
 */
269
xmlSecSize
270
0
xmlSecBufferGetMaxSize(xmlSecBufferPtr buf) {
271
0
    xmlSecAssert2(buf != NULL, 0);
272
273
0
    return(buf->maxSize);
274
0
}
275
276
/**
277
 * xmlSecBufferSetMaxSize:
278
 * @buf:                the pointer to buffer object.
279
 * @size:               the new maximum size.
280
 *
281
 * Sets new buffer maximum size. If necessary, buffer grows to
282
 * have at least @size bytes.
283
 *
284
 * Returns: 0 on success or a negative value if an error occurs.
285
 */
286
int
287
37.9k
xmlSecBufferSetMaxSize(xmlSecBufferPtr buf, xmlSecSize size) {
288
37.9k
    xmlSecByte* newData;
289
37.9k
    xmlSecSize newSize = 0;
290
291
37.9k
    xmlSecAssert2(buf != NULL, -1);
292
37.9k
    if(size <= buf->maxSize) {
293
18.9k
        return(0);
294
18.9k
    }
295
296
18.9k
    switch(buf->allocMode) {
297
0
        case xmlSecAllocModeExact:
298
0
            newSize = size + 8;
299
0
            break;
300
18.9k
        case xmlSecAllocModeDouble:
301
18.9k
            newSize = 2 * size + 32;
302
18.9k
            break;
303
18.9k
    }
304
305
18.9k
    if(newSize < gInitialSize) {
306
16.5k
        newSize = gInitialSize;
307
16.5k
    }
308
309
310
18.9k
    if(buf->data != NULL) {
311
0
        newData = (xmlSecByte*)xmlRealloc(buf->data, newSize);
312
18.9k
    } else {
313
18.9k
        newData = (xmlSecByte*)xmlMalloc(newSize);
314
18.9k
    }
315
18.9k
    if(newData == NULL) {
316
0
        xmlSecMallocError(newSize, NULL);
317
0
        return(-1);
318
0
    }
319
320
18.9k
    buf->data = newData;
321
18.9k
    buf->maxSize = newSize;
322
323
18.9k
    if(buf->size < buf->maxSize) {
324
18.9k
        xmlSecAssert2(buf->data != NULL, -1);
325
18.9k
        memset(buf->data + buf->size, 0, buf->maxSize - buf->size);
326
18.9k
    }
327
328
18.9k
    return(0);
329
18.9k
}
330
331
0
#define SWAP(type, a, b) do { type tmp = (a); (a) = (b); (b) = tmp; } while (0)
332
333
/**
334
 * xmlSecBufferSwap:
335
 * @buf1:               the pointer to the first buffer object.
336
 * @buf2:               the pointer to the second buffer object.
337
 *
338
 * Swaps the content of the two buffers.
339
 */
340
void
341
0
xmlSecBufferSwap(xmlSecBufferPtr buf1, xmlSecBufferPtr buf2) {
342
0
    xmlSecAssert(buf1 != NULL);
343
0
    xmlSecAssert(buf2 != NULL);
344
345
0
    SWAP(xmlSecByte*,       buf1->data, buf2->data);
346
0
    SWAP(xmlSecSize,        buf1->size, buf2->size);
347
0
    SWAP(xmlSecSize,        buf1->maxSize, buf2->maxSize);
348
0
    SWAP(xmlSecAllocMode,   buf1->allocMode, buf2->allocMode);
349
0
}
350
351
/**
352
 * xmlSecBufferAppend:
353
 * @buf:                the pointer to buffer object.
354
 * @data:               the data.
355
 * @size:               the data size.
356
 *
357
 * Appends the @data after the current data stored in the buffer.
358
 *
359
 * Returns: 0 on success or a negative value if an error occurs.
360
 */
361
int
362
0
xmlSecBufferAppend(xmlSecBufferPtr buf, const xmlSecByte* data, xmlSecSize size) {
363
0
    int ret;
364
365
0
    xmlSecAssert2(buf != NULL, -1);
366
367
0
    if(size > 0) {
368
0
        xmlSecAssert2(data != NULL, -1);
369
370
0
        ret = xmlSecBufferSetMaxSize(buf, buf->size + size);
371
0
        if(ret < 0) {
372
0
            xmlSecInternalError2("xmlSecBufferSetMaxSize", NULL,
373
0
                "size=" XMLSEC_SIZE_FMT, (buf->size + size));
374
0
            return(-1);
375
0
        }
376
377
0
        memcpy(buf->data + buf->size, data, size);
378
0
        buf->size += size;
379
0
    }
380
381
0
    return(0);
382
0
}
383
384
/**
385
 * xmlSecBufferPrepend:
386
 * @buf:                the pointer to buffer object.
387
 * @data:               the data.
388
 * @size:               the data size.
389
 *
390
 * Prepends the @data before the current data stored in the buffer.
391
 *
392
 * Returns: 0 on success or a negative value if an error occurs.
393
 */
394
int
395
0
xmlSecBufferPrepend(xmlSecBufferPtr buf, const xmlSecByte* data, xmlSecSize size) {
396
0
    int ret;
397
398
0
    xmlSecAssert2(buf != NULL, -1);
399
400
0
    if(size > 0) {
401
0
        xmlSecAssert2(data != NULL, -1);
402
403
0
        ret = xmlSecBufferSetMaxSize(buf, buf->size + size);
404
0
        if(ret < 0) {
405
0
            xmlSecInternalError2("xmlSecBufferSetMaxSize", NULL,
406
0
                "size=" XMLSEC_SIZE_FMT, (buf->size + size));
407
0
            return(-1);
408
0
        }
409
410
0
        memmove(buf->data + size, buf->data, buf->size);
411
0
        memcpy(buf->data, data, size);
412
0
        buf->size += size;
413
0
    }
414
415
0
    return(0);
416
0
}
417
418
/**
419
 * xmlSecBufferRemoveHead:
420
 * @buf:                the pointer to buffer object.
421
 * @size:               the number of bytes to be removed.
422
 *
423
 * Removes @size bytes from the beginning of the current buffer.
424
 *
425
 * Returns: 0 on success or a negative value if an error occurs.
426
 */
427
int
428
0
xmlSecBufferRemoveHead(xmlSecBufferPtr buf, xmlSecSize size) {
429
0
    xmlSecAssert2(buf != NULL, -1);
430
431
0
    if(size < buf->size) {
432
0
        xmlSecAssert2(buf->data != NULL, -1);
433
434
0
        buf->size -= size;
435
0
        memmove(buf->data, buf->data + size, buf->size);
436
0
    } else {
437
0
        buf->size = 0;
438
0
    }
439
0
    if(buf->size < buf->maxSize) {
440
0
        xmlSecAssert2(buf->data != NULL, -1);
441
0
        memset(buf->data + buf->size, 0, buf->maxSize - buf->size);
442
0
    }
443
0
    return(0);
444
0
}
445
446
/**
447
 * xmlSecBufferRemoveTail:
448
 * @buf:                the pointer to buffer object.
449
 * @size:               the number of bytes to be removed.
450
 *
451
 * Removes @size bytes from the end of current buffer.
452
 *
453
 * Returns: 0 on success or a negative value if an error occurs.
454
 */
455
int
456
0
xmlSecBufferRemoveTail(xmlSecBufferPtr buf, xmlSecSize size) {
457
0
    xmlSecAssert2(buf != NULL, -1);
458
459
0
    if(size < buf->size) {
460
0
        buf->size -= size;
461
0
    } else {
462
0
        buf->size = 0;
463
0
    }
464
0
    if(buf->size < buf->maxSize) {
465
0
        xmlSecAssert2(buf->data != NULL, -1);
466
0
        memset(buf->data + buf->size, 0, buf->maxSize - buf->size);
467
0
    }
468
0
    return(0);
469
0
}
470
471
/**
472
 * xmlSecBufferReverse:
473
 * @buf:                the pointer to buffer object.
474
 *
475
 * Reverses order of bytes in the buffer @buf.
476
 *
477
 * Returns: 0 on success or a negative value if an error occurs.
478
 */
479
int
480
0
xmlSecBufferReverse(xmlSecBufferPtr buf) {
481
0
    xmlSecByte* pp;
482
0
    xmlSecByte* qq;
483
0
    xmlSecSize  size;
484
0
    xmlSecByte ch;
485
486
0
    xmlSecAssert2(buf != NULL, -1);
487
488
    /* trivial case */
489
0
    size = xmlSecBufferGetSize(buf);
490
0
    if (size <= 1) {
491
0
        return(0);
492
0
    }
493
494
0
    pp = xmlSecBufferGetData(buf);
495
0
    xmlSecAssert2(pp != NULL, -1);
496
497
0
    for (qq = pp + size - 1; pp < qq; ++pp, --qq) {
498
0
        ch = *(pp);
499
0
        *(pp) = *(qq);
500
0
        *(qq) = ch;
501
0
    }
502
503
0
    return(0);
504
0
}
505
506
507
/**
508
 * xmlSecBufferReadFile:
509
 * @buf:                the pointer to buffer object.
510
 * @filename:           the filename.
511
 *
512
 * Reads the content of the file @filename in the buffer.
513
 *
514
 * Returns: 0 on success or a negative value if an error occurs.
515
 */
516
int
517
0
xmlSecBufferReadFile(xmlSecBufferPtr buf, const char* filename) {
518
0
    xmlSecByte buffer[1024];
519
0
    FILE* f = NULL;
520
0
    xmlSecSize size;
521
0
    size_t len;
522
0
    int ret;
523
0
    int res = -1;
524
525
0
    xmlSecAssert2(buf != NULL, -1);
526
0
    xmlSecAssert2(filename != NULL, -1);
527
528
0
#ifndef _MSC_VER
529
0
    f = fopen(filename, "rb");
530
#else
531
    fopen_s(&f, filename, "rb");
532
#endif /* _MSC_VER */
533
0
    if(f == NULL) {
534
0
        xmlSecIOError("fopen", filename, NULL);
535
0
        goto done;
536
0
    }
537
538
0
    while(!feof(f)) {
539
0
        len = fread(buffer, 1, sizeof(buffer), f);
540
0
        if(ferror(f)) {
541
0
            xmlSecIOError("fread", filename, NULL);
542
0
            goto done;
543
0
        }
544
545
0
        XMLSEC_SAFE_CAST_SIZE_T_TO_SIZE(len, size, goto done, NULL);
546
0
        ret = xmlSecBufferAppend(buf, buffer, size);
547
0
        if(ret < 0) {
548
0
            xmlSecInternalError2("xmlSecBufferAppend", NULL, "size=" XMLSEC_SIZE_T_FMT, len);
549
0
            goto done;
550
0
        }
551
0
    }
552
553
    /* success */
554
0
    res = 0;
555
556
0
done:
557
0
    if(f != NULL) {
558
0
        fclose(f);
559
0
    }
560
0
    return(res);
561
0
}
562
563
/**
564
 * xmlSecBufferBase64NodeContentRead:
565
 * @buf:                the pointer to buffer object.
566
 * @node:               the pointer to node.
567
 *
568
 * Reads the content of the @node, base64 decodes it and stores the
569
 * result in the buffer.
570
 *
571
 * Returns: 0 on success or a negative value if an error occurs.
572
 */
573
int
574
0
xmlSecBufferBase64NodeContentRead(xmlSecBufferPtr buf, xmlNodePtr node) {
575
0
    xmlChar* content = NULL;
576
0
    xmlSecSize outWritten;
577
0
    int ret;
578
0
    int res = -1;
579
580
0
    xmlSecAssert2(buf != NULL, -1);
581
0
    xmlSecAssert2(node != NULL, -1);
582
583
0
    content = xmlSecGetNodeContentAndTrim(node);
584
0
    if(content == NULL) {
585
0
        xmlSecInvalidNodeContentError(node, NULL, "empty");
586
0
        goto done;
587
0
    }
588
589
    /* base64 decode size is less than input size */
590
0
    ret = xmlSecBufferSetMaxSize(buf, xmlSecStrlen(content));
591
0
    if(ret < 0) {
592
0
        xmlSecInternalError("xmlSecBufferSetMaxSize", NULL);
593
0
        goto done;
594
0
    }
595
596
0
    ret = xmlSecBase64Decode_ex(content, xmlSecBufferGetData(buf),
597
0
        xmlSecBufferGetMaxSize(buf), &outWritten);
598
0
    if(ret < 0) {
599
0
        xmlSecInternalError("xmlSecBase64Decode_ex", NULL);
600
0
        goto done;
601
0
    }
602
603
0
    ret = xmlSecBufferSetSize(buf, outWritten);
604
0
    if(ret < 0) {
605
0
        xmlSecInternalError2("xmlSecBufferSetSize", NULL,
606
0
            "size=" XMLSEC_SIZE_FMT, outWritten);
607
0
        goto done;
608
0
    }
609
610
    /* success */
611
0
    res = 0;
612
613
0
done:
614
0
    if(content != NULL) {
615
0
        xmlFree(content);
616
0
    }
617
0
    return(res);
618
0
}
619
620
/**
621
 * xmlSecBufferBase64NodeContentWrite:
622
 * @buf:                the pointer to buffer object.
623
 * @node:               the pointer to a node.
624
 * @columns:            the max line size for base64 encoded data.
625
 *
626
 * Sets the content of the @node to the base64 encoded buffer data.
627
 *
628
 * Returns: 0 on success or a negative value if an error occurs.
629
 */
630
int
631
0
xmlSecBufferBase64NodeContentWrite(xmlSecBufferPtr buf, xmlNodePtr node, int columns) {
632
0
    xmlChar* content;
633
634
0
    xmlSecAssert2(buf != NULL, -1);
635
0
    xmlSecAssert2(node != NULL, -1);
636
637
0
    content = xmlSecBase64Encode(xmlSecBufferGetData(buf), xmlSecBufferGetSize(buf), columns);
638
0
    if(content == NULL) {
639
0
        xmlSecInternalError("xmlSecBase64Encode", NULL);
640
0
        return(-1);
641
0
    }
642
643
0
    xmlNodeAddContent(node, content);
644
0
    xmlFree(content);
645
646
0
    return(0);
647
0
}
648
649
650
/**
651
 * xmlSecBufferHexRead:
652
 * @buf:                the pointer to buffer object.
653
 * @hexStr:             the hex string.
654
 *
655
 * Reads content of hex encoded @hexStr into @buf.
656
 *
657
 * Returns: 0 on success or a negative value if an error occurs.
658
 */
659
int
660
0
xmlSecBufferHexRead(xmlSecBufferPtr buf, const xmlChar* hexStr) {
661
0
    xmlSecSize hexStrSize, bufSize;
662
0
    xmlSecByte * data;
663
0
    xmlChar ch1, ch2;
664
0
    int ret;
665
666
0
    xmlSecAssert2(buf != NULL, -1);
667
0
    xmlSecAssert2(hexStr != NULL, -1);
668
669
    /* trivial case */
670
0
    hexStrSize = xmlSecStrlen(hexStr);
671
0
    if(hexStrSize <= 0) {
672
0
        xmlSecBufferEmpty(buf);
673
0
        return(0);
674
0
    }
675
676
    /* we expect each byte to be represented by 2 chars */
677
0
    if((hexStrSize % 2) != 0) {
678
0
        xmlSecInvalidSizeDataError("hexStrSize", hexStrSize, "even", NULL);
679
0
        return(-1);
680
0
    }
681
0
    bufSize = hexStrSize / 2;
682
683
0
    ret = xmlSecBufferSetSize(buf, bufSize);
684
0
    if(ret < 0) {
685
0
        xmlSecInternalError2("xmlSecBufferSetSize", NULL,
686
0
            "bufSize=" XMLSEC_SIZE_FMT, bufSize);
687
0
        return (-1);
688
0
    }
689
690
0
    data = xmlSecBufferGetData(buf);
691
0
    xmlSecAssert2(data != NULL, -1);
692
693
0
    for( ; (*hexStr) != '\0'; ++data) {
694
0
        ch1 = *(hexStr++);
695
0
        ch2 = *(hexStr++);
696
0
        if(!xmlSecIsHex(ch1) || !xmlSecIsHex(ch2)) {
697
0
            xmlSecInvalidDataError("Unexpected character (not hex)", NULL);
698
0
            return (-1);
699
0
        }
700
0
        (*data) = xmlSecFromHex2(ch1, ch2);
701
0
    }
702
703
    /* sucess */
704
0
    return(0);
705
0
}
706
707
/************************************************************************
708
 *
709
 * IO buffer
710
 *
711
 ************************************************************************/
712
static int      xmlSecBufferIOWrite                             (xmlSecBufferPtr buf,
713
                                                                 const xmlSecByte *data,
714
                                                                 int len);
715
static int      xmlSecBufferIOClose                             (xmlSecBufferPtr buf);
716
717
/**
718
 * xmlSecBufferCreateOutputBuffer:
719
 * @buf:                the pointer to buffer.
720
 *
721
 * Creates new LibXML output buffer to store data in the @buf. Caller is
722
 * responsible for destroying @buf when processing is done.
723
 *
724
 * Returns: pointer to newly allocated output buffer or NULL if an error
725
 * occurs.
726
 */
727
xmlOutputBufferPtr
728
0
xmlSecBufferCreateOutputBuffer(xmlSecBufferPtr buf) {
729
0
    return(xmlOutputBufferCreateIO((xmlOutputWriteCallback)xmlSecBufferIOWrite,
730
0
                                     (xmlOutputCloseCallback)xmlSecBufferIOClose,
731
0
                                     buf,
732
0
                                     NULL));
733
0
}
734
735
static int
736
0
xmlSecBufferIOWrite(xmlSecBufferPtr buf, const xmlSecByte *data, int len) {
737
0
    xmlSecSize size;
738
0
    int ret;
739
740
0
    xmlSecAssert2(buf != NULL, -1);
741
0
    xmlSecAssert2(data != NULL, -1);
742
0
    xmlSecAssert2(len >= 0, -1);
743
744
0
    XMLSEC_SAFE_CAST_INT_TO_SIZE(len, size, return(-1), NULL);
745
0
    ret = xmlSecBufferAppend(buf, data, size);
746
0
    if(ret < 0) {
747
0
        xmlSecInternalError2("xmlSecBufferAppend", NULL, "size=" XMLSEC_SIZE_FMT, size);
748
0
        return(-1);
749
0
    }
750
    /* we appended the whole input buffer */
751
0
    return(len);
752
0
}
753
754
static int
755
0
xmlSecBufferIOClose(xmlSecBufferPtr buf) {
756
0
    xmlSecAssert2(buf != NULL, -1);
757
758
    /* just do nothing */
759
0
    return(0);
760
0
}