]>
git.saurik.com Git - apple/security.git/blob - SecuritySNACCRuntime/c++-lib/src/sm_vdasnacc.cpp
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
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
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.
20 static char SccsId
[ ] = "@(#) sm_vdasnacc.cpp 1.18 6/1/98 11:07:01";
26 This file handles any additional miscellaneous routines to support
27 the integration of the MSP into SNACC environment.
31 #include "sm_vdasnacc.h"
32 #include "sm_vdatypes.h"
34 long vdasnacc_sortSetTag(
35 CSM_Buffer
*pEncBuf
[], // IN/OUT, buffer to sort
36 int start_index
, // IN, start index for sort.
37 int icount
, // IN, size of array.
38 int tag
); // IN, tag to place.
39 long SM_DetermineLengthBuf(AsnBuf
&SNACCinputBuf
);
42 /** This function sorts the specified "Str_struct" array in reverse order.
43 This is done for the "Set Of" ASN.1 ordering. The ASN.1 components will
44 be loaded in ascending order; they will be loaded in the reverse order
45 of this array (hence, we load them in descending order).
47 long vdasnacc_sortSetOf(CSM_Buffer
**&pEncBuf
, int icount
)
53 const char *ptr1
,*ptr2
;
56 for (i
=0; i
< icount
; i
++)
58 for (j
=i
+1; j
< icount
; j
++) /** always start with present "i". **/
60 ptr1
= pEncBuf
[i
]->Access();
61 ptr2
= pEncBuf
[j
]->Access();
62 l1
= pEncBuf
[i
]->Length();
63 l2
= pEncBuf
[j
]->Length();
68 if (memcmp(ptr1
, ptr2
, lessCount
) < 0 ||
69 (memcmp(ptr1
, ptr2
, lessCount
) == 0 &&
70 l1
< l2
)) /** check if = with more */
71 { /** SWITCH buffers so that greater is first. **/
73 pEncBuf
[i
] = pEncBuf
[j
];
85 /** This function sorts the specified "Str_struct" array in reverse order.
86 This is done for the "Set" ASN.1 ordering. The ASN.1 components will
87 be loaded in ascending order; they will be loaded in the reverse order
88 of this array (hence, we load them in descending order). The SET ordering
89 is based on the lower 5 bits of the tag item (guaranteed to be unique
90 based on the ASN.1 definition of a SET). This is based on the ISO rules.
92 #define ASN_UNIVERSAL 0x00
93 #define ASN_APPLICATION 0x40
94 #define ASN_CONTEXT 0x80
95 #define ASN_PRIVATE 0xC0
96 long vdasnacc_sortSet(CSM_Buffer
*pEncBuf
[], int icount
)
102 // This algorithm for Set ordering requires Universal tags first
103 // followed by Application, then Context specific tags.
104 // Each entry in this category is then sorted by the lower 5 bits.
105 // (They are loaded in reverse order for SNACC buffer loads.)
106 tag_count
= vdasnacc_sortSetTag(pEncBuf
, tag_index
, icount
,
108 tag_index
+= tag_count
; // skip this set of tags, onto the next.
109 tag_count
= vdasnacc_sortSetTag(pEncBuf
, tag_index
, icount
,
111 tag_index
+= tag_count
; // skip this set of tags, onto the next.
112 tag_count
= vdasnacc_sortSetTag(pEncBuf
, tag_index
, icount
,
114 tag_index
+= tag_count
;
115 tag_count
= vdasnacc_sortSetTag(pEncBuf
, tag_index
, icount
,
122 // vdasnacc_sortSetTag
123 // This routine sorts the specified buffer from the start index to the end
124 // for the specified tag. This entails switching all entries until the
125 // tagged entries are consecutive, then sorting according the lower 5 bits
126 // of the tags within that tag. The number of entries of that tag type
128 long vdasnacc_sortSetTag(
129 CSM_Buffer
*pEncBuf
[], // IN/OUT, buffer to sort
130 int start_index
, // IN, start index for sort.
131 int icount
, // IN, size of array.
132 int tag
) // IN, tag to place.
137 const char *ptri
,*ptrj
;
138 int mask
= 0x1f; /** for SET, not SET OF logic, only sort based on
139 first 5 bits of tag. **/
140 int mask_TAG
= 0xc0; /** mask for upper tag bits indicating UNIVERSAL,
141 APPLICATION or CONTEXT ASN.1 Class. **/
143 for (i
=start_index
; i
< icount
; i
++)
145 ptri
= pEncBuf
[i
]->Access();
146 if (((ptri
[0]&mask_TAG
)^tag
) != 0)
148 for (j
=i
+1; (j
< icount
) && (((ptri
[0]&mask_TAG
)^tag
) != 0); j
++)
149 /** always start with present "i". **/
151 ptrj
= pEncBuf
[j
]->Access();
152 if (((ptri
[0]&mask_TAG
)^tag
) != 0 &&
153 ((ptrj
[0]&mask_TAG
)^tag
) == 0)
154 { /** SWITCH buffers so that greater is first. **/
156 pEncBuf
[i
] = pEncBuf
[j
];
158 ptri
= pEncBuf
[i
]->Access();
159 ptrj
= pEncBuf
[j
]->Access();
163 if (((ptri
[0]&mask_TAG
)^tag
) == 0)
164 tag_count
++; // COUNT each of this tag type.
167 for (i
=start_index
; i
< tag_count
; i
++)
169 for (j
=i
+1; j
< tag_count
; j
++) /** always start with present "i". **/
171 ptri
= pEncBuf
[i
]->Access();
172 ptrj
= pEncBuf
[j
]->Access();
173 if ((ptri
[0]&mask
) < (ptrj
[0]&mask
))
174 { /** SWITCH buffers so that greater is first. **/
176 pEncBuf
[i
] = pEncBuf
[j
];
187 long SM_WriteToAsnBuf(
188 CSM_Buffer
&CBuf
, // IN,class must be pre-allocated
189 AsnBuf
&SNACCoutputBuf
)
192 CSM_Buffer
*pCBuf
=&CBuf
;
194 status
= SM_WriteToAsnBuf(pCBuf
, SNACCoutputBuf
);
197 long SM_WriteToAsnBuf(
198 CSM_Buffer
*&pCBuf
, // IN,class must be pre-allocated
199 AsnBuf
&SNACCoutputBuf
)
207 pCBuf
->Open(SM_FOPEN_READ
);
208 for (jj
= 0; jj
< pCBuf
->Length() && lRead
> 0; jj
+= lRead
)
210 if (jj
== 0) // first time, only get last X bytes within 4096 block.
212 lOffset
= pCBuf
->Length() - (pCBuf
->Length() % 4096);
216 pCBuf
->Seek(lOffset
, 0);
217 ptr
= pCBuf
->nRead(4096, lRead
);
218 SNACCoutputBuf
.PutSegRvs(ptr
, lRead
);
221 //SNACCoutputBuf.ResetInReadMode();
223 status
= 1; // error.
227 // SM_ReadFromAsnBuf (pre-alloced version)
228 // This function does the same thing as SM_ReadFromAsnBuf but does not
229 // allocate the incoming CSM_Buffer...
230 long SM_ReadFromAsnBuf(
231 AsnBuf
&SNACCinputBuf
, // IN, input SNACC buffer
232 CSM_Buffer
*pCBuf
, // OUT, copied data
233 long length
, // IN, length of data to read.
234 CSM_Buffer
*preLoad
) // IN, optional data to be pre-loaded;
235 // (for SNACC support)
238 unsigned int jj
, lWritten
, lToRead
;
241 if (length
== INDEFINITE_LEN
)
243 // RWC; Call custom routine to trace the actual unknown ASN data in the
244 // RWC; buffer and determine the actual length of the buffer (this may
245 // RWC; be a recursive call).
246 AsnBuf SNACCinputBuf2
= SNACCinputBuf
; // Create new, working copy for
247 // ASN ANY length determination.
248 length
= SM_DetermineLengthBuf(SNACCinputBuf2
);
253 tmpLength
+= preLoad
->Length();
254 // pCBuf should already be allocated and ready for use...
257 pCBuf
->Open(SM_FOPEN_WRITE
);
258 if (preLoad
) // load requested data in front of SNACC buf.
259 pCBuf
->Write(preLoad
->Access(), preLoad
->Length());
260 for (jj
=0, lWritten
=1;
261 jj
< (unsigned int)length
&& lWritten
> 0; jj
+= lWritten
)
263 if (length
- jj
< 4096) lToRead
= length
- jj
;
265 lWritten
= SNACCinputBuf
.CopyOut(&tmpBuf
[0], lToRead
);
267 pCBuf
->Write(&tmpBuf
[0], lWritten
);
274 // SM_ReadFromAsnBuf (allocating version)
275 // NOTE::: IMPORTANT NOT TO RESET CSM_Buffer Write BUFFER.
276 // ALSO, DO NOT RESET THE AsnBuf from SNACC; this function is used
277 // to read data from ANY components in the incomming SNACC message.
278 long SM_ReadFromAsnBuf(CSM_Buffer
*&pCBuf
, // OUT,copied data.
279 AsnBuf
&SNACCinputBuf
, // IN, input SNACC buffer
280 long length
, // IN, length of data to read.
281 CSM_Buffer
*preLoad
) // IN, optional data to be pre-loaded;
282 // (for SNACC support)
288 tmpLength
+= preLoad
->Length();
289 #if defined(macintosh) || defined(__APPLE__)
290 pCBuf
= new CSM_Buffer(length
== INDEFINITE_LEN
? 0 : preLoad
? tmpLength
: length
);
292 if (SNACCinputBuf
.DataLen() > 16384) // RWC; MUST BE FIXED!!!!
293 pCBuf
= new CSM_Buffer(tmpnam(NULL
), 0);
295 pCBuf
= new CSM_Buffer(0);
297 return (SM_ReadFromAsnBuf(SNACCinputBuf
, pCBuf
, length
, preLoad
));
300 //////////////////////////////////////////////////////////////////////////
301 // SM_AsnBits2Buffer gets the bits out of the snacc AsnBits class and
302 // stores them in a buffer LSB style.
303 long SM_AsnBits2Buffer(AsnBits
*pBits
, CSM_Buffer
*pBuffer
)
313 if ((pBits
== NULL
) || (pBuffer
== NULL
))
316 lBits
= pBits
->BitLen();
317 // calculate the number of bytes being put into the buffer
318 lNumBytes
= lBits
/ 8;
322 if ((pch
= pBuffer
->Alloc(lNumBytes
)) == NULL
)
325 for (i
= 0; i
< lNumBytes
; i
++)
327 for (j
= 0; j
< 8 && ((i
*8)+j
) < lBits
; j
++)
329 pch
[i
] += (pBits
->GetBit((i
*8)+j
) << j
);
333 pBuffer
->Open(SM_FOPEN_WRITE
);
343 //////////////////////////////////////////////////////////////////////////
344 // SM_Buffer2AsnBits gets the bits out of the snacc AsnBits class and
345 // stores them in a buffer LSB style.
346 long SM_Buffer2AsnBits(CSM_Buffer
*pBuffer
, AsnBits
*pBits
, size_t lBits
)
353 if ((pBits
!= NULL
) && (pBuffer
!= NULL
))
357 // calculate the number of bytes being put into the buffer
358 lNumBytes
= lBits
/ 8;
361 pch
= pBuffer
->Access();
363 for (i
= 0; i
< lNumBytes
; i
++)
365 for (j
= 0; j
< 8 && ((i
*8)+j
) < lBits
; j
++)
367 if ((pch
[i
] >> j
) & 0x01)
368 pBits
->SetBit((i
*8)+j
);
377 long SM_BufferReverseBits(CSM_Buffer
*pBuffer
)
383 static const short bbb
[256]=
385 static short bbb
[256]=
387 { 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
388 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
389 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
390 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
391 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
392 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
393 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
394 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
395 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
396 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
397 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
398 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
399 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
400 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
401 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
402 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
407 ptr
= (unsigned char *)pBuffer
->Access();
408 for (i
=0; i
< pBuffer
->Length(); i
++)
410 ptr
[i
] = (char)bbb
[ptr
[i
]];
417 #if SM_BUF_2_BIG_INT_STR
419 long SM_Buffer2BigIntegerStr( CSM_Buffer
*asn1Data
,
420 BigIntegerStr
&pSnaccBigIntStr
,
423 BigIntegerStr
*p
= &pSnaccBigIntStr
;
425 return(SM_Buffer2BigIntegerStr(asn1Data
, p
, unsignedFlag
));
428 // FUNCTION: SM_Buffer2BigIntegerStr()
430 // PURPOSE: Encforce ASN.1 encoding rules on the asn1Data. Make sure it's
431 // unsigned if the unsignedFlag is set to true.
433 long SM_Buffer2BigIntegerStr( CSM_Buffer
*asn1Data
,
434 BigIntegerStr
*&ppSnaccBigIntStr
,
437 char *pDataCopy
= const_cast<char*>(asn1Data
->Access());
438 SM_SIZE_T dataLen
= asn1Data
->Length();
442 /* IF the Fortezza Card generates an r,s,p,q,g or y value in which the
443 * first 9 bits are all set to 0, then the encoding software deletes the
444 * first octet from the octets to be encoded. This rule is applied
445 * repeatedly to the remaining octets until the first 9 bits are not all
448 if (unsignedFlag
== 1)
450 while ( !( (pDataCopy
[0] & 0xFF) || (pDataCopy
[1] & 0x80)) )
452 memcpy( &pDataCopy
[0], &pDataCopy
[1], (dataLen
- 1));
454 pDataCopy
[dataLen
] = 0;
457 /* If the Fortezza Card generates a r,s,p,q,g, or y value in which the
458 * MSB is set to 1, THEN the software prepends a single octet in which
459 * all bits are set to 0.
461 if (pDataCopy
[0] & 0x80)
465 tmp
= (char *) calloc(1, dataLen
+ 1);
468 memcpy(&tmp
[1], pDataCopy
, dataLen
);
476 * ASN.1 rules state that the first 9 bits of an integer encoding can
477 * not be all ones or all zeros.
481 /* check for first first 9 bits all ones
483 while ( (pDataCopy
[0] & 0xFF) && (pDataCopy
[1] & 0x80) )
485 memcpy( &pDataCopy
[0], &pDataCopy
[1], dataLen
- 1);
487 pDataCopy
[dataLen
] = 0;
490 /* check for first 9 bits all zeros
492 while (pDataCopy
[0] == 0 && (pDataCopy
[1] >> 7) == 0)
494 memcpy( &pDataCopy
[0], &pDataCopy
[1], (dataLen
- 1));
496 pDataCopy
[dataLen
] = 0;
500 if (ppSnaccBigIntStr
== NULL
)
501 ppSnaccBigIntStr
= new BigIntegerStr( pDataCopy
, dataLen
);
503 ppSnaccBigIntStr
->ReSet( pDataCopy
, dataLen
);
508 #endif /* SM_BUF_2_BIG_INT_STR */
512 // RULES for recursive operation, determining the length of the specified
514 // - Always assume only the data from a valid ANY was passed in, missing tag
516 // - Parse data from the 1st byte; if ASN data sets do not match the specified
517 // length or EOC designator, then we assume it is part of sequence and
520 long SM_DetermineLengthBuf(AsnBuf
&SNACCinputBuf
)
523 unsigned long int tagId1
;
525 AsnLen elmtLen0
=INDEFINITE_LEN
;
528 while (elmtLen0
== INDEFINITE_LEN
)
530 tagId1
= BDecTag (SNACCinputBuf
, length
, env
);
532 if ((tagId1
== EOC_TAG_ID
) && (elmtLen0
== INDEFINITE_LEN
))
534 BDEC_2ND_EOC_OCTET (SNACCinputBuf
, length
, env
);
537 elmtLen1
= BDecLen (SNACCinputBuf
, length
, env
);
538 if (elmtLen1
== INDEFINITE_LEN
)
540 elmtLen1
= SM_DetermineLengthBuf(SNACCinputBuf
);
543 else if (!SNACCinputBuf
.ReadError())
545 SNACCinputBuf
.Skip(elmtLen1
); // SKIP this ASN.1 component.
555 return((long)length
);
560 /*** EOF smimesnacc.CPP ***/