MODULE CryptoDiffieHellman;

IMPORT B := CryptoBigNumbers, Log := KernelLog;

TYPE
	DH* = OBJECT
			VAR
				p, g: B.BigNumber;
				priv: B.BigNumber;
				initstate: SET;

				PROCEDURE & Init*( prkeybits: INTEGER;  CONST pname: ARRAY OF CHAR );
				BEGIN
					ASSERT( (prkeybits > 0) OR (pname # "") );
					IF pname # "" THEN
						GetDHPrime( pname, p, g );  priv := B.NewRandRange( p );
						initstate := {1, 2, 3}
					ELSE
						priv := B.NewRand( prkeybits, 1, 0 );
						initstate := {3}
					END;
				END Init;

				PROCEDURE ComputeKey*( pub: B.BigNumber ): B.BigNumber;
				BEGIN
					ASSERT( initstate = {1, 2, 3} );
					RETURN  B.ModExp( pub, priv, p );
				END ComputeKey;

				PROCEDURE GenPubKey*( ): B.BigNumber;
				BEGIN
					ASSERT( initstate = {1, 2, 3} );
					RETURN B.ModExp( g, priv, p );
				END GenPubKey;

				PROCEDURE SetPrime*( prime, gen: B.BigNumber );
				BEGIN
					B.Copy( prime, p );  B.Copy( gen, g );
					initstate := initstate + {1, 2}
				END SetPrime;

				PROCEDURE SetPrivKey*( key: B.BigNumber );
				BEGIN
					B.Copy( key, priv );
					initstate := initstate + {3}
				END SetPrivKey;

			END DH;



	PROCEDURE GetDHPrime( CONST name: ARRAY OF CHAR;  VAR p, g: B.BigNumber );
	VAR 
		buf: ARRAY 1048 OF CHAR; 
		pos: LONGINT;

		PROCEDURE Append( CONST val: ARRAY OF CHAR );
		VAR i: LONGINT;  c: CHAR;
		BEGIN
			FOR i := 0 TO LEN( val ) - 1 DO  
				c := val[i];
				IF c > ' ' THEN  buf[pos] := c;  INC( pos )  END
			END;
		END Append;

	BEGIN
		IF name = "dh.ssl.192" THEN			(* openssl 1.0 *)
			pos := 0;
			Append( "D4A0BA02 50B6FD2E C626E7EF D637DF76 C716E22D 0944B88B" );
			B.AssignHex( p, buf, 48 );
			B.AssignInt( g, 3 )
		ELSIF name = "dh.ssl.512" THEN		(* openssl 1.0 *)
			pos := 0;
			Append( "DA583C16 D9852289 D0E4AF75 6F4CCA92 DD4BE533 B804FB0F" );
			Append( "ED94EF9C 8A4403ED 574650D3 6999DB29 D776276B A2D3D412" );
			Append( "E218F4DD 1E084CF6 D8003E7C 4774E833" );
			B.AssignHex( p, buf, 128 );
			B.AssignInt( g, 2 );
		ELSIF name = "dh.ssl.1024" THEN	(* openssl 1.0 *)
			pos := 0;
			Append( "F881897D 1424C5D1 E6F7BF3A E490F4FC 73FB34B5 FA4C56A2" );
 			Append( "EAA7E9C0 C0CE89E1 FA633FB0 6B3266F1 D17BB000 8FCA87C2" );
 			Append( "AE988926 17C205D2 EC08D08C FF17528C C5079303 B1F62FB8" );
			Append( "1C524727 1BDBD18D 9D691D52 4B3281AA 7F00C8DC E6D9CCC1" );
			Append( "112D3734 6CEA0297 4B0EBBB1 71330915 FDDD2387 075E89AB" );
			Append( "6B7C5FEC A624DC53" );
			B.AssignHex( p, buf, 256 );
			B.AssignInt( g, 2 )
		ELSIF name = "dh.1536.MODP" THEN		(* rfc 2409 *)
			pos := 0;
			Append( "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" );
			Append( "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" );
			Append( "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" );
			Append( "E485B576 625E7EC6 F44C42E9 A63A3620 FFFFFFFF FFFFFFFF" );
			B.AssignHex( p, buf, 192 );
			B.AssignInt( g, 2 )
		ELSIF name = "dh.ssh.group1" THEN		(* rfc 2409 *)
			pos := 0;
			Append( "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" );
			Append( "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" );
			Append( "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" );
			Append( "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" );
			Append( "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381" );
			Append( "FFFFFFFF FFFFFFFF" );
			B.AssignHex( p, buf, 256 );
			B.AssignInt( g, 2 )
		ELSIF name = "dh.ssh.group14" THEN		(* rfc 3526 *)
			pos := 0;
			Append( "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1" );
			Append( "29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD" );
			Append( "EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245" );
			Append( "E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED" );
			Append( "EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D" );
			Append( "C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F" );
			Append( "83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" );
			Append( "670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B" );
			Append( "E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9" );
			Append( "DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510" );
			Append( "15728E5A 8AACAA68 FFFFFFFF FFFFFFFF" );
			B.AssignHex( p, buf, 512 );
			B.AssignInt( g, 2 )
		ELSIF name = "dh.1024.MODP.160" THEN		(* rfc 5140 *)
			pos := 0;
			Append( "B10B8F96 A080E01D DE92DE5E AE5D54EC 52C99FBC FB06A3C6" );
			Append( "9A6A9DCA 52D23B61 6073E286 75A23D18 9838EF1E 2EE652C0" );
			Append( "13ECB4AE A9061123 24975C3C D49B83BF ACCBDD7D 90C4BD70" );
			Append( "98488E9C 219A7372 4EFFD6FA E5644738 FAA31A4F F55BCCC0" );
			Append( "A151AF5F 0DC8B4BD 45BF37DF 365C1A65 E68CFDA7 6D4DA708" );
			Append( "DF1FB2BC 2E4A4371" );
			B.AssignHex( p, buf, 256 );
			pos := 0;
			Append( "A4D1CBD5 C3FD3412 6765A442 EFB99905 F8104DD2 58AC507F" );
			Append( "D6406CFF 14266D31 266FEA1E 5C41564B 777E690F 5504F213" );
			Append( "160217B4 B01B886A 5E91547F 9E2749F4 D7FBD7D3 B9A92EE1" );
			Append( "909D0D22 63F80A76 A6A24C08 7A091F53 1DBF0A01 69B6A28A" );
			Append( "D662A4D1 8E73AFA3 2D779D59 18D08BC8 858F4DCE F97C2A24" );
			Append( "855E6EEB 22B3B2E5" );
			B.AssignHex( g, buf, 256 );
		ELSIF name = "dh.2048.MODP.224" THEN		(* rfc 5140 *)
			pos := 0;
			Append( "AD107E1E 9123A9D0 D660FAA7 9559C51F A20D64E5 683B9FD1" );
        		Append( "B54B1597 B61D0A75 E6FA141D F95A56DB AF9A3C40 7BA1DF15" );
        		Append( "EB3D688A 309C180E 1DE6B85A 1274A0A6 6D3F8152 AD6AC212" );
        		Append( "9037C9ED EFDA4DF8 D91E8FEF 55B7394B 7AD5B7D0 B6C12207" );
        		Append( "C9F98D11 ED34DBF6 C6BA0B2C 8BBC27BE 6A00E0A0 B9C49708" );
        		Append( "B3BF8A31 70918836 81286130 BC8985DB 1602E714 415D9330" );
        		Append( "278273C7 DE31EFDC 7310F712 1FD5A074 15987D9A DC0A486D" );
        		Append( "CDF93ACC 44328387 315D75E1 98C641A4 80CD86A1 B9E587E8" );
        		Append( "BE60E69C C928B2B9 C52172E4 13042E9B 23F10B0E 16E79763" );
        		Append( "C9B53DCF 4BA80A29 E3FB73C1 6B8E75B9 7EF363E2 FFA31F71" );
        		Append( "CF9DE538 4E71B81C 0AC4DFFE 0C10E64F" );
        		B.AssignHex( p, buf, 512 );
 			pos := 0;
 			Append( "AC4032EF 4F2D9AE3 9DF30B5C 8FFDAC50 6CDEBE7B 89998CAF" );
        		Append( "74866A08 CFE4FFE3 A6824A4E 10B9A6F0 DD921F01 A70C4AFA" );
        		Append( "AB739D77 00C29F52 C57DB17C 620A8652 BE5E9001 A8D66AD7" );
        		Append( "C1766910 1999024A F4D02727 5AC1348B B8A762D0 521BC98A" );
        		Append( "E2471504 22EA1ED4 09939D54 DA7460CD B5F6C6B2 50717CBE" );
        		Append( "F180EB34 118E98D1 19529A45 D6F83456 6E3025E3 16A330EF" );
        		Append( "BB77A86F 0C1AB15B 051AE3D4 28C8F8AC B70A8137 150B8EEB" );
        		Append( "10E183ED D19963DD D9E263E4 770589EF 6AA21E7F 5F2FF381" );
        		Append( "B539CCE3 409D13CD 566AFBB4 8D6C0191 81E1BCFE 94B30269" );
        		Append( "EDFE72FE 9B6AA4BD 7B5A0F1C 71CFFF4C 19C418E1 F6EC0179" );
        		Append( "81BC087F 2A7065B3 84B890D3 191F2BFA" );
        		B.AssignHex( g, buf, 512 );
        ELSIF name = "dh.2048.MODP.256" THEN		(* rfc 5140 *)
			pos := 0;
			Append( "87A8E61D B4B6663C FFBBD19C 65195999 8CEEF608 660DD0F2" );
       		Append( "5D2CEED4 435E3B00 E00DF8F1 D61957D4 FAF7DF45 61B2AA30" );
       		Append( "16C3D911 34096FAA 3BF4296D 830E9A7C 209E0C64 97517ABD" );
       		Append( "5A8A9D30 6BCF67ED 91F9E672 5B4758C0 22E0B1EF 4275BF7B" );
       		Append( "6C5BFC11 D45F9088 B941F54E B1E59BB8 BC39A0BF 12307F5C" );
       		Append( "4FDB70C5 81B23F76 B63ACAE1 CAA6B790 2D525267 35488A0E" );
       		Append( "F13C6D9A 51BFA4AB 3AD83477 96524D8E F6A167B5 A41825D9" );
       		Append( "67E144E5 14056425 1CCACB83 E6B486F6 B3CA3F79 71506026" );
       		Append( "C0B857F6 89962856 DED4010A BD0BE621 C3A3960A 54E710C3" );
       		Append( "75F26375 D7014103 A4B54330 C198AF12 6116D227 6E11715F" );
       		Append( "693877FA D7EF09CA DB094AE9 1E1A1597" );
       		B.AssignHex( p, buf, 512 );
			pos := 0;
			Append( "3FB32C9B 73134D0B 2E775066 60EDBD48 4CA7B18F 21EF2054" );
 			Append( "07F4793A 1A0BA125 10DBC150 77BE463F FF4FED4A AC0BB555" );
       		Append( "BE3A6C1B 0C6B47B1 BC3773BF 7E8C6F62 901228F8 C28CBB18" );
       		Append( "A55AE313 41000A65 0196F931 C77A57F2 DDF463E5 E9EC144B" );
       		Append( "777DE62A AAB8A862 8AC376D2 82D6ED38 64E67982 428EBC83" );
       		Append( "1D14348F 6F2F9193 B5045AF2 767164E1 DFC967C1 FB3F2E55" );
       		Append( "A4BD1BFF E83B9C80 D052B985 D182EA0A DB2A3B73 13D3FE14" );
       		Append( "C8484B1E 052588B9 B7D2BBD2 DF016199 ECD06E15 57CD0915" );
       		Append( "B3353BBB 64E0EC37 7FD02837 0DF92B52 C7891428 CDC67EB6" );
       		Append( "184B523D 1DB246C3 2F630784 90F00EF8 D647D148 D4795451" );
      		Append( "5E2327CF EF98C582 664B4C0F 6CC41659" );
      		B.AssignHex( g, buf, 512 );
		ELSE
			Log.String( "### unknown Diffie Hellman prime '" );  Log.String( name );  Log.String( "' " );
			Log.Ln;
			HALT( 99 )
		END ;
	END GetDHPrime;



END CryptoDiffieHellman.