فهرست منبع

fcl-hash: added ASNFetch

mattias 3 سال پیش
والد
کامیت
ca9ea2be61
1فایلهای تغییر یافته به همراه102 افزوده شده و 5 حذف شده
  1. 102 5
      packages/fcl-hash/src/fpasn.pp

+ 102 - 5
packages/fcl-hash/src/fpasn.pp

@@ -44,11 +44,14 @@ const
   ASN_ecdsa_with_SHA384 = '1.2.840.10045.4.3.3';
   ASN_ecdsa_with_SHA224 = '1.2.840.10045.4.3.1';
 
+  ASN_MaxOIDSize = 1000;
+
 //------------------------------------------------------------------------------
 // ASN
 //------------------------------------------------------------------------------
 procedure ASNEncodeOID(const Value: Int64; var Result: AnsiString);
-function ASNDecodeOID(var Start: Integer; const S: AnsiString): Int64;
+function ASNDecodeOID(var Start: Integer; const S: AnsiString): Int64; overload;
+function ASNDecodeOID(var Buffer: PByte; BufferEnd: PByte): Int64; overload;
 function ASNGetEncodedLen(const Len: Integer): Integer;
 procedure ASNEncodeLen(const Len: Integer; var Buffer: TBytes);
 function ASNReadLen(const Buffer: TBytes; var Offset: Int32): Int32;
@@ -59,7 +62,8 @@ procedure ASNObject(const Data: Ansistring; const ASNType: Integer; var Buffer:
 // Encodes an MIB OID Ansistring to binary form
 procedure MibToId(Mib: Ansistring; var Result: AnsiString);
 // Decodes MIB OID from binary form to Ansistring form.
-procedure IdToMib(const Id: Ansistring; var Result: Ansistring);
+procedure IdToMib(const Id: Ansistring; var Result: Ansistring); overload;
+function IdToMib(Buffer, BufferEnd: PByte): string; overload;
 procedure ASNDebug(const Buffer: TBytes; var Output: TBytes);
 procedure ASNParse(const Buffer: TBytes; List: TStrings);
 procedure PemToDER(const PEM: AnsiString; const BeginTag, EndTag: Ansistring; Out DER: TBytes); overload;
@@ -67,6 +71,9 @@ procedure PemToDER(PEM: TBytes; const BeginTag, EndTag: Ansistring; Out DER: TBy
 procedure ASNParsePemSection(const PEM: TBytes; List: TStrings; const BeginTag, EndTag: Ansistring);
 procedure ASNParsePemSection(const PEM: AnsiString; List: TStrings; const BeginTag, EndTag: Ansistring);
 
+function ASNFetch(const Buffer: TBytes; var Offset: Int32; Out ASNType, ASNSize: Int32): Boolean; overload;
+function ASNFetch(var Buffer: PByte; BufferEnd: PByte; Out ASNType, ASNSize: Int32): Boolean; overload;
+function ASNFetchOID(var Buffer: PByte; BufferEnd: PByte; out OID: String): Boolean; overload;
 
 implementation
 
@@ -112,6 +119,22 @@ begin
   until (x and $80) = 0;
 end;
 
+function ASNDecodeOID(var Buffer: PByte; BufferEnd: PByte): Int64;
+var
+  x: Byte;
+begin
+  Result := 0;
+  repeat
+    if Buffer>=BufferEnd then
+      exit(-1);
+    x := Buffer^;
+    Inc(Buffer);
+    Result := (Result shl 7) + (x and $7F);
+    if Result>high(dword) then
+      exit(-1);
+  until (x and $80) = 0;
+end;
+
 procedure ASNEncodeLen(const Len: Integer; var Buffer: TBytes);
 var
   x, y: Integer;
@@ -161,6 +184,11 @@ begin
   if Result < $80 then
     Exit;
   Len := Result and $7F;
+  if (Len>4) or (Offset+Len >= length(Buffer)) then
+  begin
+    Offset:=length(Buffer)+1;
+    exit;
+  end;
   Result := 0;
   while Len > 0 do
   begin
@@ -526,8 +554,26 @@ begin
   end;
 end;
 
-// Convert ASN.1 DER encoded buffer to human readable form for debugging
+function IdToMib(Buffer, BufferEnd: PByte): string;
+var
+  x: Int64;
+begin
+  Result:='';
+  while Buffer<BufferEnd do
+  begin
+    x := ASNDecodeOID(Buffer, BufferEnd);
+    if x<0 then
+      raise Exception.Create('20220427114808');
+    if Result='' then
+    begin
+      Result:=IntToStr(x div 40);
+      x := x mod 40;
+    end;
+    Result:=Result+'.'+IntToStr(x);
+  end;
+end;
 
+// Convert ASN.1 DER encoded buffer to human readable form for debugging
 procedure ASNDebug(const Buffer: TBytes; var Output: TBytes);
 
 const
@@ -637,7 +683,7 @@ var
 begin
   Result := False;
   Len := Length(Buffer);
-  if Offset > Len then
+  if Offset+2 > Len then
     Exit;
   ASNType := Buffer[Offset];
   Inc(Offset);
@@ -647,6 +693,57 @@ begin
   Result := True;
 end;
 
+function ASNFetch(var Buffer: PByte; BufferEnd: PByte; out ASNType,
+  ASNSize: Int32): Boolean;
+var
+  Len: byte;
+begin
+  Result:=false;
+  if Buffer>=BufferEnd then exit;
+  ASNType := Buffer^;
+  inc(Buffer);
+  if Buffer>=BufferEnd then exit;
+  ASNSize := Buffer^;
+  Inc(Buffer);
+  if ASNSize < $80 then
+    Exit(true);
+  Len := ASNSize and $7F;
+  if (Len>4) or ((BufferEnd-Buffer)<Len) then
+    exit;
+  ASNSize := 0;
+  while Len > 0 do
+  begin
+    ASNSize := ASNSize*256 + Buffer^;
+    Inc(Buffer);
+    Dec(Len);
+  end;
+  Result:=true;
+end;
+
+function ASNFetchOID(var Buffer: PByte; BufferEnd: PByte; out OID: String): Boolean;
+var
+  ASNType, ASNSize: Int32;
+  OIDEnd: PByte;
+begin
+  OID:='';
+  Result := ASNFetch(Buffer, BufferEnd, ASNType, ASNSize);
+  if not Result then
+    Exit;
+  Result := ASNType = ASN1_OBJID;
+  if not Result then
+    Exit;
+  if ASNSize=0 then
+    Exit;
+  if ASNSize>ASN_MaxOIDSize then
+    Exit;
+  if (BufferEnd-Buffer)<ASNSize then
+    Exit;
+  OIDEnd:=Buffer+ASNSize;
+  OID:=IdToMib(Buffer, OIDEnd);
+  Buffer:=OIDEnd;
+  Result := OID<>'';
+end;
+
 // Beginning with the @Start position, decode the ASN.1 item of the next element in @Buffer. Type of item is stored in @ASNType
 // @Offset starts at 0
 
@@ -786,7 +883,7 @@ end;
 procedure ASNParsePemSection(const PEM: AnsiString; List: TStrings; const BeginTag, EndTag: AnsiString);
 
 var
-  BufferSection,res: TBytes;
+  BufferSection: TBytes;
 //  S : AnsiString;
 
 begin