File Coverage

inc/matrixssl-3-9-3-open/core/psbuf.h
Criterion Covered Total %
statement 0 5 0.0
branch 0 8 0.0
condition n/a
subroutine n/a
pod n/a
total 0 13 0.0


line stmt bran cond sub pod time code
1             /**
2             * @file psbuf.h
3             * @version 950bba4 (HEAD -> master)
4             *
5             * API for handling buffers containing binary data.
6             */
7             /*
8             * Copyright (c) 2017 INSIDE Secure Corporation
9             * All Rights Reserved
10             *
11             * The latest version of this code is available at http://www.matrixssl.org
12             *
13             * This software is open source; you can redistribute it and/or modify
14             * it under the terms of the GNU General Public License as published by
15             * the Free Software Foundation; either version 2 of the License, or
16             * (at your option) any later version.
17             *
18             * This General Public License does NOT permit incorporating this software
19             * into proprietary programs. If you are unable to comply with the GPL, a
20             * commercial license for this software may be purchased from INSIDE at
21             * http://www.insidesecure.com/
22             *
23             * This program is distributed in WITHOUT ANY WARRANTY; without even the
24             * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
25             * See the GNU General Public License for more details.
26             *
27             * You should have received a copy of the GNU General Public License
28             * along with this program; if not, write to the Free Software
29             * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30             * http://www.gnu.org/copyleft/gpl.html
31             */
32             /******************************************************************************/
33              
34             #ifndef _h_PS_BUF
35             # define _h_PS_BUF
36              
37             # include "coreApi.h"
38             # include
39              
40             /* API for psBuf initialization and basic usage.*/
41             void *psBufInit(psPool_t *pool, psBuf_t *buf, size_t capacity);
42             void psBufUninit(psPool_t *pool, psBuf_t *buf);
43             int32_t psBufFromStaticData(psBuf_t *buf, const void *data, size_t len);
44             int32_t psBufEmptyFromPointerSize(psBuf_t *buf, void *data, size_t len);
45             void *psBufDetach(psPool_t *pool, psBuf_t *buf, size_t *len_p);
46             void *psBufAppendSize(psBuf_t *buf, size_t sz);
47             size_t psBufGetMaxAppendSize(const psBuf_t *buf);
48             void psBufReservePrepend(psBuf_t *buf, size_t sz);
49             void *psBufPrependSize(psBuf_t *buf, size_t sz);
50             size_t psBufGetMaxPrependSize(const psBuf_t *buf);
51             void *psBufGetData(psBuf_t *buf);
52             size_t psBufGetDataSize(const psBuf_t *buf);
53             void psBufNormalize(psBuf_t *buf);
54             char *psBufAsHex(psPool_t *pool, const psBuf_t *buf);
55             int32_t psBufCopyDataN(psBuf_t *buf, size_t reqLen,
56             unsigned char *target, size_t *targetlen);
57              
58             int32_t psBufFromData(psPool_t *pool, psBuf_t *buf,
59             const void *data, size_t len);
60              
61              
62 0           static __inline int psBufEq(const psBuf_t *buf1, const psBuf_t *buf2)
63             {
64 0 0         return (buf1->end - buf1->start) == (buf2->end - buf2->start) &&
65 0 0         buf1->start != NULL &&
66 0 0         buf2->start != NULL &&
    0          
67 0           memcmp(buf1->start, buf2->start, (buf1->end - buf1->start))
68             == 0;
69             }
70              
71             static __inline void *psBufAppendChar(psBuf_t *buf, char ch)
72             {
73             void *loc = psBufAppendSize(buf, 1);
74              
75             if (loc)
76             {
77             *(char *) loc = ch;
78             }
79             return loc;
80             }
81              
82             static __inline void *psBufPrependChar(psBuf_t *buf, char ch)
83             {
84             void *loc = psBufPrependSize(buf, 1);
85              
86             if (loc)
87             {
88             *(char *) loc = ch;
89             }
90             return loc;
91             }
92              
93             /* API for Dynamic Buffers initialization and basic usage. */
94             void *psDynBufInit(psPool_t *pool, psDynBuf_t *db, size_t capacity);
95             void psDynBufUninit(psDynBuf_t *db);
96             void *psDynBufDetach(psDynBuf_t *db, size_t *len_p);
97             void *psDynBufAppendSize(psDynBuf_t *db, size_t sz);
98             void psDynBufReservePrepend(psDynBuf_t *db, size_t sz);
99             void *psDynBufPrependSize(psDynBuf_t *db, size_t sz);
100              
101             static __inline void *psDynBufAppendChar(psDynBuf_t *db, char ch)
102             {
103             void *loc = psDynBufAppendSize(db, 1);
104              
105             if (loc)
106             {
107             *(char *) loc = ch;
108             }
109             return loc;
110             }
111              
112             void *psDynBufAppendUtf8(psDynBuf_t *db, int chr);
113              
114             static __inline void *psDynBufPrependChar(psDynBuf_t *db, char ch)
115             {
116             void *loc = psDynBufPrependSize(db, 1);
117              
118             if (loc)
119             {
120             *(char *) loc = ch;
121             }
122             return loc;
123             }
124              
125             static __inline void *psDynBufAppendStr(psDynBuf_t *db, const char *s)
126             {
127             size_t len = s ? strlen(s) : 0;
128             void *loc = psDynBufAppendSize(db, len);
129              
130             if (loc)
131             {
132             memcpy(loc, s, len);
133             }
134             return loc;
135             }
136              
137             static __inline void *psDynBufPrependStr(psDynBuf_t *db, const char *s)
138             {
139             size_t len = s ? strlen(s) : 0;
140             void *loc = psDynBufPrependSize(db, len);
141              
142             if (loc)
143             {
144             memcpy(loc, s, len);
145             }
146             return loc;
147             }
148              
149             static __inline void *psDynBufAppendOctets(psDynBuf_t *db, const void *data,
150             size_t len)
151             {
152             void *loc = psDynBufAppendSize(db, len);
153              
154             if (loc)
155             {
156             memcpy(loc, data, len);
157             }
158             return loc;
159             }
160              
161             static __inline void *psDynBufAppendBuf(psDynBuf_t *db, const psBuf_t *b)
162             {
163             return psDynBufAppendOctets(db, b->start, b->end - b->start);
164             }
165              
166             static __inline void *psDynBufAppendParseBuf(psDynBuf_t *db,
167             const psParseBuf_t *pb)
168             {
169             if (!pb || pb->err)
170             {
171             db->err++;
172             return NULL;
173             }
174             return psDynBufAppendBuf(db, &(pb->buf));
175             }
176            
177             static __inline void *psDynBufIncorporateDynBuf(psDynBuf_t *db, psDynBuf_t *db2)
178             {
179             size_t len;
180             void *data = psDynBufDetach(db2, &len);
181              
182             if (data)
183             {
184             return psDynBufAppendOctets(db, data, len);
185             }
186             else
187             {
188             db->err++;
189             return NULL;
190             }
191             }
192              
193             /* Dynamic buffer subbuffers. */
194             void *psDynBufSubInit(psDynBuf_t *db, psDynBuf_t *sub, size_t capacity);
195             void *psDynBufSubInitAt(psDynBuf_t *db, psDynBuf_t *sub, size_t at,
196             size_t length);
197             void *psDynBufSubFinish(psDynBuf_t *sub);
198              
199             /* Note: This variable argument function is currently implemented as a macro. */
200             # define psDynBufAppendStrf(ps_dyn_buf_p, ...) \
201             do { \
202             char tmp; \
203             size_t len = 1 + snprintf(&tmp, 1, __VA_ARGS__); \
204             char *target = psDynBufAppendSize((ps_dyn_buf_p), len); \
205             if (target) { \
206             snprintf(target, len, __VA_ARGS__); \
207             (ps_dyn_buf_p)->buf.end -= 1; \
208             } \
209             } while (0)
210              
211              
212             /* Subset of ASN.1 via psDynBuf. */
213             char *psDynBufAppendAsn1TagGen(psDynBuf_t *db, unsigned char tag,
214             const unsigned char *bytes, size_t len);
215              
216             static inline
217             char *psDynBufAppendAsn1IntegerSmall(psDynBuf_t *db, signed char byte)
218             {
219             unsigned char bytes[1];
220              
221             bytes[0] = (unsigned char) byte;
222             return psDynBufAppendAsn1TagGen(db, 0x02, bytes, 1);
223             }
224              
225             static inline
226             char *psDynBufAppendAsn1OctetString(psDynBuf_t *db,
227             const unsigned char *bytes, size_t len)
228             {
229             return psDynBufAppendAsn1TagGen(db, 0x04, bytes, len);
230             }
231              
232             static inline
233             char *psDynBufAppendAsn1Oid(psDynBuf_t *db,
234             const unsigned char *oidbytes, size_t len)
235             {
236             /* Note: oidbytes shall not include OID identifier (6) or length. */
237             return psDynBufAppendAsn1TagGen(db, 0x06, oidbytes, len);
238             }
239              
240             char *psDynBufBeginConstructedTag(psDynBuf_t *db, psDynBuf_t *sub);
241             char *psDynBufEndConstructedTag(psDynBuf_t *sub, unsigned char tag);
242              
243             static __inline char *psDynBufBeginSequence(psDynBuf_t *db, psDynBuf_t *sub)
244             {
245             return psDynBufBeginConstructedTag(db, sub);
246             }
247              
248             static __inline char *psDynBufEndSequence(psDynBuf_t *sub)
249             {
250             return psDynBufEndConstructedTag(sub, 0x30);
251             }
252              
253             static __inline int32_t psDynBufDetachBuf(psDynBuf_t *db, psBuf_t *target)
254             {
255             size_t sz;
256             void *buf;
257              
258             buf = psDynBufDetach(db, &sz);
259             target->start = target->buf = (unsigned char *) buf;
260             if (!buf)
261             {
262             /* Exception path: memory allocation failure. */
263             target->size = 0;
264             target->end = (unsigned char *) buf;
265             return PS_MEM_FAIL;
266             }
267              
268             target->size = sz;
269             target->end = ((unsigned char *) buf) + sz;
270             return PS_SUCCESS;
271             }
272              
273             /* Start parsing static data using psParseBuf_t. */
274             int32_t psParseBufFromStaticData(psParseBuf_t *pb,
275             const void *data, size_t len);
276              
277             /* Check if there is sufficient data to parse left. */
278             static __inline int psParseCanRead(const psParseBuf_t *pb, size_t nbytes)
279             {
280             size_t bytes_readable;
281              
282             if (pb->err)
283             {
284             return 0;
285             }
286              
287             bytes_readable = pb->buf.end - pb->buf.start;
288             return bytes_readable >= nbytes;
289             }
290              
291             /* Get length of following ASN.1 tag
292             (specify tag as unsigned char or 0 for ANY).
293              
294             This is for parsing content of parsebuf as ASN.1 DER data.
295              
296             If hdrLen_p is non-null, the function also returns the length of tag header.
297             */
298             size_t psParseBufGetTagLen(const psParseBuf_t *pb, unsigned char tag,
299             size_t *hdrLen_p);
300             /* Test if there is specific (tag > 0) or any (tag == 0) ASN.1 der
301             encoding at current parsing location.
302             return 0 no, 1 yes */
303             int psParseBufCanGetTag(const psParseBuf_t *pb, unsigned char tag);
304             /* Try read ASN.1 DER specific (tag > 0) or any (tag == 0) at the
305             current parsing location. Reading will return sub parsebuf,
306             which allows reading constructed tags.
307             Returns length of tag read (including header) or 0 if no tag was read.
308             Parsing location will advance once finished with content.
309             */
310             size_t psParseBufTryReadTagSub(const psParseBuf_t *pb,
311             psParseBuf_t *content, unsigned char tag);
312             /* Read specified (or any) ASN.1 tag at the current parsing location.
313             it is considered error if read fails.
314             Parsing location will advance once finished with content. */
315             size_t psParseBufReadTagSub(psParseBuf_t *pb,
316             psParseBuf_t *content, unsigned char tag);
317             /* Copy all data from parse buffer. Supports length negotiations.
318             Fails if parsing errors have been seen. */
319             int32_t psParseBufCopyAll(const psParseBuf_t *pb, unsigned char *target,
320             size_t *targetlen);
321             /* Return true only if buffers have encountered no parsing errors and
322             the contents are equal. */
323             int psParseBufEq(const psParseBuf_t *pb1, const psParseBuf_t *pb2);
324             /* return PS_SUCCESS if pb has not encountered parsing errors. */
325             int32_t psParseBufCheckState(const psParseBuf_t *pb);
326              
327             /* Alias (implemented as a macro) for psParseBufTryReadTagSub used on sequence.
328             */
329             # define psParseBufTryReadSequenceSub(pb, content) \
330             psParseBufTryReadTagSub(pb, content, 0x30)
331              
332             /* Alias (implemented as a macro) for psParseBufReadTagSub used on sequence. */
333             # define psParseBufReadSequenceSub(pb, content) \
334             psParseBufReadTagSub(pb, content, 0x30)
335              
336             /* Skip tag with specified tag id (or 0 for any) if possible.
337             If tag was skipped, return length in bytes that was skipped. */
338             size_t psParseBufTrySkipTag(psParseBuf_t *pb, unsigned char tag);
339              
340             /* Skip tag with specified tag id (or 0 for any) if possible.
341             Tag not existing is considered error and error is set in pb. */
342             size_t psParseBufSkipTag(psParseBuf_t *pb, unsigned char tag);
343              
344             /* Signal errors from sub to master buffer.
345             If invoked on allocated main parse buffer, the memory will be freed.
346             If invoked on subbuffer, the position on main buffer is advanced.
347             The return value will only be PS_SUCCESS is no errors have been observed. */
348             int32_t psParseBufFinish(psParseBuf_t *buf);
349              
350             /* Cancel processing of subbuffer.
351             Errors are not propagated to the master buffer, and master buffer is not
352             advanced.
353             If invoked on allocated main parse buffer, any memory allocated will
354             still be freed. */
355             void psParseBufCancel(psParseBuf_t *buf);
356              
357             /* Skip specified bytes (such as tag with specific contents or non-ASN.1 data)*/
358             size_t psParseBufTrySkipBytes(psParseBuf_t *pb,
359             const unsigned char *bytes,
360             size_t numbytes);
361              
362             /* Skip specified bytes. Not finding the bytes is an error. */
363             size_t psParseBufSkipBytes(psParseBuf_t *pb, const unsigned char *bytes,
364             size_t numbytes);
365              
366             /* Read given tag and fill-in reference with the content.
367             Parse buffer is moved to point to the next parsing location. */
368             size_t psParseBufReadTagRef(psParseBuf_t *pb,
369             psBuf_t *ref, unsigned char tag);
370              
371             /* Copy data from parse buffer until stopbyte is seen.
372             The target shall be large enough or NULL to inquire size.
373             The stopbyte will be included in bytes copied.
374             This function does not update buffer parsing position. */
375             int32_t psParseBufCopyUntilByte(psParseBuf_t *pb, unsigned char stopbyte,
376             unsigned char *target, size_t *targetlen);
377             /* Copy specified amount of data from parse buffer without moving buffer
378             parsing position. */
379             int32_t psParseBufCopyN(const psParseBuf_t *pb, size_t reqLen,
380             unsigned char *target, size_t *targetlen);
381             #endif /* _h_PS_BUF */
382             /* end of file psbuf.h */