16007Sthurlow // Copyright (C) 2002 Microsoft Corporation
26007Sthurlow // All rights reserved.
36007Sthurlow //
46007Sthurlow // THIS CODE AND INFORMATION IS PROVIDED "AS IS"
56007Sthurlow // WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
66007Sthurlow // OR IMPLIED, INCLUDING BUT NOT LIMITED
76007Sthurlow // TO THE IMPLIED WARRANTIES OF MERCHANTIBILITY
86007Sthurlow // AND/OR FITNESS FOR A PARTICULAR PURPOSE.
96007Sthurlow //
106007Sthurlow // Date - 10/08/2002
116007Sthurlow // Author - Sanj Surati
126007Sthurlow
136007Sthurlow
146007Sthurlow /////////////////////////////////////////////////////////////
156007Sthurlow //
166007Sthurlow // DERPARSE.C
176007Sthurlow //
186007Sthurlow // SPNEGO Token Handler Source File
196007Sthurlow //
206007Sthurlow // Contains implementation of ASN.1 DER read/write functions
216007Sthurlow // as defined in DERPARSE.H.
226007Sthurlow //
236007Sthurlow /////////////////////////////////////////////////////////////
246007Sthurlow
256007Sthurlow #include <stdlib.h>
266007Sthurlow #include <stdio.h>
276007Sthurlow #include <memory.h>
286007Sthurlow #include <sys/byteorder.h>
296007Sthurlow #include "spnego.h"
306007Sthurlow #include "derparse.h"
316007Sthurlow
326007Sthurlow //
336007Sthurlow // The GSS Mechanism OID enumeration values (SPNEGO_MECH_OID) control which offset in
346007Sthurlow // the array below, that a mechanism can be found.
356007Sthurlow //
36*10023SGordon.Ross@Sun.COM
376007Sthurlow #pragma error_messages (off,E_INITIALIZATION_TYPE_MISMATCH)
386007Sthurlow MECH_OID g_stcMechOIDList [] =
396007Sthurlow {
406007Sthurlow {"\x06\x09\x2a\x86\x48\x82\xf7\x12\x01\x02\x02", 11, 9,
416007Sthurlow spnego_mech_oid_Kerberos_V5_Legacy }, // 1.2.840.48018.1.2.2
426007Sthurlow {"\x06\x09\x2a\x86\x48\x86\xf7\x12\x01\x02\x02", 11, 9,
436007Sthurlow spnego_mech_oid_Kerberos_V5 }, // 1.2.840.113554.1.2.2
446007Sthurlow {"\x06\x06\x2b\x06\x01\x05\x05\x02", 8, 6,
456007Sthurlow spnego_mech_oid_Spnego }, // 1.3.6.1.5.5.2
466007Sthurlow {"\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a", 12, 10,
476007Sthurlow spnego_mech_oid_NTLMSSP }, // 1.3.6.1.4.1.311.2.2.10
486007Sthurlow {"", 0, 0, spnego_mech_oid_NotUsed } // Placeholder
496007Sthurlow };
506007Sthurlow #pragma error_messages (default,E_INITIALIZATION_TYPE_MISMATCH)
516007Sthurlow
526007Sthurlow /////////////////////////////////////////////////////////////////////////////
536007Sthurlow //
546007Sthurlow // Function:
556007Sthurlow // ASNDerGetLength
566007Sthurlow //
576007Sthurlow // Parameters:
586007Sthurlow // [in] pbLengthData - DER Length Data
596007Sthurlow // [in] nBoundaryLength - Length that value must not exceed.
606007Sthurlow // [out] pnLength - Filled out with length value
616007Sthurlow // [out] pnNumLengthBytes - Filled out with number of bytes
626007Sthurlow // consumed by DER length.
636007Sthurlow //
646007Sthurlow // Returns:
656007Sthurlow // int Success - SPNEGO_E_SUCCESS
666007Sthurlow // Failure - SPNEGO API Error code
676007Sthurlow //
686007Sthurlow // Comments :
696007Sthurlow // Interprets the data at pbLengthData as a DER length. The length must
706007Sthurlow // fit within the bounds of nBoundary length. We do not currently
716007Sthurlow // process lengths that take more than 4 bytes.
726007Sthurlow //
736007Sthurlow ////////////////////////////////////////////////////////////////////////////
746007Sthurlow
ASNDerGetLength(unsigned char * pbLengthData,long nBoundaryLength,long * pnLength,long * pnNumLengthBytes)756007Sthurlow int ASNDerGetLength( unsigned char* pbLengthData, long nBoundaryLength, long* pnLength,
766007Sthurlow long* pnNumLengthBytes )
776007Sthurlow {
786007Sthurlow int nReturn = SPNEGO_E_INVALID_LENGTH;
796007Sthurlow int nNumLengthBytes = 0;
806007Sthurlow
816007Sthurlow // First check if the extended length bit is set
826007Sthurlow
836007Sthurlow if ( *pbLengthData & LEN_XTND )
846007Sthurlow {
856007Sthurlow // Lower 7 bits contain the number of trailing bytes that describe the length
866007Sthurlow nNumLengthBytes = *pbLengthData & LEN_MASK;
876007Sthurlow
886007Sthurlow // Check that the number of bytes we are about to read is within our boundary
896007Sthurlow // constraints
906007Sthurlow
916007Sthurlow if ( nNumLengthBytes <= nBoundaryLength - 1 )
926007Sthurlow {
936007Sthurlow
946007Sthurlow // For now, our handler won't deal with lengths greater than 4 bytes
956007Sthurlow if ( nNumLengthBytes >= 1 && nNumLengthBytes <= 4 )
966007Sthurlow {
976007Sthurlow // 0 out the initial length
986007Sthurlow *pnLength = 0L;
996007Sthurlow
1006007Sthurlow // Bump by 1 byte
1016007Sthurlow pbLengthData++;
1026007Sthurlow
1036007Sthurlow #ifdef _LITTLE_ENDIAN
1046007Sthurlow
1056007Sthurlow // There may be a cleaner way to do this, but for now, this seems to be
1066007Sthurlow // an easy way to do the transformation
1076007Sthurlow switch ( nNumLengthBytes )
1086007Sthurlow {
1096007Sthurlow case 1:
1106007Sthurlow {
1116007Sthurlow *( ( (unsigned char*) pnLength ) ) = *pbLengthData;
1126007Sthurlow break;
1136007Sthurlow }
1146007Sthurlow
1156007Sthurlow case 2:
1166007Sthurlow {
1176007Sthurlow *( ( (unsigned char*) pnLength ) ) = *(pbLengthData + 1);
1186007Sthurlow *( ( (unsigned char*) pnLength ) + 1 ) = *(pbLengthData);
1196007Sthurlow
1206007Sthurlow break;
1216007Sthurlow }
1226007Sthurlow
1236007Sthurlow case 3:
1246007Sthurlow {
1256007Sthurlow *( ( (unsigned char*) pnLength ) ) = *(pbLengthData + 2);
1266007Sthurlow *( ( (unsigned char*) pnLength ) + 2 ) = *(pbLengthData + 1);
1276007Sthurlow *( ( (unsigned char*) pnLength ) + 3 ) = *(pbLengthData);
1286007Sthurlow break;
1296007Sthurlow }
1306007Sthurlow
1316007Sthurlow case 4:
1326007Sthurlow {
1336007Sthurlow *( ( (unsigned char*) pnLength ) ) = *(pbLengthData + 3);
1346007Sthurlow *( ( (unsigned char*) pnLength ) + 1 ) = *(pbLengthData + 2);
1356007Sthurlow *( ( (unsigned char*) pnLength ) + 2 ) = *(pbLengthData + 1);
1366007Sthurlow *( ( (unsigned char*) pnLength ) + 3 ) = *(pbLengthData);
1376007Sthurlow break;
1386007Sthurlow }
1396007Sthurlow
1406007Sthurlow } // SWITCH ( nNumLengthBytes )
1416007Sthurlow
1426007Sthurlow #else
1436007Sthurlow // We are Big-Endian, so the length can be copied in from the source
1446007Sthurlow // as is. Ensure that we adjust for the number of bytes we actually
1456007Sthurlow // copy.
1466007Sthurlow
1476007Sthurlow memcpy( ( (unsigned char *) pnLength ) + ( 4 - nNumLengthBytes ),
1486007Sthurlow pbLengthData, nNumLengthBytes );
1496007Sthurlow #endif
1506007Sthurlow
1516007Sthurlow // Account for the initial length byte
1526007Sthurlow *pnNumLengthBytes = nNumLengthBytes + 1;
1536007Sthurlow nReturn = SPNEGO_E_SUCCESS;
1546007Sthurlow
1556007Sthurlow } // IF Valid Length
1566007Sthurlow
1576007Sthurlow } // IF num bytes to read is within the boundary length
1586007Sthurlow
1596007Sthurlow } // IF xtended length
1606007Sthurlow else
1616007Sthurlow {
1626007Sthurlow
1636007Sthurlow // Extended bit is not set, so the length is in the value and the one
1646007Sthurlow // byte describes the length
1656007Sthurlow *pnLength = *pbLengthData & LEN_MASK;
1666007Sthurlow *pnNumLengthBytes = 1;
1676007Sthurlow nReturn = SPNEGO_E_SUCCESS;
1686007Sthurlow
1696007Sthurlow }
1706007Sthurlow
1716007Sthurlow return nReturn;
1726007Sthurlow }
1736007Sthurlow
1746007Sthurlow
1756007Sthurlow /////////////////////////////////////////////////////////////////////////////
1766007Sthurlow //
1776007Sthurlow // Function:
1786007Sthurlow // ASNDerCheckToken
1796007Sthurlow //
1806007Sthurlow // Parameters:
1816007Sthurlow // [in] pbTokenData - Token Data
1826007Sthurlow // [in] nToken - Token identifier to check for
1836007Sthurlow // [in] nLengthWithToken - Expected token length (with data)
1846007Sthurlow // [in] nBoundaryLength - Length that value must not exceed.
1856007Sthurlow // [out] pnLength - Filled out with data length
1866007Sthurlow // [out] pnTokenLength - Filled out with number of bytes
1876007Sthurlow // consumed by token identifier and length.
1886007Sthurlow //
1896007Sthurlow // Returns:
1906007Sthurlow // int Success - SPNEGO_E_SUCCESS
1916007Sthurlow // Failure - SPNEGO API Error code
1926007Sthurlow //
1936007Sthurlow // Comments :
1946007Sthurlow // Checks the data pointed to by pbTokenData for the specified token
1956007Sthurlow // identifier and the length that immediately follows. If
1966007Sthurlow // nLengthWithToken is > 0, the calculated length must match. The
1976007Sthurlow // length must also not exceed the specified boundary length .
1986007Sthurlow //
1996007Sthurlow ////////////////////////////////////////////////////////////////////////////
2006007Sthurlow
ASNDerCheckToken(unsigned char * pbTokenData,unsigned char nToken,long nLengthWithToken,long nBoundaryLength,long * pnLength,long * pnTokenLength)2016007Sthurlow int ASNDerCheckToken( unsigned char* pbTokenData, unsigned char nToken,
2026007Sthurlow long nLengthWithToken, long nBoundaryLength,
2036007Sthurlow long* pnLength, long* pnTokenLength )
2046007Sthurlow {
2056007Sthurlow
2066007Sthurlow int nReturn = SPNEGO_E_INVALID_LENGTH;
2076007Sthurlow long nNumLengthBytes = 0L;
2086007Sthurlow
2096007Sthurlow // Make sure that we've at least got 2 bytes of room to work with
2106007Sthurlow
2116007Sthurlow if ( nBoundaryLength >= 2 )
2126007Sthurlow {
2136007Sthurlow // The first byte of the token data MUST match the specified token
2146007Sthurlow if ( *pbTokenData == nToken )
2156007Sthurlow {
2166007Sthurlow // Next byte indicates the length
2176007Sthurlow pbTokenData++;
2186007Sthurlow
2196007Sthurlow // Get the length described by the token
2206007Sthurlow if ( ( nReturn = ASNDerGetLength( pbTokenData, nBoundaryLength, pnLength,
2216007Sthurlow &nNumLengthBytes ) ) == SPNEGO_E_SUCCESS )
2226007Sthurlow {
2236007Sthurlow // Verify that the length is LESS THAN the boundary length
2246007Sthurlow // (this should prevent us walking out of our buffer)
2256007Sthurlow if ( ( nBoundaryLength - ( nNumLengthBytes + 1 ) < *pnLength ) )
2266007Sthurlow {
2276007Sthurlow
2286007Sthurlow nReturn = SPNEGO_E_INVALID_LENGTH;
2296007Sthurlow
2306007Sthurlow }
2316007Sthurlow
2326007Sthurlow // If we were passed a length to check, do so now
2336007Sthurlow if ( nLengthWithToken > 0L )
2346007Sthurlow {
2356007Sthurlow
2366007Sthurlow // Check that the expected length matches
2376007Sthurlow if ( ( nLengthWithToken - ( nNumLengthBytes + 1 ) ) != *pnLength )
2386007Sthurlow {
2396007Sthurlow
2406007Sthurlow nReturn = SPNEGO_E_INVALID_LENGTH;
2416007Sthurlow
2426007Sthurlow }
2436007Sthurlow
2446007Sthurlow } // IF need to validate length
2456007Sthurlow
2466007Sthurlow if ( SPNEGO_E_SUCCESS == nReturn )
2476007Sthurlow {
2486007Sthurlow *pnTokenLength = nNumLengthBytes + 1;
2496007Sthurlow }
2506007Sthurlow
2516007Sthurlow } // IF ASNDerGetLength
2526007Sthurlow
2536007Sthurlow } // IF token matches
2546007Sthurlow else
2556007Sthurlow {
2566007Sthurlow nReturn = SPNEGO_E_TOKEN_NOT_FOUND;
2576007Sthurlow }
2586007Sthurlow
2596007Sthurlow } // IF Boundary Length is at least 2 bytes
2606007Sthurlow
2616007Sthurlow return nReturn;
2626007Sthurlow }
2636007Sthurlow
2646007Sthurlow /////////////////////////////////////////////////////////////////////////////
2656007Sthurlow //
2666007Sthurlow // Function:
2676007Sthurlow // ASNDerCheckOID
2686007Sthurlow //
2696007Sthurlow // Parameters:
2706007Sthurlow // [in] pbTokenData - Token Data
2716007Sthurlow // [in] nMechOID - OID we are looking for
2726007Sthurlow // [in] nBoundaryLength - Length that value must not exceed.
2736007Sthurlow // [out] pnTokenLength - Filled out with number of bytes
2746007Sthurlow // consumed by token and data.
2756007Sthurlow //
2766007Sthurlow // Returns:
2776007Sthurlow // int Success - SPNEGO_E_SUCCESS
2786007Sthurlow // Failure - SPNEGO API Error code
2796007Sthurlow //
2806007Sthurlow // Comments :
2816007Sthurlow // Checks the data pointed to by pbTokenData for the specified OID.
2826007Sthurlow //
2836007Sthurlow ////////////////////////////////////////////////////////////////////////////
2846007Sthurlow
ASNDerCheckOID(unsigned char * pbTokenData,SPNEGO_MECH_OID nMechOID,long nBoundaryLength,long * pnTokenLength)2856007Sthurlow int ASNDerCheckOID( unsigned char* pbTokenData, SPNEGO_MECH_OID nMechOID, long nBoundaryLength,
2866007Sthurlow long* pnTokenLength )
2876007Sthurlow {
2886007Sthurlow int nReturn = 0L;
2896007Sthurlow long nLength = 0L;
2906007Sthurlow
2916007Sthurlow // Verify that we have an OID token
2926007Sthurlow if ( ( nReturn = ASNDerCheckToken( pbTokenData, OID, 0L, nBoundaryLength,
2936007Sthurlow &nLength, pnTokenLength ) ) == SPNEGO_E_SUCCESS )
2946007Sthurlow {
2956007Sthurlow // Add the data length to the Token Length
2966007Sthurlow *pnTokenLength += nLength;
2976007Sthurlow
2986007Sthurlow // Token Lengths plus the actual length must match the length in our OID list element.
2996007Sthurlow // If it doesn't, we're done
3006007Sthurlow if ( *pnTokenLength == g_stcMechOIDList[nMechOID].iLen )
3016007Sthurlow {
3026007Sthurlow // Memcompare the token and the expected field
3036007Sthurlow if ( memcmp( pbTokenData, g_stcMechOIDList[nMechOID].ucOid, *pnTokenLength ) != 0 )
3046007Sthurlow {
3056007Sthurlow nReturn = SPNEGO_E_UNEXPECTED_OID;
3066007Sthurlow }
3076007Sthurlow }
3086007Sthurlow else
3096007Sthurlow {
3106007Sthurlow nReturn = SPNEGO_E_UNEXPECTED_OID;
3116007Sthurlow }
3126007Sthurlow
3136007Sthurlow } // IF OID Token CHecks
3146007Sthurlow
3156007Sthurlow return nReturn;
3166007Sthurlow }
3176007Sthurlow
3186007Sthurlow /////////////////////////////////////////////////////////////////////////////
3196007Sthurlow //
3206007Sthurlow // Function:
3216007Sthurlow // ASNDerCalcNumLengthBytes
3226007Sthurlow //
3236007Sthurlow // Parameters:
3246007Sthurlow // [in] nLength - Length to calculate length bytes for.
3256007Sthurlow //
3266007Sthurlow // Returns:
3276007Sthurlow // int Number of bytes necessary to represent length
3286007Sthurlow //
3296007Sthurlow // Comments :
3306007Sthurlow // Helper function to calculate the number of length bytes necessary to
3316007Sthurlow // represent a length value. For our purposes, a 32-bit value should be
3326007Sthurlow // enough to describea length.
3336007Sthurlow //
3346007Sthurlow ////////////////////////////////////////////////////////////////////////////
3356007Sthurlow
ASNDerCalcNumLengthBytes(long nLength)3366007Sthurlow int ASNDerCalcNumLengthBytes( long nLength )
3376007Sthurlow {
3386007Sthurlow if ( nLength <= 0x7F )
3396007Sthurlow {
3406007Sthurlow // A single byte will be sufficient for describing this length.
3416007Sthurlow // The byte will simply contain the length
3426007Sthurlow return 1;
3436007Sthurlow }
3446007Sthurlow else if ( nLength <= 0xFF )
3456007Sthurlow {
3466007Sthurlow // Two bytes are necessary, one to say how many following bytes
3476007Sthurlow // describe the length, and one to give the length
3486007Sthurlow return 2;
3496007Sthurlow }
3506007Sthurlow else if ( nLength <= 0xFFFF )
3516007Sthurlow {
3526007Sthurlow // Three bytes are necessary, one to say how many following bytes
3536007Sthurlow // describe the length, and two to give the length
3546007Sthurlow return 3;
3556007Sthurlow }
3566007Sthurlow else if ( nLength <= 0xFFFFFF )
3576007Sthurlow {
3586007Sthurlow // Four bytes are necessary, one to say how many following bytes
3596007Sthurlow // describe the length, and three to give the length
3606007Sthurlow return 4;
3616007Sthurlow }
3626007Sthurlow else
3636007Sthurlow {
3646007Sthurlow // Five bytes are necessary, one to say how many following bytes
3656007Sthurlow // describe the length, and four to give the length
3666007Sthurlow return 5;
3676007Sthurlow }
3686007Sthurlow }
3696007Sthurlow
3706007Sthurlow
3716007Sthurlow /////////////////////////////////////////////////////////////////////////////
3726007Sthurlow //
3736007Sthurlow // Function:
3746007Sthurlow // ASNDerCalcTokenLength
3756007Sthurlow //
3766007Sthurlow // Parameters:
3776007Sthurlow // [in] nLength - Length to calculate length bytes for.
3786007Sthurlow // [in] nDataLength - Actual Data length value.
3796007Sthurlow //
3806007Sthurlow // Returns:
3816007Sthurlow // long Number of bytes necessary to represent a token, length and data
3826007Sthurlow //
3836007Sthurlow // Comments :
3846007Sthurlow // Helper function to calculate a token and value size, based on a
3856007Sthurlow // supplied length value, and any binary data that will need to be
3866007Sthurlow // written out.
3876007Sthurlow //
3886007Sthurlow ////////////////////////////////////////////////////////////////////////////
3896007Sthurlow
ASNDerCalcTokenLength(long nLength,long nDataLength)3906007Sthurlow long ASNDerCalcTokenLength( long nLength, long nDataLength )
3916007Sthurlow {
3926007Sthurlow // Add a byte to the length size to account for a single byte to
3936007Sthurlow // hold the token type.
3946007Sthurlow long nTotalLength = ASNDerCalcNumLengthBytes( nLength ) + 1;
3956007Sthurlow
3966007Sthurlow return nTotalLength + nDataLength;
3976007Sthurlow }
3986007Sthurlow
3996007Sthurlow
4006007Sthurlow /////////////////////////////////////////////////////////////////////////////
4016007Sthurlow //
4026007Sthurlow // Function:
4036007Sthurlow // ASNDerCalcElementLength
4046007Sthurlow //
4056007Sthurlow // Parameters:
4066007Sthurlow // [in] nDataLength - Length of data.
4076007Sthurlow // [out] pnInternalLength - Filled out with length of element
4086007Sthurlow // without sequence info.
4096007Sthurlow //
4106007Sthurlow // Returns:
4116007Sthurlow // long Number of bytes necessary to represent an element
4126007Sthurlow //
4136007Sthurlow // Comments :
4146007Sthurlow // Helper function to calculate an element length. An element consists
4156007Sthurlow // of a sequence token, a type token and then the data.
4166007Sthurlow //
4176007Sthurlow ////////////////////////////////////////////////////////////////////////////
4186007Sthurlow
ASNDerCalcElementLength(long nDataLength,long * pnInternalLength)4196007Sthurlow long ASNDerCalcElementLength( long nDataLength, long* pnInternalLength )
4206007Sthurlow {
4216007Sthurlow // First the type token and the actual data
4226007Sthurlow long nTotalLength = ASNDerCalcTokenLength( nDataLength, nDataLength );
4236007Sthurlow
4246007Sthurlow // Internal length is the length without the element sequence token
4256007Sthurlow if ( NULL != pnInternalLength )
4266007Sthurlow {
4276007Sthurlow *pnInternalLength = nTotalLength;
4286007Sthurlow }
4296007Sthurlow
4306007Sthurlow // Next add in the element's sequence token (remember that its
4316007Sthurlow // length is the total length of the type token and data)
4326007Sthurlow nTotalLength += ASNDerCalcTokenLength( nTotalLength, 0L );
4336007Sthurlow
4346007Sthurlow return nTotalLength;
4356007Sthurlow }
4366007Sthurlow
4376007Sthurlow /////////////////////////////////////////////////////////////////////////////
4386007Sthurlow //
4396007Sthurlow // Function:
4406007Sthurlow // ASNDerCalcMechListLength
4416007Sthurlow //
4426007Sthurlow // Parameters:
4436007Sthurlow // [in] mechoid - Mech OID to put in list.
4446007Sthurlow // [out] pnInternalLength - Filled out with length of element
4456007Sthurlow // without the primary sequence token.
4466007Sthurlow //
4476007Sthurlow // Returns:
4486007Sthurlow // long Number of bytes necessary to represent a mechList
4496007Sthurlow //
4506007Sthurlow // Comments :
4516007Sthurlow // Helper function to calculate a MechList length. A mechlist consists
4526007Sthurlow // of a NegTokenInit sequence token, a sequence token for the MechList
4536007Sthurlow // and finally a list of OIDs. In our case, we only really have one
4546007Sthurlow // OID.
4556007Sthurlow //
4566007Sthurlow ////////////////////////////////////////////////////////////////////////////
4576007Sthurlow
ASNDerCalcMechListLength(SPNEGO_MECH_OID mechoid,long * pnInternalLength)4586007Sthurlow long ASNDerCalcMechListLength( SPNEGO_MECH_OID mechoid, long* pnInternalLength )
4596007Sthurlow {
4606007Sthurlow // First the OID
4616007Sthurlow long nTotalLength = g_stcMechOIDList[mechoid].iLen;
4626007Sthurlow
4636007Sthurlow // Next add in a sequence token
4646007Sthurlow nTotalLength += ASNDerCalcTokenLength( nTotalLength, 0L );
4656007Sthurlow
4666007Sthurlow // Internal length is the length without the element sequence token
4676007Sthurlow if ( NULL != pnInternalLength )
4686007Sthurlow {
4696007Sthurlow *pnInternalLength = nTotalLength;
4706007Sthurlow }
4716007Sthurlow
4726007Sthurlow // Finally add in the element's sequence token
4736007Sthurlow nTotalLength += ASNDerCalcTokenLength( nTotalLength, 0L );
4746007Sthurlow
4756007Sthurlow return nTotalLength;
4766007Sthurlow }
4776007Sthurlow
4786007Sthurlow
4796007Sthurlow /////////////////////////////////////////////////////////////////////////////
4806007Sthurlow //
4816007Sthurlow // Function:
4826007Sthurlow // ASNDerWriteLength
4836007Sthurlow //
4846007Sthurlow // Parameters:
4856007Sthurlow // [out] pbData - Buffer to write into.
4866007Sthurlow // [in] nLength - Length to write out.
4876007Sthurlow //
4886007Sthurlow // Returns:
4896007Sthurlow // int Number of bytes written out
4906007Sthurlow //
4916007Sthurlow // Comments :
4926007Sthurlow // Helper function to write out a length value following DER rules .
4936007Sthurlow //
4946007Sthurlow ////////////////////////////////////////////////////////////////////////////
4956007Sthurlow
ASNDerWriteLength(unsigned char * pbData,long nLength)4966007Sthurlow int ASNDerWriteLength( unsigned char* pbData, long nLength )
4976007Sthurlow {
4986007Sthurlow int nNumBytesRequired = ASNDerCalcNumLengthBytes( nLength );
4996007Sthurlow int nNumLengthBytes = nNumBytesRequired - 1;
5006007Sthurlow
5016007Sthurlow
5026007Sthurlow if ( nNumBytesRequired > 1 )
5036007Sthurlow {
5046007Sthurlow
5056007Sthurlow // Write out the number of bytes following which will be used
5066007Sthurlow *pbData = (unsigned char ) ( LEN_XTND | nNumLengthBytes );
5076007Sthurlow
5086007Sthurlow // Point to where we'll actually write the length
5096007Sthurlow pbData++;
5106007Sthurlow
5116007Sthurlow #ifdef _LITTLE_ENDIAN
5126007Sthurlow
5136007Sthurlow // There may be a cleaner way to do this, but for now, this seems to be
5146007Sthurlow // an easy way to do the transformation
5156007Sthurlow switch ( nNumLengthBytes )
5166007Sthurlow {
5176007Sthurlow case 1:
5186007Sthurlow {
5196007Sthurlow // Cast the length to a single byte, since we know that it
5206007Sthurlow // is 0x7F or less (or we wouldn't only need a single byte).
5216007Sthurlow
5226007Sthurlow *pbData = (unsigned char) nLength;
5236007Sthurlow break;
5246007Sthurlow }
5256007Sthurlow
5266007Sthurlow case 2:
5276007Sthurlow {
5286007Sthurlow *pbData = *( ( (unsigned char*) &nLength ) + 1 );
5296007Sthurlow *( pbData + 1) = *( ( (unsigned char*) &nLength ) );
5306007Sthurlow break;
5316007Sthurlow }
5326007Sthurlow
5336007Sthurlow case 3:
5346007Sthurlow {
5356007Sthurlow *pbData = *( ( (unsigned char*) &nLength ) + 3 );
5366007Sthurlow *( pbData + 1) = *( ( (unsigned char*) &nLength ) + 2 );
5376007Sthurlow *( pbData + 2) = *( ( (unsigned char*) &nLength ) );
5386007Sthurlow break;
5396007Sthurlow }
5406007Sthurlow
5416007Sthurlow case 4:
5426007Sthurlow {
5436007Sthurlow *pbData = *( ( (unsigned char*) &nLength ) + 3 );
5446007Sthurlow *( pbData + 1) = *( ( (unsigned char*) &nLength ) + 2 );
5456007Sthurlow *( pbData + 2) = *( ( (unsigned char*) &nLength ) + 1 );
5466007Sthurlow *( pbData + 3) = *( ( (unsigned char*) &nLength ) );
5476007Sthurlow break;
5486007Sthurlow }
5496007Sthurlow
5506007Sthurlow } // SWITCH ( nNumLengthBytes )
5516007Sthurlow
5526007Sthurlow #else
5536007Sthurlow // We are Big-Endian, so the length can be copied in from the source
5546007Sthurlow // as is. Ensure that we adjust for the number of bytes we actually
5556007Sthurlow // copy.
5566007Sthurlow
5576007Sthurlow memcpy( pbData,
5586007Sthurlow ( (unsigned char *) &nLength ) + ( 4 - nNumLengthBytes ), nNumLengthBytes );
5596007Sthurlow #endif
5606007Sthurlow
5616007Sthurlow } // IF > 1 byte for length
5626007Sthurlow else
5636007Sthurlow {
5646007Sthurlow // Cast the length to a single byte, since we know that it
5656007Sthurlow // is 0x7F or less (or we wouldn't only need a single byte).
5666007Sthurlow
5676007Sthurlow *pbData = (unsigned char) nLength;
5686007Sthurlow }
5696007Sthurlow
5706007Sthurlow return nNumBytesRequired;
5716007Sthurlow }
5726007Sthurlow
5736007Sthurlow /////////////////////////////////////////////////////////////////////////////
5746007Sthurlow //
5756007Sthurlow // Function:
5766007Sthurlow // ASNDerWriteToken
5776007Sthurlow //
5786007Sthurlow // Parameters:
5796007Sthurlow // [out] pbData - Buffer to write into.
5806007Sthurlow // [in] ucType - Token Type
5816007Sthurlow // [in] pbTokenValue - Actual Value
5826007Sthurlow // [in] nLength - Length of Data.
5836007Sthurlow //
5846007Sthurlow // Returns:
5856007Sthurlow // int Number of bytes written out
5866007Sthurlow //
5876007Sthurlow // Comments :
5886007Sthurlow // Helper function to write out a token and any associated data. If
5896007Sthurlow // pbTokenValue is non-NULL, then it is written out in addition to the
5906007Sthurlow // token identifier and the length bytes.
5916007Sthurlow //
5926007Sthurlow ////////////////////////////////////////////////////////////////////////////
5936007Sthurlow
ASNDerWriteToken(unsigned char * pbData,unsigned char ucType,unsigned char * pbTokenValue,long nLength)5946007Sthurlow int ASNDerWriteToken( unsigned char* pbData, unsigned char ucType,
5956007Sthurlow unsigned char* pbTokenValue, long nLength )
5966007Sthurlow {
5976007Sthurlow int nTotalBytesWrittenOut = 0L;
5986007Sthurlow int nNumLengthBytesWritten = 0L;
5996007Sthurlow
6006007Sthurlow // Write out the type
6016007Sthurlow *pbData = ucType;
6026007Sthurlow
6036007Sthurlow // Wrote 1 byte, and move data pointer
6046007Sthurlow nTotalBytesWrittenOut++;
6056007Sthurlow pbData++;
6066007Sthurlow
6076007Sthurlow // Now write out the length and adjust the number of bytes written out
6086007Sthurlow nNumLengthBytesWritten = ASNDerWriteLength( pbData, nLength );
6096007Sthurlow
6106007Sthurlow nTotalBytesWrittenOut += nNumLengthBytesWritten;
6116007Sthurlow pbData += nNumLengthBytesWritten;
6126007Sthurlow
6136007Sthurlow // Write out the token value if we got one. The assumption is that the
6146007Sthurlow // nLength value indicates how many bytes are in pbTokenValue.
6156007Sthurlow
6166007Sthurlow if ( NULL != pbTokenValue )
6176007Sthurlow {
6186007Sthurlow memcpy( pbData, pbTokenValue, nLength );
6196007Sthurlow nTotalBytesWrittenOut += nLength;
6206007Sthurlow }
6216007Sthurlow
6226007Sthurlow return nTotalBytesWrittenOut;
6236007Sthurlow }
6246007Sthurlow
6256007Sthurlow
6266007Sthurlow /////////////////////////////////////////////////////////////////////////////
6276007Sthurlow //
6286007Sthurlow // Function:
6296007Sthurlow // ASNDerWriteOID
6306007Sthurlow //
6316007Sthurlow // Parameters:
6326007Sthurlow // [out] pbData - Buffer to write into.
6336007Sthurlow // [in] eMechOID - OID to write out.
6346007Sthurlow //
6356007Sthurlow // Returns:
6366007Sthurlow // int Number of bytes written out
6376007Sthurlow //
6386007Sthurlow // Comments :
6396007Sthurlow // Helper function to write out an OID. For these we have the raw bytes
6406007Sthurlow // listed in a global structure. The caller simply indicates which OID
6416007Sthurlow // should be written and we will splat out the data.
6426007Sthurlow //
6436007Sthurlow ////////////////////////////////////////////////////////////////////////////
6446007Sthurlow
ASNDerWriteOID(unsigned char * pbData,SPNEGO_MECH_OID eMechOID)6456007Sthurlow int ASNDerWriteOID( unsigned char* pbData, SPNEGO_MECH_OID eMechOID )
6466007Sthurlow {
6476007Sthurlow
6486007Sthurlow memcpy( pbData, g_stcMechOIDList[eMechOID].ucOid, g_stcMechOIDList[eMechOID].iLen );
6496007Sthurlow
6506007Sthurlow return g_stcMechOIDList[eMechOID].iLen;
6516007Sthurlow }
6526007Sthurlow
6536007Sthurlow
6546007Sthurlow /////////////////////////////////////////////////////////////////////////////
6556007Sthurlow //
6566007Sthurlow // Function:
6576007Sthurlow // ASNDerWriteMechList
6586007Sthurlow //
6596007Sthurlow // Parameters:
6606007Sthurlow // [out] pbData - Buffer to write into.
6616007Sthurlow // [in] eMechOID - OID to put in MechList.
6626007Sthurlow //
6636007Sthurlow // Returns:
6646007Sthurlow // int Number of bytes written out
6656007Sthurlow //
6666007Sthurlow // Comments :
6676007Sthurlow // Helper function to write out a MechList. A MechList consists of the
6686007Sthurlow // Init Token Sequence, a sequence token and then the list of OIDs. In
6696007Sthurlow // our case the OID is from a global array of known OIDs.
6706007Sthurlow //
6716007Sthurlow ////////////////////////////////////////////////////////////////////////////
6726007Sthurlow
ASNDerWriteMechList(unsigned char * pbData,SPNEGO_MECH_OID mechoid)6736007Sthurlow long ASNDerWriteMechList( unsigned char* pbData, SPNEGO_MECH_OID mechoid )
6746007Sthurlow {
6756007Sthurlow // First get the length
6766007Sthurlow long nInternalLength = 0L;
6776007Sthurlow long nMechListLength = ASNDerCalcMechListLength( mechoid, &nInternalLength );
6786007Sthurlow long nTempLength = 0L;
6796007Sthurlow
6806007Sthurlow nTempLength = ASNDerWriteToken( pbData, SPNEGO_NEGINIT_ELEMENT_MECHTYPES,
6816007Sthurlow NULL, nInternalLength );
6826007Sthurlow
6836007Sthurlow // Adjust the data pointer
6846007Sthurlow pbData += nTempLength;
6856007Sthurlow
6866007Sthurlow // Now write the Sequence token and the OID (the OID is a BLOB in the global
6876007Sthurlow // structure.
6886007Sthurlow
6896007Sthurlow nTempLength = ASNDerWriteToken( pbData, SPNEGO_CONSTRUCTED_SEQUENCE,
6906007Sthurlow g_stcMechOIDList[mechoid].ucOid,
6916007Sthurlow g_stcMechOIDList[mechoid].iLen );
6926007Sthurlow
6936007Sthurlow return nMechListLength;
6946007Sthurlow }
6956007Sthurlow
6966007Sthurlow
6976007Sthurlow /////////////////////////////////////////////////////////////////////////////
6986007Sthurlow //
6996007Sthurlow // Function:
7006007Sthurlow // ASNDerWriteElement
7016007Sthurlow //
7026007Sthurlow // Parameters:
7036007Sthurlow // [out] pbData - Buffer to write into.
7046007Sthurlow // [in] ucElementSequence - Sequence Token
7056007Sthurlow // [in] ucType - Token Type
7066007Sthurlow // [in] pbTokenValue - Actual Value
7076007Sthurlow // [in] nLength - Length of Data.
7086007Sthurlow //
7096007Sthurlow // Returns:
7106007Sthurlow // int Number of bytes written out
7116007Sthurlow //
7126007Sthurlow // Comments :
7136007Sthurlow // Helper function to write out a SPNEGO Token element. An element
7146007Sthurlow // consists of a sequence token, a type token and the associated data.
7156007Sthurlow //
7166007Sthurlow ////////////////////////////////////////////////////////////////////////////
7176007Sthurlow
ASNDerWriteElement(unsigned char * pbData,unsigned char ucElementSequence,unsigned char ucType,unsigned char * pbTokenValue,long nLength)7186007Sthurlow int ASNDerWriteElement( unsigned char* pbData, unsigned char ucElementSequence,
7196007Sthurlow unsigned char ucType, unsigned char* pbTokenValue, long nLength )
7206007Sthurlow {
7216007Sthurlow // First get the length
7226007Sthurlow long nInternalLength = 0L;
7236007Sthurlow long nElementLength = ASNDerCalcElementLength( nLength, &nInternalLength );
7246007Sthurlow long nTempLength = 0L;
7256007Sthurlow
7266007Sthurlow // Write out the sequence byte and the length of the type and data
7276007Sthurlow nTempLength = ASNDerWriteToken( pbData, ucElementSequence, NULL, nInternalLength );
7286007Sthurlow
7296007Sthurlow // Adjust the data pointer
7306007Sthurlow pbData += nTempLength;
7316007Sthurlow
7326007Sthurlow // Now write the type and the data.
7336007Sthurlow nTempLength = ASNDerWriteToken( pbData, ucType, pbTokenValue, nLength );
7346007Sthurlow
7356007Sthurlow return nElementLength;
7366007Sthurlow }
737