diff -uNr a/smg_comms/c_wrappers/c_wrappers.c b/smg_comms/c_wrappers/c_wrappers.c --- a/smg_comms/c_wrappers/c_wrappers.c 0bd7662525269421638c3cf0b5013c4e89b3181be9d081fd6ce4cac5afd731ae831eeae39f854bcbd5d31a134c47d1083f3c92a44f6ddf64d6160de04e4d561c +++ b/smg_comms/c_wrappers/c_wrappers.c 9c01f9ea1e1a4a1dc1397aea8621c926dcbaadb9fb07b2356e0df61f3c7ffaf2cee2cbe2d036850a2cad4ee5b51ab532b9f3d263f0271b21c9ac86b013d17457 @@ -27,10 +27,10 @@ MPI u = mpi_alloc(nlimbs_a); MPI v = mpi_alloc(nlimbs_b); - //set the given octets as the values of the 2 MPIs + //set the given octets as the values of the 2 MPIs and normalize //the sign is set to 0 (last parameter). - mpi_set_buffer(u, a, len_a, 0); - mpi_set_buffer(v, b, len_b, 0); + mpi_set_normalized(u, a, len_a, 0); + mpi_set_normalized(v, b, len_b, 0); //compare the MPIs as numbers and store the result result = mpi_cmp(u, v); @@ -66,17 +66,16 @@ MPI out_mpi = mpi_alloc(nlimbs_out); //set input as buffer for in_mpi - mpi_set_buffer(in_mpi, input, len_input, 0); - + mpi_set_normalized(in_mpi, input, len_input, 0); //create public key structure and set its contents to given n, e RSA_public_key pk; unsigned int nlimbs_n = mpi_nlimb_hint_from_nbytes( len_n ); unsigned int nlimbs_e = mpi_nlimb_hint_from_nbytes( len_e ); pk.n = mpi_alloc(nlimbs_n); pk.e = mpi_alloc(nlimbs_e); - mpi_set_buffer(pk.n, n, len_n, 0); - mpi_set_buffer(pk.e, e, len_e, 0); - + //NB MPI lib gets STUCK on 0-leading MPIs so set + normalize + mpi_set_normalized(pk.n, n, len_n, 0); + mpi_set_normalized(pk.e, e, len_e, 0); //call rsa public_key encryption and retrieve the result, storing it in out public_rsa( out_mpi, in_mpi, &pk); int len = len_out; @@ -118,7 +117,7 @@ MPI out_mpi = mpi_alloc(nlimbs_out); //set input as buffer for in_mpi - mpi_set_buffer(in_mpi, input, len_input, 0); + mpi_set_normalized(in_mpi, input, len_input, 0); //create private key structure and set its contents to given n,e,d,p,q,u RSA_secret_key sk; @@ -134,12 +133,13 @@ sk.p = mpi_alloc(nlimbs_p); sk.q = mpi_alloc(nlimbs_q); sk.u = mpi_alloc(nlimbs_u); - mpi_set_buffer(sk.n, n, len_n, 0); - mpi_set_buffer(sk.e, e, len_e, 0); - mpi_set_buffer(sk.d, d, len_d, 0); - mpi_set_buffer(sk.p, p, len_p, 0); - mpi_set_buffer(sk.q, q, len_q, 0); - mpi_set_buffer(sk.u, u, len_u, 0); + //HAVE TO set AND normalize those or lib MPI gets stuck idiotically on 0-led + mpi_set_normalized(sk.n, n, len_n, 0); + mpi_set_normalized(sk.e, e, len_e, 0); + mpi_set_normalized(sk.d, d, len_d, 0); + mpi_set_normalized(sk.p, p, len_p, 0); + mpi_set_normalized(sk.q, q, len_q, 0); + mpi_set_normalized(sk.u, u, len_u, 0); //call rsa secret_key encryption and retrieve the result, storing it in out secret_rsa( out_mpi, in_mpi, &sk ); @@ -220,3 +220,9 @@ xfree( buffer ); //free the buffer that was allocated by mpi_get_buffer } + +void mpi_set_normalized(MPI m, const char *buffer, + unsigned int noctets, int sign) { + mpi_set_buffer( m, buffer, noctets, sign ); + mpi_normalize( m ); +} diff -uNr a/smg_comms/c_wrappers/c_wrappers.h b/smg_comms/c_wrappers/c_wrappers.h --- a/smg_comms/c_wrappers/c_wrappers.h c24569926e5388672b1af9e79b01b55902f2176de3f2887c978327871820cf1ee19bc9b0b52ba614a90ff197fac4a91c0975133ec55b38f362be48e3deace1b3 +++ b/smg_comms/c_wrappers/c_wrappers.h c09fb6859c6fe556058d2ea35ca102cc45128f7a87a038f7000f0dcf256515c36c0e979519368f33655b9bab9c6780e834fec415d131514aea2ec9cde5487e87 @@ -103,3 +103,11 @@ //@param len_out size of out; will be replaced by actual number of octets copied //@param m The MPI whose octets are to be retrieved void mpi_to_octets( char *out, unsigned int *len_out, MPI m); + + +//This calls mpi_set_buffer and then mpi_normalize - i.e. it *changes* given MPI +//by setting its internal buffer and trimming any leading 0. +//NB: the MPI lib fails to work correctly with non-normalized MPIs.... +//NB: this may allocate/deallocate memory for the mpi! +void mpi_set_normalized(MPI m, const char *buffer, + unsigned int noctets, int sign); diff -uNr a/smg_comms/manifest b/smg_comms/manifest --- a/smg_comms/manifest a11ec7a815179c71a1c1b0239ee392930b811cffc2d83328bc4d6d9d7182eb9d5d55f3c010ed9fb8a1a98b14e578407331fb6229b479386abe16f6dff21b98f1 +++ b/smg_comms/manifest 58a5a4d81e10e1017a43df99ec183c85d77223cbae6d3657a5c6b87d8325650dde3c63bd0bf9598d84e5c0f87626820763af763714194b71767c74f0524d39ad @@ -10,3 +10,4 @@ 550310 smg_comms_keymgm diana_coman Adds read/write for Keys Management messages (both Serpent and RSA). Refactors the read/write of Serpent Keys messages so that the same core is called by RSA/Serpent specific-methods, adding also read/write of keys from/to RSA messages. 551086 smg_comms_files diana_coman Adds read/write for File Transfer (4.3) and File Request (4.4). Refactors the rest to have read/write of 16 bits values in one single place (i.e. separate method called from everywhere else) because of how common it is + sensitive to endianness. 551832 smg_comms_actions_rsa diana_coman Adds read/write for RSA keys (5.1) and Client Action (4.5). Refactors to allow choice of padding and enable direct testing of private procedure in Messages. +552633 smg_comms_shorter_e diana_coman Changes to support arbitrary size of public exponent both at key generation time (rsa.c) and at use for packing/unpacking messages. Also adds required changes to c_wrappers to work around the idiocy in MPI lib that means it will get stuck in endless loop in some cases when the buffer of an mpi is set to 0-leading values. diff -uNr a/smg_comms/rsa/include/smg_rsa.h b/smg_comms/rsa/include/smg_rsa.h --- a/smg_comms/rsa/include/smg_rsa.h 73247011fcc9996859cab02ade955cd8d5fa04b85593e182645ebe0f497686abfc771ecdf1e43b0e39506c85b25f365d80a81031fb82f13919e2ff5824eda5ef +++ b/smg_comms/rsa/include/smg_rsa.h 3010bfbd5a317c39bbf1362a8a82cfccb497a0b1f07cbabe8e0ceae972a70a44ed4e1b0e4a1c47043a881d1ea5a9d5f28a55c6603a6eb8bee4d1c5c2d867d054 @@ -22,6 +22,16 @@ */ static const int KEY_LENGTH_OCTETS = 490; +/** + * This is the length of the public exponent e, given in octets. + * TMSR standard e has KEY_LENGTH_OCTETS / 2 octets. + * Eulora's communication protocol uses however e with 8 octets length. + * New keypairs generated will have e precisely this length. + * Change this to your preferred size of e for generating new keys with that size of e. + * NB: this impacts key generation ONLY! (i.e. NOT encrypt/decrypt). + */ +static const int E_LENGTH_OCTETS = 8; + typedef struct { MPI n; /* modulus */ MPI e; /* public exponent */ diff -uNr a/smg_comms/rsa/rsa.c b/smg_comms/rsa/rsa.c --- a/smg_comms/rsa/rsa.c 388a33be262faa152fb74089b6ac814c7e5c6248a5b52f91a8c69c0e19ec9f9eea12b0551b0aadc751f73cdd5ac4004c8c493aa1e6041118a922070ead3a7ecb +++ b/smg_comms/rsa/rsa.c 6069c916778aa2adfd471d7510c0232ff29acbf4b55df90b841050cb57cb46762099372a442a2d792ad17713f10515728d810ef4282d3120b5d9653007a2f136 @@ -52,7 +52,7 @@ /* choose random prime e, public exponent, with 3 < e < phi */ /* because e is prime, gcd(e, phi) is always 1 so no need to check it */ do { - gen_random_prime( noctets_pq, sk->e); + gen_random_prime( E_LENGTH_OCTETS, sk->e); } while ( (mpi_cmp_ui(sk->e, 3) < 0) || (mpi_cmp(sk->e, phi) > 0)); /* calculate private exponent d, 1 < d < phi, where e * d = 1 mod phi */ diff -uNr a/smg_comms/rsa/tests/tests.c b/smg_comms/rsa/tests/tests.c --- a/smg_comms/rsa/tests/tests.c 4835ebbc34c00a3a78a2a4ee13c9f553697525a2a21cb137e629d65d8b7e70a7dd1283f395a2c4590024e522c82d1dc027bbcbbb26c27a7d844b4a1fbd6f2941 +++ b/smg_comms/rsa/tests/tests.c c3156e1dd050f02d729572baf449e973925be2df1464c3f7eb7a3430f016ad138205516bff6ed1e2e580ece5db84b2ded1069863ad552e6abe1443c8e3b0a574 @@ -305,6 +305,104 @@ } +void test_rsa_8e(int nruns) { + RSA_secret_key sk; + int noctets = KEY_LENGTH_OCTETS; + int noctets_pq = noctets / 2; + int nlimbs_pq = mpi_nlimb_hint_from_nbytes(noctets_pq); + + sk.n = mpi_alloc(0); + sk.e = mpi_alloc(0); + sk.d = mpi_alloc(0); + sk.p = mpi_alloc(0); + sk.q = mpi_alloc(0); + sk.u = mpi_alloc(0); + + mpi_fromstr(sk.n, "0x\ +B51BE851F39159EAC714F3E0376713A84DAD36A82D446D0A257A391870F45FAE13C4CC\ +F400DDA9F604991134C0934161554EEFEAA3147BF0EADC77B99E2B9B6E4EE942EA9D07\ +5F015EE2465B491F4130E04E1BBB6CCDC98F6E8789D4F7FCA3E3FF83C6100CAF2B764E\ +A5AF7CBA9B27C13EE72EA7A8602F34B32E17C2BA56CFBA4223F7D9A03C23336095D34F\ +BF66E88BF5CE661D66C251DFAD4CB2BA8D1E1669AC927894EA20DABABD2495BC2A4BA3\ +A25C79ABEC2D57F45F0F889D962C777A663D0AB25D3650DFDC6D77C528803C0C6E12BD\ +05281B33C603BEA66A0C2ACBEBD1CA53D32C2269294C9B93E742CA563AF39E939C32CE\ +51D5ED827F9C217EF58CC518B635D0E03BA778BCEBAF9A2CDB493282D751A5977CB907\ +C8708D1EF1CAE644C1F2525DDE98E29761B1ADF0965F08AA856DF540AEFD67F96B92AE\ +83636C31A507C59635C6D435C5E7EE333DC2257C07BC0FCE27CF400F6EB7A6B90FFF00\ +C3C1179615BF5DA6137476926C09D8CCD03257DFCAEF12BE9DC1D3F621D6C97D7F3E6D\ +534337579B4B65AE212ACC26FC3861E24033E6F12A601D473A65EFC5F25ABD5D6049EA\ +DD6D76BA60AA218C5EBE13439AAFFF0088C49ACC0E9F7DE56DB03F585E1AC2862EB990\ +59724FD407C4ACD3DD14A53A6A35F6AFAE03EA53A4E742CC370087692E206A2422FF9D"); + + sk.e = mpi_alloc(nlimbs_pq); + int i; + char echar[109]; + int ne = 109; + for (i=0;i '0'); Half : String(1..RSA_half'Length*2) := (others => '0'); + e : String(1..E_Len_Chars) := (others => '0'); + d : String(1..D_Len_Chars) := (others => '0'); F : Char_IO.File_Type; C : Character; begin Open( File => F, Mode => In_File, Name => Filename ); - -- read n for I in Full'Range loop Read(F, Full(I)); @@ -24,23 +28,33 @@ -- read new line character and convert to hex Read(F, C); Hex2Octets(Full, Key.n); - -- read e - for I in Half'Range loop - Read(F, Half(I)); + for I in e'Range loop + Read(F, e(I)); end loop; - -- read new line character and convert to hex + -- read new line character and convert to hex, pad with 0 if needed Read(F, C); + -- move it to Half, possibly at the end if e'len < half'len (0-led) + if e'Length > Half'Length then + raise Incorrect_E_Len; + else + Half(Half'Last-e'Length+1 .. Half'Last) := e; + end if; Hex2Octets(Half, Key.e); - -- read d - for I in Full'Range loop - Read(F, Full(I)); + for I in d'Range loop + Read(F, d(I)); end loop; + -- read new line character and convert to hex Read(F, C); + if d'Length > Full'Length then + raise Incorrect_D_Len; + else + Full := ( others => '0' ); + Full(Full'Last-d'Length+1 .. Full'Last) := d; + end if; Hex2Octets(Full, Key.d); - -- read p for I in Half'Range loop Read(F, Half(I)); @@ -48,7 +62,6 @@ -- read new line character and convert to hex Read(F, C); Hex2Octets(Half, Key.p); - -- read q for I in Half'Range loop Read(F, Half(I)); @@ -56,16 +69,13 @@ -- read new line character and convert to hex Read(F, C); Hex2Octets(Half, Key.q); - -- read u for I in Half'Range loop Read(F, Half(I)); end loop; Hex2Octets(Half, Key.u); - -- Close file Close( F ); - exception when Char_IO.End_Error => Put_Line("ReadRSAKey ERROR: Unexpected end of file in " & Filename); @@ -80,7 +90,7 @@ H : String(1..Hex'Length+Hex'Length mod 2) := (others=>'0'); begin -- first char is 0 if needed to cover full octet... - H(H'Length-Hex'Length+1..H'Length) := Hex; + H(H'Last-Hex'Length+1..H'Last) := Hex; O := (others => 0); for I in 0 .. H'Length/2-1 loop S := "16#" & H(H'First + I*2 .. H'First + I*2 + 1) & "#"; diff -uNr a/smg_comms/tests/io_rsa.ads b/smg_comms/tests/io_rsa.ads --- a/smg_comms/tests/io_rsa.ads 57ad398331bf9b99c93592fca3bdeff7ca8ebfd630ec3fc142706498eb4a7dcb05f21520670d5945c26046237c7de2c93e021801157b5bf8bf99308fb004d8e4 +++ b/smg_comms/tests/io_rsa.ads 57ae10788359bec09ccf96403f641c0ec34c4152fc90ce172b93e4bc8c15e92a7c2248fceef9d6cb9caa7fc929c239466ca99bb4209bdb5c21ea5ea1983b75d0 @@ -7,13 +7,24 @@ package IO_RSA is + Incorrect_E_Len: exception; + Incorrect_D_Len: exception; + -- reads a full private key from specified file, in Hex format -- one component per line, in order: n, e, d, p, q, u -- NB: length of each component has to match *precisely* the expected length + -- e (public exponent) has the length given as argument + -- if E_Len < RSA_half'Length then e is stored 0-led in Key.e + -- if E_Len > RSA_half'Length then this will FAIL. -- specifically, using Raw_Types: - -- n, d are RSA_len'Length*2; - -- e, p, q, u are RSA_half'Length*2 - procedure ReadRSAKey( Filename: in String; Key: out RSA_OAEP.RSA_skey ); + -- n is RSA_len'Length octets (so *2 chars read); + -- p, q, u are RSA_half'Length (so *2 chars read); + -- e is RSA_half'Length but E_Len_Chars chars will be read; + -- d is RSA_len'Length but D_Len_Chars chars will be read; + procedure ReadRSAKey( Filename : in String; + E_Len_Chars : in Positive; + D_Len_Chars : in Positive; + Key : out RSA_OAEP.RSA_skey ); -- convert hexadecimal strings to octets representation procedure Hex2Octets( Hex: in String; O: out Raw_Types.Octets ); diff -uNr a/smg_comms/tests/test_packing.adb b/smg_comms/tests/test_packing.adb --- a/smg_comms/tests/test_packing.adb a8a3f14cbacaec0691d66c7058cd758c510e3addec91d5529093f6259ad65d3353b714f316a32cde7cc476cac611b167250ce6615db506cb7d62ed98cbcc8bdf +++ b/smg_comms/tests/test_packing.adb 1aaefe465677a28bd4cecc89d018dc6b10d2337f9b62ff332cc0cb688534980722a8190a62dec8dec5eccf6fb9e9e6ed7a5e47bdedb7cb5b3cc4f56b9620dbc1 @@ -74,7 +74,8 @@ Pkt : RSA_Pkt; begin -- initialize with RSA pair previously generated - IO_RSA.ReadRSAKey( "keys_rsa.txt", SKey ); + IO_RSA.ReadRSAKey( "keys_rsa.txt", Raw_Types.RSA_KEY_OCTETS, + Raw_Types.RSA_KEY_OCTETS*2, SKey ); -- copy n and e for public key PKey.n := SKey.n; diff -uNr a/smg_comms/tests/test_rsa_oaep.adb b/smg_comms/tests/test_rsa_oaep.adb --- a/smg_comms/tests/test_rsa_oaep.adb 6d2a795035290c00e290240a4d93260acdc2d7253ce4742bee41515920fdfb6ee78c4154753ef5f0fff15ded3d28fc69ca0aa90ef417fac0e914f3e4d4eb4a10 +++ b/smg_comms/tests/test_rsa_oaep.adb 86bffb60703b5608bb628be9af7ebe09b9fd6f185d831eca7384438934ed06647cad2613976533547471345b53267e3dde80ccb96a2bc8353b99cb1f91ae662b @@ -96,7 +96,9 @@ end test_oaep; -- test JUST RSA (i.e. without oaep) with RSA key pair previously generated - procedure test_rsa is + procedure test_rsa( E_Len : in Positive; + D_Len : in Positive; + Filename : in String) is Plain: OAEP_Block := (others => 0); Decr : OAEP_Block := (others => 0); Encr : RSA_len; @@ -104,7 +106,7 @@ skey: RSA_skey; begin -- initialize with RSA pair previously generated - IO_RSA.ReadRSAKey( "keys_rsa.txt", skey ); + IO_RSA.ReadRSAKey( Filename, E_Len, D_Len, skey ); -- copy n and e for public key pkey.n := skey.n; @@ -114,11 +116,12 @@ -- make first octet < RSA key's modulus first octet Plain(Plain'First) := 16#00#; -- naked rsa encrypt/decrypt -Put_Line("Encrypting with RSA public key..."); + Put_Line("Encrypting with RSA public key with e len " & + Positive'Image(E_Len) & "..."); Public_RSA( Plain, pkey, Encr ); -Put_Line("Decrypting with RSA private key..."); + Put_Line("Decrypting with RSA private key..."); Private_RSA( Encr, skey, Decr ); -Put_Line("Checking..."); + Put_Line("Checking..."); -- check result if Decr /= Plain then @@ -140,7 +143,8 @@ Len : Natural; begin -- initialize with RSA pair previously generated - IO_RSA.ReadRSAKey( "keys_rsa.txt", skey ); + IO_RSA.ReadRSAKey( "keys_rsa.txt", Raw_Types.RSA_KEY_OCTETS, + Raw_Types.RSA_KEY_OCTETS*2, skey ); -- copy n and e for public key pkey.n := skey.n; pkey.e := skey.e; diff -uNr a/smg_comms/tests/test_rsa_oaep.ads b/smg_comms/tests/test_rsa_oaep.ads --- a/smg_comms/tests/test_rsa_oaep.ads 30c188e997945f1e93be60c3d4c9d19f96c316252ca5fd8e538bce871d6e67c0538ee113ea9456b37e0e91572d2b218e70b139a5bdb8d79b64eed2d5e7afc71b +++ b/smg_comms/tests/test_rsa_oaep.ads 131d3d56175adb343684c0a7a8403bf0cea551aa938d8b588d81ef87324fca574fef5fcd1e2a6293950ba29522362cdd951a09df5b6a257bf451fced90502b5c @@ -6,7 +6,9 @@ package Test_RSA_OAEP is procedure test_char_array; procedure test_oaep; -- test oaep only - procedure test_rsa; -- test rsa only + procedure test_rsa( E_Len : in Positive; + D_Len : in Positive; + Filename : in String);-- test rsa only procedure test_rsa_oaep; -- test rsa+oaep procedure PrintOctets( O: in Raw_Types.Octets; Title: in String ); diff -uNr a/smg_comms/tests/testall.adb b/smg_comms/tests/testall.adb --- a/smg_comms/tests/testall.adb 4fcbe6d5f83c385c895668661f49ec5994d54b274866f52ed032815938ce3b3cdf94d8dfc18523aaa45ad17f9d691263aa6ef4080fb8cc55f2184217af041f4a +++ b/smg_comms/tests/testall.adb 9562018997131fc2926bf0bb38b1df008d5bd93a214e5f0c6e0eb2af94f5c23d94f7b623a899f7ea9b1fa5567f0faf5780488655e2bda6f081b66d2fc458ecd3 @@ -4,13 +4,17 @@ with Test_Packing; with Test_RSA_OAEP; with Messages.Test_Serializing; +with Raw_Types; procedure testall is begin Test_Serpent.Selftest; Test_RSA_OAEP.test_char_array; Test_RSA_OAEP.test_oaep; - Test_RSA_OAEP.test_rsa; + Test_RSA_OAEP.test_rsa( Raw_Types.RSA_KEY_OCTETS, + Raw_Types.RSA_KEY_OCTETS*2, "keys_rsa.txt" ); + Test_RSA_OAEP.test_rsa( Raw_Types.E_LENGTH_OCTETS*2, + Raw_Types.RSA_KEY_OCTETS*2 - 1, "8_keys.txt" ); Test_RSA_OAEP.test_rsa_oaep; Test_Packing.Test_Pack_Unpack_Serpent; Test_Packing.Test_Pack_Unpack_RSA;