2 * Copyright (c) 2006,2011-2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
30 #define ALIGNMENT sizeof(void*)
31 #define ALIGNUP(LEN) (((LEN - 1) & ~(ALIGNMENT - 1)) + ALIGNMENT)
35 * *cpp is a pointer to the bytes, *sizep is the count.
36 * If *cpp is NULL maxsize bytes are allocated
38 bool_t
sec_xdr_bytes(XDR
*xdrs
, uint8_t **cpp
, u_int
*sizep
, u_int maxsize
)
40 uint8_t *sp
= cpp
? *cpp
: NULL
; /* sp is the actual string pointer */
41 u_int nodesize
= sizep
? *sizep
: 0;
44 * first deal with the length since xdr bytes are counted
46 if (! xdr_u_int(xdrs
, &nodesize
))
49 if ((nodesize
> maxsize
) && (xdrs
->x_op
!= XDR_FREE
))
52 if (sizep
&& (xdrs
->x_op
== XDR_DECODE
))
55 bool_t sizeof_alloc
= sec_xdr_arena_size_allocator(xdrs
);
58 * now deal with the actual bytes
65 if (!sec_mem_alloc(xdrs
, nodesize
, &sp
))
68 *cpp
= sp
; /* sp can be NULL when counting required space */
72 return (xdr_opaque(xdrs
, (char *)sp
, nodesize
));
76 sec_mem_free(xdrs
, sp
, nodesize
);
85 bool_t
sec_xdr_charp(XDR
*xdrs
, char **cpp
, u_int maxsize
)
87 char *sp
= cpp
? *cpp
: NULL
; /* sp is the actual string pointer */
92 if (sp
== NULL
) return(TRUE
); /* already free */
93 sec_mem_free(xdrs
, sp
, size
);
97 if (sp
) size
= (u_int
)(strlen(sp
) + 1);
100 return sec_xdr_bytes(xdrs
, (uint8_t**)cpp
, &size
, maxsize
);
106 bool_t
sec_mem_alloc(XDR
*xdr
, u_int bsize
, uint8_t **data
)
111 assert(xdr
->x_op
== XDR_DECODE
);
113 sec_xdr_arena_allocator_t
*allocator
= sec_xdr_arena_allocator(xdr
);
116 return (TRUE
); // no allocation needed
118 switch(allocator
->magic
) {
119 case xdr_arena_magic
:
120 bytes_left
= allocator
->end
- allocator
->offset
;
121 if (bsize
> bytes_left
)
124 uint8_t *temp
= allocator
->offset
;
125 allocator
->offset
+= bsize
;
130 allocator
->offset
= (uint8_t*)((size_t)allocator
->offset
+ bsize
);
135 void *alloc
= calloc(1, bsize
);
143 void sec_mem_free(XDR
*xdr
, void *ptr
, u_int bsize
)
145 if (sec_xdr_arena_allocator(xdr
))
151 static const sec_xdr_arena_allocator_t size_alloc
= { xdr_size_magic
, 0, 0, 0 };
152 void sec_xdr_arena_init_size_alloc(sec_xdr_arena_allocator_t
*arena
, XDR
*xdr
)
154 memcpy(arena
, &size_alloc
, sizeof(size_alloc
));
155 xdr
->x_public
= (char *)arena
;
158 bool_t
sec_xdr_arena_init(sec_xdr_arena_allocator_t
*arena
, XDR
*xdr
,
159 size_t in_length
, uint8_t *in_data
)
163 uint8_t *data
= in_data
? in_data
: calloc(1, ALIGNUP(in_length
));
166 arena
->magic
= xdr_arena_magic
;
167 arena
->offset
= data
;
169 arena
->end
= data
+ in_length
;
170 xdr
->x_public
= (void*)arena
;
174 void sec_xdr_arena_free(sec_xdr_arena_allocator_t
*arena
,
175 void *ptr
, size_t bsize
)
177 assert(arena
->magic
== xdr_arena_magic
);
181 void *sec_xdr_arena_data(sec_xdr_arena_allocator_t
*arena
)
189 sec_xdr_arena_allocator_t
*sec_xdr_arena_allocator(XDR
*xdr
)
191 sec_xdr_arena_allocator_t
*allocator
= xdr
? (sec_xdr_arena_allocator_t
*)xdr
->x_public
: NULL
;
194 (allocator
->magic
== xdr_arena_magic
||
195 allocator
->magic
== xdr_size_magic
))
201 bool_t
sec_xdr_arena_size_allocator(XDR
*xdr
)
203 sec_xdr_arena_allocator_t
*allocator
= xdr
? (sec_xdr_arena_allocator_t
*)xdr
->x_public
: NULL
;
204 if (allocator
&& (allocator
->magic
== xdr_size_magic
))
211 bool_t
copyin(void *data
, xdrproc_t proc
, void** copy
, u_int
*size
)
216 // xdr_sizeof is illbehaved
217 u_int length
= sec_xdr_sizeof_in(proc
, data
);
218 uint8_t *xdr_data
= malloc(length
);
223 sec_xdrmem_create(&xdr
, (char *)xdr_data
, length
, XDR_ENCODE
);
225 // cast to void* - function can go both ways (xdr->x_op)
226 if (proc(&xdr
, data
, 0)) {
228 if (size
) *size
= length
;
236 // Unmarshall xdr data and return pointer to single allocation containing data
237 // Generally use *_PTR for xdrproc_t taking an objp that matches data's type
238 // ie. xdr_CSSM_POSSIBLY_KEY_IN_DATA_PTR(XDR *xdrs, CSSM_DATA_PTR *objp)
239 // with data matching objp
240 // If you pass in length pointing to a non-zero value, data will be assumed
241 // to have pre-allocated space for use by copyout in that amount.
242 // If *data is not NULL it will be assumed to be allocated already.
243 bool_t
copyout(const void *copy
, u_int size
, xdrproc_t proc
, void **data
, u_int
*length
)
246 if (!data
|| (size
> ~(u_int
)0))
250 sec_xdrmem_create(&xdr
, (void *)copy
, size
, XDR_DECODE
);
252 u_int length_required
= sec_xdr_sizeof_out(copy
, size
, proc
, data
);
253 u_int length_out
= length
? *length
: 0;
255 if (length_out
&& (length_required
> length_out
))
258 bool_t passed_in_data
= (*data
&& length_out
);
259 sec_xdr_arena_allocator_t arena
;
260 // set up arena with memory passed in (length_out > 0) or ask to allocate
261 if (!sec_xdr_arena_init(&arena
, &xdr
, length_out
? length_out
: length_required
, length_out
? *data
: NULL
))
264 if (proc(&xdr
, data
, 0))
266 *length
= length_required
;
271 sec_xdr_arena_free(sec_xdr_arena_allocator(&xdr
), NULL
, 0);
275 // unmarshall xdr data and return pointer to individual allocations containing data
276 // only use *_PTR for xdrproc_ts and pointers for data
277 bool_t
copyout_chunked(const void *copy
, u_int size
, xdrproc_t proc
, void **data
)
279 if (!data
|| (size
> ~(u_int
)0))
283 sec_xdrmem_create(&xdr
, (void *)copy
, size
, XDR_DECODE
);
285 void *data_out
= NULL
;
287 if (proc(&xdr
, &data_out
, 0))