1/*
2 * Copyright (c) 2006-2008,2011-2012 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24#include <architecture/byte_order.h>
25#include <string.h>		/* bzero() */
26#include <stdlib.h>		/* exit() */
27#include <assert.h>		/* assert() */
28#include <stdio.h>		/* XXX/gh  because utilities/debugging.h doesn't */
29#include <security_utilities/debugging.h>
30
31#include "xdr_cssm.h"
32
33// All functions with the "writes" comment write to memory without regard for size only operation.  This is okay as long as they aren't used "naked", ie. as toplevel encoders.  For our purposes they're always in a struct or array, or with a pointer pointing at them.
34
35// XXX/cs writes
36bool_t sec_xdr_clip_long(XDR *xdrs, long *objp)
37{
38	uint32_t clip = 0;
39
40	if (objp && xdrs->x_op == XDR_ENCODE)
41		clip = *objp & UINT32_MAX;
42    if (!xdr_uint32(xdrs, &clip))
43		return (FALSE);
44	if (objp && xdrs->x_op == XDR_DECODE)
45		*objp = clip;
46    return (TRUE);
47}
48
49// XXX/cs writes
50bool_t xdr_voidptr(XDR *xdrs, void **objp)
51{
52    long ptr = 0;
53
54    if (*objp)
55		ptr = (intptr_t)*objp;
56    if (!sec_xdr_clip_long(xdrs, &ptr))
57		return (FALSE);
58	// not returned
59
60    return (TRUE);
61}
62
63bool_t xdr_CSSM_DATA(XDR *xdrs, CSSM_DATA *objp)
64{
65    u_int valueLength; // objp->Length is a size_t
66    if (xdrs->x_op == XDR_ENCODE) {
67        if (objp->Length > (u_int)~0)
68            return (FALSE);
69        valueLength = (u_int)objp->Length;
70    }
71    if (!sec_xdr_bytes(xdrs, &objp->Data, &valueLength, ~0))
72        return (FALSE);
73    if (xdrs->x_op == XDR_DECODE)
74        objp->Length = valueLength;
75    return (TRUE);
76}
77
78bool_t xdr_CSSM_GUID(XDR *xdrs, CSSM_GUID *objp)
79{
80    return xdr_opaque(xdrs, (char *)objp, sizeof(CSSM_GUID));
81}
82
83bool_t xdr_CSSM_VERSION(XDR *xdrs, CSSM_VERSION *objp)
84{
85    if (!xdr_uint32(xdrs, &objp->Major))
86        return (FALSE);
87    if (!xdr_uint32(xdrs, &objp->Minor))
88        return (FALSE);
89    return (TRUE);
90}
91
92bool_t xdr_CSSM_SUBSERVICE_UID(XDR *xdrs, CSSM_SUBSERVICE_UID *objp)
93{
94    if (!xdr_CSSM_GUID(xdrs, &objp->Guid))
95        return (FALSE);
96    if (!xdr_CSSM_VERSION(xdrs, &objp->Version))
97        return (FALSE);
98    if (!xdr_uint32(xdrs, &objp->SubserviceId))
99        return (FALSE);
100    if (!xdr_CSSM_SERVICE_TYPE(xdrs, &objp->SubserviceType))
101        return (FALSE);
102    return (TRUE);
103}
104
105bool_t xdr_CSSM_NET_ADDRESS(XDR *xdrs, CSSM_NET_ADDRESS *objp)
106{
107    if (!xdr_CSSM_NET_ADDRESS_TYPE(xdrs, &objp->AddressType))
108        return (FALSE);
109    if (!xdr_CSSM_DATA(xdrs, &objp->Address))
110        return (FALSE);
111    return (TRUE);
112}
113
114// XXX/cs crypto_data will automagically send callback data when necessary, on the pass out it will reappear in Param, which is also the alternative data sent.  So Callback!=NULL means Param is crypto callback data, otherwise it is param data.
115bool_t xdr_CSSM_CRYPTO_DATA(XDR *xdrs, CSSM_CRYPTO_DATA *objp)
116{
117    void *cb = (void *)objp->Callback;
118    if (!xdr_voidptr(xdrs, &cb))
119        return (FALSE);
120    if (!xdr_voidptr(xdrs, &objp->CallerCtx))
121        return (FALSE);
122
123    // Encode callback result if existing, otherwise just param
124    // Result comes back in Param
125    if (xdrs->x_op == XDR_ENCODE && objp->Callback)
126    {
127        CSSM_CALLBACK func = objp->Callback;
128        CSSM_DATA data;
129        CSSM_RETURN err;
130        if ((err = func(&data, objp->CallerCtx)))
131            return (FALSE); // XXX/cs meaningfully return err
132        if (!xdr_CSSM_DATA(xdrs, &data))
133            return (FALSE);
134    }
135    else
136    {
137        if (!xdr_CSSM_DATA(xdrs, &objp->Param))
138            return (FALSE);
139    }
140    return (TRUE);
141}
142
143bool_t inline xdr_CSSM_LIST_ELEMENT(XDR *xdrs, CSSM_LIST_ELEMENT *objp)
144{
145    if (!xdr_CSSM_WORDID_TYPE(xdrs, &objp->WordID))
146        return (FALSE);
147    if (!xdr_CSSM_LIST_ELEMENT_TYPE(xdrs, &objp->ElementType))
148        return (FALSE);
149    switch(objp->ElementType) {
150    case CSSM_LIST_ELEMENT_DATUM:
151        if (!xdr_CSSM_DATA(xdrs, &objp->Element.Word)) return (FALSE); break;
152    case CSSM_LIST_ELEMENT_SUBLIST:
153        if (!xdr_CSSM_LIST(xdrs, &objp->Element.Sublist)) return (FALSE); break;
154    case CSSM_LIST_ELEMENT_WORDID:
155        break;
156    default:
157        secdebug("secxdr", "Illegal CSSM_LIST_ELEMENT type: %u", objp->ElementType); return (FALSE);
158    }
159
160    if (!sec_xdr_pointer(xdrs, (uint8_t**)&objp->NextElement, sizeof(CSSM_LIST_ELEMENT), (xdrproc_t)xdr_CSSM_LIST_ELEMENT))
161        return (FALSE);
162
163    return (TRUE);
164}
165
166bool_t xdr_CSSM_LIST(XDR *xdrs, CSSM_LIST *objp)
167{
168    if (!xdr_CSSM_LIST_TYPE(xdrs, &objp->ListType))
169        return (FALSE);
170    if (!sec_xdr_pointer(xdrs, (uint8_t**)&objp->Head, sizeof(CSSM_LIST_ELEMENT), (xdrproc_t)xdr_CSSM_LIST_ELEMENT))
171        return (FALSE);
172    // if we're restoring things, make sure to fix up Tail to point
173    // to the right place
174    if (xdrs->x_op == XDR_DECODE)
175    {
176        bool_t size_alloc = sec_xdr_arena_size_allocator(xdrs);
177        if (!size_alloc)
178            for (objp->Tail = objp->Head; objp->Tail && objp->Tail->NextElement; objp->Tail = objp->Tail->NextElement);
179    }
180    return (TRUE);
181}
182
183bool_t xdr_CSSM_SAMPLE(XDR *xdrs, CSSM_SAMPLE *objp)
184{
185    if (!xdr_CSSM_LIST(xdrs, &objp->TypedSample))
186        return (FALSE);
187    if (!sec_xdr_pointer(xdrs, (uint8_t**)&objp->Verifier, sizeof(CSSM_SUBSERVICE_UID), (xdrproc_t)xdr_CSSM_SUBSERVICE_UID))
188        return (FALSE);
189    return (TRUE);
190}
191
192bool_t xdr_CSSM_SAMPLEGROUP(XDR *xdrs, CSSM_SAMPLEGROUP *objp)
193{
194    assert(sizeof(objp->NumberOfSamples) == sizeof(int));
195    if (!sec_xdr_array(xdrs, (uint8_t**)&objp->Samples, (u_int *)&objp->NumberOfSamples, ~0, sizeof(CSSM_SAMPLE), (xdrproc_t)xdr_CSSM_SAMPLE))
196        return (FALSE);
197    return (TRUE);
198}
199
200bool_t xdr_CSSM_ENCODED_CERT(XDR *xdrs, CSSM_ENCODED_CERT *objp)
201{
202
203    if (!xdr_CSSM_CERT_TYPE(xdrs, &objp->CertType))
204        return (FALSE);
205    if (!xdr_CSSM_CERT_ENCODING(xdrs, &objp->CertEncoding))
206        return (FALSE);
207    if (!xdr_CSSM_DATA(xdrs, &objp->CertBlob))
208        return (FALSE);
209    return (TRUE);
210}
211
212bool_t xdr_CSSM_CERTGROUP(XDR *xdrs, CSSM_CERTGROUP *objp)
213{
214    if (!xdr_CSSM_CERT_TYPE(xdrs, &objp->CertType))
215        return (FALSE);
216    if (!xdr_CSSM_CERT_ENCODING(xdrs, &objp->CertEncoding))
217        return (FALSE);
218
219    // NumCerts encoded as part of sec_xdr_array below (we need it
220    // before the switch on decode)
221    if (!xdr_CSSM_CERTGROUP_TYPE(xdrs, &objp->CertGroupType))
222        return (FALSE);
223
224    switch (objp->CertGroupType) {
225    case CSSM_CERTGROUP_DATA:
226        if (!sec_xdr_array(xdrs, (uint8_t**)&objp->GroupList.CertList, &objp->NumCerts, ~0, sizeof(CSSM_DATA), (xdrproc_t)xdr_CSSM_DATA))
227            return (FALSE);
228        break;
229    case CSSM_CERTGROUP_ENCODED_CERT:
230        if (!sec_xdr_array(xdrs, (uint8_t**)&objp->GroupList.EncodedCertList,
231                    &objp->NumCerts, ~0,
232                    sizeof(CSSM_ENCODED_CERT), (xdrproc_t)xdr_CSSM_ENCODED_CERT))
233            return (FALSE);
234        break;
235    case CSSM_CERTGROUP_PARSED_CERT: // unimplemented -> there are no walkers for it
236    case CSSM_CERTGROUP_CERT_PAIR:   // unimplemented -> there are no walkers for it
237        assert(FALSE);
238    default:
239        return (FALSE);
240    }
241
242    if (!xdr_voidptr(xdrs, &objp->Reserved))
243        return (FALSE);
244    return (TRUE);
245}
246
247bool_t xdr_CSSM_BASE_CERTS(XDR *xdrs, CSSM_BASE_CERTS *objp)
248{
249    if (!xdr_CSSM_TP_HANDLE(xdrs, &objp->TPHandle))
250        return (FALSE);
251    if (!xdr_CSSM_CL_HANDLE(xdrs, &objp->CLHandle))
252        return (FALSE);
253    if (!xdr_CSSM_CERTGROUP(xdrs, &objp->Certs))
254        return (FALSE);
255    return (TRUE);
256}
257
258bool_t xdr_CSSM_ACCESS_CREDENTIALS(XDR *xdrs, CSSM_ACCESS_CREDENTIALS *objp)
259{
260    // XXX/cs this was for executing the callback but we're not doing that apparently void *cb = (void *)objp->Callback;
261
262    if (!xdr_CSSM_STRING(xdrs, objp->EntryTag))
263        return (FALSE);
264    if (!xdr_CSSM_BASE_CERTS(xdrs, &objp->BaseCerts))
265        return (FALSE);
266    if (!xdr_CSSM_SAMPLEGROUP(xdrs, &objp->Samples))
267        return (FALSE);
268    // @@@ treating both Callback and CallerCtx like intptr_t
269    //     in case it ever turns into a magic cookie
270    if (!xdr_voidptr(xdrs, (void *)&objp->Callback))
271        return (FALSE);
272    if (!xdr_voidptr(xdrs, &objp->CallerCtx))
273        return (FALSE);
274
275    return (TRUE);
276}
277
278bool_t xdr_CSSM_ACCESS_CREDENTIALS_PTR(XDR *xdrs, CSSM_ACCESS_CREDENTIALS_PTR *objp)
279{
280    return sec_xdr_reference(xdrs, (uint8_t **)objp, sizeof(CSSM_ACCESS_CREDENTIALS), (xdrproc_t)xdr_CSSM_ACCESS_CREDENTIALS);
281}
282
283bool_t xdr_CSSM_AUTHORIZATIONGROUP(XDR *xdrs, CSSM_AUTHORIZATIONGROUP *objp)
284{
285    assert(sizeof(objp->NumberOfAuthTags) == sizeof(int));
286    if (!sec_xdr_array(xdrs, (uint8_t **)&objp->AuthTags, (u_int *)&objp->NumberOfAuthTags, ~0, sizeof(CSSM_ACL_AUTHORIZATION_TAG), (xdrproc_t)xdr_CSSM_ACL_AUTHORIZATION_TAG))
287        return (FALSE);
288    return (TRUE);
289}
290
291bool_t xdr_CSSM_ACL_VALIDITY_PERIOD(XDR *xdrs, CSSM_ACL_VALIDITY_PERIOD *objp)
292{
293    if (!xdr_CSSM_DATA(xdrs, &objp->StartDate))
294        return (FALSE);
295    if (!xdr_CSSM_DATA(xdrs, &objp->EndDate))
296        return (FALSE);
297    return (TRUE);
298}
299
300bool_t xdr_CSSM_ACL_ENTRY_PROTOTYPE(XDR *xdrs, CSSM_ACL_ENTRY_PROTOTYPE *objp)
301{
302    if (!xdr_CSSM_LIST(xdrs, &objp->TypedSubject))
303        return (FALSE);
304    //	if (!xdr_CSSM_BOOL(xdrs, &objp->Delegate))
305    //		return (FALSE);
306    if (!xdr_CSSM_AUTHORIZATIONGROUP(xdrs, &objp->Authorization))
307        return (FALSE);
308    // XXX/cs enable once securityd stops leaving garbage in here
309    //	if (!xdr_CSSM_ACL_VALIDITY_PERIOD(xdrs, &objp->TimeRange))
310    //		return (FALSE);
311    if (!xdr_CSSM_STRING(xdrs, objp->EntryTag))
312        return (FALSE);
313    return (TRUE);
314}
315
316bool_t xdr_CSSM_ACL_ENTRY_PROTOTYPE_PTR(XDR *xdrs, CSSM_ACL_ENTRY_PROTOTYPE_PTR *objp)
317{
318    return sec_xdr_reference(xdrs, (uint8_t **)objp, sizeof(CSSM_ACL_ENTRY_PROTOTYPE), (xdrproc_t)xdr_CSSM_ACL_ENTRY_PROTOTYPE);
319}
320
321bool_t xdr_CSSM_ACL_OWNER_PROTOTYPE(XDR *xdrs, CSSM_ACL_OWNER_PROTOTYPE *objp)
322{
323    if (!xdr_CSSM_LIST(xdrs, &objp->TypedSubject))
324        return (FALSE);
325    if (!xdr_CSSM_BOOL(xdrs, &objp->Delegate))
326        return (FALSE);
327    return (TRUE);
328}
329
330bool_t xdr_CSSM_ACL_OWNER_PROTOTYPE_PTR(XDR *xdrs, CSSM_ACL_OWNER_PROTOTYPE_PTR *objp)
331{
332    return sec_xdr_reference(xdrs, (uint8_t **)objp,sizeof(CSSM_ACL_OWNER_PROTOTYPE), (xdrproc_t)xdr_CSSM_ACL_OWNER_PROTOTYPE);
333}
334
335bool_t xdr_CSSM_ACL_ENTRY_INPUT(XDR *xdrs, CSSM_ACL_ENTRY_INPUT *objp)
336{
337    if (!xdr_CSSM_ACL_ENTRY_PROTOTYPE(xdrs, &objp->Prototype))
338        return (FALSE);
339    // XXX/cs not currently using this
340    // @@@ treating both Callback and CallerCtx like intptr_t
341    //     in case it ever turns into a magic cookie
342    //	if (!xdr_voidptr(xdrs, &cb))
343    //		return (FALSE);
344    //	if (!xdr_voidptr(xdrs, &objp->CallerContext))
345    //		return (FALSE);
346    return (TRUE);
347}
348
349bool_t xdr_CSSM_ACL_ENTRY_INPUT_PTR(XDR *xdrs, CSSM_ACL_ENTRY_INPUT_PTR *objp)
350{
351    return sec_xdr_reference(xdrs, (uint8_t **)objp,sizeof(CSSM_ACL_ENTRY_INPUT), (xdrproc_t)xdr_CSSM_ACL_ENTRY_INPUT);
352}
353
354bool_t xdr_CSSM_ACL_ENTRY_INFO(XDR *xdrs, CSSM_ACL_ENTRY_INFO *objp)
355{
356
357    if (!xdr_CSSM_ACL_ENTRY_PROTOTYPE(xdrs, &objp->EntryPublicInfo))
358        return (FALSE);
359    if (!xdr_CSSM_ACL_HANDLE(xdrs, &objp->EntryHandle))
360        return (FALSE);
361    return (TRUE);
362}
363
364bool_t xdr_CSSM_ACL_ENTRY_INFO_ARRAY(XDR *xdrs, CSSM_ACL_ENTRY_INFO_ARRAY *objp)
365{
366    return sec_xdr_array(xdrs, (uint8_t **)&objp->acls, (u_int *)&objp->count, ~0, sizeof(CSSM_ACL_ENTRY_INFO), (xdrproc_t)xdr_CSSM_ACL_ENTRY_INFO);
367}
368
369bool_t xdr_CSSM_ACL_ENTRY_INFO_ARRAY_PTR(XDR *xdrs, CSSM_ACL_ENTRY_INFO_ARRAY_PTR *objp)
370{
371    return sec_xdr_reference(xdrs, (uint8_t **)objp, sizeof(CSSM_ACL_ENTRY_INFO_ARRAY), (xdrproc_t)xdr_CSSM_ACL_ENTRY_INFO_ARRAY);
372}
373
374
375bool_t xdr_CSSM_DATE(XDR *xdrs, CSSM_DATE *objp)
376{
377    return xdr_opaque(xdrs, (char *)objp, sizeof(CSSM_DATE));
378}
379
380bool_t xdr_CSSM_RANGE(XDR *xdrs, CSSM_RANGE *objp)
381{
382
383    if (!xdr_uint32(xdrs, &objp->Min))
384        return (FALSE);
385    if (!xdr_uint32(xdrs, &objp->Max))
386        return (FALSE);
387    return (TRUE);
388}
389
390bool_t xdr_CSSM_KEYHEADER(XDR *xdrs, CSSM_KEYHEADER *objp)
391{
392
393    if (!xdr_CSSM_HEADERVERSION(xdrs, &objp->HeaderVersion))
394        return (FALSE);
395    if (!xdr_CSSM_GUID(xdrs, &objp->CspId))
396        return (FALSE);
397    if (!xdr_CSSM_KEYBLOB_TYPE(xdrs, &objp->BlobType))
398        return (FALSE);
399    if (!xdr_CSSM_KEYBLOB_FORMAT(xdrs, &objp->Format))
400        return (FALSE);
401    if (!xdr_CSSM_ALGORITHMS(xdrs, &objp->AlgorithmId))
402        return (FALSE);
403    if (!xdr_CSSM_KEYCLASS(xdrs, &objp->KeyClass))
404        return (FALSE);
405    if (!xdr_uint32(xdrs, &objp->LogicalKeySizeInBits))
406        return (FALSE);
407    if (!xdr_CSSM_KEYATTR_FLAGS(xdrs, &objp->KeyAttr))
408        return (FALSE);
409    if (!xdr_CSSM_KEYUSE(xdrs, &objp->KeyUsage))
410        return (FALSE);
411    if (!xdr_CSSM_DATE(xdrs, &objp->StartDate))
412        return (FALSE);
413    if (!xdr_CSSM_DATE(xdrs, &objp->EndDate))
414        return (FALSE);
415    if (!xdr_CSSM_ALGORITHMS(xdrs, &objp->WrapAlgorithmId))
416        return (FALSE);
417    if (!xdr_CSSM_ENCRYPT_MODE(xdrs, &objp->WrapMode))
418        return (FALSE);
419    if (!xdr_uint32(xdrs, &objp->Reserved))
420        return (FALSE);
421    return (TRUE);
422}
423
424bool_t xdr_CSSM_KEYHEADER_PTR(XDR *xdrs, CSSM_KEYHEADER_PTR *objp)
425{
426    return sec_xdr_reference(xdrs, (uint8_t **)objp, sizeof(CSSM_KEYHEADER), (xdrproc_t)xdr_CSSM_KEYHEADER);
427}
428
429bool_t xdr_CSSM_KEY(XDR *xdrs, CSSM_KEY *objp)
430{
431    if (!xdr_CSSM_KEYHEADER(xdrs, &objp->KeyHeader))
432        return (FALSE);
433    if (!xdr_CSSM_DATA(xdrs, &objp->KeyData))
434        return (FALSE);
435    return (TRUE);
436}
437
438bool_t xdr_CSSM_KEY_PTR(XDR *xdrs, CSSM_KEY_PTR *objp)
439{
440    if (!sec_xdr_reference(xdrs, (uint8_t **)objp, sizeof(CSSM_KEY), (xdrproc_t)xdr_CSSM_KEY))
441        return (FALSE);
442    return (TRUE);
443}
444
445// CSSM_DATA passed through in the following calls: findFirst, findNext and
446// findRecordHandle actually contains a CSSM_KEY if the item is a key.
447// Since a key has byte order sensitive bits it needs to be encoded.
448// At this level we can only guess based on the length of the CSSM_DATA passed in
449// during encode, whether it's a CSSM_KEY, so we're currently letting securityd
450// call xdr_CSSM_KEY_IN_DATA or xdr_CSSM_NO_KEY_IN_DATA to let us know.
451bool_t xdr_CSSM_POSSIBLY_KEY_IN_DATA_WITH_BOOL(XDR *xdrs, CSSM_DATA *objp, bool_t in_iskey)
452{
453    bool_t size_alloc = sec_xdr_arena_size_allocator(xdrs);
454    bool_t is_key = FALSE; /* shut compiler up */
455    if (xdrs->x_op == XDR_ENCODE)
456	is_key = (in_iskey && objp->Length == sizeof(CSSM_KEY));
457    if (!xdr_CSSM_BOOL(xdrs, &is_key))
458        return (FALSE);
459    if (is_key) {
460        if (!xdr_CSSM_KEY_PTR(xdrs, (CSSM_KEY_PTR*)&objp->Data))
461            return (FALSE);
462        if (!size_alloc && (xdrs->x_op == XDR_DECODE))
463            objp->Length = sizeof(CSSM_KEY);
464    } else {
465        if (!xdr_CSSM_DATA(xdrs, objp))
466            return (FALSE);
467    }
468    return (TRUE);
469}
470
471bool_t xdr_CSSM_POSSIBLY_KEY_IN_DATA(XDR *xdrs, CSSM_DATA *objp)
472{
473    return xdr_CSSM_POSSIBLY_KEY_IN_DATA_WITH_BOOL(xdrs, objp, FALSE);
474}
475
476bool_t xdr_CSSM_POSSIBLY_KEY_IN_DATA_PTR(XDR *xdrs, CSSM_DATA_PTR *objp)
477{
478    if (!sec_xdr_reference(xdrs, (uint8_t **)objp, sizeof(CSSM_DATA), (xdrproc_t)xdr_CSSM_POSSIBLY_KEY_IN_DATA))
479        return (FALSE);
480    return (TRUE);
481}
482
483bool_t xdr_CSSM_KEY_IN_DATA(XDR *xdrs, CSSM_DATA *objp)
484{
485    return xdr_CSSM_POSSIBLY_KEY_IN_DATA_WITH_BOOL(xdrs, objp, TRUE);
486}
487
488bool_t xdr_CSSM_NO_KEY_IN_DATA(XDR *xdrs, CSSM_DATA *objp)
489{
490    return xdr_CSSM_POSSIBLY_KEY_IN_DATA_WITH_BOOL(xdrs, objp, FALSE);
491}
492
493bool_t xdr_CSSM_DB_ATTRIBUTE_INFO(XDR *xdrs, CSSM_DB_ATTRIBUTE_INFO *objp)
494{
495    if (!xdr_CSSM_DB_ATTRIBUTE_NAME_FORMAT(xdrs, &objp->AttributeNameFormat))
496        return (FALSE);
497    switch (objp->AttributeNameFormat)
498    {
499    case CSSM_DB_ATTRIBUTE_NAME_AS_STRING:
500        if (!sec_xdr_charp(xdrs, &objp->Label.AttributeName, ~0))
501            return (FALSE);
502        break;
503    case CSSM_DB_ATTRIBUTE_NAME_AS_OID:
504        if (!xdr_CSSM_OID(xdrs, &objp->Label.AttributeOID))
505            return (FALSE);
506        break;
507    case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER: // @@@ apparently unused
508        if (!xdr_uint32(xdrs, &objp->Label.AttributeID))
509            return (FALSE);
510        break;
511    default:
512        return (FALSE);
513    }
514    if (!xdr_CSSM_DB_ATTRIBUTE_FORMAT(xdrs, &objp->AttributeFormat))
515        return (FALSE);
516    return (TRUE);
517}
518
519static
520bool_t xdr_CSSM_DATA_FLIPPED(XDR *xdrs, CSSM_DATA *objp)
521{
522	bool_t size_alloc = sec_xdr_arena_size_allocator(xdrs);
523    if ((xdrs->x_op == XDR_ENCODE) && !size_alloc) {
524        switch (objp->Length) {
525        case sizeof(uint32_t): *(uint32_t*)objp->Data = htonl(*(uint32_t*)objp->Data); break;
526        case sizeof(uint64_t): *(uint64_t*)objp->Data = OSSwapHostToBigInt64(*(uint64_t*)objp->Data); break;
527		case sizeof(uint8_t): break;
528        default: assert(FALSE); break;
529        }
530    }
531    if (!xdr_CSSM_DATA(xdrs, objp))
532        return (FALSE);
533    if ((xdrs->x_op == XDR_DECODE) && !size_alloc) {
534        switch (objp->Length) {
535        case sizeof(uint32_t): *(uint32_t*)objp->Data = ntohl(*(uint32_t*)objp->Data); break;
536        case sizeof(uint64_t): *(uint64_t*)objp->Data = OSSwapBigToHostInt64(*(uint64_t*)objp->Data); break;
537		case sizeof(uint8_t): break;
538        default: assert(FALSE); break;
539        }
540    }
541    return (TRUE);
542}
543
544bool_t xdr_CSSM_DB_ATTRIBUTE_DATA(XDR *xdrs, CSSM_DB_ATTRIBUTE_DATA *objp)
545{
546    if (!xdr_CSSM_DB_ATTRIBUTE_INFO(xdrs, &objp->Info))
547        return (FALSE);
548    assert(sizeof(objp->NumberOfValues) == sizeof(int));
549    CSSM_DB_ATTRIBUTE_FORMAT format = objp->Info.AttributeFormat;
550    xdrproc_t proc = (xdrproc_t)xdr_CSSM_DATA; // fallback
551    switch(format) {
552    case CSSM_DB_ATTRIBUTE_FORMAT_STRING:
553    case CSSM_DB_ATTRIBUTE_FORMAT_BLOB:
554    case CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE: // all byte strings
555        break;
556    case CSSM_DB_ATTRIBUTE_FORMAT_UINT32:
557    case CSSM_DB_ATTRIBUTE_FORMAT_SINT32:
558    case CSSM_DB_ATTRIBUTE_FORMAT_REAL:
559        proc = (xdrproc_t)xdr_CSSM_DATA_FLIPPED;
560        break;
561		/* XXX/cs unhandled:
562			Note that in case of values being passed from CopyIn, it will be normal
563			for the format to be set to CSSM_DB_ATTRIBUTE_FORMAT_COMPLEX, as that
564			is the "not-yet-filled-in" value in the CssmDbAttributeInfo constructor
565			(see Record::addAttributes for where this is called).
566		 */
567	case CSSM_DB_ATTRIBUTE_FORMAT_BIG_NUM:
568	case CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32:
569	case CSSM_DB_ATTRIBUTE_FORMAT_COMPLEX:
570		assert(objp->NumberOfValues == 0);
571		break;
572	default:
573        assert(FALSE);
574    }
575    if (!sec_xdr_array(xdrs, (uint8_t **)&objp->Value, (u_int *)&objp->NumberOfValues, ~0, sizeof(CSSM_DATA), proc))
576        return (FALSE);
577    return (TRUE);
578}
579
580bool_t xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA(XDR *xdrs, CSSM_DB_RECORD_ATTRIBUTE_DATA *objp)
581{
582    if (!xdr_CSSM_DB_RECORDTYPE(xdrs, &objp->DataRecordType))
583        return (FALSE);
584    if (!xdr_uint32(xdrs, &objp->SemanticInformation))
585        return (FALSE);
586    assert(sizeof(objp->NumberOfAttributes) == sizeof(int));
587    if (!sec_xdr_array(xdrs, (uint8_t **)&objp->AttributeData, (u_int *)&objp->NumberOfAttributes, ~0, sizeof(CSSM_DB_ATTRIBUTE_DATA), (xdrproc_t)xdr_CSSM_DB_ATTRIBUTE_DATA))
588        return (FALSE);
589    return (TRUE);
590}
591
592bool_t xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR(XDR *xdrs, CSSM_DB_RECORD_ATTRIBUTE_DATA_PTR *objp)
593{
594    return sec_xdr_reference(xdrs, (uint8_t **)objp, sizeof(CSSM_DB_RECORD_ATTRIBUTE_DATA), (xdrproc_t)xdr_CSSM_DB_RECORD_ATTRIBUTE_DATA);
595}
596
597bool_t xdr_CSSM_SELECTION_PREDICATE(XDR *xdrs, CSSM_SELECTION_PREDICATE *objp)
598{
599
600    if (!xdr_CSSM_DB_OPERATOR(xdrs, &objp->DbOperator))
601        return (FALSE);
602    if (!xdr_CSSM_DB_ATTRIBUTE_DATA(xdrs, &objp->Attribute))
603        return (FALSE);
604    return (TRUE);
605}
606
607bool_t xdr_CSSM_QUERY_LIMITS(XDR *xdrs, CSSM_QUERY_LIMITS *objp)
608{
609
610    if (!xdr_uint32(xdrs, &objp->TimeLimit))
611        return (FALSE);
612    if (!xdr_uint32(xdrs, &objp->SizeLimit))
613        return (FALSE);
614    return (TRUE);
615}
616
617bool_t xdr_CSSM_QUERY(XDR *xdrs, CSSM_QUERY *objp)
618{
619
620    if (!xdr_CSSM_DB_RECORDTYPE(xdrs, &objp->RecordType))
621        return (FALSE);
622    if (!xdr_CSSM_DB_CONJUNCTIVE(xdrs, &objp->Conjunctive))
623        return (FALSE);
624    assert(sizeof(objp->NumSelectionPredicates) == sizeof(int));
625    if (!sec_xdr_array(xdrs, (uint8_t **)&objp->SelectionPredicate, (u_int *)&objp->NumSelectionPredicates, ~0, sizeof(CSSM_SELECTION_PREDICATE), (xdrproc_t)xdr_CSSM_SELECTION_PREDICATE))
626        return (FALSE);
627    if (!xdr_CSSM_QUERY_LIMITS(xdrs, &objp->QueryLimits))
628        return (FALSE);
629    if (!xdr_CSSM_QUERY_FLAGS(xdrs, &objp->QueryFlags))
630        return (FALSE);
631    return (TRUE);
632}
633
634bool_t xdr_CSSM_QUERY_PTR(XDR *xdrs, CSSM_QUERY_PTR *objp)
635{
636    return sec_xdr_reference(xdrs, (uint8_t **)objp, sizeof(CSSM_QUERY), (xdrproc_t)xdr_CSSM_QUERY);
637}
638
639bool_t xdr_CSSM_CONTEXT_ATTRIBUTE(XDR *xdrs, CSSM_CONTEXT_ATTRIBUTE *objp)
640{
641    if (!xdr_CSSM_ATTRIBUTE_TYPE(xdrs, &objp->AttributeType))
642        return (FALSE);
643    // @@@ original walkers skirt the issue: set to 0 on copyin, set to sizeof(attr) on copyout - all attrs do have internal size or null termination.
644    if (!xdr_uint32(xdrs, &objp->AttributeLength))
645        return (FALSE);
646    switch(objp->AttributeType & CSSM_ATTRIBUTE_TYPE_MASK)
647    {
648    case CSSM_ATTRIBUTE_DATA_CSSM_DATA:
649        if (!sec_xdr_reference(xdrs, (uint8_t **)&objp->Attribute.Data, sizeof(CSSM_DATA), (xdrproc_t)xdr_CSSM_DATA)) return (FALSE); break;
650    case CSSM_ATTRIBUTE_DATA_CRYPTO_DATA:
651        if (!sec_xdr_reference(xdrs, (uint8_t **)&objp->Attribute.CryptoData, sizeof(CSSM_CRYPTO_DATA), (xdrproc_t)xdr_CSSM_CRYPTO_DATA)) return (FALSE); break;
652    case CSSM_ATTRIBUTE_DATA_KEY:
653        if (!sec_xdr_reference(xdrs, (uint8_t **)&objp->Attribute.Key, sizeof(CSSM_KEY), (xdrproc_t)xdr_CSSM_KEY)) return (FALSE); break;
654    case CSSM_ATTRIBUTE_DATA_STRING:
655        if (!sec_xdr_charp(xdrs, &objp->Attribute.String, ~0)) return (FALSE); break;
656    case CSSM_ATTRIBUTE_DATA_DATE:
657        if (!sec_xdr_reference(xdrs, (uint8_t **)&objp->Attribute.Date, sizeof(CSSM_DATE), (xdrproc_t)xdr_CSSM_DATE)) return (FALSE); break;
658    case CSSM_ATTRIBUTE_DATA_RANGE:
659        if (!sec_xdr_reference(xdrs, (uint8_t **)&objp->Attribute.Range, sizeof(CSSM_RANGE), (xdrproc_t)xdr_CSSM_RANGE)) return (FALSE); break;
660    case CSSM_ATTRIBUTE_DATA_ACCESS_CREDENTIALS:
661        if (!sec_xdr_reference(xdrs, (uint8_t **)&objp->Attribute.AccessCredentials, sizeof(CSSM_ACCESS_CREDENTIALS), (xdrproc_t)xdr_CSSM_ACCESS_CREDENTIALS)) return (FALSE); break;
662    case CSSM_ATTRIBUTE_DATA_VERSION:
663        if (!sec_xdr_reference(xdrs, (uint8_t **)&objp->Attribute.Version, sizeof(CSSM_VERSION), (xdrproc_t)xdr_CSSM_VERSION)) return (FALSE); break;
664    case CSSM_ATTRIBUTE_DATA_DL_DB_HANDLE:
665        if (!sec_xdr_reference(xdrs, (uint8_t **)&objp->Attribute.DLDBHandle, sizeof(CSSM_DL_DB_HANDLE), (xdrproc_t)xdr_CSSM_DL_DB_HANDLE)) return (FALSE); break;
666    case CSSM_ATTRIBUTE_NONE:
667        break;
668    case CSSM_ATTRIBUTE_DATA_UINT32:
669        if (!xdr_uint32(xdrs, &objp->Attribute.Uint32))
670            return (FALSE);
671        break;
672    default:
673        return (FALSE);
674    }
675
676    return (TRUE);
677}
678
679bool_t xdr_CSSM_CONTEXT(XDR *xdrs, CSSM_CONTEXT *objp)
680{
681    if (!xdr_CSSM_CONTEXT_TYPE(xdrs, &objp->ContextType))
682        return (FALSE);
683    if (!xdr_CSSM_ALGORITHMS(xdrs, &objp->AlgorithmType))
684        return (FALSE);
685    if (!sec_xdr_array(xdrs, (uint8_t **)&objp->ContextAttributes, (u_int *)&objp->NumberOfAttributes, ~0, sizeof(CSSM_CONTEXT_ATTRIBUTE), (xdrproc_t)xdr_CSSM_CONTEXT_ATTRIBUTE))
686        return (FALSE);
687    if (!xdr_CSSM_CSP_HANDLE(xdrs, &objp->CSPHandle))
688        return (FALSE);
689    if (!xdr_CSSM_BOOL(xdrs, &objp->Privileged))
690        return (FALSE);
691    if (!xdr_uint32(xdrs, &objp->EncryptionProhibited))
692        return (FALSE);
693    if (!xdr_uint32(xdrs, &objp->WorkFactor))
694        return (FALSE);
695    if (!xdr_uint32(xdrs, &objp->Reserved))
696        return (FALSE);
697    return (TRUE);
698}
699
700bool_t xdr_CSSM_CONTEXT_PTR(XDR *xdrs, CSSM_CONTEXT_PTR *objp)
701{
702    return sec_xdr_reference(xdrs, (uint8_t **)objp, sizeof(CSSM_CONTEXT), (xdrproc_t)xdr_CSSM_CONTEXT);
703}
704
705// this is possibly not actually used in favor of the flatidentifier
706bool_t xdr_CSSM_DL_DB_HANDLE(XDR *xdrs, CSSM_DL_DB_HANDLE *objp)
707{
708    if (!xdr_CSSM_DL_HANDLE(xdrs, &objp->DLHandle))
709        return (FALSE);
710    if (!xdr_CSSM_DB_HANDLE(xdrs, &objp->DBHandle))
711        return (FALSE);
712    return (TRUE);
713}
714
715bool_t xdr_CSSM_PKCS5_PBKDF2_PARAMS(XDR *xdrs, CSSM_PKCS5_PBKDF2_PARAMS *objp)
716{
717    if (!xdr_CSSM_DATA(xdrs, &objp->Passphrase))
718        return (FALSE);
719    if (!xdr_CSSM_PKCS5_PBKDF2_PRF(xdrs, &objp->PseudoRandomFunction))
720        return (FALSE);
721    return (TRUE);
722}
723
724bool_t xdr_CSSM_DERIVE_DATA(XDR *xdrs, CSSM_DERIVE_DATA *objp)
725{
726    if (!xdr_CSSM_ALGORITHMS(xdrs,&objp->algorithm))
727        return (FALSE);
728    switch (objp->algorithm) {
729    case CSSM_ALGID_PKCS5_PBKDF2:
730        if ((xdrs->x_op == XDR_ENCODE) &&
731                (!objp->baseData.Data) &&
732                (objp->baseData.Length != sizeof(CSSM_PKCS5_PBKDF2_PARAMS)))
733            return (FALSE); //CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS);
734        if (!sec_xdr_reference(xdrs, &(objp->baseData.Data), sizeof(CSSM_PKCS5_PBKDF2_PARAMS), (xdrproc_t)xdr_CSSM_PKCS5_PBKDF2_PARAMS))
735            return (FALSE);
736        objp->baseData.Length = sizeof(CSSM_PKCS5_PBKDF2_PARAMS);
737        break;
738    default:
739        if (!xdr_CSSM_DATA(xdrs, &objp->baseData))
740            return (FALSE);
741        break;
742    }
743    return (TRUE);
744}
745
746bool_t xdr_CSSM_DERIVE_DATA_PTR(XDR *xdrs, CSSM_DERIVE_DATA **objp)
747{
748    return sec_xdr_reference(xdrs, (uint8_t **)objp, sizeof(CSSM_DERIVE_DATA), (xdrproc_t)xdr_CSSM_DERIVE_DATA);
749}
750
751bool_t xdr_CSSM_ACL_OWNER_PROTOTYPE_ARRAY(XDR *xdrs, CSSM_ACL_OWNER_PROTOTYPE_ARRAY *objp)
752{
753    if (!sec_xdr_array(xdrs, (uint8_t **)&objp->acls, (u_int *)&objp->count, ~0, sizeof(CSSM_ACL_OWNER_PROTOTYPE), (xdrproc_t)xdr_CSSM_ACL_OWNER_PROTOTYPE))
754        return (FALSE);
755    return (TRUE);
756}
757
758
759#if 0 /* unimplemented in current stack */
760
761bool_t xdr_CSSM_FIELD(XDR *xdrs, CSSM_FIELD *objp)
762{
763
764    if (!xdr_CSSM_OID(xdrs, &objp->FieldOid))
765        return (FALSE);
766    if (!xdr_CSSM_DATA(xdrs, &objp->FieldValue))
767        return (FALSE);
768    return (TRUE);
769}
770
771bool_t xdr_CSSM_FIELDGROUP(XDR *xdrs, CSSM_FIELDGROUP *objp)
772{
773    assert(sizeof(objp->NumberOfFields) == sizeof(int));
774    if (!sec_xdr_array(xdrs, (uint8_t**)&objp->Fields, (u_int *)&objp->NumberOfFields, ~0, sizeof(CSSM_FIELD), (xdrproc_t)xdr_CSSM_FIELD))
775        return (FALSE);
776    return (TRUE);
777}
778
779bool_t xdr_CSSM_TUPLE(XDR *xdrs, CSSM_TUPLE *objp)
780{
781    if (!xdr_CSSM_LIST(xdrs, &objp->Issuer))
782        return (FALSE);
783    if (!xdr_CSSM_LIST(xdrs, &objp->Subject))
784        return (FALSE);
785    if (!xdr_CSSM_BOOL(xdrs, &objp->Delegate))
786        return (FALSE);
787    if (!xdr_CSSM_LIST(xdrs, &objp->AuthorizationTag))
788        return (FALSE);
789    if (!xdr_CSSM_LIST(xdrs, &objp->ValidityPeriod))
790        return (FALSE);
791    return (TRUE);
792}
793
794bool_t xdr_CSSM_PARSED_CERT(XDR *xdrs, CSSM_PARSED_CERT *objp)
795{
796    if (!xdr_CSSM_CERT_TYPE(xdrs, &objp->CertType))
797        return (FALSE);
798    switch (objp->ParsedCertFormat)
799    {
800    case CSSM_CERT_PARSE_FORMAT_NONE:
801    case CSSM_CERT_PARSE_FORMAT_CUSTOM:		/* void* */
802        /* XXX/gh  SOL? */
803        break;
804    case CSSM_CERT_PARSE_FORMAT_SEXPR:
805        if (!xdr_CSSM_LIST(xdrs, (CSSM_LIST *)objp->ParsedCert))
806            return (FALSE);
807        break;
808    case CSSM_CERT_PARSE_FORMAT_COMPLEX:	/* void* */
809        /* XXX/gh  SOL? */
810        break;
811    case CSSM_CERT_PARSE_FORMAT_OID_NAMED:
812        if (!xdr_CSSM_FIELDGROUP(xdrs, (CSSM_FIELDGROUP *)objp->ParsedCert))
813            return (FALSE);
814        break;
815    case CSSM_CERT_PARSE_FORMAT_TUPLE:
816        if (!xdr_CSSM_TUPLE(xdrs, (CSSM_TUPLE *)objp->ParsedCert))
817            return (FALSE);
818        break;
819    case CSSM_CERT_PARSE_FORMAT_MULTIPLE:
820        /* multiple forms; each cert carries a parse format indicator */
821        /* XXX/gh  ??? */
822        break;
823    case CSSM_CERT_PARSE_FORMAT_LAST:
824        /* XXX/gh  ??? */
825        break;
826    case CSSM_CL_CUSTOM_CERT_PARSE_FORMAT:
827        /* XXX/gh  ??? */
828        break;
829    default:
830        return (FALSE);
831    }
832    return (TRUE);
833}
834
835bool_t xdr_CSSM_CERT_PAIR(XDR *xdrs, CSSM_CERT_PAIR *objp)
836{
837
838    if (!xdr_CSSM_ENCODED_CERT(xdrs, &objp->EncodedCert))
839        return (FALSE);
840    if (!xdr_CSSM_PARSED_CERT(xdrs, &objp->ParsedCert))
841        return (FALSE);
842    return (TRUE);
843}
844
845#endif /* unimplemented in current stack */
846
847