Subversion Repositories decoder

Rev

Blame | Last modification | View Log | RSS feed

  1. {Copyright:      Hagen Reddmann  HaReddmann at T-Online dot de
  2.  Author:         Hagen Reddmann
  3.  Remarks:        Shareware, this Copyright must be included
  4.  known Problems: none
  5.  Version:        5.1, Delphi Encryption Compendium
  6.                  Delphi 2-6, BCB 3-4, designed and testet under D3-6
  7.  Description:    ASN.1 protocoll base routines
  8.  
  9.  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
  10.  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  11.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  12.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
  13.  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  14.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  15.  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  16.  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  17.  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  18.  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  19.  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  20.  }
  21. {$I VER.INC}
  22. unit ASN1;
  23.  
  24. interface
  25.  
  26. uses Classes, SysUtils;
  27.  
  28. type
  29.   EASN1 = class(Exception);
  30.  
  31. procedure ASN1_ChangeEndian(var Buffer; Size: LongInt);
  32. function  ASN1_SwapEndian(Value: Integer): Integer; overload;
  33. function  ASN1_SwapEndian(Value: Cardinal): Cardinal; overload;
  34. function  ASN1_SwapEndian(Value: Word): Word; overload;
  35. function  ASN1_CalcLen(var Len: LongInt): Byte;
  36. function  ASN1_WriteLen(Stream: TStream; Len: LongInt): LongInt;
  37. function  ASN1_ReadLen(Stream: TStream): LongInt;
  38. function  ASN1_WriteStr(Stream: TStream; const Value: String): LongInt;
  39. function  ASN1_ReadStr(Stream: TStream): String;
  40. function  ASN1_WriteWStr(Stream: TStream; const Value: WideString): LongInt;
  41. function  ASN1_ReadWStr(Stream: TStream): WideString;
  42. function  ASN1_WriteBuf(Stream: TStream; const Buffer; Size: LongInt): LongInt;
  43. function  ASN1_ReadBuf(Stream: TStream; var Buffer; Size: LongInt): LongInt;
  44.  
  45. var
  46.   ASN1_Integer: Byte = $02;  // Tag for asn1 integer
  47.  
  48. implementation
  49.  
  50. // only <= 4 Bytes asn1 Length are supported
  51. // we follow Borland Style and use LongInt for compatibility to TStream
  52.  
  53. procedure ASN1_ChangeEndian(var Buffer; Size: Integer); assembler; register;
  54. // not fast, but easy
  55. asm
  56.        CMP    EDX,1
  57.        JLE    @@3
  58.        AND    EAX,EAX
  59.        JZ     @@3
  60.        PUSH   EBX
  61.        MOV    ECX,EDX
  62.        LEA    EDX,[EAX + ECX -1]
  63.        SHR    ECX,1
  64. @@1:   MOV    BL,[EAX]
  65.        XCHG   BL,[EDX]
  66.        DEC    EDX
  67.        MOV    [EAX],BL
  68.        INC    EAX
  69.        DEC    ECX
  70.        JNZ    @@1
  71. @@2:   POP    EBX
  72. @@3:
  73. end;
  74.  
  75. function ASN1_SwapEndian(Value: Integer): Integer;
  76. asm
  77.        BSWAP  EAX
  78. end;
  79.  
  80. function ASN1_SwapEndian(Value: Cardinal): Cardinal;
  81. asm
  82.        BSWAP  EAX
  83. end;
  84.  
  85. function ASN1_SwapEndian(Value: Word): Word;
  86. asm
  87.        XCHG   AL,AH
  88. end;
  89.  
  90. procedure ASN1_Raise(Msg: PResStringRec);
  91. resourcestring
  92.   sASN1LenCoding = 'Invalid ASN1 Length encoded Tag detected.';
  93. var
  94.   ErrorAddr: Pointer;
  95. begin
  96.   asm
  97.        MOV   EAX,[EBP + 8]
  98.        SUB   EAX,4
  99.        MOV   ErrorAddr,EAX
  100.   end;
  101.   raise EASN1.Create(LoadResString(Msg)) at ErrorAddr;
  102. end;
  103.  
  104. procedure ASN1_RaiseLen;
  105. resourcestring
  106.   sASN1LenCoding = 'Invalid ASN1 Length encoded Tag detected';
  107. begin
  108.   ASN1_Raise(@sASN1LenCoding);
  109. end;
  110.  
  111. procedure ASN1_RaiseWrite;
  112. resourcestring
  113.   sASN1Writing = 'ASN1 stream write error';
  114. begin
  115.   ASN1_Raise(@sASN1Writing);
  116. end;
  117.  
  118. procedure ASN1_RaiseRead;
  119. resourcestring
  120.   sASN1Reading = 'ASN1 stream read error';
  121. begin
  122.   ASN1_Raise(@sASN1Reading);
  123. end;
  124.  
  125. function ASN1_CalcLen(var Len: LongInt): Byte;
  126. begin
  127.   if Len < 0 then ASN1_RaiseLen;
  128.   if Len > $7F then
  129.   begin
  130.     if Len and $FFFFFF00 = 0 then Result := 1 else
  131.       if Len and $FFFF0000 = 0 then Result := 2 else
  132.         if Len and $FF000000 = 0 then Result := 3
  133.           else Result := 4;
  134.     ASN1_ChangeEndian(Len, Result);
  135.     Result := Result or $80;
  136.   end else Result := Len;
  137. end;
  138.  
  139. function ASN1_WriteLen(Stream: TStream; Len: LongInt): LongInt;
  140. var
  141.   B: Byte;
  142. begin
  143.   B := ASN1_CalcLen(Len);
  144.   if Stream.Write(B, SizeOf(B)) <> SizeOf(B) then ASN1_RaiseWrite;
  145.   if B and $80 <> 0 then
  146.   begin
  147.     B := B and $7F;
  148.     if Stream.Write(Len, B) <> B then ASN1_RaiseWrite;
  149.     Result := B + SizeOf(B);
  150.   end else Result := SizeOf(B);
  151. end;
  152.  
  153. function ASN1_ReadLen(Stream: TStream): LongInt;
  154. var
  155.   B: Byte;
  156. begin
  157.   Result := 0;
  158.   if Stream.Read(B, SizeOf(B)) <> SizeOf(B) then ASN1_RaiseRead;
  159.   if B and $80 <> 0 then
  160.   begin
  161.     B := B and $7F;
  162.     if B > 4 then ASN1_RaiseLen;
  163.     if B > 0 then
  164.     begin
  165.       if Stream.Read(Result, B) <> B then ASN1_RaiseRead;
  166.       ASN1_ChangeEndian(Result, B);
  167.       if Result < 0 then ASN1_RaiseLen;
  168.     end else Result := Stream.Size - Stream.Position;
  169.   end else Result := B;
  170. end;
  171.  
  172. function ASN1_WriteStr(Stream: TStream; const Value: String): LongInt;
  173. var
  174.   I: LongInt;
  175. begin
  176.   I := Length(Value);
  177.   Result := ASN1_WriteLen(Stream, I) + I;
  178.   if Stream.Write(PChar(Value)^, I) <> I then ASN1_RaiseWrite;
  179. end;
  180.  
  181. function ASN1_ReadStr(Stream: TStream): String;
  182. var
  183.   I: LongInt;
  184. begin
  185.   I := ASN1_ReadLen(Stream);
  186.   SetLength(Result, I);
  187.   if Stream.Read(PChar(Result)^, I) <> I then ASN1_RaiseRead;
  188. end;
  189.  
  190. function ASN1_WriteWStr(Stream: TStream; const Value: WideString): LongInt;
  191. var
  192.   I: LongInt;
  193. begin
  194.   I := Length(Value) * 2;
  195.   Result := ASN1_WriteLen(Stream, I) + I;
  196.   if Stream.Write(Pointer(Value)^, I) <> I then ASN1_RaiseWrite;
  197. end;
  198.  
  199. function ASN1_ReadWStr(Stream: TStream): WideString;
  200. var
  201.   I: LongInt;
  202. begin
  203.   I := ASN1_ReadLen(Stream);
  204.   SetLength(Result, I);
  205.   if Stream.Read(Pointer(Result)^, I) <> I then ASN1_RaiseRead;
  206. end;
  207.  
  208. function ASN1_WriteBuf(Stream: TStream; const Buffer; Size: LongInt): LongInt;
  209. begin
  210.   Result := ASN1_WriteLen(Stream, Size) + Size;
  211.   if Stream.Write(Buffer, Size) <> Size then ASN1_RaiseWrite;
  212. end;
  213.  
  214. function ASN1_ReadBuf(Stream: TStream; var Buffer; Size: LongInt): LongInt;
  215. begin
  216.   Result := ASN1_ReadLen(Stream);
  217.   if Result > Size then ASN1_RaiseRead;
  218.   if Stream.Read(Buffer, Result) <> Result then ASN1_RaiseRead;
  219. end;
  220.  
  221. end.
  222.