]> git.saurik.com Git - apple/security.git/blob - SecuritySNACCRuntime/c-lib/src/asn-octs.c
Security-54.1.tar.gz
[apple/security.git] / SecuritySNACCRuntime / c-lib / src / asn-octs.c
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 /*
20 * .../c-lib/src/asn-octs.c - BER encode, decode, print and free routines for the ASN.1 OCTET STRING type.
21 *
22 * MS 92
23 * Copyright (C) 1992 Michael Sample and the University of British Columbia
24 *
25 * This library is free software; you can redistribute it and/or
26 * modify it provided that this copyright/license information is retained
27 * in original form.
28 *
29 * If you modify this file, you must clearly indicate your changes.
30 *
31 * This source code is distributed in the hope that it will be
32 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
33 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
34 *
35 * $Header: /cvs/Darwin/Security/SecuritySNACCRuntime/c-lib/src/asn-octs.c,v 1.1.1.1 2001/05/18 23:14:08 mb Exp $
36 * $Log: asn-octs.c,v $
37 * Revision 1.1.1.1 2001/05/18 23:14:08 mb
38 * Move from private repository to open source repository
39 *
40 * Revision 1.2 2001/05/05 00:59:25 rmurphy
41 * Adding darwin license headers
42 *
43 * Revision 1.1.1.1 1999/03/16 18:06:31 aram
44 * Originals from SMIME Free Library.
45 *
46 * Revision 1.3 1995/07/27 09:00:32 rj
47 * use memcmpeq that is defined in .../snacc.h to use either memcmp or bcmp.
48 *
49 * changed `_' to `-' in file names.
50 *
51 * Revision 1.2 1994/09/01 00:06:15 rj
52 * reduce the risk of unwanted surprises with macro expansion by properly separating the C tokens.
53 *
54 * Revision 1.1 1994/08/28 09:45:58 rj
55 * first check-in. for a list of changes to the snacc-1.1 distribution please refer to the ChangeLog.
56 *
57 */
58
59 #include <ctype.h>
60
61 #include "asn-config.h"
62 #include "asn-len.h"
63 #include "asn-tag.h"
64 #include "str-stk.h"
65 #include "asn-bits.h" /* for TO_HEX macro */
66 #include "asn-octs.h"
67
68
69 /*
70 * encodes universal TAG LENGTH and Contents of and ASN.1 OCTET STRING
71 */
72 AsnLen
73 BEncAsnOcts PARAMS ((b, data),
74 BUF_TYPE b _AND_
75 AsnOcts *data)
76 {
77 AsnLen len;
78
79 len = BEncAsnOctsContent (b, data);
80 len += BEncDefLen (b, len);
81 len += BEncTag1 (b, UNIV, PRIM, OCTETSTRING_TAG_CODE);
82 return len;
83 } /* BEncAsnOcts */
84
85
86 /*
87 * decodes universal TAG LENGTH and Contents of and ASN.1 OCTET STRING
88 */
89 void
90 BDecAsnOcts PARAMS ((b, result, bytesDecoded, env),
91 BUF_TYPE b _AND_
92 AsnOcts *result _AND_
93 AsnLen *bytesDecoded _AND_
94 jmp_buf env)
95 {
96 AsnTag tag;
97 AsnLen elmtLen;
98
99 if (((tag = BDecTag (b, bytesDecoded, env)) != MAKE_TAG_ID (UNIV, PRIM, OCTETSTRING_TAG_CODE)) && (tag != MAKE_TAG_ID (UNIV, CONS, OCTETSTRING_TAG_CODE)))
100 {
101 Asn1Error ("BDecAsnOcts: ERROR - wrong tag on OCTET STRING.\n");
102 longjmp (env, -40);
103 }
104
105 elmtLen = BDecLen (b, bytesDecoded, env);
106 BDecAsnOctsContent (b, tag, elmtLen, result, bytesDecoded, env);
107
108 } /* BDecAsnOcts */
109
110 /*
111 * BER encodes just the content of an OCTET STRING.
112 */
113 AsnLen
114 BEncAsnOctsContent PARAMS ((b, o),
115 BUF_TYPE b _AND_
116 AsnOcts *o)
117 {
118 BufPutSegRvs (b, o->octs, o->octetLen);
119 return o->octetLen;
120 } /* BEncAsnOctsContent */
121
122
123
124 /*
125 * Used for decoding constructed OCTET STRING values into
126 * a contiguous local rep.
127 * fills string stack with references to the pieces of a
128 * construced octet string
129 */
130 static void
131 FillOctetStringStk PARAMS ((b, elmtLen0, bytesDecoded, env),
132 BUF_TYPE b _AND_
133 AsnLen elmtLen0 _AND_
134 AsnLen *bytesDecoded _AND_
135 jmp_buf env)
136 {
137 unsigned long int refdLen;
138 unsigned long int totalRefdLen;
139 char *strPtr;
140 unsigned long int totalElmtsLen1 = 0;
141 unsigned long int tagId1;
142 unsigned long int elmtLen1;
143
144 for (; (totalElmtsLen1 < elmtLen0) || (elmtLen0 == INDEFINITE_LEN); )
145 {
146 tagId1 = BDecTag (b, &totalElmtsLen1, env);
147
148 if ((tagId1 == EOC_TAG_ID) && (elmtLen0 == INDEFINITE_LEN))
149 {
150 BDEC_2ND_EOC_OCTET (b, &totalElmtsLen1, env);
151 break;
152 }
153
154 elmtLen1 = BDecLen (b, &totalElmtsLen1, env);
155 if (tagId1 == MAKE_TAG_ID (UNIV, PRIM, OCTETSTRING_TAG_CODE))
156 {
157 /*
158 * primitive part of string, put references to piece (s) in
159 * str stack
160 */
161 totalRefdLen = 0;
162 refdLen = elmtLen1;
163 while (1)
164 {
165 strPtr = BufGetSeg (b, &refdLen);
166
167 PUSH_STR (strPtr, refdLen, env);
168 totalRefdLen += refdLen;
169 if (totalRefdLen == elmtLen1)
170 break; /* exit this while loop */
171
172 if (refdLen == 0) /* end of data */
173 {
174 Asn1Error ("BDecConsOctetString: ERROR - attempt to decode past end of data\n");
175 longjmp (env, -18);
176 }
177 refdLen = elmtLen1 - totalRefdLen;
178 }
179 totalElmtsLen1 += elmtLen1;
180 }
181
182
183 else if (tagId1 == MAKE_TAG_ID (UNIV, CONS, OCTETSTRING_TAG_CODE))
184 {
185 /*
186 * constructed octets string embedding in this constructed
187 * octet string. decode it.
188 */
189 FillOctetStringStk (b, elmtLen1, &totalElmtsLen1, env);
190 }
191 else /* wrong tag */
192 {
193 Asn1Error ("BDecConsOctetString: ERROR - decoded non-OCTET STRING tag inside a constructed OCTET STRING\n");
194 longjmp (env, -19);
195 }
196 } /* end of for */
197
198 (*bytesDecoded) += totalElmtsLen1;
199
200 } /* FillOctetStringStk */
201
202
203 /*
204 * Decodes a seq of universally tagged octets strings until either EOC is
205 * encountered or the given len is decoded. Merges them into a single
206 * string. puts a NULL terminator on the string but does not include
207 * this in the length.
208 */
209 static void
210 BDecConsAsnOcts PARAMS ((b, len, result, bytesDecoded, env),
211 BUF_TYPE b _AND_
212 AsnLen len _AND_
213 AsnOcts *result _AND_
214 AsnLen *bytesDecoded _AND_
215 jmp_buf env)
216 {
217 char *bufCurr;
218 unsigned long int curr;
219
220 RESET_STR_STK();
221
222 /*
223 * decode each piece of the octet string, puting
224 * an entry in the octet string stack for each
225 */
226 FillOctetStringStk (b, len, bytesDecoded, env);
227
228 result->octetLen = strStkG.totalByteLen;
229
230 /* alloc str for all octs pieces with extra byte for null terminator */
231 bufCurr = result->octs = Asn1Alloc (strStkG.totalByteLen +1);
232
233 /* copy octet str pieces into single blk */
234 for (curr = 0; curr < strStkG.nextFreeElmt; curr++)
235 {
236 memcpy (bufCurr, strStkG.stk[curr].str, strStkG.stk[curr].len);
237 bufCurr += strStkG.stk[curr].len;
238 }
239
240 /* add null terminator - this is not included in the str's len */
241 *bufCurr = '\0';
242
243 } /* BDecConsAsnOcts */
244
245 /*
246 * Decodes the content of a BER OCTET STRING value
247 */
248 void
249 BDecAsnOctsContent PARAMS ((b, tagId, len, result, bytesDecoded, env),
250 BUF_TYPE b _AND_
251 AsnTag tagId _AND_
252 AsnLen len _AND_
253 AsnOcts *result _AND_
254 AsnLen *bytesDecoded _AND_
255 jmp_buf env)
256 {
257 /*
258 * tagId is encoded tag shifted into long int.
259 * if CONS bit is set then constructed octet string
260 */
261 if (TAG_IS_CONS (tagId))
262 BDecConsAsnOcts (b, len, result, bytesDecoded, env);
263
264 else /* primitive octet string */
265 {
266 result->octetLen = len;
267 result->octs = Asn1Alloc (len+1);
268 BufCopy (result->octs, b, len);
269
270 if (BufReadError (b))
271 {
272 Asn1Error ("BDecOctetString: ERROR - decoded past end of data\n");
273 longjmp (env, -20);
274 }
275
276 /* add null terminator - this is not included in the str's len */
277 result->octs[len] = '\0';
278 (*bytesDecoded) += len;
279 }
280 } /* BDecAsnOctsContent */
281
282
283 /*
284 * Frees the string part of the given OCTET STRING
285 */
286 void
287 FreeAsnOcts PARAMS ((v),
288 AsnOcts *v)
289 {
290 Asn1Free (v->octs);
291 } /* FreeAsnOcts */
292
293 /*
294 * Prints the given OCTET STRING value to the given FILE * in ASN.1
295 * Value Notation. Since the value notation uses the hard to read
296 * hex format, the ASCII version is included in an ASN.1 comment.
297 */
298 void
299 PrintAsnOcts PARAMS ((f,v, indent),
300 FILE *f _AND_
301 AsnOcts *v _AND_
302 unsigned short indent)
303 {
304 int i;
305
306 /* print hstring value */
307 fprintf (f,"'");
308
309 for (i = 0; i < v->octetLen; i++)
310 fprintf (f,"%c%c", TO_HEX (v->octs[i] >> 4), TO_HEX (v->octs[i]));
311
312 fprintf (f,"'H");
313
314 /* show printable chars in comment */
315 fprintf (f," -- \"");
316
317 for (i = 0; i < v->octetLen; i++)
318 {
319 if (isprint (v->octs[i]))
320 fprintf (f,"%c", v->octs[i]);
321 else
322 fprintf (f,".");
323 }
324 fprintf (f,"\" --");
325 }
326
327
328 /*
329 * Returns TRUE if the given OCTET STRING values are identical.
330 * Returns FALSE otherwise.
331 */
332 int
333 AsnOctsEquiv PARAMS ((o1, o2),
334 AsnOcts *o1 _AND_
335 AsnOcts *o2)
336 {
337 return o1->octetLen == o2->octetLen && !memcmpeq (o1->octs, o2->octs, o1->octetLen);
338 } /* AsnOctsEquiv */