14bff34e3Sthurlow // Copyright (C) 2002 Microsoft Corporation
24bff34e3Sthurlow // All rights reserved.
34bff34e3Sthurlow //
44bff34e3Sthurlow // THIS CODE AND INFORMATION IS PROVIDED "AS IS"
54bff34e3Sthurlow // WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
64bff34e3Sthurlow // OR IMPLIED, INCLUDING BUT NOT LIMITED
74bff34e3Sthurlow // TO THE IMPLIED WARRANTIES OF MERCHANTIBILITY
84bff34e3Sthurlow // AND/OR FITNESS FOR A PARTICULAR PURPOSE.
94bff34e3Sthurlow //
104bff34e3Sthurlow // Date - 10/08/2002
114bff34e3Sthurlow // Author - Sanj Surati
124bff34e3Sthurlow
134bff34e3Sthurlow
144bff34e3Sthurlow /////////////////////////////////////////////////////////////
154bff34e3Sthurlow //
164bff34e3Sthurlow // DERPARSE.C
174bff34e3Sthurlow //
184bff34e3Sthurlow // SPNEGO Token Handler Source File
194bff34e3Sthurlow //
204bff34e3Sthurlow // Contains implementation of ASN.1 DER read/write functions
214bff34e3Sthurlow // as defined in DERPARSE.H.
224bff34e3Sthurlow //
234bff34e3Sthurlow /////////////////////////////////////////////////////////////
244bff34e3Sthurlow
254bff34e3Sthurlow #include <stdlib.h>
264bff34e3Sthurlow #include <stdio.h>
274bff34e3Sthurlow #include <memory.h>
284bff34e3Sthurlow #include <sys/byteorder.h>
294bff34e3Sthurlow #include "spnego.h"
304bff34e3Sthurlow #include "derparse.h"
314bff34e3Sthurlow
324bff34e3Sthurlow //
334bff34e3Sthurlow // The GSS Mechanism OID enumeration values (SPNEGO_MECH_OID) control which offset in
344bff34e3Sthurlow // the array below, that a mechanism can be found.
354bff34e3Sthurlow //
36613a2f6bSGordon Ross
374bff34e3Sthurlow #pragma error_messages (off,E_INITIALIZATION_TYPE_MISMATCH)
384bff34e3Sthurlow MECH_OID g_stcMechOIDList [] =
394bff34e3Sthurlow {
40*228c5c17SRichard Lowe {(unsigned char *)"\x06\x09\x2a\x86\x48\x82\xf7\x12\x01\x02\x02",
41*228c5c17SRichard Lowe 11, 9, spnego_mech_oid_Kerberos_V5_Legacy}, // 1.2.840.48018.1.2.2
42*228c5c17SRichard Lowe {(unsigned char *)"\x06\x09\x2a\x86\x48\x86\xf7\x12\x01\x02\x02",
43*228c5c17SRichard Lowe 11, 9, spnego_mech_oid_Kerberos_V5}, // 1.2.840.113554.1.2.2
44*228c5c17SRichard Lowe {(unsigned char *)"\x06\x06\x2b\x06\x01\x05\x05\x02",
45*228c5c17SRichard Lowe 8, 6, spnego_mech_oid_Spnego}, // 1.3.6.1.5.5.2
46*228c5c17SRichard Lowe {(unsigned char *)"\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a",
47*228c5c17SRichard Lowe 12, 10, spnego_mech_oid_NTLMSSP}, // 1.3.6.1.4.1.311.2.2.10
48*228c5c17SRichard Lowe {(unsigned char *)"", 0, 0, spnego_mech_oid_NotUsed // Placeholder
49*228c5c17SRichard Lowe }
504bff34e3Sthurlow };
514bff34e3Sthurlow #pragma error_messages (default,E_INITIALIZATION_TYPE_MISMATCH)
524bff34e3Sthurlow
534bff34e3Sthurlow /////////////////////////////////////////////////////////////////////////////
544bff34e3Sthurlow //
554bff34e3Sthurlow // Function:
564bff34e3Sthurlow // ASNDerGetLength
574bff34e3Sthurlow //
584bff34e3Sthurlow // Parameters:
594bff34e3Sthurlow // [in] pbLengthData - DER Length Data
604bff34e3Sthurlow // [in] nBoundaryLength - Length that value must not exceed.
614bff34e3Sthurlow // [out] pnLength - Filled out with length value
624bff34e3Sthurlow // [out] pnNumLengthBytes - Filled out with number of bytes
634bff34e3Sthurlow // consumed by DER length.
644bff34e3Sthurlow //
654bff34e3Sthurlow // Returns:
664bff34e3Sthurlow // int Success - SPNEGO_E_SUCCESS
674bff34e3Sthurlow // Failure - SPNEGO API Error code
684bff34e3Sthurlow //
694bff34e3Sthurlow // Comments :
704bff34e3Sthurlow // Interprets the data at pbLengthData as a DER length. The length must
714bff34e3Sthurlow // fit within the bounds of nBoundary length. We do not currently
724bff34e3Sthurlow // process lengths that take more than 4 bytes.
734bff34e3Sthurlow //
744bff34e3Sthurlow ////////////////////////////////////////////////////////////////////////////
754bff34e3Sthurlow
ASNDerGetLength(unsigned char * pbLengthData,long nBoundaryLength,long * pnLength,long * pnNumLengthBytes)764bff34e3Sthurlow int ASNDerGetLength( unsigned char* pbLengthData, long nBoundaryLength, long* pnLength,
774bff34e3Sthurlow long* pnNumLengthBytes )
784bff34e3Sthurlow {
794bff34e3Sthurlow int nReturn = SPNEGO_E_INVALID_LENGTH;
804bff34e3Sthurlow int nNumLengthBytes = 0;
814bff34e3Sthurlow
824bff34e3Sthurlow // First check if the extended length bit is set
834bff34e3Sthurlow
844bff34e3Sthurlow if ( *pbLengthData & LEN_XTND )
854bff34e3Sthurlow {
864bff34e3Sthurlow // Lower 7 bits contain the number of trailing bytes that describe the length
874bff34e3Sthurlow nNumLengthBytes = *pbLengthData & LEN_MASK;
884bff34e3Sthurlow
894bff34e3Sthurlow // Check that the number of bytes we are about to read is within our boundary
904bff34e3Sthurlow // constraints
914bff34e3Sthurlow
924bff34e3Sthurlow if ( nNumLengthBytes <= nBoundaryLength - 1 )
934bff34e3Sthurlow {
944bff34e3Sthurlow
954bff34e3Sthurlow // For now, our handler won't deal with lengths greater than 4 bytes
964bff34e3Sthurlow if ( nNumLengthBytes >= 1 && nNumLengthBytes <= 4 )
974bff34e3Sthurlow {
984bff34e3Sthurlow // 0 out the initial length
994bff34e3Sthurlow *pnLength = 0L;
1004bff34e3Sthurlow
1014bff34e3Sthurlow // Bump by 1 byte
1024bff34e3Sthurlow pbLengthData++;
1034bff34e3Sthurlow
1044bff34e3Sthurlow #ifdef _LITTLE_ENDIAN
1054bff34e3Sthurlow
1064bff34e3Sthurlow // There may be a cleaner way to do this, but for now, this seems to be
1074bff34e3Sthurlow // an easy way to do the transformation
1084bff34e3Sthurlow switch ( nNumLengthBytes )
1094bff34e3Sthurlow {
1104bff34e3Sthurlow case 1:
1114bff34e3Sthurlow {
1124bff34e3Sthurlow *( ( (unsigned char*) pnLength ) ) = *pbLengthData;
1134bff34e3Sthurlow break;
1144bff34e3Sthurlow }
1154bff34e3Sthurlow
1164bff34e3Sthurlow case 2:
1174bff34e3Sthurlow {
1184bff34e3Sthurlow *( ( (unsigned char*) pnLength ) ) = *(pbLengthData + 1);
1194bff34e3Sthurlow *( ( (unsigned char*) pnLength ) + 1 ) = *(pbLengthData);
1204bff34e3Sthurlow
1214bff34e3Sthurlow break;
1224bff34e3Sthurlow }
1234bff34e3Sthurlow
1244bff34e3Sthurlow case 3:
1254bff34e3Sthurlow {
1264bff34e3Sthurlow *( ( (unsigned char*) pnLength ) ) = *(pbLengthData + 2);
1274bff34e3Sthurlow *( ( (unsigned char*) pnLength ) + 2 ) = *(pbLengthData + 1);
1284bff34e3Sthurlow *( ( (unsigned char*) pnLength ) + 3 ) = *(pbLengthData);
1294bff34e3Sthurlow break;
1304bff34e3Sthurlow }
1314bff34e3Sthurlow
1324bff34e3Sthurlow case 4:
1334bff34e3Sthurlow {
1344bff34e3Sthurlow *( ( (unsigned char*) pnLength ) ) = *(pbLengthData + 3);
1354bff34e3Sthurlow *( ( (unsigned char*) pnLength ) + 1 ) = *(pbLengthData + 2);
1364bff34e3Sthurlow *( ( (unsigned char*) pnLength ) + 2 ) = *(pbLengthData + 1);
1374bff34e3Sthurlow *( ( (unsigned char*) pnLength ) + 3 ) = *(pbLengthData);
1384bff34e3Sthurlow break;
1394bff34e3Sthurlow }
1404bff34e3Sthurlow
1414bff34e3Sthurlow } // SWITCH ( nNumLengthBytes )
1424bff34e3Sthurlow
1434bff34e3Sthurlow #else
1444bff34e3Sthurlow // We are Big-Endian, so the length can be copied in from the source
1454bff34e3Sthurlow // as is. Ensure that we adjust for the number of bytes we actually
1464bff34e3Sthurlow // copy.
1474bff34e3Sthurlow
1484bff34e3Sthurlow memcpy( ( (unsigned char *) pnLength ) + ( 4 - nNumLengthBytes ),
1494bff34e3Sthurlow pbLengthData, nNumLengthBytes );
1504bff34e3Sthurlow #endif
1514bff34e3Sthurlow
1524bff34e3Sthurlow // Account for the initial length byte
1534bff34e3Sthurlow *pnNumLengthBytes = nNumLengthBytes + 1;
1544bff34e3Sthurlow nReturn = SPNEGO_E_SUCCESS;
1554bff34e3Sthurlow
1564bff34e3Sthurlow } // IF Valid Length
1574bff34e3Sthurlow
1584bff34e3Sthurlow } // IF num bytes to read is within the boundary length
1594bff34e3Sthurlow
1604bff34e3Sthurlow } // IF xtended length
1614bff34e3Sthurlow else
1624bff34e3Sthurlow {
1634bff34e3Sthurlow
1644bff34e3Sthurlow // Extended bit is not set, so the length is in the value and the one
1654bff34e3Sthurlow // byte describes the length
1664bff34e3Sthurlow *pnLength = *pbLengthData & LEN_MASK;
1674bff34e3Sthurlow *pnNumLengthBytes = 1;
1684bff34e3Sthurlow nReturn = SPNEGO_E_SUCCESS;
1694bff34e3Sthurlow
1704bff34e3Sthurlow }
1714bff34e3Sthurlow
1724bff34e3Sthurlow return nReturn;
1734bff34e3Sthurlow }
1744bff34e3Sthurlow
1754bff34e3Sthurlow
1764bff34e3Sthurlow /////////////////////////////////////////////////////////////////////////////
1774bff34e3Sthurlow //
1784bff34e3Sthurlow // Function:
1794bff34e3Sthurlow // ASNDerCheckToken
1804bff34e3Sthurlow //
1814bff34e3Sthurlow // Parameters:
1824bff34e3Sthurlow // [in] pbTokenData - Token Data
1834bff34e3Sthurlow // [in] nToken - Token identifier to check for
1844bff34e3Sthurlow // [in] nLengthWithToken - Expected token length (with data)
1854bff34e3Sthurlow // [in] nBoundaryLength - Length that value must not exceed.
1864bff34e3Sthurlow // [out] pnLength - Filled out with data length
1874bff34e3Sthurlow // [out] pnTokenLength - Filled out with number of bytes
1884bff34e3Sthurlow // consumed by token identifier and length.
1894bff34e3Sthurlow //
1904bff34e3Sthurlow // Returns:
1914bff34e3Sthurlow // int Success - SPNEGO_E_SUCCESS
1924bff34e3Sthurlow // Failure - SPNEGO API Error code
1934bff34e3Sthurlow //
1944bff34e3Sthurlow // Comments :
1954bff34e3Sthurlow // Checks the data pointed to by pbTokenData for the specified token
1964bff34e3Sthurlow // identifier and the length that immediately follows. If
1974bff34e3Sthurlow // nLengthWithToken is > 0, the calculated length must match. The
1984bff34e3Sthurlow // length must also not exceed the specified boundary length .
1994bff34e3Sthurlow //
2004bff34e3Sthurlow ////////////////////////////////////////////////////////////////////////////
2014bff34e3Sthurlow
ASNDerCheckToken(unsigned char * pbTokenData,unsigned char nToken,long nLengthWithToken,long nBoundaryLength,long * pnLength,long * pnTokenLength)2024bff34e3Sthurlow int ASNDerCheckToken( unsigned char* pbTokenData, unsigned char nToken,
2034bff34e3Sthurlow long nLengthWithToken, long nBoundaryLength,
2044bff34e3Sthurlow long* pnLength, long* pnTokenLength )
2054bff34e3Sthurlow {
2064bff34e3Sthurlow
2074bff34e3Sthurlow int nReturn = SPNEGO_E_INVALID_LENGTH;
2084bff34e3Sthurlow long nNumLengthBytes = 0L;
2094bff34e3Sthurlow
2104bff34e3Sthurlow // Make sure that we've at least got 2 bytes of room to work with
2114bff34e3Sthurlow
2124bff34e3Sthurlow if ( nBoundaryLength >= 2 )
2134bff34e3Sthurlow {
2144bff34e3Sthurlow // The first byte of the token data MUST match the specified token
2154bff34e3Sthurlow if ( *pbTokenData == nToken )
2164bff34e3Sthurlow {
2174bff34e3Sthurlow // Next byte indicates the length
2184bff34e3Sthurlow pbTokenData++;
2194bff34e3Sthurlow
2204bff34e3Sthurlow // Get the length described by the token
2214bff34e3Sthurlow if ( ( nReturn = ASNDerGetLength( pbTokenData, nBoundaryLength, pnLength,
2224bff34e3Sthurlow &nNumLengthBytes ) ) == SPNEGO_E_SUCCESS )
2234bff34e3Sthurlow {
2244bff34e3Sthurlow // Verify that the length is LESS THAN the boundary length
2254bff34e3Sthurlow // (this should prevent us walking out of our buffer)
2264bff34e3Sthurlow if ( ( nBoundaryLength - ( nNumLengthBytes + 1 ) < *pnLength ) )
2274bff34e3Sthurlow {
2284bff34e3Sthurlow
2294bff34e3Sthurlow nReturn = SPNEGO_E_INVALID_LENGTH;
2304bff34e3Sthurlow
2314bff34e3Sthurlow }
2324bff34e3Sthurlow
2334bff34e3Sthurlow // If we were passed a length to check, do so now
2344bff34e3Sthurlow if ( nLengthWithToken > 0L )
2354bff34e3Sthurlow {
2364bff34e3Sthurlow
2374bff34e3Sthurlow // Check that the expected length matches
2384bff34e3Sthurlow if ( ( nLengthWithToken - ( nNumLengthBytes + 1 ) ) != *pnLength )
2394bff34e3Sthurlow {
2404bff34e3Sthurlow
2414bff34e3Sthurlow nReturn = SPNEGO_E_INVALID_LENGTH;
2424bff34e3Sthurlow
2434bff34e3Sthurlow }
2444bff34e3Sthurlow
2454bff34e3Sthurlow } // IF need to validate length
2464bff34e3Sthurlow
2474bff34e3Sthurlow if ( SPNEGO_E_SUCCESS == nReturn )
2484bff34e3Sthurlow {
2494bff34e3Sthurlow *pnTokenLength = nNumLengthBytes + 1;
2504bff34e3Sthurlow }
2514bff34e3Sthurlow
2524bff34e3Sthurlow } // IF ASNDerGetLength
2534bff34e3Sthurlow
2544bff34e3Sthurlow } // IF token matches
2554bff34e3Sthurlow else
2564bff34e3Sthurlow {
2574bff34e3Sthurlow nReturn = SPNEGO_E_TOKEN_NOT_FOUND;
2584bff34e3Sthurlow }
2594bff34e3Sthurlow
2604bff34e3Sthurlow } // IF Boundary Length is at least 2 bytes
2614bff34e3Sthurlow
2624bff34e3Sthurlow return nReturn;
2634bff34e3Sthurlow }
2644bff34e3Sthurlow
2654bff34e3Sthurlow /////////////////////////////////////////////////////////////////////////////
2664bff34e3Sthurlow //
2674bff34e3Sthurlow // Function:
2684bff34e3Sthurlow // ASNDerCheckOID
2694bff34e3Sthurlow //
2704bff34e3Sthurlow // Parameters:
2714bff34e3Sthurlow // [in] pbTokenData - Token Data
2724bff34e3Sthurlow // [in] nMechOID - OID we are looking for
2734bff34e3Sthurlow // [in] nBoundaryLength - Length that value must not exceed.
2744bff34e3Sthurlow // [out] pnTokenLength - Filled out with number of bytes
2754bff34e3Sthurlow // consumed by token and data.
2764bff34e3Sthurlow //
2774bff34e3Sthurlow // Returns:
2784bff34e3Sthurlow // int Success - SPNEGO_E_SUCCESS
2794bff34e3Sthurlow // Failure - SPNEGO API Error code
2804bff34e3Sthurlow //
2814bff34e3Sthurlow // Comments :
2824bff34e3Sthurlow // Checks the data pointed to by pbTokenData for the specified OID.
2834bff34e3Sthurlow //
2844bff34e3Sthurlow ////////////////////////////////////////////////////////////////////////////
2854bff34e3Sthurlow
ASNDerCheckOID(unsigned char * pbTokenData,SPNEGO_MECH_OID nMechOID,long nBoundaryLength,long * pnTokenLength)2864bff34e3Sthurlow int ASNDerCheckOID( unsigned char* pbTokenData, SPNEGO_MECH_OID nMechOID, long nBoundaryLength,
2874bff34e3Sthurlow long* pnTokenLength )
2884bff34e3Sthurlow {
2894bff34e3Sthurlow int nReturn = 0L;
2904bff34e3Sthurlow long nLength = 0L;
2914bff34e3Sthurlow
2924bff34e3Sthurlow // Verify that we have an OID token
2934bff34e3Sthurlow if ( ( nReturn = ASNDerCheckToken( pbTokenData, OID, 0L, nBoundaryLength,
2944bff34e3Sthurlow &nLength, pnTokenLength ) ) == SPNEGO_E_SUCCESS )
2954bff34e3Sthurlow {
2964bff34e3Sthurlow // Add the data length to the Token Length
2974bff34e3Sthurlow *pnTokenLength += nLength;
2984bff34e3Sthurlow
2994bff34e3Sthurlow // Token Lengths plus the actual length must match the length in our OID list element.
3004bff34e3Sthurlow // If it doesn't, we're done
3014bff34e3Sthurlow if ( *pnTokenLength == g_stcMechOIDList[nMechOID].iLen )
3024bff34e3Sthurlow {
3034bff34e3Sthurlow // Memcompare the token and the expected field
3044bff34e3Sthurlow if ( memcmp( pbTokenData, g_stcMechOIDList[nMechOID].ucOid, *pnTokenLength ) != 0 )
3054bff34e3Sthurlow {
3064bff34e3Sthurlow nReturn = SPNEGO_E_UNEXPECTED_OID;
3074bff34e3Sthurlow }
3084bff34e3Sthurlow }
3094bff34e3Sthurlow else
3104bff34e3Sthurlow {
3114bff34e3Sthurlow nReturn = SPNEGO_E_UNEXPECTED_OID;
3124bff34e3Sthurlow }
3134bff34e3Sthurlow
3144bff34e3Sthurlow } // IF OID Token CHecks
3154bff34e3Sthurlow
3164bff34e3Sthurlow return nReturn;
3174bff34e3Sthurlow }
3184bff34e3Sthurlow
3194bff34e3Sthurlow /////////////////////////////////////////////////////////////////////////////
3204bff34e3Sthurlow //
3214bff34e3Sthurlow // Function:
3224bff34e3Sthurlow // ASNDerCalcNumLengthBytes
3234bff34e3Sthurlow //
3244bff34e3Sthurlow // Parameters:
3254bff34e3Sthurlow // [in] nLength - Length to calculate length bytes for.
3264bff34e3Sthurlow //
3274bff34e3Sthurlow // Returns:
3284bff34e3Sthurlow // int Number of bytes necessary to represent length
3294bff34e3Sthurlow //
3304bff34e3Sthurlow // Comments :
3314bff34e3Sthurlow // Helper function to calculate the number of length bytes necessary to
3324bff34e3Sthurlow // represent a length value. For our purposes, a 32-bit value should be
3334bff34e3Sthurlow // enough to describea length.
3344bff34e3Sthurlow //
3354bff34e3Sthurlow ////////////////////////////////////////////////////////////////////////////
3364bff34e3Sthurlow
ASNDerCalcNumLengthBytes(long nLength)3374bff34e3Sthurlow int ASNDerCalcNumLengthBytes( long nLength )
3384bff34e3Sthurlow {
3394bff34e3Sthurlow if ( nLength <= 0x7F )
3404bff34e3Sthurlow {
3414bff34e3Sthurlow // A single byte will be sufficient for describing this length.
3424bff34e3Sthurlow // The byte will simply contain the length
3434bff34e3Sthurlow return 1;
3444bff34e3Sthurlow }
3454bff34e3Sthurlow else if ( nLength <= 0xFF )
3464bff34e3Sthurlow {
3474bff34e3Sthurlow // Two bytes are necessary, one to say how many following bytes
3484bff34e3Sthurlow // describe the length, and one to give the length
3494bff34e3Sthurlow return 2;
3504bff34e3Sthurlow }
3514bff34e3Sthurlow else if ( nLength <= 0xFFFF )
3524bff34e3Sthurlow {
3534bff34e3Sthurlow // Three bytes are necessary, one to say how many following bytes
3544bff34e3Sthurlow // describe the length, and two to give the length
3554bff34e3Sthurlow return 3;
3564bff34e3Sthurlow }
3574bff34e3Sthurlow else if ( nLength <= 0xFFFFFF )
3584bff34e3Sthurlow {
3594bff34e3Sthurlow // Four bytes are necessary, one to say how many following bytes
3604bff34e3Sthurlow // describe the length, and three to give the length
3614bff34e3Sthurlow return 4;
3624bff34e3Sthurlow }
3634bff34e3Sthurlow else
3644bff34e3Sthurlow {
3654bff34e3Sthurlow // Five bytes are necessary, one to say how many following bytes
3664bff34e3Sthurlow // describe the length, and four to give the length
3674bff34e3Sthurlow return 5;
3684bff34e3Sthurlow }
3694bff34e3Sthurlow }
3704bff34e3Sthurlow
3714bff34e3Sthurlow
3724bff34e3Sthurlow /////////////////////////////////////////////////////////////////////////////
3734bff34e3Sthurlow //
3744bff34e3Sthurlow // Function:
3754bff34e3Sthurlow // ASNDerCalcTokenLength
3764bff34e3Sthurlow //
3774bff34e3Sthurlow // Parameters:
3784bff34e3Sthurlow // [in] nLength - Length to calculate length bytes for.
3794bff34e3Sthurlow // [in] nDataLength - Actual Data length value.
3804bff34e3Sthurlow //
3814bff34e3Sthurlow // Returns:
3824bff34e3Sthurlow // long Number of bytes necessary to represent a token, length and data
3834bff34e3Sthurlow //
3844bff34e3Sthurlow // Comments :
3854bff34e3Sthurlow // Helper function to calculate a token and value size, based on a
3864bff34e3Sthurlow // supplied length value, and any binary data that will need to be
3874bff34e3Sthurlow // written out.
3884bff34e3Sthurlow //
3894bff34e3Sthurlow ////////////////////////////////////////////////////////////////////////////
3904bff34e3Sthurlow
ASNDerCalcTokenLength(long nLength,long nDataLength)3914bff34e3Sthurlow long ASNDerCalcTokenLength( long nLength, long nDataLength )
3924bff34e3Sthurlow {
3934bff34e3Sthurlow // Add a byte to the length size to account for a single byte to
3944bff34e3Sthurlow // hold the token type.
3954bff34e3Sthurlow long nTotalLength = ASNDerCalcNumLengthBytes( nLength ) + 1;
3964bff34e3Sthurlow
3974bff34e3Sthurlow return nTotalLength + nDataLength;
3984bff34e3Sthurlow }
3994bff34e3Sthurlow
4004bff34e3Sthurlow
4014bff34e3Sthurlow /////////////////////////////////////////////////////////////////////////////
4024bff34e3Sthurlow //
4034bff34e3Sthurlow // Function:
4044bff34e3Sthurlow // ASNDerCalcElementLength
4054bff34e3Sthurlow //
4064bff34e3Sthurlow // Parameters:
4074bff34e3Sthurlow // [in] nDataLength - Length of data.
4084bff34e3Sthurlow // [out] pnInternalLength - Filled out with length of element
4094bff34e3Sthurlow // without sequence info.
4104bff34e3Sthurlow //
4114bff34e3Sthurlow // Returns:
4124bff34e3Sthurlow // long Number of bytes necessary to represent an element
4134bff34e3Sthurlow //
4144bff34e3Sthurlow // Comments :
4154bff34e3Sthurlow // Helper function to calculate an element length. An element consists
4164bff34e3Sthurlow // of a sequence token, a type token and then the data.
4174bff34e3Sthurlow //
4184bff34e3Sthurlow ////////////////////////////////////////////////////////////////////////////
4194bff34e3Sthurlow
ASNDerCalcElementLength(long nDataLength,long * pnInternalLength)4204bff34e3Sthurlow long ASNDerCalcElementLength( long nDataLength, long* pnInternalLength )
4214bff34e3Sthurlow {
4224bff34e3Sthurlow // First the type token and the actual data
4234bff34e3Sthurlow long nTotalLength = ASNDerCalcTokenLength( nDataLength, nDataLength );
4244bff34e3Sthurlow
4254bff34e3Sthurlow // Internal length is the length without the element sequence token
4264bff34e3Sthurlow if ( NULL != pnInternalLength )
4274bff34e3Sthurlow {
4284bff34e3Sthurlow *pnInternalLength = nTotalLength;
4294bff34e3Sthurlow }
4304bff34e3Sthurlow
4314bff34e3Sthurlow // Next add in the element's sequence token (remember that its
4324bff34e3Sthurlow // length is the total length of the type token and data)
4334bff34e3Sthurlow nTotalLength += ASNDerCalcTokenLength( nTotalLength, 0L );
4344bff34e3Sthurlow
4354bff34e3Sthurlow return nTotalLength;
4364bff34e3Sthurlow }
4374bff34e3Sthurlow
4384bff34e3Sthurlow /////////////////////////////////////////////////////////////////////////////
4394bff34e3Sthurlow //
4404bff34e3Sthurlow // Function:
4414bff34e3Sthurlow // ASNDerCalcMechListLength
4424bff34e3Sthurlow //
4434bff34e3Sthurlow // Parameters:
4444bff34e3Sthurlow // [in] mechoid - Mech OID to put in list.
4454bff34e3Sthurlow // [out] pnInternalLength - Filled out with length of element
4464bff34e3Sthurlow // without the primary sequence token.
4474bff34e3Sthurlow //
4484bff34e3Sthurlow // Returns:
4494bff34e3Sthurlow // long Number of bytes necessary to represent a mechList
4504bff34e3Sthurlow //
4514bff34e3Sthurlow // Comments :
4524bff34e3Sthurlow // Helper function to calculate a MechList length. A mechlist consists
4534bff34e3Sthurlow // of a NegTokenInit sequence token, a sequence token for the MechList
4544bff34e3Sthurlow // and finally a list of OIDs. In our case, we only really have one
4554bff34e3Sthurlow // OID.
4564bff34e3Sthurlow //
4574bff34e3Sthurlow ////////////////////////////////////////////////////////////////////////////
4584bff34e3Sthurlow
ASNDerCalcMechListLength(SPNEGO_MECH_OID mechoid,long * pnInternalLength)4594bff34e3Sthurlow long ASNDerCalcMechListLength( SPNEGO_MECH_OID mechoid, long* pnInternalLength )
4604bff34e3Sthurlow {
4614bff34e3Sthurlow // First the OID
4624bff34e3Sthurlow long nTotalLength = g_stcMechOIDList[mechoid].iLen;
4634bff34e3Sthurlow
4644bff34e3Sthurlow // Next add in a sequence token
4654bff34e3Sthurlow nTotalLength += ASNDerCalcTokenLength( nTotalLength, 0L );
4664bff34e3Sthurlow
4674bff34e3Sthurlow // Internal length is the length without the element sequence token
4684bff34e3Sthurlow if ( NULL != pnInternalLength )
4694bff34e3Sthurlow {
4704bff34e3Sthurlow *pnInternalLength = nTotalLength;
4714bff34e3Sthurlow }
4724bff34e3Sthurlow
4734bff34e3Sthurlow // Finally add in the element's sequence token
4744bff34e3Sthurlow nTotalLength += ASNDerCalcTokenLength( nTotalLength, 0L );
4754bff34e3Sthurlow
4764bff34e3Sthurlow return nTotalLength;
4774bff34e3Sthurlow }
4784bff34e3Sthurlow
4794bff34e3Sthurlow
4804bff34e3Sthurlow /////////////////////////////////////////////////////////////////////////////
4814bff34e3Sthurlow //
4824bff34e3Sthurlow // Function:
4834bff34e3Sthurlow // ASNDerWriteLength
4844bff34e3Sthurlow //
4854bff34e3Sthurlow // Parameters:
4864bff34e3Sthurlow // [out] pbData - Buffer to write into.
4874bff34e3Sthurlow // [in] nLength - Length to write out.
4884bff34e3Sthurlow //
4894bff34e3Sthurlow // Returns:
4904bff34e3Sthurlow // int Number of bytes written out
4914bff34e3Sthurlow //
4924bff34e3Sthurlow // Comments :
4934bff34e3Sthurlow // Helper function to write out a length value following DER rules .
4944bff34e3Sthurlow //
4954bff34e3Sthurlow ////////////////////////////////////////////////////////////////////////////
4964bff34e3Sthurlow
ASNDerWriteLength(unsigned char * pbData,long nLength)4974bff34e3Sthurlow int ASNDerWriteLength( unsigned char* pbData, long nLength )
4984bff34e3Sthurlow {
4994bff34e3Sthurlow int nNumBytesRequired = ASNDerCalcNumLengthBytes( nLength );
5004bff34e3Sthurlow int nNumLengthBytes = nNumBytesRequired - 1;
5014bff34e3Sthurlow
5024bff34e3Sthurlow
5034bff34e3Sthurlow if ( nNumBytesRequired > 1 )
5044bff34e3Sthurlow {
5054bff34e3Sthurlow
5064bff34e3Sthurlow // Write out the number of bytes following which will be used
5074bff34e3Sthurlow *pbData = (unsigned char ) ( LEN_XTND | nNumLengthBytes );
5084bff34e3Sthurlow
5094bff34e3Sthurlow // Point to where we'll actually write the length
5104bff34e3Sthurlow pbData++;
5114bff34e3Sthurlow
5124bff34e3Sthurlow #ifdef _LITTLE_ENDIAN
5134bff34e3Sthurlow
5144bff34e3Sthurlow // There may be a cleaner way to do this, but for now, this seems to be
5154bff34e3Sthurlow // an easy way to do the transformation
5164bff34e3Sthurlow switch ( nNumLengthBytes )
5174bff34e3Sthurlow {
5184bff34e3Sthurlow case 1:
5194bff34e3Sthurlow {
5204bff34e3Sthurlow // Cast the length to a single byte, since we know that it
5214bff34e3Sthurlow // is 0x7F or less (or we wouldn't only need a single byte).
5224bff34e3Sthurlow
5234bff34e3Sthurlow *pbData = (unsigned char) nLength;
5244bff34e3Sthurlow break;
5254bff34e3Sthurlow }
5264bff34e3Sthurlow
5274bff34e3Sthurlow case 2:
5284bff34e3Sthurlow {
5294bff34e3Sthurlow *pbData = *( ( (unsigned char*) &nLength ) + 1 );
5304bff34e3Sthurlow *( pbData + 1) = *( ( (unsigned char*) &nLength ) );
5314bff34e3Sthurlow break;
5324bff34e3Sthurlow }
5334bff34e3Sthurlow
5344bff34e3Sthurlow case 3:
5354bff34e3Sthurlow {
5364bff34e3Sthurlow *pbData = *( ( (unsigned char*) &nLength ) + 3 );
5374bff34e3Sthurlow *( pbData + 1) = *( ( (unsigned char*) &nLength ) + 2 );
5384bff34e3Sthurlow *( pbData + 2) = *( ( (unsigned char*) &nLength ) );
5394bff34e3Sthurlow break;
5404bff34e3Sthurlow }
5414bff34e3Sthurlow
5424bff34e3Sthurlow case 4:
5434bff34e3Sthurlow {
5444bff34e3Sthurlow *pbData = *( ( (unsigned char*) &nLength ) + 3 );
5454bff34e3Sthurlow *( pbData + 1) = *( ( (unsigned char*) &nLength ) + 2 );
5464bff34e3Sthurlow *( pbData + 2) = *( ( (unsigned char*) &nLength ) + 1 );
5474bff34e3Sthurlow *( pbData + 3) = *( ( (unsigned char*) &nLength ) );
5484bff34e3Sthurlow break;
5494bff34e3Sthurlow }
5504bff34e3Sthurlow
5514bff34e3Sthurlow } // SWITCH ( nNumLengthBytes )
5524bff34e3Sthurlow
5534bff34e3Sthurlow #else
5544bff34e3Sthurlow // We are Big-Endian, so the length can be copied in from the source
5554bff34e3Sthurlow // as is. Ensure that we adjust for the number of bytes we actually
5564bff34e3Sthurlow // copy.
5574bff34e3Sthurlow
5584bff34e3Sthurlow memcpy( pbData,
5594bff34e3Sthurlow ( (unsigned char *) &nLength ) + ( 4 - nNumLengthBytes ), nNumLengthBytes );
5604bff34e3Sthurlow #endif
5614bff34e3Sthurlow
5624bff34e3Sthurlow } // IF > 1 byte for length
5634bff34e3Sthurlow else
5644bff34e3Sthurlow {
5654bff34e3Sthurlow // Cast the length to a single byte, since we know that it
5664bff34e3Sthurlow // is 0x7F or less (or we wouldn't only need a single byte).
5674bff34e3Sthurlow
5684bff34e3Sthurlow *pbData = (unsigned char) nLength;
5694bff34e3Sthurlow }
5704bff34e3Sthurlow
5714bff34e3Sthurlow return nNumBytesRequired;
5724bff34e3Sthurlow }
5734bff34e3Sthurlow
5744bff34e3Sthurlow /////////////////////////////////////////////////////////////////////////////
5754bff34e3Sthurlow //
5764bff34e3Sthurlow // Function:
5774bff34e3Sthurlow // ASNDerWriteToken
5784bff34e3Sthurlow //
5794bff34e3Sthurlow // Parameters:
5804bff34e3Sthurlow // [out] pbData - Buffer to write into.
5814bff34e3Sthurlow // [in] ucType - Token Type
5824bff34e3Sthurlow // [in] pbTokenValue - Actual Value
5834bff34e3Sthurlow // [in] nLength - Length of Data.
5844bff34e3Sthurlow //
5854bff34e3Sthurlow // Returns:
5864bff34e3Sthurlow // int Number of bytes written out
5874bff34e3Sthurlow //
5884bff34e3Sthurlow // Comments :
5894bff34e3Sthurlow // Helper function to write out a token and any associated data. If
5904bff34e3Sthurlow // pbTokenValue is non-NULL, then it is written out in addition to the
5914bff34e3Sthurlow // token identifier and the length bytes.
5924bff34e3Sthurlow //
5934bff34e3Sthurlow ////////////////////////////////////////////////////////////////////////////
5944bff34e3Sthurlow
ASNDerWriteToken(unsigned char * pbData,unsigned char ucType,unsigned char * pbTokenValue,long nLength)5954bff34e3Sthurlow int ASNDerWriteToken( unsigned char* pbData, unsigned char ucType,
5964bff34e3Sthurlow unsigned char* pbTokenValue, long nLength )
5974bff34e3Sthurlow {
5984bff34e3Sthurlow int nTotalBytesWrittenOut = 0L;
5994bff34e3Sthurlow int nNumLengthBytesWritten = 0L;
6004bff34e3Sthurlow
6014bff34e3Sthurlow // Write out the type
6024bff34e3Sthurlow *pbData = ucType;
6034bff34e3Sthurlow
6044bff34e3Sthurlow // Wrote 1 byte, and move data pointer
6054bff34e3Sthurlow nTotalBytesWrittenOut++;
6064bff34e3Sthurlow pbData++;
6074bff34e3Sthurlow
6084bff34e3Sthurlow // Now write out the length and adjust the number of bytes written out
6094bff34e3Sthurlow nNumLengthBytesWritten = ASNDerWriteLength( pbData, nLength );
6104bff34e3Sthurlow
6114bff34e3Sthurlow nTotalBytesWrittenOut += nNumLengthBytesWritten;
6124bff34e3Sthurlow pbData += nNumLengthBytesWritten;
6134bff34e3Sthurlow
6144bff34e3Sthurlow // Write out the token value if we got one. The assumption is that the
6154bff34e3Sthurlow // nLength value indicates how many bytes are in pbTokenValue.
6164bff34e3Sthurlow
6174bff34e3Sthurlow if ( NULL != pbTokenValue )
6184bff34e3Sthurlow {
6194bff34e3Sthurlow memcpy( pbData, pbTokenValue, nLength );
6204bff34e3Sthurlow nTotalBytesWrittenOut += nLength;
6214bff34e3Sthurlow }
6224bff34e3Sthurlow
6234bff34e3Sthurlow return nTotalBytesWrittenOut;
6244bff34e3Sthurlow }
6254bff34e3Sthurlow
6264bff34e3Sthurlow
6274bff34e3Sthurlow /////////////////////////////////////////////////////////////////////////////
6284bff34e3Sthurlow //
6294bff34e3Sthurlow // Function:
6304bff34e3Sthurlow // ASNDerWriteOID
6314bff34e3Sthurlow //
6324bff34e3Sthurlow // Parameters:
6334bff34e3Sthurlow // [out] pbData - Buffer to write into.
6344bff34e3Sthurlow // [in] eMechOID - OID to write out.
6354bff34e3Sthurlow //
6364bff34e3Sthurlow // Returns:
6374bff34e3Sthurlow // int Number of bytes written out
6384bff34e3Sthurlow //
6394bff34e3Sthurlow // Comments :
6404bff34e3Sthurlow // Helper function to write out an OID. For these we have the raw bytes
6414bff34e3Sthurlow // listed in a global structure. The caller simply indicates which OID
6424bff34e3Sthurlow // should be written and we will splat out the data.
6434bff34e3Sthurlow //
6444bff34e3Sthurlow ////////////////////////////////////////////////////////////////////////////
6454bff34e3Sthurlow
ASNDerWriteOID(unsigned char * pbData,SPNEGO_MECH_OID eMechOID)6464bff34e3Sthurlow int ASNDerWriteOID( unsigned char* pbData, SPNEGO_MECH_OID eMechOID )
6474bff34e3Sthurlow {
6484bff34e3Sthurlow
6494bff34e3Sthurlow memcpy( pbData, g_stcMechOIDList[eMechOID].ucOid, g_stcMechOIDList[eMechOID].iLen );
6504bff34e3Sthurlow
6514bff34e3Sthurlow return g_stcMechOIDList[eMechOID].iLen;
6524bff34e3Sthurlow }
6534bff34e3Sthurlow
6544bff34e3Sthurlow
6554bff34e3Sthurlow /////////////////////////////////////////////////////////////////////////////
6564bff34e3Sthurlow //
6574bff34e3Sthurlow // Function:
6584bff34e3Sthurlow // ASNDerWriteMechList
6594bff34e3Sthurlow //
6604bff34e3Sthurlow // Parameters:
6614bff34e3Sthurlow // [out] pbData - Buffer to write into.
6624bff34e3Sthurlow // [in] eMechOID - OID to put in MechList.
6634bff34e3Sthurlow //
6644bff34e3Sthurlow // Returns:
6654bff34e3Sthurlow // int Number of bytes written out
6664bff34e3Sthurlow //
6674bff34e3Sthurlow // Comments :
6684bff34e3Sthurlow // Helper function to write out a MechList. A MechList consists of the
6694bff34e3Sthurlow // Init Token Sequence, a sequence token and then the list of OIDs. In
6704bff34e3Sthurlow // our case the OID is from a global array of known OIDs.
6714bff34e3Sthurlow //
6724bff34e3Sthurlow ////////////////////////////////////////////////////////////////////////////
6734bff34e3Sthurlow
ASNDerWriteMechList(unsigned char * pbData,SPNEGO_MECH_OID mechoid)6744bff34e3Sthurlow long ASNDerWriteMechList( unsigned char* pbData, SPNEGO_MECH_OID mechoid )
6754bff34e3Sthurlow {
6764bff34e3Sthurlow // First get the length
6774bff34e3Sthurlow long nInternalLength = 0L;
6784bff34e3Sthurlow long nMechListLength = ASNDerCalcMechListLength( mechoid, &nInternalLength );
6794bff34e3Sthurlow long nTempLength = 0L;
6804bff34e3Sthurlow
6814bff34e3Sthurlow nTempLength = ASNDerWriteToken( pbData, SPNEGO_NEGINIT_ELEMENT_MECHTYPES,
6824bff34e3Sthurlow NULL, nInternalLength );
6834bff34e3Sthurlow
6844bff34e3Sthurlow // Adjust the data pointer
6854bff34e3Sthurlow pbData += nTempLength;
6864bff34e3Sthurlow
6874bff34e3Sthurlow // Now write the Sequence token and the OID (the OID is a BLOB in the global
6884bff34e3Sthurlow // structure.
6894bff34e3Sthurlow
6904bff34e3Sthurlow nTempLength = ASNDerWriteToken( pbData, SPNEGO_CONSTRUCTED_SEQUENCE,
6914bff34e3Sthurlow g_stcMechOIDList[mechoid].ucOid,
6924bff34e3Sthurlow g_stcMechOIDList[mechoid].iLen );
6934bff34e3Sthurlow
6944bff34e3Sthurlow return nMechListLength;
6954bff34e3Sthurlow }
6964bff34e3Sthurlow
6974bff34e3Sthurlow
6984bff34e3Sthurlow /////////////////////////////////////////////////////////////////////////////
6994bff34e3Sthurlow //
7004bff34e3Sthurlow // Function:
7014bff34e3Sthurlow // ASNDerWriteElement
7024bff34e3Sthurlow //
7034bff34e3Sthurlow // Parameters:
7044bff34e3Sthurlow // [out] pbData - Buffer to write into.
7054bff34e3Sthurlow // [in] ucElementSequence - Sequence Token
7064bff34e3Sthurlow // [in] ucType - Token Type
7074bff34e3Sthurlow // [in] pbTokenValue - Actual Value
7084bff34e3Sthurlow // [in] nLength - Length of Data.
7094bff34e3Sthurlow //
7104bff34e3Sthurlow // Returns:
7114bff34e3Sthurlow // int Number of bytes written out
7124bff34e3Sthurlow //
7134bff34e3Sthurlow // Comments :
7144bff34e3Sthurlow // Helper function to write out a SPNEGO Token element. An element
7154bff34e3Sthurlow // consists of a sequence token, a type token and the associated data.
7164bff34e3Sthurlow //
7174bff34e3Sthurlow ////////////////////////////////////////////////////////////////////////////
7184bff34e3Sthurlow
ASNDerWriteElement(unsigned char * pbData,unsigned char ucElementSequence,unsigned char ucType,unsigned char * pbTokenValue,long nLength)7194bff34e3Sthurlow int ASNDerWriteElement( unsigned char* pbData, unsigned char ucElementSequence,
7204bff34e3Sthurlow unsigned char ucType, unsigned char* pbTokenValue, long nLength )
7214bff34e3Sthurlow {
7224bff34e3Sthurlow // First get the length
7234bff34e3Sthurlow long nInternalLength = 0L;
7244bff34e3Sthurlow long nElementLength = ASNDerCalcElementLength( nLength, &nInternalLength );
7254bff34e3Sthurlow long nTempLength = 0L;
7264bff34e3Sthurlow
7274bff34e3Sthurlow // Write out the sequence byte and the length of the type and data
7284bff34e3Sthurlow nTempLength = ASNDerWriteToken( pbData, ucElementSequence, NULL, nInternalLength );
7294bff34e3Sthurlow
7304bff34e3Sthurlow // Adjust the data pointer
7314bff34e3Sthurlow pbData += nTempLength;
7324bff34e3Sthurlow
7334bff34e3Sthurlow // Now write the type and the data.
7344bff34e3Sthurlow nTempLength = ASNDerWriteToken( pbData, ucType, pbTokenValue, nLength );
7354bff34e3Sthurlow
7364bff34e3Sthurlow return nElementLength;
7374bff34e3Sthurlow }
738