1-- This program is free software; you can redistribute it and/or
2-- modify it under the terms of the GNU General Public License as
3-- published by the Free Software Foundation; either version 2 of the
4-- License, or (at your option) any later version.
5
6-- This program is distributed in the hope that it will be useful,
7-- but WITHOUT ANY WARRANTY; without even the implied warranty of
8-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
9-- General Public License for more details.
10
11-- You should have received a copy of the GNU General Public License
12-- along with this program; if not, write to the Free Software
13-- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
14-- 02111-1307, USA.
15
16-- As a special exception, if other files instantiate generics from
17-- this unit, or you link this unit with other files to produce an
18-- executable, this unit does not by itself cause the resulting
19-- executable to be covered by the GNU General Public License. This
20-- exception does not however invalidate any other reasons why the
21-- executable file might be covered by the GNU Public License.
22
23with Crypto.Symmetric.Hashfunction_SHA1;
24
25package body Crypto.Asymmetric.ECDSA is
26   package SHA1 renames Crypto.Symmetric.Hashfunction_SHA1;
27   use Big.Mod_Utils;
28   use Big.Utils;
29
30
31
32-------------------------------------------------------------------------------
33
34   -- check if key is initialited
35   function Is_Init(Key : ECDSA_P_KEY) return Boolean is
36   begin
37      if Key.n /= Big_Unsigned_Zero then
38         return True;
39      else return False;
40      end if;
41   end Is_Init; Pragma Inline (Is_Init);
42
43-------------------------------------------------------------------------------
44
45   -- check if key is initialited
46   function Is_Init(Key : ECDSA_S_KEY) return Boolean is
47   begin
48      if Key.d /= Big_Unsigned_Zero then
49			return True;
50      else return False;
51      end if;
52   end Is_Init; Pragma Inline (Is_Init);
53
54-------------------------------------------------------------------------------
55
56   procedure Gen_Public_Key(
57			    Public_Key  : out Public_Key_ECDSA;
58			    length      : in DB.Bit_Length) is
59   begin
60      Get_Elliptic_Curve(Public_Key.E, Public_Key.P, Public_Key.n, length);
61      init(Public_Key.E);
62   end Gen_Public_Key;
63
64   ----------------------------------------------------------------------------
65
66   procedure Gen_Private_Key(
67			     Public_Key  : in out Public_Key_ECDSA;
68			     Private_Key : out Private_Key_ECDSA) is
69   begin
70      Private_Key.d := Get_Random(Get_P(Public_Key.E) - Big_Unsigned_Three)
71	+ Big_Unsigned_One;
72
73      Private_Key.Q 	:= Private_Key.d * Public_Key.P;
74      Public_Key.Q 	:= Private_Key.Q;
75   end Gen_Private_Key;
76
77   ----------------------------------------------------------------------------
78
79   procedure Sign(Public_Key  : in  Public_Key_ECDSA;
80		  Private_Key : in  Private_Key_ECDSA;
81                  SHA1_Hash   : in  W_Block160;
82                  Signature   : out Signature_ECDSA) is
83      temp_k : Big_Unsigned;
84      temp_EC: EC_Point;
85      temp_H : constant Big_Unsigned := To_Big_Unsigned(To_Bytes(Sha1_Hash));
86   begin
87      loop
88	 temp_k := Get_Random(Get_P(Public_Key.E) - Big_Unsigned_Three) +
89	   Big_Unsigned_One;
90
91	 temp_EC:= temp_k * Public_Key.P;
92	 Signature.R := temp_EC.X mod Public_Key.n;
93	 if Signature.R /= Big_Unsigned_Zero then
94	    exit;
95	 end if;
96      end loop;
97
98      Signature.S := Mult(Inverse(temp_k, Public_Key.n),
99			  Add(temp_H, Mult(Private_Key.d, Signature.R,
100					   Public_Key.n),Public_Key.n),
101			  Public_Key.n);
102   end Sign;
103
104-------------------------------------------------------------------------------
105
106   function Verify(Public_Key  : Public_Key_ECDSA;
107                   SHA1_Hash   : W_Block160;
108                   Signature   : Signature_ECDSA) return Boolean is
109      W  : constant Big_Unsigned := Inverse(Signature.S, Public_Key.n);
110      U1 : constant Big_Unsigned := Mult(To_Big_Unsigned(To_Bytes(Sha1_Hash)),
111					 W,Public_Key.n);
112      U2 : constant Big_Unsigned := Mult(Signature.R, W, Public_Key.n);
113      tmp_EC: constant EC_Point := (U1 * Public_Key.P) + (U2 * Public_Key.Q);
114      V : constant Big_Unsigned:= tmp_EC.x mod Get_P(Public_Key.E);
115   begin
116      if V = Signature.R then return True;
117      else return False;
118      end if;
119   end Verify;
120
121-------------------------------------------------------------------------------
122
123   procedure Sign_File(Filename    : in  String;
124                       Public_Key  : in Public_Key_ECDSA;
125		       Private_Key : in  Private_Key_ECDSA;
126                       Signature   : out Signature_ECDSA) is
127   begin
128      if Is_Init(ECDSA_S_Key(Private_Key)) and
129	Is_Init(ECDSA_P_Key(Public_Key)) then
130         Sign(Public_Key, Private_Key, SHA1.F_Hash(Filename), Signature);
131      else
132         raise Invalid_Private_Key_Error;
133      end if;
134   end Sign_File;
135
136-------------------------------------------------------------------------------
137
138   function Verify_File(
139                        Filename   : String;
140                        Public_Key : Public_Key_ECDSA;
141                        Signature  : Signature_ECDSA) return Boolean is
142   begin
143      if Is_Init(ECDSA_P_Key(Public_Key)) then
144         return Verify(Public_Key, SHA1.F_Hash(Filename), Signature);
145      else
146         raise Invalid_Public_Key_Error;
147      end if;
148   end Verify_File;
149
150
151-------------------------------------------------------------------------------
152
153   function Verify_Key_Pair(
154                            Private_Key : Private_Key_ECDSA;
155                            Public_Key  : Public_Key_ECDSA) return Boolean is
156   begin
157      if Is_Init(ECDSA_P_KEY(Public_Key)) = False or
158        Is_Init(ECDSA_S_KEY(Private_Key)) = False then
159         return False;
160      elsif
161			--- do some more? ---
162        	(Private_Key.d * Public_Key.P = Public_Key.Q) and (Public_Key.Q = Private_Key.Q) then
163         return True;
164      else return False;
165      end if;
166   end Verify_Key_Pair;
167
168-------------------------------------------------------------------------------
169
170	function equal_Public_Key_Curve(
171 						Public_Key_A  : Public_Key_ECDSA;
172						Public_Key_B  : Public_Key_ECDSA) return Boolean is
173	begin
174		if (Public_Key_A.E = Public_Key_B.E) and (Public_Key_A.P = Public_Key_B.P) and (Public_Key_A.n = Public_Key_B.n) then
175			return true;
176		else
177			return false;
178		end if;
179	end equal_Public_Key_Curve;
180
181-------------------------------------------------------------------------------
182
183end Crypto.Asymmetric.ECDSA;
184