You've already forked linux-packaging-mono
							
							
		
			
	
	
		
			343 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			343 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|   | //------------------------------------------------------------ | ||
|  | // Copyright (c) Microsoft Corporation.  All rights reserved. | ||
|  | //------------------------------------------------------------ | ||
|  | 
 | ||
|  | namespace System.IdentityModel.Tokens | ||
|  | { | ||
|  | 
 | ||
|  |     // ASN.1 DER. DER refers to Distinguished Encoding Rules. | ||
|  |     internal static class DEREncoding | ||
|  |     { | ||
|  |         // OID=1.2.840.113554.1.2.2 (Kerberos V5) { 0x06, 0x09, 0x2a, 0x86,  | ||
|  |         //      0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02 } | ||
|  | 
 | ||
|  |         // 1. 0x60 -- Tag for [APPLICATION 0] SEQUENCE; indicates that | ||
|  |         // -- constructed form, definite length encoding follows. | ||
|  |         // 2. Token length octets, specifying length of subsequent data | ||
|  |         // (i.e., the summed lengths of elements 3-5 in this list, and of the | ||
|  |         // mechanism-defined token object following the tag).  This element | ||
|  |         // comprises a variable number of octets: | ||
|  |         // 2a. If the indicated value is less than 128, it shall be | ||
|  |         // represented in a single octet with bit 8 (high order) set to | ||
|  |         // "0" and the remaining bits representing the value. | ||
|  |         // 2b. If the indicated value is 128 or more, it shall be | ||
|  |         // represented in two or more octets, with bit 8 of the first | ||
|  |         // octet set to "1" and the remaining bits of the first octet | ||
|  |         // specifying the number of additional octets.  The subsequent | ||
|  |         // octets carry the value, 8 bits per octet, most significant | ||
|  |         // digit first.  The minimum number of octets shall be used to | ||
|  |         // encode the length (i.e., no octets representing leading zeros | ||
|  |         // shall be included within the length encoding). | ||
|  | 
 | ||
|  |         // 3. 0x06 -- Tag for OBJECT IDENTIFIER | ||
|  | 
 | ||
|  |         // 4. Object identifier length -- length (number of octets) of | ||
|  |         // -- the encoded object identifier contained in element 5, | ||
|  |         // -- encoded per rules as described in 2a. and 2b. above. | ||
|  | 
 | ||
|  |         // 5. Object identifier octets -- variable number of octets, | ||
|  |         // -- encoded per ASN.1 BER rules: | ||
|  | 
 | ||
|  |         // 5a. The first octet contains the sum of two values: (1) the | ||
|  |         // top-level object identifier component, multiplied by 40 | ||
|  |         // (decimal), and (2) the second-level object identifier | ||
|  |         // component.  This special case is the only point within an | ||
|  |         // object identifier encoding where a single octet represents | ||
|  |         // contents of more than one component. | ||
|  | 
 | ||
|  |         // 5b. Subsequent octets, if required, encode successively-lower | ||
|  |         // components in the represented object identifier.  A component's | ||
|  |         // encoding may span multiple octets, encoding 7 bits per octet | ||
|  |         // (most significant bits first) and with bit 8 set to "1" on all | ||
|  |         // but the final octet in the component's encoding.  The minimum | ||
|  |         // number of octets shall be used to encode each component (i.e., | ||
|  |         // no octets representing leading zeros shall be included within a | ||
|  |         // component's encoding). | ||
|  | 
 | ||
|  |         // (Note: In many implementations, elements 3-5 may be stored and | ||
|  |         // referenced as a contiguous string constant.) | ||
|  | 
 | ||
|  | 
 | ||
|  |         static byte[] mech = new byte[] { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x12, 0x01, 0x02, 0x02 }; | ||
|  |         static byte[] type = new byte[] { 0x01, 0x00 }; | ||
|  | 
 | ||
|  |         private static bool BufferIsEqual(byte[] arrayOne, int offsetOne, byte[] arrayTwo, int offsetTwo, int length) | ||
|  |         { | ||
|  |             if (length > arrayOne.Length - offsetOne) | ||
|  |             { | ||
|  |                 return false; | ||
|  |             } | ||
|  | 
 | ||
|  |             if (length > arrayTwo.Length - offsetTwo) | ||
|  |             { | ||
|  |                 return false; | ||
|  |             } | ||
|  | 
 | ||
|  |             for (int i = 0; i < length; i++) | ||
|  |             { | ||
|  |                 if (arrayOne[offsetOne + i] != arrayTwo[offsetTwo + i]) | ||
|  |                 { | ||
|  |                     return false; | ||
|  |                 } | ||
|  |             } | ||
|  | 
 | ||
|  |             return true; | ||
|  |         } | ||
|  | 
 | ||
|  |         // | ||
|  |         // length is assumed to be non negative | ||
|  |         // | ||
|  | 
 | ||
|  |         public static int LengthSize(int length) | ||
|  |         { | ||
|  | 
 | ||
|  |             if (length < (1 << 7)) | ||
|  |             { | ||
|  | 
 | ||
|  |                 return 1; | ||
|  |             } | ||
|  |             else if (length < (1 << 8)) | ||
|  |             { | ||
|  | 
 | ||
|  |                 return 2; | ||
|  |             } | ||
|  |             else if (length < (1 << 16)) | ||
|  |             { | ||
|  | 
 | ||
|  |                 return 3; | ||
|  |             } | ||
|  |             else if (length < (1 << 24)) | ||
|  |             { | ||
|  | 
 | ||
|  |                 return 4; | ||
|  |             } | ||
|  |             else | ||
|  |             { | ||
|  | 
 | ||
|  |                 return 5; | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         // | ||
|  |         // fills in a buffer with the token header.  The buffer is assumed  | ||
|  |         // to be the right size.  buffer is advanced past the token header  | ||
|  |         // | ||
|  |         // bodySize includes TokenId | ||
|  |         //  | ||
|  | 
 | ||
|  |         public static void MakeTokenHeader(int bodySize, byte[] buffer, ref int offset, ref int len) | ||
|  |         { | ||
|  | 
 | ||
|  |             buffer[offset++] = 0x60; | ||
|  |             len--; | ||
|  | 
 | ||
|  |             WriteLength(buffer, ref offset, ref len, 1 + LengthSize(mech.Length) + mech.Length + type.Length + bodySize); | ||
|  | 
 | ||
|  |             buffer[offset++] = 0x06; // OID | ||
|  |             len--; | ||
|  | 
 | ||
|  |             WriteLength(buffer, ref offset, ref len, mech.Length); | ||
|  | 
 | ||
|  |             System.Buffer.BlockCopy(mech, 0, buffer, offset, mech.Length); | ||
|  |             offset += mech.Length; | ||
|  |             len -= mech.Length; | ||
|  | 
 | ||
|  |             System.Buffer.BlockCopy(type, 0, buffer, offset, type.Length); | ||
|  |             offset += type.Length; | ||
|  |             len -= type.Length; | ||
|  |         } | ||
|  | 
 | ||
|  |         // | ||
|  |         // returns decoded length, or < 0 on failure.  Advances buffer and | ||
|  |         // decrements length | ||
|  |         // | ||
|  | 
 | ||
|  |         public static int ReadLength(byte[] buffer, ref int offset, ref int length) | ||
|  |         { | ||
|  | 
 | ||
|  |             int tmp; | ||
|  |             int ret = 0; | ||
|  | 
 | ||
|  |             if (length < 1) | ||
|  |             { | ||
|  | 
 | ||
|  |                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SystemException()); | ||
|  |             } | ||
|  | 
 | ||
|  |             tmp = buffer[offset++]; | ||
|  | 
 | ||
|  |             length--; | ||
|  | 
 | ||
|  |             if ((tmp & 0x80) != 0) | ||
|  |             { | ||
|  | 
 | ||
|  |                 if ((tmp &= 0x7f) > (length - 1)) | ||
|  |                 { | ||
|  | 
 | ||
|  |                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SystemException()); | ||
|  |                 } | ||
|  | 
 | ||
|  |                 if (tmp > 4) | ||
|  |                 { // 4 == sizeof(int) | ||
|  | 
 | ||
|  |                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SystemException()); | ||
|  |                 } | ||
|  | 
 | ||
|  |                 for (; tmp != 0; tmp--) | ||
|  |                 { | ||
|  | 
 | ||
|  |                     ret = (ret << 8) + buffer[offset++]; | ||
|  |                     length--; | ||
|  |                 } | ||
|  | 
 | ||
|  |             } | ||
|  |             else | ||
|  |             { | ||
|  | 
 | ||
|  |                 ret = tmp; | ||
|  |             } | ||
|  | 
 | ||
|  |             return ret; | ||
|  |         } | ||
|  | 
 | ||
|  |         // | ||
|  |         // returns the length of a token, given the mech oid and the body | ||
|  |         // size  | ||
|  |         // | ||
|  | 
 | ||
|  |         public static int TokenSize(int bodySize) | ||
|  |         { | ||
|  | 
 | ||
|  |             // set body size to sequence contents size, 2 for token id | ||
|  |             bodySize += 2 + mech.Length + LengthSize(mech.Length) + 1; | ||
|  | 
 | ||
|  |             return (1 + LengthSize(bodySize) + bodySize); | ||
|  |         } | ||
|  | 
 | ||
|  |         // | ||
|  |         // given a buffer containing a token, reads and verifies the token, | ||
|  |         // leaving buffer advanced past the token header, and setting body_size | ||
|  |         // to the number of remaining bytes | ||
|  |         // | ||
|  | 
 | ||
|  |         public static void VerifyTokenHeader(byte[] buffer, ref int offset, ref int len) | ||
|  |         { | ||
|  | 
 | ||
|  |             if ((len -= 1) < 0) | ||
|  |             { | ||
|  | 
 | ||
|  |                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SystemException()); | ||
|  |             } | ||
|  | 
 | ||
|  |             if (buffer[offset++] != 0x60) | ||
|  |             { | ||
|  | 
 | ||
|  |                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SystemException()); | ||
|  |             } | ||
|  | 
 | ||
