1/*
2 * Copyright (c) 2005-2011 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 * DER_Decode.h - DER decoding routines
26 */
27
28#ifndef	_DER_DECODE_H_
29#define _DER_DECODE_H_
30
31#ifdef __cplusplus
32extern "C" {
33#endif
34
35#include <libDER/libDER.h>
36#include <stdbool.h>
37
38/*
39 * Decoding one item consists of extracting its tag, a pointer
40 * to the actual content, and the length of the content. Those
41 * three are represented by a DERDecodedInfo.
42 */
43typedef struct {
44	DERTag		tag;
45	DERItem		content;
46} DERDecodedInfo;
47
48/*
49 * Basic decoding primitive. Only works with:
50 *
51 *  -- definite length encoding
52 *  -- one-byte tags
53 *  -- max content length fits in a DERSize
54 *
55 * No malloc or copy of the contents is performed; the returned
56 * content->content.data is a pointer into the incoming der data.
57 */
58DERReturn DERDecodeItem(
59	const DERItem	*der,			/* data to decode */
60	DERDecodedInfo	*decoded);		/* RETURNED */
61
62/*
63 * Given a BIT_STRING, in the form of its raw content bytes,
64 * obtain the number of unused bits and the raw bit string bytes.
65 */
66DERReturn DERParseBitString(
67	const DERItem	*contents,
68	DERItem			*bitStringBytes,	/* RETURNED */
69	DERByte			*numUnusedBits);	/* RETURNED */
70
71/*
72 * Given a BOOLEAN, in the form of its raw content bytes,
73 * obtain it's value.
74 */
75DERReturn DERParseBoolean(
76	const DERItem	*contents,
77	bool			defaultValue,
78	bool			*value);	/* RETURNED */
79
80DERReturn DERParseInteger(
81	const DERItem	*contents,
82	uint32_t        *value);	/* RETURNED */
83
84/*
85 * Sequence/set decode support.
86 */
87
88/* state representing a sequence or set being decoded */
89typedef struct {
90	DERByte	*nextItem;
91	DERByte	*end;
92} DERSequence;
93
94/*
95 * To decode a set or sequence, call DERDecodeSeqInit or
96 * DERDecodeSeqContentInit once, then call DERDecodeSeqNext to
97 * get each enclosed item.
98 *
99 * DERDecodeSeqNext returns DR_EndOfSequence when no more
100 * items are available.
101 */
102
103/*
104 * Use this to parse the top level sequence's tag and content length.
105 */
106DERReturn DERDecodeSeqInit(
107	const DERItem	*der,			/* data to decode */
108	DERTag			*tag,			/* RETURNED tag of sequence/set. This will be
109									 *    either ASN1_CONSTR_SEQUENCE or
110									 *    ASN1_CONSTR_SET. */
111	DERSequence		*derSeq);		/* RETURNED, to use in DERDecodeSeqNext */
112
113/*
114 * Use this to start in on decoding a sequence's content, when
115 * the top-level tag and content have already been decoded.
116 */
117DERReturn DERDecodeSeqContentInit(
118	const DERItem	*content,
119	DERSequence		*derSeq);		/* RETURNED, to use in DERDecodeSeqNext */
120
121/* obtain the next decoded item in a sequence or set */
122DERReturn DERDecodeSeqNext(
123	DERSequence		*derSeq,
124	DERDecodedInfo	*decoded);		/* RETURNED */
125
126/*
127 * High level sequence decode.
128 */
129
130/*
131 * Per-item decode options.
132 */
133
134/* Explicit default, no options */
135#define DER_DEC_NO_OPTS		0x0000
136
137/* This item optional, can be skipped during decode */
138#define DER_DEC_OPTIONAL	0x0001
139
140/* Skip the tag check; accept anything. */
141#define DER_DEC_ASN_ANY		0x0002
142
143/* Skip item, no write to DERDecodedInfo (but tag check still performed) */
144#define DER_DEC_SKIP		0x0004
145
146/* Save full DER encoding in DERDecodedInfo, including tag and length. Normally
147 * only the content is saved. */
148#define DER_DEC_SAVE_DER	0x0008
149
150/*
151 * High level sequence parse, starting with top-level tag and content.
152 * Top level tag must be ASN1_CONSTR_SEQUENCE - if it's not, and that's
153 * OK, use DERParseSequenceContent().
154 *
155 * These never return DR_EndOfSequence - if an *unexpected* end of sequence
156 * occurs, return DR_IncompleteSeq.
157 *
158 * Results of the decoding of one item are placed in a DERItem whose address
159 * is the dest arg plus the offset value in the associated DERItemSpec.
160 *
161 * Items which are optional (DER_DEC_OPTIONAL) and which are not found,
162 * leave their associated DERDecodedInfos unmodified.
163 *
164 * Processing of a sequence ends on detection of any error or after the
165 * last DERItemSpec is processed.
166 *
167 * The sizeToZero argument, if nonzero, indicates the number of bytes
168 * starting at dest to zero before processing the sequence. This is
169 * generally desirable, particularly if there are any DER_DEC_OPTIONAL
170 * items in the sequence; skipped optional items are detected by the
171 * caller via a NULL DERDecodedInfo.content.data; if this hasn't been
172 * explicitly zeroed (generally, by passing a nonzero value of sizeToZero),
173 * skipped items can't be detected.
174 */
175DERReturn DERParseSequence(
176	const DERItem			*der,
177	DERShort				numItems,		/* size of itemSpecs[] */
178	const DERItemSpec		*itemSpecs,
179	void					*dest,			/* DERDecodedInfo(s) here RETURNED */
180	DERSize					sizeToZero);	/* optional */
181
182/* high level sequence parse, starting with sequence's content */
183DERReturn DERParseSequenceContent(
184	const DERItem			*content,
185	DERShort				numItems,		/* size of itemSpecs[] */
186	const DERItemSpec		*itemSpecs,
187	void					*dest,			/* DERDecodedInfo(s) here RETURNED */
188	DERSize					sizeToZero);	/* optional */
189
190#ifdef __cplusplus
191}
192#endif
193
194#endif	/* _DER_DECODE_H_ */
195
196