]> git.saurik.com Git - apple/security.git/blob - SecuritySNACCRuntime/c++-lib/c++/asn-bits.cpp
Security-54.1.7.tar.gz
[apple/security.git] / SecuritySNACCRuntime / c++-lib / c++ / asn-bits.cpp
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 // file: .../c++-lib/src/asn-bits.C - AsnBits (ASN.1 BIT STRING) Type
20 //
21 // Mike Sample
22 // 92/07/02
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/root/Security/SecuritySNACCRuntime/c++-lib/c++/Attic/asn-bits.cpp,v 1.4 2002/03/21 05:38:44 dmitch Exp $
36 // $Log: asn-bits.cpp,v $
37 // Revision 1.4 2002/03/21 05:38:44 dmitch
38 // Radar 2868524: no more setjmp/longjmp in SNACC-generated code.
39 //
40 // Revision 1.3.44.1 2002/03/20 00:36:48 dmitch
41 // Radar 2868524: SNACC-generated code now uses throw/catch instead of setjmp/longjmp.
42 //
43 // Revision 1.3 2001/06/28 23:36:11 dmitch
44 // Removed SccsId statics. numToHexCharTblG table now const. Radar 2705410.
45 //
46 // Revision 1.2 2001/06/27 23:09:14 dmitch
47 // Pusuant to Radar 2664258, avoid all cerr-based output in NDEBUG configuration.
48 //
49 // Revision 1.1.1.1 2001/05/18 23:14:05 mb
50 // Move from private repository to open source repository
51 //
52 // Revision 1.3 2001/05/05 00:59:17 rmurphy
53 // Adding darwin license headers
54 //
55 // Revision 1.2 2000/12/07 22:15:49 dmitch
56 // Thread-safe mods: added a local StrStk strStkG to the routines which need it.
57 //
58 // Revision 1.1 2000/06/15 18:44:57 dmitch
59 // These snacc-generated source files are now checked in to allow cross-platform build.
60 //
61 // Revision 1.2 2000/06/08 20:05:34 dmitch
62 // Mods for X port. These files are actually machine generated and probably don't need to be in CVS....
63 //
64 // Revision 1.1.1.1 2000/03/09 01:00:05 rmurphy
65 // Base Fortissimo Tree
66 //
67 // Revision 1.3 1999/03/21 02:07:35 mb
68 // Added Copy to every AsnType.
69 //
70 // Revision 1.2 1999/02/26 00:23:39 mb
71 // Fixed for Mac OS 8
72 //
73 // Revision 1.1 1999/02/25 05:21:50 mb
74 // Added snacc c++ library
75 //
76 // Revision 1.9 1997/08/27 15:55:15 wan
77 // GetBit now returns 0 or 1, not 0 or <#bit>, even if bool type is emulated.
78 //
79 // Revision 1.8 1997/02/28 13:39:44 wan
80 // Modifications collected for new version 1.3: Bug fixes, tk4.2.
81 //
82 // Revision 1.7 1997/01/01 20:19:01 rj
83 // dereferencing pointer to member function is neither necessary nor allowed
84 //
85 // Revision 1.6 1995/08/17 15:37:49 rj
86 // set Tcl's errorCode variable
87 //
88 // Revision 1.5 1995/07/24 20:09:07 rj
89 // use memzero that is defined in .../snacc.h to use either memset or bzero.
90 // use memcmpeq that is defined in .../snacc.h to use either memcmp or bcmp.
91 //
92 // call constructor with additional pdu and create arguments.
93 //
94 // #if TCL ... #endif wrapped into #if META ... #endif
95 //
96 // changed `_' to `-' in file names.
97 //
98 // Revision 1.4 1994/10/08 04:18:21 rj
99 // code for meta structures added (provides information about the generated code itself).
100 //
101 // code for Tcl interface added (makes use of the above mentioned meta code).
102 //
103 // virtual inline functions (the destructor, the Clone() function, BEnc(), BDec() and Print()) moved from inc/*.h to src/*.C because g++ turns every one of them into a static non-inline function in every file where the .h file gets included.
104 //
105 // made Print() const (and some other, mainly comparison functions).
106 //
107 // several `unsigned long int' turned into `size_t'.
108 //
109 // Revision 1.3 1994/08/31 23:37:57 rj
110 // TRUE turned into true
111 //
112 // Revision 1.2 1994/08/28 10:01:11 rj
113 // comment leader fixed.
114 //
115 // Revision 1.1 1994/08/28 09:20:57 rj
116 // first check-in. for a list of changes to the snacc-1.1 distribution please refer to the ChangeLog.
117
118 #include "asn-config.h"
119 #include "asn-len.h"
120 #include "asn-tag.h"
121 #include "asn-type.h"
122 #include "asn-bits.h"
123 #include "str-stk.h"
124
125 #ifndef __APPLE__
126
127 /* OS X - thread safe - the only routine which uses this allocates
128 * it on the stack */
129 extern StrStk strStkG;
130 unsigned short int strStkUnusedBitsG;
131 #endif /* __APPLE__ */
132
133 const
134 char numToHexCharTblG[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
135
136 AsnBits::~AsnBits()
137 {
138 delete bits;
139 }
140
141 AsnType *AsnBits::Clone() const
142 {
143 return new AsnBits;
144 }
145
146 AsnType *AsnBits::Copy() const
147 {
148 return new AsnBits (*this);
149 }
150
151 // Initializes the bits string with a bit string numBits in length.
152 // All bits are zeroed.
153 void AsnBits::Set (size_t numBits)
154 {
155 bitLen = numBits;
156 size_t octetLen = (bitLen+7)/8;
157
158 #ifndef _IBM_ENC_
159 bits = Asn1Alloc (octetLen);
160 #else
161 bits = (char *) mem_mgr_ptr->Get (octetLen); // Guido Grassel, 11.8.93
162 #endif /* _IBM_ENC_ */
163 memzero (bits, octetLen); // init to zeros
164 }
165
166 // initializes a BIT STRING with the given string and bit length
167 // Copies the bits from bitsOcts.
168 void AsnBits::Set (const char *bitOcts, size_t numBits)
169 {
170 if (bitOcts != bits)
171 {
172 bitLen = numBits;
173 size_t octetLen = (bitLen+7)/8;
174 #ifndef _IBM_ENC_
175 bits = new char[octetLen];
176 #else
177 bits = (char *) mem_mgr_ptr->Get (octetLen); // Guido Grassel, 11.8.93
178 #endif /* _IBM_ENC_ */
179 memcpy (bits, bitOcts, octetLen);
180 }
181 }
182
183 // initializes a BIT STRING by copying another BIT STRING's bits
184 void AsnBits::Set (const AsnBits &b)
185 {
186 if (&b != this)
187 {
188 bitLen = b.bitLen;
189 size_t octetLen = (bitLen+7)/8;
190 #ifndef _IBM_ENC_
191 bits = new char[octetLen];
192 #else
193 bits = (char *) mem_mgr_ptr->Get (octetLen); // Guido Grassel, 11.8.93
194 #endif /* _IBM_ENC_ */
195 memcpy (bits, b.bits, octetLen);
196 }
197 }
198
199 // Initializes the bits string with a bit string numBits in length.
200 // All bits are zeroed.
201 void AsnBits::ReSet (size_t numBits)
202 {
203 #ifndef _IBM_ENC_
204 delete bits;
205 Set (numBits);
206 #else
207 mem_mgr_ptr->Put ((void *) bits); // Guido Grassel, 11.8.93
208 Set (numBits);
209 #endif /* _IBM_ENC_ */
210 }
211
212 // frees old bits value and then re-initializes the
213 // BIT STRING with the given string and bit length
214 // Copies the bitOcts into bits.
215 void AsnBits::ReSet (const char *bitOcts, size_t numBits)
216 {
217 if (bitOcts != bits)
218 {
219 #ifndef _IBM_ENC_
220 delete bits;
221 Set (bitOcts, numBits);
222 #else
223 mem_mgr_ptr->Put ((void *) bits); // Guido Grassel, 11.8.93
224 Set (bitOcts, numBits);
225 #endif /* _IBM_ENC_ */
226 }
227 }
228
229 // frees old bits value and then re-initializes the
230 // BIT STRING by copying another BIT STRING's bits
231 void AsnBits::ReSet (const AsnBits &b)
232 {
233 if (&b != this) // avoid b = b; probs
234 {
235 #ifndef _IBM_ENC_
236 delete bits;
237 Set (b);
238 #else
239 mem_mgr_ptr->Put ((void *) bits); // Guido Grassel, 11.8.93
240 Set (b);
241 #endif /* _IBM_ENC_ */
242 }
243 }
244
245
246 // Returns true if the given BIT STRING is the same as this one
247 bool AsnBits::BitsEquiv (const AsnBits &ab) const
248 {
249 size_t octetsLessOne = (bitLen-1)/8;
250 size_t octetBits = 7 - (bitLen % 8);
251
252 if (!bitLen && !ab.bitLen)
253 return true;
254
255 // trailing bits may not be significant
256 return bitLen == ab.bitLen
257 && !memcmpeq (bits, ab.bits, octetsLessOne)
258 && (bits[octetsLessOne] & (0xFF << octetBits)) == (ab.bits[octetsLessOne] & (0xFF << octetBits));
259 } /* AsnBits::BitsEquiv */
260
261
262 // set given bit to 1. Most signif. bit is bit 0, least signif bit is bitLen-1
263 void AsnBits::SetBit (size_t bit)
264 {
265 if (bit < bitLen)
266 {
267 size_t octet = bit/8;
268 size_t octetsBit = 7 - (bit % 8); // bit zero is first/most sig bit in octet
269 bits[octet] |= 1 << octetsBit;
270 }
271 #ifdef DEBUG
272 else
273 Asn1Errror << "AsnBits::SetBit: ERROR - bit larger than bit string" << endl;
274 #endif
275 } /* AsnBits::SetBit */
276
277 // Clr bit. Most signif. bit is bit 0, least signif bit is bitLen-1
278 void AsnBits::ClrBit (size_t bit)
279 {
280 if (bit < bitLen)
281 {
282 size_t octet = bit/8;
283 size_t octetsBit = 7 - (bit % 8); // bit zero is first/most sig bit in octet
284 bits[octet] &= ~(1 << octetsBit);
285 }
286 #ifdef DEBUG
287 else
288 Asn1Errror << "AsnBits::ClrBit: ERROR - bit larger than bit string" << endl;
289 #endif
290 } /* AsnBits::ClrBit */
291
292 // returns given bit. Most signif. bit is bit 0, least signif bit is bitLen-1.
293 // Returns false if the givnen bit index is out of range.
294 bool AsnBits::GetBit (size_t bit) const
295 {
296 if (bit < bitLen)
297 {
298 size_t octet = bit/8;
299 size_t octetsBit = 7 - (bit % 8); // bit zero is first/most sig bit in octet
300 return !!(bits[octet] & (1 << octetsBit));
301 }
302 #ifdef DEBUG
303 else
304 Asn1Errror << "AsnBits::GetBit: ERROR - bit larger than bit string" << endl;
305 #endif
306
307 return false;
308 } /* AsnBits::GetBit */
309
310
311 // Encoded the content (included unused bits octet) of the BIT STRING
312 // to the given buffer.
313 AsnLen AsnBits::BEncContent (BUF_TYPE b)
314 {
315 size_t byteLen = (bitLen+7)/8;
316 b.PutSegRvs (bits, byteLen);
317
318 size_t unusedBits = (bitLen % 8);
319 if (unusedBits != 0)
320 unusedBits = 8 - unusedBits;
321 b.PutByteRvs (unusedBits);
322
323 return byteLen + 1;
324
325 } /* AsnBits::BEncContent */
326
327
328 // Decodes a BER BIT STRING from the given buffer and stores
329 // the value in this object.
330 void AsnBits::BDecContent (BUF_TYPE b, AsnTag tagId, AsnLen elmtLen, AsnLen &bytesDecoded, ENV_TYPE env)
331 {
332 // char *tmp;
333
334 /*
335 * tagId is encoded tag shifted into long int.
336 * if CONS bit is set then constructed bit string
337 */
338 if (tagId & 0x20000000)
339 BDecConsBits (b, elmtLen, bytesDecoded, env);
340
341 else /* primitive octet string */
342 {
343 bytesDecoded += elmtLen;
344 elmtLen--;
345 bitLen = (elmtLen * 8) - (unsigned int)b.GetByte();
346 #ifndef _IBM_ENC_
347 bits = Asn1Alloc (elmtLen);
348 #else
349 bits = (char *) mem_mgr_ptr->Get (elmtLen); // Guido Grassel, 11.8.93
350 #endif /* _IBM_ENC_ */
351 b.CopyOut (bits, elmtLen);
352 if (b.ReadError())
353 {
354 Asn1Error << "BDecBitString: ERROR - decoded past end of data" << endl;
355 #if SNACC_EXCEPTION_ENABLE
356 SnaccExcep::throwMe(-1);
357 #else
358 longjmp (env, -1);
359 #endif
360 }
361 }
362
363 } /* AsnBits::BDecContent */
364
365 AsnLen AsnBits::BEnc (BUF_TYPE b)
366 {
367 AsnLen l;
368 l = BEncContent (b);
369 l += BEncDefLen (b, l);
370 l += BEncTag1 (b, UNIV, PRIM, BITSTRING_TAG_CODE);
371 return l;
372 }
373
374 void AsnBits::BDec (BUF_TYPE b, AsnLen &bytesDecoded, ENV_TYPE env)
375 {
376 AsnLen elmtLen;
377 AsnTag tag;
378
379 tag = BDecTag (b, bytesDecoded, env);
380 if ((tag != MAKE_TAG_ID (UNIV, PRIM, BITSTRING_TAG_CODE))
381 && (tag != MAKE_TAG_ID (UNIV, CONS, BITSTRING_TAG_CODE)))
382 {
383 Asn1Error << "AsnBits::BDec: ERROR tag on BIT STRING is wrong." << endl;
384 #if SNACC_EXCEPTION_ENABLE
385 SnaccExcep::throwMe(-50);
386 #else
387 longjmp (env,-50);
388 #endif
389 }
390 elmtLen = BDecLen (b, bytesDecoded, env);
391 BDecContent (b, tag, elmtLen, bytesDecoded, env);
392 }
393
394 /*
395 * Used to concatentate constructed bit strings when decoding.
396 *
397 * fills string stack with references to the pieces of a
398 * construced bit string. sets strStkUnusedBitsG appropriately.
399 * and strStkTotalByteLenG to bytelen needed to hold the bitstring
400 */
401 #ifdef __APPLE__
402 void AsnBits::FillBitStringStk (BUF_TYPE b, AsnLen elmtLen0,
403 AsnLen &bytesDecoded, ENV_TYPE env,
404 StrStk &strStkG,
405 unsigned short int &strStkUnusedBitsG)
406 #else
407 void AsnBits::FillBitStringStk (BUF_TYPE b, AsnLen elmtLen0,
408 AsnLen &bytesDecoded, ENV_TYPE env)
409 #endif
410 {
411 size_t refdLen;
412 size_t totalRefdLen;
413 char *strPtr;
414 AsnLen totalElmtsLen1 = 0;
415 unsigned long int tagId1;
416 AsnLen elmtLen1;
417 size_t lenToRef;
418 // size_t unusedBits;
419
420 for (; (totalElmtsLen1 < elmtLen0) || (elmtLen0 == INDEFINITE_LEN); )
421 {
422 tagId1 = BDecTag (b, totalElmtsLen1, env);
423
424 if ((tagId1 == EOC_TAG_ID) && (elmtLen0 == INDEFINITE_LEN))
425 {
426 BDEC_2ND_EOC_OCTET (b, totalElmtsLen1, env);
427 break;
428 }
429
430 elmtLen1 = BDecLen (b, totalElmtsLen1, env);
431 if (tagId1 == MAKE_TAG_ID (UNIV, PRIM, BITSTRING_TAG_CODE))
432 {
433 /*
434 * primitive part of string, put references to piece (s) in
435 * str stack
436 */
437
438 /*
439 * get unused bits octet
440 */
441 if (strStkUnusedBitsG != 0)
442 {
443 /*
444 * whoa - only allowed non-octed aligned bits on
445 * on last piece of bits string
446 */
447 Asn1Error << "BDecConsBitString: ERROR - a component of a constructed BIT STRING that is not the last has non-zero unused bits" << endl;
448 #if SNACC_EXCEPTION_ENABLE
449 SnaccExcep::throwMe(-2);
450 #else
451 longjmp (env, -2);
452 #endif
453 }
454
455 if (elmtLen1 != 0)
456 strStkUnusedBitsG = b.GetByte();
457
458 totalRefdLen = 0;
459 lenToRef =elmtLen1-1; /* remove one octet for the unused bits oct*/
460 refdLen = lenToRef;
461 while (1)
462 {
463 strPtr = b.GetSeg (&refdLen);
464
465 strStkG.Push (strPtr, refdLen);
466 totalRefdLen += refdLen;
467 if (totalRefdLen == lenToRef)
468 break; /* exit this while loop */
469
470 if (refdLen == 0) /* end of data */
471 {
472 Asn1Error << "BDecConsOctetString: ERROR - expecting more data" << endl;
473 #if SNACC_EXCEPTION_ENABLE
474 SnaccExcep::throwMe(-3);
475 #else
476 longjmp (env, -3);
477 #endif
478 }
479 refdLen = lenToRef - totalRefdLen;
480 }
481 totalElmtsLen1 += elmtLen1;
482 }
483
484
485 else if (tagId1 == MAKE_TAG_ID (UNIV, CONS, BITSTRING_TAG_CODE))
486 {
487 /*
488 * constructed octets string embedding in this constructed
489 * octet string. decode it.
490 */
491 FillBitStringStk (b, elmtLen1, totalElmtsLen1, env
492 #ifdef __APPLE__
493 , strStkG, strStkUnusedBitsG
494 #endif
495 );
496 }
497 else /* wrong tag */
498 {
499 Asn1Error << "BDecConsBitString: ERROR - decoded non-BIT STRING tag inside a constructed BIT STRING" << endl;
500 #if SNACC_EXCEPTION_ENABLE
501 SnaccExcep::throwMe(-4);
502 #else
503 longjmp (env, -4);
504 #endif
505 }
506 } /* end of for */
507
508 bytesDecoded += totalElmtsLen1;
509 } /* FillBitStringStk */
510
511
512 /*
513 * decodes a seq of universally tagged bits until either EOC is
514 * encountered or the given len decoded. Return them in a
515 * single concatenated bit string
516 */
517 void AsnBits::BDecConsBits (BUF_TYPE b, AsnLen elmtLen, AsnLen &bytesDecoded, ENV_TYPE env)
518 {
519 #ifdef __APPLE__
520 StrStk strStkG(128, 64);
521 unsigned short int strStkUnusedBitsG;
522 #endif
523 strStkG.Reset();
524 strStkUnusedBitsG = 0;
525
526 /*
527 * decode each piece of the octet string, puting
528 * an entry in the octet/bit string stack for each
529 */
530 FillBitStringStk (b, elmtLen, bytesDecoded, env, strStkG,
531 strStkUnusedBitsG);
532
533 /* alloc single str long enough for combined bitstring */
534 bitLen = strStkG.totalByteLen*8 - strStkUnusedBitsG;
535
536 #ifndef _IBM_ENC_
537 bits = Asn1Alloc (strStkG.totalByteLen);
538 #else
539 bits = (char *) mem_mgr_ptr->Get (strStkG.totalByteLen); // Guido Grassel, 11.8.93
540 #endif /* _IBM_ENC_ */
541
542 strStkG.CopyOut (bits);
543
544 } /* BDecConsBits */
545
546 // prints the BIT STRING to the given ostream.
547 void AsnBits::Print (ostream &os) const
548 {
549 #ifndef NDEBUG
550 size_t octetLen = (bitLen+7)/8;
551
552 os << "'";
553 for (unsigned i = 0; i < octetLen; i++)
554 os << TO_HEX (bits[i] >> 4) << (TO_HEX (bits[i]));
555 os << "'H -- BIT STRING bitlen = " << bitLen << " --";
556 #endif /* NDEBUG */
557 }
558
559 #if META
560
561 const AsnBitsTypeDesc AsnBits::_desc (NULL, NULL, false, AsnTypeDesc::BIT_STRING, NULL, NULL);
562
563 const AsnTypeDesc *AsnBits::_getdesc() const
564 {
565 return &_desc;
566 }
567
568 #if TCL
569
570 int AsnBits::TclGetVal (Tcl_Interp *interp) const
571 {
572 Tcl_ResetResult(interp);
573 for (int i=0; i<bitLen; i++)
574 Tcl_AppendResult(interp,GetBit (i) ? "1" : "0",NULL);
575 return TCL_OK;
576 }
577
578 int AsnBits::TclSetVal (Tcl_Interp *interp, const char *valstr)
579 {
580 int i;
581 const char *p;
582
583 for (i=0, p=valstr; *p; i++, p++)
584 switch (*p)
585 {
586 case '0':
587 case '1':
588 break;
589 default:
590 const char c[2] = { *p, '\0' };
591 Tcl_AppendResult (interp, "illegal character '", c, "' for bit in type ", _getdesc()->getmodule()->name, ".", _getdesc()->getname(), NULL);
592 Tcl_SetErrorCode (interp, "SNACC", "ILLBIT", NULL);
593 return TCL_ERROR;
594 }
595
596 ReSet (i);
597
598 for (i=0, p=valstr; i<bitLen; i++, p++)
599 *p == '0' ? ClrBit(i) : SetBit(i);
600
601 return TCL_OK;
602 }
603
604 #endif /* TCL */
605 #endif /* META */