]>
Commit | Line | Data |
---|---|---|
bac41a7b A |
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 | * asn_int.c - BER encode, decode, print and free routines for the | |
21 | * ASN.1 INTEGER type | |
22 | * | |
23 | * MS 92 | |
24 | * Copyright (C) 1992 Michael Sample and the University of British Columbia | |
25 | * | |
26 | * This library is free software; you can redistribute it and/or | |
27 | * modify it provided that this copyright/license information is retained | |
28 | * in original form. | |
29 | * | |
30 | * If you modify this file, you must clearly indicate your changes. | |
31 | * | |
32 | * This source code is distributed in the hope that it will be | |
33 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty | |
34 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
35 | * | |
5a719ac8 | 36 | * $Header: /cvs/Darwin/src/live/Security/SecuritySNACCRuntime/c-lib/src/asn-int.c,v 1.1.1.1 2001/05/18 23:14:08 mb Exp $ |
bac41a7b A |
37 | * $Log: asn-int.c,v $ |
38 | * Revision 1.1.1.1 2001/05/18 23:14:08 mb | |
39 | * Move from private repository to open source repository | |
40 | * | |
41 | * Revision 1.2 2001/05/05 00:59:25 rmurphy | |
42 | * Adding darwin license headers | |
43 | * | |
44 | * Revision 1.1.1.1 1999/03/16 18:06:30 aram | |
45 | * Originals from SMIME Free Library. | |
46 | * | |
47 | * Revision 1.3 1995/07/24 21:04:51 rj | |
48 | * changed `_' to `-' in file names. | |
49 | * | |
50 | * Revision 1.2 1994/09/01 00:05:05 rj | |
51 | * reduce the risk of unwanted surprises with macro expansion by properly separating the C tokens. | |
52 | * | |
53 | * Revision 1.1 1994/08/28 09:45:53 rj | |
54 | * first check-in. for a list of changes to the snacc-1.1 distribution please refer to the ChangeLog. | |
55 | * | |
56 | */ | |
57 | ||
58 | #include "asn-config.h" | |
59 | #include "asn-len.h" | |
60 | #include "asn-tag.h" | |
61 | #include "asn-int.h" | |
62 | ||
63 | /* | |
64 | * encodes universal TAG LENGTH and Contents of and ASN.1 INTEGER | |
65 | */ | |
66 | AsnLen | |
67 | BEncAsnInt PARAMS ((b, data), | |
68 | BUF_TYPE b _AND_ | |
69 | AsnInt *data) | |
70 | { | |
71 | AsnLen len; | |
72 | ||
73 | len = BEncAsnIntContent (b, data); | |
74 | len += BEncDefLen (b, len); | |
75 | len += BEncTag1 (b, UNIV, PRIM, INTEGER_TAG_CODE); | |
76 | return len; | |
77 | } /* BEncAsnInt */ | |
78 | ||
79 | ||
80 | /* | |
81 | * decodes universal TAG LENGTH and Contents of and ASN.1 INTEGER | |
82 | */ | |
83 | void | |
84 | BDecAsnInt PARAMS ((b, result, bytesDecoded, env), | |
85 | BUF_TYPE b _AND_ | |
86 | AsnInt *result _AND_ | |
87 | AsnLen *bytesDecoded _AND_ | |
88 | jmp_buf env) | |
89 | { | |
90 | AsnTag tag; | |
91 | AsnLen elmtLen; | |
92 | ||
93 | if ((tag = BDecTag (b, bytesDecoded, env)) != MAKE_TAG_ID (UNIV, PRIM, INTEGER_TAG_CODE)) | |
94 | { | |
95 | Asn1Error ("BDecAsnInt: ERROR wrong tag on INTEGER.\n"); | |
96 | longjmp (env, -40); | |
97 | } | |
98 | ||
99 | elmtLen = BDecLen (b, bytesDecoded, env); | |
100 | BDecAsnIntContent (b, tag, elmtLen, result, bytesDecoded, env); | |
101 | ||
102 | } /* BDecAsnInt */ | |
103 | ||
104 | ||
105 | /* | |
106 | * encodes signed long integer's contents | |
107 | */ | |
108 | AsnLen | |
109 | BEncAsnIntContent PARAMS ((b, data), | |
110 | BUF_TYPE b _AND_ | |
111 | AsnInt *data) | |
112 | { | |
113 | int len; | |
114 | int i; | |
115 | unsigned long int mask; | |
116 | unsigned long int dataCpy; | |
117 | ||
118 | #define INT_MASK (0x7f80 << ((sizeof(AsnInt) - 2) * 8)) | |
119 | ||
120 | dataCpy = *data; | |
121 | ||
122 | /* | |
123 | * calculate encoded length of the integer (content) | |
124 | */ | |
125 | mask = INT_MASK; | |
126 | if ((long int)dataCpy < 0) | |
127 | for (len = sizeof (AsnInt); len > 1; --len) | |
128 | { | |
129 | if ((dataCpy & mask) == mask) | |
130 | mask >>= 8; | |
131 | else | |
132 | break; | |
133 | } | |
134 | else | |
135 | for (len = sizeof (AsnInt); len > 1; --len) | |
136 | { | |
137 | if ((dataCpy & mask) == 0) | |
138 | mask >>= 8; | |
139 | else | |
140 | break; | |
141 | } | |
142 | ||
143 | /* | |
144 | * write the BER integer | |
145 | */ | |
146 | for (i = 0; i < len; i++) | |
147 | { | |
148 | BufPutByteRvs (b, dataCpy); | |
149 | dataCpy >>= 8; | |
150 | } | |
151 | ||
152 | return len; | |
153 | ||
154 | } /* BEncAsnIntContent */ | |
155 | ||
156 | ||
157 | /* | |
158 | * Decodes content of BER a INTEGER value. The given tag is ignored. | |
159 | */ | |
160 | void | |
161 | BDecAsnIntContent PARAMS ((b, tagId, len, result, bytesDecoded, env), | |
162 | BUF_TYPE b _AND_ | |
163 | AsnTag tagId _AND_ | |
164 | AsnLen len _AND_ | |
165 | AsnInt *result _AND_ | |
166 | AsnLen *bytesDecoded _AND_ | |
167 | jmp_buf env) | |
168 | { | |
169 | int i; | |
170 | long int retVal; | |
171 | unsigned long int byte; | |
172 | ||
173 | ||
174 | if (len > sizeof (AsnInt)) | |
175 | { | |
176 | Asn1Error ("BDecAsnIntContent: ERROR - integer to big to decode.\n"); | |
177 | longjmp (env, -7); | |
178 | } | |
179 | ||
180 | /* | |
181 | * look at integer value | |
182 | */ | |
183 | byte = (unsigned long int) BufGetByte (b); | |
184 | ||
185 | if (byte & 0x80) /* top bit of first byte is sign bit */ | |
186 | retVal = (-1 << 8) | byte; | |
187 | else | |
188 | retVal = byte; | |
189 | ||
190 | /* | |
191 | * write from buffer into long int | |
192 | */ | |
193 | for (i = 1; i < len; i++) | |
194 | retVal = (retVal << 8) | (unsigned long int)(BufGetByte (b)); | |
195 | ||
196 | if (BufReadError (b)) | |
197 | { | |
198 | Asn1Error ("BDecAsnIntContent: ERROR - decoded past end of data \n"); | |
199 | longjmp (env, -8); | |
200 | } | |
201 | (*bytesDecoded) += len; | |
202 | ||
203 | *result = retVal; | |
204 | ||
205 | } /* BDecAsnIntContent */ | |
206 | ||
207 | ||
208 | /* | |
209 | * Prints the given integer to the given FILE * in Value Notation. | |
210 | * indent is ignored. | |
211 | */ | |
212 | void | |
213 | PrintAsnInt PARAMS ((f, v, indent), | |
214 | FILE *f _AND_ | |
215 | AsnInt *v _AND_ | |
216 | unsigned short int indent) | |
217 | { | |
218 | fprintf (f,"%d", *v); | |
219 | } | |
220 | ||
221 | ||
222 | /* | |
223 | * The following deal with UNSIGNED long ints. | |
224 | * They do the same as the above routines for unsigned values. | |
225 | * | |
226 | * The compiler generated code does not call them. (It should | |
227 | * based on subtype info but it does not). | |
228 | */ | |
229 | ||
230 | ||
231 | /* | |
232 | * encodes universal TAG LENGTH and Contents of and ASN.1 INTEGER | |
233 | */ | |
234 | AsnLen | |
235 | BEncUAsnInt PARAMS ((b, data), | |
236 | BUF_TYPE b _AND_ | |
237 | UAsnInt *data) | |
238 | { | |
239 | AsnLen len; | |
240 | ||
241 | len = BEncUAsnIntContent (b, data); | |
242 | len += BEncDefLen (b, len); | |
243 | len += BEncTag1 (b, UNIV, PRIM, INTEGER_TAG_CODE); | |
244 | return len; | |
245 | } /* BEncUAsnInt */ | |
246 | ||
247 | ||
248 | /* | |
249 | * decodes universal TAG LENGTH and Contents of and ASN.1 INTEGER | |
250 | */ | |
251 | void | |
252 | BDecUAsnInt PARAMS ((b, result, bytesDecoded, env), | |
253 | BUF_TYPE b _AND_ | |
254 | UAsnInt *result _AND_ | |
255 | AsnLen *bytesDecoded _AND_ | |
256 | jmp_buf env) | |
257 | { | |
258 | AsnTag tag; | |
259 | AsnLen elmtLen; | |
260 | ||
261 | if ((tag = BDecTag (b, bytesDecoded, env)) != MAKE_TAG_ID (UNIV, PRIM, INTEGER_TAG_CODE)) | |
262 | { | |
263 | Asn1Error ("BDecAsnInt: ERROR wrong tag on INTGER.\n"); | |
264 | longjmp (env, -40); | |
265 | } | |
266 | ||
267 | elmtLen = BDecLen (b, bytesDecoded, env); | |
268 | BDecUAsnIntContent (b, tag, elmtLen, result, bytesDecoded, env); | |
269 | ||
270 | } /* BDecUAsnInt */ | |
271 | ||
272 | ||
273 | /* | |
274 | * encodes unsigned long integer. This allows you to correctly | |
275 | * handle unsiged values that used the most significant (sign) bit. | |
276 | */ | |
277 | AsnLen | |
278 | BEncUAsnIntContent PARAMS ((b, data), | |
279 | BUF_TYPE b _AND_ | |
280 | UAsnInt *data) | |
281 | { | |
282 | int len; | |
283 | int i; | |
284 | unsigned long int mask; | |
285 | unsigned long int dataCpy; | |
286 | ||
287 | dataCpy = *data; | |
288 | ||
289 | /* | |
290 | * calculate encoded length of the integer (content) | |
291 | */ | |
292 | mask = INT_MASK; | |
293 | if ((long int)dataCpy < 0) | |
294 | { | |
295 | /*write integer as normal (remember writing in reverse) */ | |
296 | for (i = 0; i < sizeof (UAsnInt); i++) | |
297 | { | |
298 | BufPutByteRvs (b, dataCpy); | |
299 | dataCpy >>= 8; | |
300 | } | |
301 | /* | |
302 | * write zero byte at beginning of int, since high bit | |
303 | * is set and need to differentiate between sign | |
304 | * bit and high bit in unsigned case. | |
305 | * (this code follows the prev for loop since writing | |
306 | * in reverse) | |
307 | */ | |
308 | BufPutByteRvs (b, 0); | |
309 | ||
310 | return sizeof (UAsnInt)+1; | |
311 | } | |
312 | else | |
313 | { | |
314 | for (len = sizeof (UAsnInt); len > 1; --len) | |
315 | { | |
316 | if ((dataCpy & mask) == 0) | |
317 | mask >>= 8; | |
318 | else | |
319 | break; | |
320 | } | |
321 | ||
322 | /* write the BER integer */ | |
323 | for (i = 0; i < len; i++) | |
324 | { | |
325 | BufPutByteRvs (b, dataCpy); | |
326 | dataCpy >>= 8; | |
327 | } | |
328 | return len; | |
329 | } | |
330 | ||
331 | } /* BEncUAsnIntContent */ | |
332 | ||
333 | ||
334 | /* | |
335 | * decode integer portion - no tag or length expected or decoded | |
336 | * assumes unsigned integer - This routine is useful for | |
337 | * integer subtyped to > 0 eg Guage ::= INTEGER (0..4294967295) | |
338 | */ | |
339 | void | |
340 | BDecUAsnIntContent PARAMS ((b, tag, len, result, bytesDecoded, env), | |
341 | BUF_TYPE b _AND_ | |
342 | AsnTag tag _AND_ | |
343 | AsnLen len _AND_ | |
344 | UAsnInt *result _AND_ | |
345 | AsnLen *bytesDecoded _AND_ | |
346 | jmp_buf env) | |
347 | { | |
348 | int i; | |
349 | unsigned long int retVal; | |
350 | ||
351 | retVal = (unsigned long int) BufGetByte (b); | |
352 | ||
353 | if (len > (sizeof (UAsnInt)+1)) | |
354 | { | |
355 | Asn1Error ("BDecUAsnIntContent: ERROR - integer to big to decode.\n"); | |
356 | longjmp (env, -9); | |
357 | } | |
358 | else if (retVal & 0x80) /* top bit of first byte is sign bit */ | |
359 | { | |
360 | Asn1Error ("BDecUAsnIntContent: ERROR - integer is negative.\n"); | |
361 | longjmp (env, -10); | |
362 | } | |
363 | else if ((len == (sizeof (UAsnInt)+1)) && (retVal != 0)) | |
364 | { | |
365 | /* | |
366 | * first octet must be zero 5 octets long - extra 0 octet | |
367 | * at beginning is only used for value > 0 that need the | |
368 | * high bit | |
369 | */ | |
370 | Asn1Error ("BDecUAsnIntContent: ERROR - integer is negative.\n"); | |
371 | longjmp (env, -11); | |
372 | } | |
373 | ||
374 | /* | |
375 | * write from buffer into long int | |
376 | */ | |
377 | for (i = 1; i < len; i++) | |
378 | retVal = (retVal << 8) | (unsigned long int)(BufGetByte (b)); | |
379 | ||
380 | if (BufReadError (b)) | |
381 | { | |
382 | Asn1Error ("BDecUIntegerContent: ERROR - decoded past end of data\n"); | |
383 | longjmp (env, -12); | |
384 | } | |
385 | (*bytesDecoded) += len; | |
386 | ||
387 | *result = retVal; | |
388 | ||
389 | } /* BDecUAsnIntContent */ | |
390 | ||
391 | ||
392 | void | |
393 | PrintUAsnInt PARAMS ((f, v, indent), | |
394 | FILE *f _AND_ | |
395 | UAsnInt *v _AND_ | |
396 | unsigned short int indent) | |
397 | { | |
398 | fprintf (f, "%u", *v); | |
399 | } |