|  |             int seqSize = ReadLength(buffer, ref offset, ref len); | ||
|  | 
 | ||
|  |             if (seqSize != len) | ||
|  |             { | ||
|  | 
 | ||
|  |                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SystemException()); | ||
|  |             } | ||
|  | 
 | ||
|  |             if ((len -= 1) < 0) | ||
|  |             { | ||
|  | 
 | ||
|  |                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SystemException()); | ||
|  |             } | ||
|  | 
 | ||
|  |             if (buffer[offset++] != 0x06) | ||
|  |             { | ||
|  | 
 | ||
|  |                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SystemException()); | ||
|  |             } | ||
|  | 
 | ||
|  |             int oidLength = ReadLength(buffer, ref offset, ref len); // (byte) buffer[offset++]; | ||
|  | 
 | ||
|  |             if ((oidLength & 0x7fffffff) != mech.Length) | ||
|  |             { // Overflow???  | ||
|  | 
 | ||
|  |                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SystemException()); | ||
|  |             } | ||
|  | 
 | ||
|  |             if ((len -= oidLength) < 0) | ||
|  |             { | ||
|  | 
 | ||
|  |                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SystemException()); | ||
|  |             } | ||
|  | 
 | ||
|  |             if (!BufferIsEqual(mech, 0, buffer, offset, mech.Length)) | ||
|  |             { | ||
|  | 
 | ||
|  |                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SystemException()); | ||
|  |             } | ||
|  | 
 | ||
