1/*
2 * Copyright (c) 2000-2004,2006,2011,2014 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
25//
26// cssmwalkers - walkers for standard CSSM datatypes and wrappers
27//
28#ifndef _H_CSSMWALKERS
29#define _H_CSSMWALKERS
30
31#include <security_cdsa_utilities/walkers.h>
32#include <security_cdsa_utilities/cssmdata.h>
33#include <security_cdsa_utilities/cssmpods.h>
34#include <security_cdsa_utilities/cssmkey.h>
35
36
37
38namespace Security {
39namespace DataWalkers {
40
41
42//
43// There are lots of CSSM data structures that are variable-length records
44// of the form { count, pointer-to-array }. If you have a regular PodWrapper
45// for it, we can enumerate the array for you right here. Minimum requirement:
46//		size_t size() const;
47//		Element &operator [] (uint32 index);
48//      // and some Element *&foo() that returns a reference-to-array-pointer
49// and a reference walker for the element type (as returned by operator []).
50//
51template <class Action, class Record, class Element>
52void enumerateArray(Action &operate, Record &record, Element *& (Record::*pointer)())
53{
54	if (record.size()) {
55		Element *&root = (record.*pointer)();
56		operate.blob(root, record.size() * sizeof(Element));
57		for (uint32 ix = 0; ix < record.size(); ++ix)
58			walk(operate, record[ix]);
59	}
60}
61
62
63//
64// The full set of walkers for CssmData in all its forms.
65//
66template <class Action>
67void walk(Action &operate, CssmData &data)
68{
69	operate(data);
70	operate.blob(data.Data, data.Length);
71}
72
73template <class Action>
74CssmData *walk(Action &operate, CssmData * &data)
75{
76	operate(data);
77	operate.blob(data->Data, data->Length);
78	return data;
79}
80
81template <class Action>
82void walk(Action &operate, CSSM_DATA &data)
83{ walk(operate, CssmData::overlay(data)); }
84
85template <class Action>
86CSSM_DATA *walk(Action &operate, CSSM_DATA * &data)
87{ return walk(operate, CssmData::overlayVar(data)); }
88
89
90
91//
92// Walking a C string is almost regular (the size comes from strlen()).
93// Just make sure you honor the needsSize preference of the operator.
94//
95template <class Action>
96char *walk(Action &operate, char * &s)
97{
98	if (s)
99		operate(s, operate.needsSize ? (strlen(s) + 1) : 0);
100	return s;
101}
102
103
104//
105// Flattener functions for common CSSM data types that have internal structure.
106//
107template <class Action>
108CssmKey *walk(Action &operate, CssmKey * &key)
109{
110	operate(key);
111	walk(operate, key->keyData());
112	return key;
113}
114
115template <class Action>
116CSSM_KEY *walk(Action &operate, CSSM_KEY * &data)
117{ return walk(operate, CssmKey::overlayVar(data)); }
118
119template <class Action>
120CssmCryptoData *walk(Action &operate, CssmCryptoData * &data)
121{
122	operate(data);
123	walk(operate, data->param());
124	return data;
125}
126
127template <class Action>
128CSSM_CRYPTO_DATA *walk(Action &operate, CSSM_CRYPTO_DATA * &data)
129{ return walk(operate, CssmCryptoData::overlayVar(data)); }
130
131template <class Action>
132void walk(Action &operate, CSSM_PKCS5_PBKDF2_PARAMS &data)
133{
134    operate(data);
135    walk(operate, data.Passphrase);
136}
137
138//
139// Walkers for flat datatypes
140//
141template <class Action>
142CSSM_DATE_PTR walk(Action &operate, CSSM_DATE_PTR &date)
143{
144    operate(date);
145	return date;
146}
147
148template <class Action>
149CSSM_RANGE_PTR walk(Action &operate, CSSM_RANGE_PTR &range)
150{
151    operate(range);
152	return range;
153}
154
155template <class Action>
156CSSM_VERSION_PTR walk(Action &operate, CSSM_VERSION_PTR &version)
157{
158    operate(version);
159	return version;
160}
161
162template <class Action>
163CSSM_DL_DB_HANDLE_PTR walk(Action &operate, CSSM_DL_DB_HANDLE_PTR &dlDbHandle)
164{
165    operate(dlDbHandle);
166	return dlDbHandle;
167}
168
169template <class Action>
170CssmSubserviceUid *walk(Action &operate, CssmSubserviceUid * &ssUid)
171{
172    operate(ssUid);
173	return ssUid;
174}
175
176
177//
178// A synthetic variant of CssmData to model key derivation (input) parameters,
179// which have algorithm dependent structure. This is not likely to be useful
180// for anything else; but here's the common ancestor of all its users.
181//
182class CssmDeriveData {
183public:
184	CssmDeriveData(const CssmData &dat, CSSM_ALGORITHMS alg)
185		: baseData(dat), algorithm(alg) { }
186
187	CssmData baseData;
188	CSSM_ALGORITHMS algorithm;
189
190	template <class Action>
191	void enumerate(Action &operate)
192	{
193		walk(operate, baseData);
194		switch (algorithm) {
195		case CSSM_ALGID_PKCS5_PBKDF2:
196#if BUG_3762664
197			walk(operate, *baseData.interpretedAs<CSSM_PKCS5_PBKDF2_PARAMS>
198				(CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS));
199#else
200			if (baseData.length() != sizeof(CSSM_PKCS5_PBKDF2_PARAMS))
201				CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS);
202			walk(operate, *(CSSM_PKCS5_PBKDF2_PARAMS *)baseData.data());
203#endif
204			break;
205		default:
206			break;
207		}
208	}
209};
210
211
212template <class Action>
213void walk(Action &operate, CssmDeriveData &data)
214{
215	operate(data);
216	data.enumerate(operate);
217}
218
219template <class Action>
220CssmDeriveData *walk(Action &operate, CssmDeriveData * &data)
221{
222	operate(data);
223	if (data)
224		data->enumerate(operate);
225	return data;
226}
227
228
229
230} // end namespace DataWalkers
231} // end namespace Security
232
233#endif //_H_CSSMWALKERS
234