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