|  |             offset += oidLength; | ||
|  | 
 | ||
|  |             if ((len -= type.Length) < 0) | ||
|  |             { | ||
|  | 
 | ||
|  |                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SystemException()); | ||
|  |             } | ||
|  | 
 | ||
|  |             if (!BufferIsEqual(type, 0, buffer, offset, type.Length)) | ||
|  |             { | ||
|  | 
 | ||
|  |                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SystemException()); | ||
|  |             } | ||
|  | 
 | ||
|  |             offset += type.Length; | ||
|  |         } | ||
|  | 
 | ||
|  |         public static void WriteLength(byte[] buffer, ref int offset, ref int bufferLength, int length) | ||
|  |         { | ||
|  | 
 | ||
|  |             if (length < (1 << 7)) | ||
|  |             { // one byte | ||
|  | 
 | ||
|  |                 // *(*buffer)++ = (unsigned char) length; | ||
|  |                 buffer[offset++] = (byte)length; | ||
|  |                 bufferLength--; | ||
|  |             } | ||
|  |             else | ||
|  |             { | ||
|  | 
 | ||
|  |                 // *(*buffer)++ = (unsigned char) (der_length_size(length) + 127); | ||
|  |                 buffer[offset++] = (byte)(LengthSize(length) + 127); | ||
|  | 
 | ||
|  |                 if (length >= (1 << 24)) | ||
|  |                 { | ||
|  | 
 | ||
|  |                     // *(*buffer)++ = (unsigned char) (length >> 24); | ||
|  |                     buffer[offset++] = (byte)(length >> 24); | ||
|  |                     bufferLength--; | ||
|  |                 } | ||
|  | 
 | ||
|  |                 if (length >= (1 << 16)) | ||
|  |                 { | ||
|  | 
 | ||
|  |                     // *(*buffer)++ = (unsigned char) ((length >> 16) & 0xff); | ||
|  |                     buffer[offset++] = (byte)((length >> 16) & 0xFF); | ||
|  |                     bufferLength--; | ||
|  |                 } | ||
|  | 
 | ||
|  |                 if (length >= (1 << 8)) | ||
|  |                 { | ||
|  | 
 | ||
|  |                     // *(*buffer)++ = (unsigned char) ((length >> 8) & 0xff); | ||
|  |                     buffer[offset++] = (byte)((length >> 8) & 0xFF); | ||
|  |                     bufferLength--; | ||
|  |                 } | ||
|  | 
 | ||
|  |                 // *(*buffer)++ = (unsigned char) (length & 0xff); | ||
|  |                 buffer[offset++] = (byte)(length & 0xFF); | ||
|  |                 bufferLength--; | ||
|  |             } | ||
|  |         } | ||
|  |     } | ||
|  | } | ||
|  | 
 |