tree checksum vpatch file split hunks
all signers: diana_coman
antecedents: smg_comms_packing_serpent smg_comms_raw_types smg_comms_c_wrappers
press order:
smg_comms_genesis | diana_coman |
smg_comms_raw_types | diana_coman |
smg_comms_packing_serpent | diana_coman |
smg_comms_c_wrappers | diana_coman |
smg_comms_rsa_oaep | diana_coman |
patch:
(144 . 78)(144 . 72)
5
6 //key pair previously generated with EuCrypt
7 mpi_fromstr(sk.n, "0x\
8 CD2C025323BEA46FFF2FA8D7A9D39817EA713421F4AE03FA8120641193892A70BFECF5\
9 83101635A432110D3DDE6339E3CC7ECC0AD91C026FCACE832DD3888A6FCA7BCE56C390\
10 5A5AC8C7BC921DA675E4B62489B254EB34659D547D71165BC998983A81937BD251AEE1\
11 2D985EC387D5376F5DCC5EF7EC530FBD6FD2AA7285EE1AF3335EA73163F0954F30402E\
12 D7B374EE84A97B1849B0674B0DA0A2050BD79B71ABB1559F3A9CFDB8557DED7BC90CF2\
13 09E8A847E9C226140845B7D03842162E7DA5DD16326CB1F71A248D841FE9076A09911F\
14 2F4F5E3EA44EA8DE40332BF00406990BCCF61C322A03C456EF3A98B341E0BDBC1088CE\
15 683E78510E76B72C2BCC1EE9AEDD80FFF18ABFC5923B2F36B581C25114AB2DF9F6C2B1\
16 9481703FD19E313DCD7ACE15FA11B27D25BCE5388C180A7E21167FB87750599E1ED7C7\
17 50F4A844E1DC2270C62D19671CF8F4C25B81E366B09FC850AE642136D204A9160AEECE\
18 575B57378AA439E9DD46DC990288CD54BAA35EEE1C02456CD39458A6F1CBF012DCEDF4\
19 27CCF3F3F53645658FC49C9C9D7F2856DB571D92B967AB5845514E0054DDB49099F5DD\
20 04A6F6F5C5CE642276834B932881AEB648D1F25E9223971F56E249EF40CF7D80F22621\
21 CDD0260E9E7D23746960ADB52CF2987584FB1DE95A69A39E5CB12B76E0F5C1A0529C0C\
22 065D2E35720810F7C7983180B9A9EA0E00C11B79DC3D");
23 C6579F8646180EED0DC1F02E0DDD2B43EABB3F702D79D9928E2CDA5E1D42DF5D9ED777\
24 3F80B1F8D9B0DB7D4D00F55647640D70768F63D3CED56A39C681D08D6191F318BB79DC\
25 969B470A7364D53335C8318EF35E39D5DF706AB6F2393C6DD2128C142DBAB1806EB35E\
26 26C908F0A48419313D2D0F33DD430655DBFEC722899EC21C238E8DB7003430BBC39BAD\
27 990F9887F6B03E1344F537EC97389B78DBC656718ACD7B0FDC13DD24534F417BC7A18F\
28 077A0C4227354CEA19670331B6CAA3DFC17BBA7E70C14510D9EB3B63F3014994EC87BD\
29 23E868C0AE6E9EC55027577F62C0280B2D7DD1135001844923E5455C4566E066B3FDE9\
30 68C6BC4DC672F229FCE366440403D7A4F4A8BFBA5679B7D0844BA1231277D13A77C9E2\
31 B5A1CB138C1B7AB5B4D4832448723A3DE70ED2E86D5FC5174F949A02DE8E404304BEB9\
32 5F9BF40F3AA3CA15622D2776294BE7E19233406FF563CB8C25A1CB5AADBC1899DA3F2A\
33 E38533931FE032EE3232C2CD4F219FADF95B91635C0762A476A4DE5013F4384093F0FB\
34 715028D97F93B2E6F057B99EE344D83ADF2686FD5C9C793928BEF3182E568C4339C36C\
35 744C8E9CA7D4B9A16AA039CBF6F38CC97B12D87644E94C9DBD6BC93A93A03ED61ECC58\
36 74586E3A310E958F858735E30019D345C62E5127B80652C8A970A14B31F03B3A157CD5");
37
38 mpi_fromstr(sk.e, "0x\
39 DD4856B4EE3D099A8604AE392D8EFEC094CDF01546A28BE87CB484F999E8E75CDFCD01\
40 D04D455A6A9254C60BD28C0B03611FC3E751CC27EF768C0B401C4FD2B27C092834A6F2\
41 49A145C4EDC47A3B3D363EC352462C945334D160AF9AA72202862912493AC6190AA3A6\
42 149D4D8B9996BA7927D3D0D2AD00D30FD630CF464E6CAF9CF49355B9A70E05DB7AE915\
43 F9F602772F8D11E5FCDFC7709210F248052615967090CC1F43D410C83724AA5912B2F0\
44 52E6B39449A89A97C79C92DC8CB8DEEFCF248C1E1D2FC5BFE85165ECA31839CAA9CEB3\
45 3A92EBDC0EB3BAC0F810938BB173C7DA21DCBB2220D44CBA0FD40A2C868FC93AC5243E\
46 C137C27B0A76D65634EBB3");
47 F74D78E382FC19B064411C6C20E0FDB2985F843007A54C7D8400BB459468624126E7D1\
48 75F397E55C57AF25858EAE2D2952FB7998C119A6103606733EB5E1D27FCA1FACF14ADE\
49 94101D383D1B25DA511805569BC344EAD384EDBF3F3A541B34887FE199D99D7F62E6E9\
50 D516F88D6F5AD3E020DF04D402A02CC628A0064362FE8516CF7CD6040E9521407AB90E\
51 E6B5AFFF9EA9EBB16A7D3407CE81FD3844F519880556AB94AB349C1F3BBB6FDB4C4B37\
52 7FE4C091EBDC2C3A1BD3AA56382D8D80E7742B5C751008FD6ECDD2EC3B2E3B6C566F69\
53 8ED672000B403766DD63C3ACBDE16A14FB02E83A2EB6AA018BFC0020401E790DEE24E9");
54
55 mpi_fromstr(sk.d, "0x\
56 7C8A6FA1199D99DCA45E9BDF567CA49D02B237340D7E999150BC4883AE29DEC5158521\
57 B338F35DC883792356BDDBB3C8B3030A6DD4C6522599A3254E751F9BA1CB1061C5633C\
58 81BBFACF6FCD64502614102DFED3F3FA284066C342D5E00953B415915331E30812E5FB\
59 CD6680ADCCDEE40B8376A3A225F2E160EA59C7566804526D73BB660A648A3EF9802313\
60 B2F841E8458B2AAACE7AACF31083E8F3F630298138393BC88BBD7D4AA4334949651D25\
61 365B10DBF4A4A08E20A6CC74BFDD37C1C38E2ADC2A283DF06590DF06B46F67F6ACA67F\
62 AC464C795261659A2F9558802D0BBAA05FD1E1AF2CDC70654723DF7EFAEA148B8CDBEB\
63 C89EA2320AB9BBB1BC4311475DF3D91446F02EF192368DFEBAC598CCFD4407DEC58FDC\
64 1A94CCDD6E5FBA9C52164ACEA8AEE633E557BCCEACB7A1AF656C379482D784A120A725\
65 32F9B2B35173D505F21D5AD4CB9511BC836DC923730B70291B70290A216CA3B21CFF79\
66 E895C35F4F7AF80E1BD9ED2773BD26919A76E4298D169160593E0335BE2A2A2D2E8516\
67 948F657E1B1260E18808A9D463C108535FB60B3B28F711C81E5DE24F40214134A53CE5\
68 9A952C8970A1D771EBEFFA2F4359DCF157995B3F1950DE3C6EC41B7FF837148F55F323\
69 372AF3F20CE8B8038E750C23D8F5041FA951327859B0E47483F0A47103EF808C72C251\
70 006FA526245291C8C84C12D2EF63FB2301EA3EEDA42B");
71 698DA05DA25B230211EEF0CBA12083A1457B749A11937AC9993859F69A3BF38D575E51\
72 66AF2EC88D77F1DF04E68AEA358EACF7659FD4722A4F5A1C8BA7676DA97A9FBA754511\
73 52F8F68887D3451A9CCFFFE9EB80979786E37495B17687A6212F77FA616E4C0CD8A8EB\
74 7AEB88EA6CCABB7F3E854FB94B35394A09F95F0D6F997947E865CC0606F437C30FE8C4\
75 8D96FBF5E2F52807BC9E9ED7BBEB23D5C45EDDCD16FE2BF410A9A1E5EF879E71C0D41F\
76 AE270C0C5D442860103F8C3944E802F33DB38432F11F763A7AF593656108E4A98A44A8\
77 549913CE5DCEC1A6500F280E3190991B2B938561CFACD8BC5183AAC9A4914BFE52C3BE\
78 39BB83688E1DE52479107EF8E087DCDB409432FC954C6349407E81DDFB11AE92BABB32\
79 A31868597958C9C76E0B4156F380955F0E09C1F3B98BB4CDD59E1B5C7D8CC2AA7491B0\
80 D319D219CF459A527CE1AA2729DEC53269653BF0ED3E0253F4451168437E3B069E4835\
81 0CA4C3EC82134E87135624C768D1330B0D70C6E447FD9945BF06FCB91AA334C0FD8EEF\
82 1ADBC15928B3DB62077B537F7E9F468CC95CD5AAFEAE1F760A863B48D07B163F670E2E\
83 5B550BB3E960230BA9FDAED9903AE2E669A7F3C4D1F1E25B8E8EDB8CC6E6FD2164E66F\
84 4E64ED77BEF1EC9E6CEA5624FD84C0680248746DC1C8187145F3CD2411659DAEAD11D");
85
86 mpi_fromstr(sk.p, "0x\
87 E236732452039C14EC1D3B8095BDDCFB7625CE27B1EA5394CF4ED09D3CEECAA4FC0BF6\
88 2F7CE975E0C8929CE84B0259D773EA038396479BF15DA065BA70E549B248D77B4B23ED\
89 A267308510DBEE2FD44E35D880EE7CFB81E0646AA8630165BD8988C3A8776D9E704C20\
90 AA25CA0A3C32F27F592D5FD363B04DD57D8C61FFDCDFCCC59E2913DE0EE47769180340\
91 E1EA5A803AA2301A010FF553A380F002601F0853FCACDB82D76FE2FACBCD6E5F294439\
92 0799EA5AE9D7880D4E1D4AE146DC1D4E8495B9DD30E57E883923C5FC26682B7142D35C\
93 D8A0FC561FE725A6CF419B15341F40FE0C31132CBD81DD8E50697BD1EBFFA16B522E16\
94 F5B49A03B707218C7DA60B");
95 CDD6F7673A501FB24C44D56CA1D434F6CB3334E193E02F8E906241906BCB7412DD2159\
96 825B24C22002F373E647C2DA62A854F3841C00FD5985D03227CA9B54A69380BA9D63BE\
97 738BDF9E65C247E43E1220EEDD9281DCA78B32A4E1B786B7697ED0C3195D5AF2990881\
98 B11D6FC9EC9F940067B2DEA2A516FAA5F269C98F0B67628A6D2708515A4A58041AA17A\
99 93E4C4DD95C85BC38351DDA1DCF3DFD91C505B22383132649CF9F9233852C7207075BC\
100 F43C71038F043F1EC53E9787FB051B7927D020903233C16897B993C8089D8464451F08\
101 6E756CF20E46CE6ED4A6AC5C327A0AAFBECBAAFD177969E7C952C76A4F4E7C85BF7F63");
102
103 mpi_fromstr(sk.q, "0x\
104 E830482A3C4F5C3A7E59C10FF8BA760DB1C6D55880B796FFDA4A82E0B60E974E81D04B\
105 2A4AD417823EBFB4E8EFB13782943562B19B6C4A680E3BA0C8E37B5023470F4F1AC1F8\
106 A0B10672EF75CD58BCD45E6B14503B8A6A70AFE79F6201AF56E7364A1C742BE1453FD2\
107 24FDC9D66522EAF4466A084BCB9E46D455A2946E94CBF028770F38D0B741C2CC59308F\
108 71D8C2B4B9C928E0AE8D68DEB48A3E9EFD84A10301EBD55F8221CA32FC567B306B2A8E\
109 116350AFB995859FDF4378C5CFD06901494E8CFA5D8FAC564D6531FA8A2E4761F5EFBA\
110 F78750B6F4662BE9EA4C2FAD67AF73EEB36B41FC15CB678810C19A51DF23555695C4C1\
111 546F3FACA39CAA7BB8DBD7");
112 F6ACF0790A250802C8D45DAC549CDBEF7806D5877A5DF0069136A458FAC4F0B0858060\
113 A873DA6355A965A064A0BC1BBB874872CD7ED89674AD407533041E74BCA317EC73597D\
114 335115523F61A05071E5ED81EE2A05331F65D4DC7A25AD7938B124CF03F49154B6693F\
115 B0B598B33ABDEF85C599A57A9B7347EAFF82638E1CBC28FCDFFF1FF04A18C2DBF39383\
116 95C2F8D1782B43D3A25EF7633B5DDAC89EFD3BAA64D976425A0891E00B876E9DE9FE4B\
117 6492B0EA8DFC7C8DEEC61721356EC816295B1BD9CD9DA3E30D2D90DC9CB3987F4BE042\
118 104900E036F3044A016749EF910CCFB9F377A90849B4CCCF4471A74E67EF6C814C9467");
119
120 mpi_fromstr(sk.u, "0x\
121 846232322775C1CD7D5569DC59E2F3E61A885AE2E9C4A4F8CB3ACBE8C3A5441E5FE348\
122 A2A8AC9C2998FBF282222BF508AA1ECF66A76AEDD2D9C97028BFD3F6CA0542E38A5312\
123 603C70B95650CE73F80FDD729988FBDB5595A5BF8A007EA34E54994A697906CE56354C\
124 E00DF10EB711DEC274A62494E3D350D88736CF67A477FB600AC9F1D6580727585092BF\
125 5EBC092CC4D6CF75769051033A1197103BE269942F372168A53771746FBA18ED6972D5\
126 0B935A9B1D6B5B3DD50CD89A27FE93C10924E9103FACF7B4C5724A046C3D3B50CC1C78\
127 5F5C8E00DBE1D6561F120F5294C170914BC10F978ED4356EED67A9F3A60D70AFE540FC\
128 5373CBAE3D0A7FD1C87273");
129 854B89ED10F52258D00D6B3FA7F1FD22752804668F51FF7806DB82E22CB8B3AA8448D9\
130 B8E9DB14D31A36AEC2BCFA89E341B7334D494E97ED8051244136192233332C4612D963\
131 E7B6AF2535FDB7FE97E28DDFEBDFB3E1AFC29D05DBDF37106A817D3AB1864C7F7F2479\
132 82897EDA6A92BED47D9C68305CD170C7301ACEB05F8A6382E73CC7614B2D8D758669B3\
133 A99AB64114809254B0BE21F40341A5B48B9B032603B14875B87EB5E16603FD16552E14\
134 6A0FC6964958DFC25AA9FFCCD1ED1F4DEAF9FBAA0D7357F5FF0803FEB9BA78E74AC6B3\
135 070F417CEC6CFC7A3CF1E305FC7B76B7ED71893999AF797B2EBDE41FE90F076CCEDBFB");
136
137 // copy the public key components
138 pk.n = mpi_copy( sk.n );
- 1D5B032F775B2B59D4BCBAFDDE81D65EFB3E11925C30962717565CD0CB2C2218434DAE770C470DC0A11B70F70B4CD78D37A3534741CFCCB2E002CF4ED4E94008(2 . 3)(2 . 4)
143 546000 smg_comms_raw_types diana_coman Part of layer 0 - raw types for the updated version of the protocol containing only two types of packets: 1470 octets RSA packet and 1472 octets Serpent packet.
144 546152 smg_comms_packing_serpent diana_coman Packing/Unpacking Serpent messages <-> Serpent packets. Includes Serpent implementation.
145 547275 smg_comms_c_wrappers diana_coman C wrappers for RSA and MPI methods that are needed by SMG Comms (so that they can be called from Ada using only arrays of octets as inputs/outputs).
146 547983 smg_comms_rsa_oaep diana_coman RSA with OAEP from ADA using the c_wrappers for RSA only. It includes reading from FG in Ada and repeat of OAEP until first octet is < first octet of key's modulus (i.e. without going through MPI for comparison).
- 52AE9657AD5ABADAC6412597E48D26257703F293EB9348353097EEB9F2B00934FC862B075776B751B68E0423CBF452FBD1F3A9DB0FB99C93E6D9F551114B33D7(26 . 7)(26 . 7)
151 --pragma Restrictions(No_Floating_Point);
152 pragma Restrictions(No_Implementation_Aspect_Specifications);
153 pragma Restrictions(No_Implementation_Units);
154 pragma Restrictions(No_Implicit_Conditionals);
155 --pragma Restrictions(No_Implicit_Conditionals);
156 pragma Restrictions(No_Implicit_Dynamic_Code);
157 pragma Restrictions(No_Implicit_Heap_Allocations);
158 pragma Restrictions(No_Implicit_Protected_Object_Allocations);
- 658150D9CC3FF5F1D4A6D134C57D9EA6740BE6AEF571EF9C2BD553A3E4931A541CCF755BF51DC5349A4DBAECF04DC11E0D4FAFF4D4745E322CF22231241570F5(1 . 7)(1 . 7)
163 -- Tests for SMG_RSA (part of EuCrypt)
164 -- S.MG, 2018
165
166 with "../smg_rsa.gpr";
167 with "../rsa.gpr";
168
169 project SMG_RSA_Tests is
170 for Languages use("C");
- 89B1C405D92E249341BDC0BDDC5A98D8AE8DD0349E04A165063D938F01DF557A057BE544C51B0EFB6D72D505F1424A1AA3A6D7957E83F229711677240123E2FD(409 . 152)(409 . 6)-
175 mpi_free(sk.u);
176 }
177
178 void test_oaep_encr_decr( int nruns ) {
179 /* a set of RSA keys previously generated with eucrypt */
180 RSA_public_key pk;
181 pk.n = mpi_alloc(0);
182 pk.e = mpi_alloc(0);
183
184 RSA_secret_key sk;
185 sk.n = mpi_alloc(0);
186 sk.e = mpi_alloc(0);
187 sk.d = mpi_alloc(0);
188 sk.p = mpi_alloc(0);
189 sk.q = mpi_alloc(0);
190 sk.u = mpi_alloc(0);
191
192 mpi_fromstr(sk.n, "0x\
193 CD2C025323BEA46FFF2FA8D7A9D39817EA713421F4AE03FA8120641193892A70BFECF5\
194 83101635A432110D3DDE6339E3CC7ECC0AD91C026FCACE832DD3888A6FCA7BCE56C390\
195 5A5AC8C7BC921DA675E4B62489B254EB34659D547D71165BC998983A81937BD251AEE1\
196 2D985EC387D5376F5DCC5EF7EC530FBD6FD2AA7285EE1AF3335EA73163F0954F30402E\
197 D7B374EE84A97B1849B0674B0DA0A2050BD79B71ABB1559F3A9CFDB8557DED7BC90CF2\
198 09E8A847E9C226140845B7D03842162E7DA5DD16326CB1F71A248D841FE9076A09911F\
199 2F4F5E3EA44EA8DE40332BF00406990BCCF61C322A03C456EF3A98B341E0BDBC1088CE\
200 683E78510E76B72C2BCC1EE9AEDD80FFF18ABFC5923B2F36B581C25114AB2DF9F6C2B1\
201 9481703FD19E313DCD7ACE15FA11B27D25BCE5388C180A7E21167FB87750599E1ED7C7\
202 50F4A844E1DC2270C62D19671CF8F4C25B81E366B09FC850AE642136D204A9160AEECE\
203 575B57378AA439E9DD46DC990288CD54BAA35EEE1C02456CD39458A6F1CBF012DCEDF4\
204 27CCF3F3F53645658FC49C9C9D7F2856DB571D92B967AB5845514E0054DDB49099F5DD\
205 04A6F6F5C5CE642276834B932881AEB648D1F25E9223971F56E249EF40CF7D80F22621\
206 CDD0260E9E7D23746960ADB52CF2987584FB1DE95A69A39E5CB12B76E0F5C1A0529C0C\
207 065D2E35720810F7C7983180B9A9EA0E00C11B79DC3D");
208
209 mpi_fromstr(sk.e, "0x\
210 DD4856B4EE3D099A8604AE392D8EFEC094CDF01546A28BE87CB484F999E8E75CDFCD01\
211 D04D455A6A9254C60BD28C0B03611FC3E751CC27EF768C0B401C4FD2B27C092834A6F2\
212 49A145C4EDC47A3B3D363EC352462C945334D160AF9AA72202862912493AC6190AA3A6\
213 149D4D8B9996BA7927D3D0D2AD00D30FD630CF464E6CAF9CF49355B9A70E05DB7AE915\
214 F9F602772F8D11E5FCDFC7709210F248052615967090CC1F43D410C83724AA5912B2F0\
215 52E6B39449A89A97C79C92DC8CB8DEEFCF248C1E1D2FC5BFE85165ECA31839CAA9CEB3\
216 3A92EBDC0EB3BAC0F810938BB173C7DA21DCBB2220D44CBA0FD40A2C868FC93AC5243E\
217 C137C27B0A76D65634EBB3");
218
219 mpi_fromstr(sk.d, "0x\
220 7C8A6FA1199D99DCA45E9BDF567CA49D02B237340D7E999150BC4883AE29DEC5158521\
221 B338F35DC883792356BDDBB3C8B3030A6DD4C6522599A3254E751F9BA1CB1061C5633C\
222 81BBFACF6FCD64502614102DFED3F3FA284066C342D5E00953B415915331E30812E5FB\
223 CD6680ADCCDEE40B8376A3A225F2E160EA59C7566804526D73BB660A648A3EF9802313\
224 B2F841E8458B2AAACE7AACF31083E8F3F630298138393BC88BBD7D4AA4334949651D25\
225 365B10DBF4A4A08E20A6CC74BFDD37C1C38E2ADC2A283DF06590DF06B46F67F6ACA67F\
226 AC464C795261659A2F9558802D0BBAA05FD1E1AF2CDC70654723DF7EFAEA148B8CDBEB\
227 C89EA2320AB9BBB1BC4311475DF3D91446F02EF192368DFEBAC598CCFD4407DEC58FDC\
228 1A94CCDD6E5FBA9C52164ACEA8AEE633E557BCCEACB7A1AF656C379482D784A120A725\
229 32F9B2B35173D505F21D5AD4CB9511BC836DC923730B70291B70290A216CA3B21CFF79\
230 E895C35F4F7AF80E1BD9ED2773BD26919A76E4298D169160593E0335BE2A2A2D2E8516\
231 948F657E1B1260E18808A9D463C108535FB60B3B28F711C81E5DE24F40214134A53CE5\
232 9A952C8970A1D771EBEFFA2F4359DCF157995B3F1950DE3C6EC41B7FF837148F55F323\
233 372AF3F20CE8B8038E750C23D8F5041FA951327859B0E47483F0A47103EF808C72C251\
234 006FA526245291C8C84C12D2EF63FB2301EA3EEDA42B");
235
236 mpi_fromstr(sk.p, "0x\
237 E236732452039C14EC1D3B8095BDDCFB7625CE27B1EA5394CF4ED09D3CEECAA4FC0BF6\
238 2F7CE975E0C8929CE84B0259D773EA038396479BF15DA065BA70E549B248D77B4B23ED\
239 A267308510DBEE2FD44E35D880EE7CFB81E0646AA8630165BD8988C3A8776D9E704C20\
240 AA25CA0A3C32F27F592D5FD363B04DD57D8C61FFDCDFCCC59E2913DE0EE47769180340\
241 E1EA5A803AA2301A010FF553A380F002601F0853FCACDB82D76FE2FACBCD6E5F294439\
242 0799EA5AE9D7880D4E1D4AE146DC1D4E8495B9DD30E57E883923C5FC26682B7142D35C\
243 D8A0FC561FE725A6CF419B15341F40FE0C31132CBD81DD8E50697BD1EBFFA16B522E16\
244 F5B49A03B707218C7DA60B");
245
246 mpi_fromstr(sk.q, "0x\
247 E830482A3C4F5C3A7E59C10FF8BA760DB1C6D55880B796FFDA4A82E0B60E974E81D04B\
248 2A4AD417823EBFB4E8EFB13782943562B19B6C4A680E3BA0C8E37B5023470F4F1AC1F8\
249 A0B10672EF75CD58BCD45E6B14503B8A6A70AFE79F6201AF56E7364A1C742BE1453FD2\
250 24FDC9D66522EAF4466A084BCB9E46D455A2946E94CBF028770F38D0B741C2CC59308F\
251 71D8C2B4B9C928E0AE8D68DEB48A3E9EFD84A10301EBD55F8221CA32FC567B306B2A8E\
252 116350AFB995859FDF4378C5CFD06901494E8CFA5D8FAC564D6531FA8A2E4761F5EFBA\
253 F78750B6F4662BE9EA4C2FAD67AF73EEB36B41FC15CB678810C19A51DF23555695C4C1\
254 546F3FACA39CAA7BB8DBD7");
255
256 mpi_fromstr(sk.u, "0x\
257 846232322775C1CD7D5569DC59E2F3E61A885AE2E9C4A4F8CB3ACBE8C3A5441E5FE348\
258 A2A8AC9C2998FBF282222BF508AA1ECF66A76AEDD2D9C97028BFD3F6CA0542E38A5312\
259 603C70B95650CE73F80FDD729988FBDB5595A5BF8A007EA34E54994A697906CE56354C\
260 E00DF10EB711DEC274A62494E3D350D88736CF67A477FB600AC9F1D6580727585092BF\
261 5EBC092CC4D6CF75769051033A1197103BE269942F372168A53771746FBA18ED6972D5\
262 0B935A9B1D6B5B3DD50CD89A27FE93C10924E9103FACF7B4C5724A046C3D3B50CC1C78\
263 5F5C8E00DBE1D6561F120F5294C170914BC10F978ED4356EED67A9F3A60D70AFE540FC\
264 5373CBAE3D0A7FD1C87273");
265
266 /* copy the public key components */
267 pk.n = mpi_copy( sk.n );
268 pk.e = mpi_copy( sk.e );
269
270 /* some plain text message */
271 MPI msg = mpi_alloc(0);
272 mpi_fromstr(msg, "0x\
273 5B6A8A0ACF4F4DB3F82EAC2D20255E4DF3E4B7C799603210766F26EF87C8980E737579\
274 EC08E6505A51D19654C26D806BAF1B62F9C032E0B13D02AF99F7313BFCFD68DA46836E\
275 CA529D7360948550F982C6476C054A97FD01635AB44BFBDBE2A90BE06F7984AC8534C3\
276 28097EF92F6E78CAE0CB97");
277
278 /* actual testing */
279 printf("TEST verify oaep_encr_decr on message: \n");
280 mpi_print( stdout, msg, 1);
281 printf("\n");
282
283 int nlimbs_n = mpi_nlimb_hint_from_nbytes( KEY_LENGTH_OCTETS);
284 MPI encr = mpi_alloc( nlimbs_n );
285 MPI decr = mpi_alloc( nlimbs_n );
286 int success;
287
288 adainit();
289 rsa_oaep_encrypt( encr, msg, &pk );
290 rsa_oaep_decrypt( decr, encr, &sk, &success );
291
292 if (success <= 0 ||
293 mpi_cmp(encr, msg) == 0 ||
294 mpi_cmp(msg, decr) != 0)
295 printf("FAILED: success flag is %d\n", success);
296 else
297 printf("PASSED\n");
298
299 /* attempt to decrypt corrupted block */
300 mpi_clear( decr );
301 rsa_oaep_decrypt( decr, pk.n, &sk, &success);
302 if (success > 0)
303 printf("FAILED: attempt to decrypt non-/corrupted oaep block\n");
304 else
305 printf("PASSED: attempt to decrypt non-/corrupted oaep block\n");
306 adafinal();
307
308 /* clean up */
309 mpi_free( sk.n );
310 mpi_free( sk.e );
311 mpi_free( sk.d );
312 mpi_free( sk.p );
313 mpi_free( sk.q );
314 mpi_free( sk.u );
315
316 mpi_free( pk.n );
317 mpi_free( pk.e );
318
319 mpi_free( msg );
320 mpi_free( encr );
321 mpi_free( decr );
322 }
323
324 void test_mpi_buffer() {
325 unsigned int noctets = 10;
326 int nlimbs = mpi_nlimb_hint_from_nbytes( noctets );
(720 . 21)(574 . 18)
328 time_rsa_gen(nruns);
329 break;
330 case 9:
331 test_oaep_encr_decr(nruns);
332 break;
333 case 10:
334 test_mpi_buffer();
335 break;
336 case 11:
337 case 10:
338 test_dirty_float_rng(nruns);
339 break;
340 case 12:
341 case 11:
342 test_ieee_float_rng(nruns);
343 break;
344 case 13:
345 case 12:
346 test_uint32_rng(nruns);
347 break;
348 case 14:
349 case 13:
350 test_uint64_rng(nruns);
351 break;
352 default:
(749 . 12)(600 . 11)
354 writes to keys.asc and check_keys.asc\n");
355 printf("7 for testing rsa exponentiation (fixed data)\n");
356 printf("8 for timing rsa key pair generator\n");
357 printf("9 for oaep encrypt/decrypt\n");
358 printf("10 for testing mpi_set/get_buffer\n");
359 printf("11 for testing smg_rng dirty float\n");
360 printf("12 for testing smg_rng ieee 745/1985 float\n");
361 printf("13 for testing smg_rng uint32 \n");
362 printf("14 for testing smg_rng uint64 \n");
363 printf("9 for testing mpi_set/get_buffer\n");
364 printf("10 for testing smg_rng dirty float\n");
365 printf("11 for testing smg_rng ieee 745/1985 float\n");
366 printf("12 for testing smg_rng uint32 \n");
367 printf("13 for testing smg_rng uint64 \n");
368 }
369
370 return 0;
(0 . 0)(1 . 271)
375 -- S.MG, 2018
376 with System; use System; -- for Bit_Order
377
378 package body Keccak is
379
380 -- public function, sponge
381 procedure Sponge( Input : in Bitstream;
382 Output : out Bitstream;
383 Block_Len : in Keccak_Rate := Default_Bitrate ) is
384 Internal : State := (others => (others => 0));
385 begin
386 --absorb input into sponge in a loop on available blocks, including padding
387 declare
388 -- number of input blocks after padding (2 to block_len bits pad)
389 Padded_Blocks : constant Positive := 1 + (Input'Length + 1) / Block_Len;
390 Padded : Bitstream ( 1 .. Padded_Blocks * Block_Len );
391 Block : Bitstream ( 1 .. Block_Len );
392 begin
393 -- initialise Padded with 0 everywhere
394 Padded := ( others => 0 );
395 -- copy and pad input with rule 10*1
396 Padded( Padded'First .. Padded'First + Input'Length - 1 ) := Input;
397 Padded( Padded'First + Input'Length ) := 1;
398 Padded( Padded'Last ) := 1;
399
400 -- loop through padded input and absorb block by block into sponge
401 -- padded input IS a multiple of blocks, so no stray bits left
402 for B in 0 .. Padded_Blocks - 1 loop
403 -- first get the current block to absorb
404 Block := Padded( Padded'First + B * Block_Len ..
405 Padded'First + (B+1) * Block_Len - 1 );
406 AbsorbBlock( Block, Internal );
407 -- scramble state with Keccak function
408 Internal := Keccak_Function( Internal );
409
410 end loop; -- end absorb loop for blocks
411 end; -- end absorb stage
412
413 --squeeze required bits from sponge in a loop as needed
414 declare
415 -- full blocks per output
416 BPO : constant Natural := Output'Length / Block_Len;
417 -- stray bits per output
418 SPO : constant Natural := Output'Length mod Block_Len;
419 Block : Bitstream( 1 .. Block_Len );
420 begin
421 -- squeeze block by block (if at least one full block is needed)
422 for I in 0 .. BPO - 1 loop
423 SqueezeBlock( Block, Internal );
424 Output( Output'First + I * Block_Len ..
425 Output'First + (I + 1) * Block_Len -1) := Block;
426
427 -- scramble state
428 Internal := Keccak_Function( Internal );
429 end loop; -- end squeezing full blocks
430
431 -- squeeze any partial block needed (stray bits)
432 if SPO > 0 then
433 SqueezeBlock( Block, Internal );
434 Output( Output'Last - SPO + 1 .. Output'Last ) :=
435 Block( Block'First .. Block'First + SPO - 1 );
436 end if; -- end squeezing partial last block (stray bits)
437
438 end; -- end squeeze stage
439 end Sponge;
440
441 -- convert from a bitstream of ZWord size to an actual ZWord number
442 function BitsToWord( BWord: in Bitword ) return ZWord is
443 W : ZWord;
444 Bits: Bitword;
445 begin
446 -- just copy octets if machine is little endian
447 -- flip octets if machine is big endian
448 if Default_Bit_Order = Low_Order_First then
449 Bits := BWord;
450 else
451 Bits := FlipOctets( BWord );
452 end if;
453 -- actual bits to word conversion
454 W := 0;
455 -- LSB bit order (inside octet) as per Keccak spec
456 for I in reverse Bitword'Range loop
457 W := Shift_Left( W, 1 ) + ZWord( Bits( I ) );
458 end loop;
459 return W;
460 end BitsToWord;
461
462 -- convert from a ZWord (lane of state) to a bitstream of ZWord size
463 function WordToBits( Word: in ZWord ) return Bitword is
464 Bits: Bitword := (others => 0);
465 W: ZWord;
466 begin
467 W := Word;
468 for I in Bitword'Range loop
469 Bits( I ) := Bit( W mod 2 );
470 W := Shift_Right( W, 1 );
471 end loop;
472
473 -- flip octets if machine is big endian
474 if Default_Bit_Order = High_Order_First then
475 Bits := FlipOctets( Bits );
476 end if;
477
478 return Bits;
479 end WordToBits;
480
481 -- flip given octets (i.e. groups of 8 bits)
482 function FlipOctets( BWord : in Bitword ) return Bitword is
483 Bits : Bitword;
484 begin
485 -- copy groups of 8 octets changing their order in the array
486 -- i.e. 1st octet in BWord becomes last octet in Bits and so on
487 for I in 0 .. ( Bitword'Length / 8 - 1 ) loop
488 Bits ( Bits'First + I * 8 .. Bits'First + I * 8 + 7 ) :=
489 BWord( BWord'Last - I * 8 - 7 .. BWord'Last - I * 8);
490 end loop;
491 return Bits;
492 end FlipOctets;
493
494 -- helper procedures for sponge absorb/squeeze
495
496 -- NO scramble here, this will absorb ALL given block, make sure it fits!
497 procedure AbsorbBlock( Block: in Bitstream; S: in out State ) is
498 WPB: constant Natural := Block'Length / Z_Length; -- words per block
499 SBB: constant Natural := Block'Length mod Z_Length; -- stray bits
500 FromPos, ToPos : Natural;
501 X, Y : XYCoord;
502 Word : ZWord;
503 BWord : Bitword;
504 begin
505 -- xor current block into first Block'Length bits of state
506 -- a block can consist in more than one word
507 X := 0;
508 Y := 0;
509 for I in 0..WPB-1 loop
510 FromPos := Block'First + I * Z_Length;
511 ToPos := FromPos + Z_Length - 1;
512 Word := BitsToWord( Block( FromPos .. ToPos ) );
513 S( X, Y ) := S( X, Y ) xor Word;
514 -- move on to next word in state
515 X := X + 1;
516 if X = 0 then
517 Y := Y + 1;
518 end if;
519 end loop;
520 -- absorb also any remaining bits from block
521 if SBB > 0 then
522 ToPos := Block'Last;
523 FromPos := ToPos - SBB + 1;
524 BWord := (others => 0);
525 BWord(Bitword'First .. Bitword'First + SBB - 1) := Block(FromPos..ToPos);
526 Word := BitsToWord( BWord );
527 S( X, Y ) := S( X, Y ) xor Word;
528 end if;
529 end AbsorbBlock;
530
531 --NO scramble here, this will squeeze Block'Length bits out of *same* state S
532 procedure SqueezeBlock( Block: out Bitstream; S: in State) is
533 X, Y : XYCoord;
534 BWord : Bitword;
535 FromPos : Natural;
536 Len : Natural;
537 begin
538 X := 0;
539 Y := 0;
540 FromPos := Block'First;
541
542 while FromPos <= Block'Last loop
543 BWord := WordToBits( S(X, Y) );
544
545 X := X + 1;
546 if X = 0 then
547 Y := Y + 1;
548 end if;
549
550 -- copy full word if it fits or
551 -- only as many bits as are still needed to fill the block
552 Len := Block'Last - FromPos + 1;
553 if Len > Z_Length then
554 Len := Z_Length;
555 end if;
556
557 Block(FromPos..FromPos+Len-1) := BWord(BWord'First..BWord'First+Len-1);
558 FromPos := FromPos + Len;
559 end loop;
560 end SqueezeBlock;
561
562
563 -- private, internal transformations
564 function Theta(Input : in State) return State is
565 Output : State;
566 C : Plane;
567 W : ZWord;
568 begin
569 for X in XYCoord loop
570 C(X) := Input(X, 0);
571 for Y in 1..XYCoord'Last loop
572 C(X) := C(X) xor Input(X, Y);
573 end loop;
574 end loop;
575
576 for X in XYCoord loop
577 W := C(X-1) xor Rotate_Left(C(X+1), 1);
578 for Y in XYCoord loop
579 Output(X,Y) := Input(X,Y) xor W;
580 end loop;
581 end loop;
582
583 return Output;
584 end Theta;
585
586 function Rho(Input : in State) return State is
587 Output : State;
588 X, Y, Old_Y : XYCoord;
589 begin
590 Output(0,0) := Input(0,0);
591 X := 1;
592 Y := 0;
593
594 for T in 0..23 loop
595 Output(X, Y) := Rotate_Left(Input(X,Y), ((T+1)*(T+2)/2) mod Z_Length);
596 Old_Y := Y;
597 Y := 2*X + 3*Y;
598 X := Old_Y;
599 end loop;
600 return Output;
601 end rho;
602
603 function Pi(Input : in State) return State is
604 Output: State;
605 begin
606 for X in XYCoord loop
607 for Y in XYCoord loop
608 Output(Y, 2*X + 3*Y) := Input(X, Y);
609 end loop;
610 end loop;
611 return Output;
612 end pi;
613
614 function Chi(Input : in State) return State is
615 Output: State;
616 begin
617 for Y in XYCoord loop
618 for X in XYCoord loop
619 Output(X, Y) := Input(X, Y) xor
620 ( (not Input(X + 1, Y)) and Input(X + 2, Y) );
621 end loop;
622 end loop;
623 return Output;
624 end chi;
625
626 function Iota(Round_Const : in ZWord; Input : in State) return State is
627 Output: State;
628 begin
629 Output := Input;
630 Output(0,0) := Input(0,0) xor Round_Const;
631 return Output;
632 end iota;
633
634 function Keccak_Function(Input: in State) return State is
635 Output: State;
636 begin
637 Output := Input;
638 for I in Round_Index loop
639 Output := Iota(RC(I), Chi(Pi(Rho(Theta(Output)))));
640 end loop;
641
642 return Output;
643 end Keccak_Function;
644
645 end Keccak;
-(0 . 0)(1 . 135)
650 -- S.MG implementation of Keccak-f permutations
651
652 -- (Based on The Keccak Reference, Version 3.0, January 14, 2011, by
653 -- Guido Bertoni, Joan Daemen, Michael Peeters and Gilles Van Assche)
654
655 -- S.MG, 2018
656
657 package Keccak is
658 pragma Pure(Keccak); --stateless, no side effects -> can cache calls
659
660 --knobs (can change as per keccak design but fixed here for S.MG purposes)--
661 Keccak_L: constant := 6; --gives keccak z (word) dimension of 2^6=64 and
662 --therefore keccak function 1600 with current
663 --constants (5*5*2^6)
664
665 Default_Bitrate: constant := 1344; --max bits the sponge can eat/spit without
666 --needing to scramble the state
667
668 --constants: dimensions of keccak state and number of rounds
669 XY_Length: constant := 5;
670 Z_Length: constant := 2**Keccak_L;
671 Width: constant := XY_Length * XY_Length * Z_Length;
672 N_Rounds: constant := 12 + 2*Keccak_L;
673
674 --types
675 type XYCoord is mod XY_Length;
676 type ZCoord is mod Z_Length;
677 type Round_Index is mod N_Rounds;
678
679 type ZWord is mod 2**Z_Length; --"lane" in keccak ref
680 type Plane is array(XYCoord) of ZWord; --a "horizontal slice" of keccak state
681 type State is array(XYCoord, XYCoord) of ZWord; --the full keccak state
682
683 type Round_Constants is array(Round_Index) of ZWord; --magic keccak constants
684
685 -- rate can be chosen by caller at each call, between 1 and width of state
686 -- higher rate means sponge "eats" more bits at a time but has fewer bits in
687 -- the "secret" part of the state (i.e. lower capacity)
688 subtype Keccak_Rate is Positive range 1..Width; -- capacity = width - rate
689
690 type Bit is mod 2;
691 type Bitstream is array( Natural range <> ) of Bit; -- any length; message
692 subtype Bitword is Bitstream( 0..Z_Length - 1 ); -- bits of one state "word"
693
694 -- type conversions
695 function BitsToWord( BWord : in Bitword ) return ZWord;
696 function WordToBits( Word : in ZWord ) return Bitword;
697
698 -- flip input octets (i.e. groups of 8 bits)
699 function FlipOctets( BWord : in Bitword ) return Bitword;
700
701 -- public function, the sponge itself
702 -- Keccak sponge structure using Keccak_Function, Pad and a given bitrate;
703 -- Input - the stream of bits to hash (the message)
704 -- Output - a bitstream of desired size for holding output
705 -- Block_Len - the bitrate to use; this is effectively the block length
706 -- for splitting Input AND squeezing output between scrambles
707 procedure Sponge(Input : in Bitstream;
708 Output : out Bitstream;
709 Block_Len : in Keccak_Rate := Default_Bitrate );
710
711 private
712 -- these are internals of the keccak implementation, not meant to be directly
713 -- accessed/used
714
715 -- this will squeeze Block'Length bits out of state S
716 -- NO scramble of state in here!
717 -- NB: make SURE that Block'Length is the correct bitrate for this sponge
718 -- specifically: Block'Length should be a correct bitrate aka LESS than Width
719 procedure SqueezeBlock( Block: out Bitstream; S: in State);
720
721 -- This absorbs into sponge the given block, modifying the state accordingly
722 -- NO scramble of state in here so make sure the whole Block fits in state!
723 -- NB: make SURE that Block'Length is *the correct bitrate* for this sponge
724 -- specifically: Block'Length should be a correct bitrate aka LESS than Width
725 procedure AbsorbBlock( Block: in Bitstream; S: in out State );
726
727 --Keccak magic numbers
728 RC : constant Round_Constants :=
729 (
730 16#0000_0000_0000_0001#,
731 16#0000_0000_0000_8082#,
732 16#8000_0000_0000_808A#,
733 16#8000_0000_8000_8000#,
734 16#0000_0000_0000_808B#,
735 16#0000_0000_8000_0001#,
736 16#8000_0000_8000_8081#,
737 16#8000_0000_0000_8009#,
738 16#0000_0000_0000_008A#,
739 16#0000_0000_0000_0088#,
740 16#0000_0000_8000_8009#,
741 16#0000_0000_8000_000A#,
742 16#0000_0000_8000_808B#,
743 16#8000_0000_0000_008B#,
744 16#8000_0000_0000_8089#,
745 16#8000_0000_0000_8003#,
746 16#8000_0000_0000_8002#,
747 16#8000_0000_0000_0080#,
748 16#0000_0000_0000_800A#,
749 16#8000_0000_8000_000A#,
750 16#8000_0000_8000_8081#,
751 16#8000_0000_0000_8080#,
752 16#0000_0000_8000_0001#,
753 16#8000_0000_8000_8008#
754 );
755
756 --gnat-specific methods to have bit-ops for modular types
757 function Rotate_Left( Value : ZWord;
758 Amount : Natural)
759 return ZWord;
760 pragma Import(Intrinsic, Rotate_Left);
761
762 function Shift_Right( Value : ZWord;
763 Amount : Natural)
764 return ZWord;
765 pragma Import(Intrinsic, Shift_Right);
766
767 function Shift_Left( Value : ZWord;
768 Amount : Natural)
769 return ZWord;
770 pragma Import(Intrinsic, Shift_Left);
771
772 --Keccak transformations of the internal state
773 function Theta ( Input : in State) return State;
774 function Rho ( Input : in State) return State;
775 function Pi ( Input : in State) return State;
776 function Chi ( Input : in State) return State;
777 function Iota ( Round_Const : in ZWord; Input : in State) return State;
778
779 --Keccak function with block width currently 1600 (Width constant above)
780 --this simply applies *all* keccak transformations in the correct order,
781 -- using the keccak magic numbers (round constants) as per keccak reference
782 function Keccak_Function(Input: in State) return State;
783
784 end Keccak;
-(0 . 0)(1 . 176)
789 -- S.MG, 2018
790
791 package body OAEP is
792
793 -- padding & formatting of maximum MAX_LEN_MSG*8 bits of the given input
794 -- uses TMSR's OAEP schema:
795 -- 1.format M00 as: [random octet][sz1][sz2]"TMSR-RSA"[random]*Message
796 -- where sz1 and sz2 store the length of the message in bits
797 -- the random octets before message are padding to make OAEP_LENGTH_OCTETS
798 -- 2. R = OAEP_HALF_OCTETS random bits
799 -- 3. X = M00 xor hash(R)
800 -- 4. Y = R xor hash(X)
801 -- 5. Result is X || Y
802 -- NB: the Entropy parameter should be random octets from which this method
803 -- will use as many as required for the OAEP encryption of given Msg
804 -- NB: at MOST MAX_LEN_MSG octets of Msg! (Msg at most 1960 bits)
805 procedure OAEP_Encrypt( Msg : in Raw_Types.Octets;
806 Entropy : in OAEP_Block;
807 Output : out OAEP_Block) is
808 M00 : OAEP_HALF;
809 R : OAEP_HALF;
810 HashR : OAEP_HALF;
811 X : OAEP_HALF;
812 HashX : OAEP_HALF;
813 Y : OAEP_HALF;
814 MsgLen : Natural;
815 PadLen : Natural;
816 begin
817 -- calculate maximum length of msg and needed amount of padding
818 -- make sure also that only MAX_LEN_MSG octets at most are used from Msg
819 MsgLen := Msg'Length; -- real msg length
820 if MsgLen > MAX_LEN_MSG then
821 MsgLen := MAX_LEN_MSG; --only first MAX_LEN_MSG octets used
822 PadLen := 0; --no padding needed
823 else
824 PadLen := MAX_LEN_MSG - MsgLen; -- add padding as needed
825 end if;
826
827 -- step 1: header and format to obtain M00
828 -- first octet is random bits
829 M00( M00'First ) := Entropy( Entropy'First );
830
831 -- next 2 octets hold the used length of Msg (number of octets)
832 M00( M00'First + 2) := Unsigned_8( ( MsgLen * 8 ) mod 256 );
833 M00( M00'First + 1) := Unsigned_8( ( (MsgLen * 8 ) / 256 ) mod 256 );
834
835 -- next 8 octets are reserved for later use, currently "TMSR-RSA"
836 M00( M00'First + 3 .. M00'First + 10 ) := TMSR;
837
838 -- random bits for padding, if Msg is less than maximum length
839 for I in 1 .. PadLen loop
840 M00( M00'First + 10 + I ) := Entropy( Entropy'First + I );
841 end loop;
842
843 -- the message itself
844 M00( M00'Last - MsgLen + 1 .. M00'Last ) :=
845 Msg( Msg'First .. Msg'First + MsgLen - 1 );
846
847 -- step 2: R = Raw_Types.OAEP_HALF_OCTETS random octets
848 -- can take LAST octets from given entropy as they are NOT used before
849 -- (even if original message was empty, padding uses at most half - 10
850 -- while entropy has full block length)
851 R := Entropy( Entropy'Last - OAEP_HALF_OCTETS + 1 .. Entropy'Last );
852
853 -- step 3: X = M00 xor hash(R)
854 HashKeccak( R, HashR );
855 X := XOR_Octets(M00, HashR);
856
857 -- step 4: Y = R xor hash(X)
858 HashKeccak( X, HashX );
859 Y := XOR_Octets(R, HashX);
860
861 -- step 5: Output is X || Y
862 Output( Output'First .. Output'First + X'Length - 1 ) := X;
863 Output( Output'Last - Y'Length + 1 .. Output'Last ) := Y;
864
865 end OAEP_Encrypt;
866
867 procedure OAEP_Decrypt( Encr : in OAEP_Block;
868 Len : out Natural;
869 Output : out OAEP_HALF;
870 Success : out Boolean ) is
871 X, Y, M, R : OAEP_HALF;
872 HashX, HashR : OAEP_HALF;
873 LenOctets : Natural;
874 begin
875 -- step 1: separate X and Y
876 X := Encr( Encr'First .. Encr'First + X'Length - 1 );
877 Y := Encr( Encr'Last - Y'Length + 1 .. Encr'Last );
878
879 -- step 2: R = Y xor hash(X)
880 HashKeccak( X, HashX );
881 R := XOR_Octets(Y, HashX);
882
883 -- step 3: M = X xor hash(R)
884 HashKeccak( R, HashR );
885 M := XOR_Octets(X, HashR);
886
887 -- step 4: extract length and message
888 Len := Natural(M( M'First + 1 )) * 256 +
889 Natural(M( M'First + 2 ));
890 LenOctets := Len / 8;
891
892 if LenOctets > MAX_LEN_MSG or LenOctets < 0 then
893 Success := False; -- error, failed to retrieve message
894 else
895 Success := True;
896 Output( Output'First .. Output'First + LenOctets - 1 ) :=
897 M( M'Last - LenOctets + 1 .. M'Last );
898 end if;
899
900 end OAEP_Decrypt;
901
902 -- private, helper methods
903 procedure HashKeccak(Input : in Raw_Types.Octets;
904 Output : out Raw_Types.Octets;
905 Block_Len : in Keccak.Keccak_Rate :=
906 Keccak.Default_Bitrate) is
907 BIn : Keccak.Bitstream( 0 .. Input'Length * 8 - 1 );
908 BOut : Keccak.Bitstream( 0 .. Output'Length * 8 - 1 );
909 begin
910 ToBitstream( Input, BIn );
911 Keccak.Sponge( BIn, BOut, Block_Len );
912 ToOctets( BOut, Output );
913 end HashKeccak;
914
915 function XOR_Octets(A : in OAEP_HALF;
916 B : in OAEP_HALF)
917 return OAEP_HALF is
918 R : OAEP_HALF;
919 begin
920 for I in R'Range loop
921 R(I) := A(I) xor B(I);
922 end loop;
923 return R;
924 end XOR_Octets;
925
926 -- conversion between types
927 procedure ToOctets(B: in Keccak.Bitstream; O: out Raw_Types.Octets ) is
928 Pos : Natural;
929 begin
930 Pos := B'First;
931 for I in O'Range loop
932 O(I) := Unsigned_8( B( Pos ) ) +
933 Unsigned_8( B( Pos + 1 ) ) * 2 +
934 Unsigned_8( B( Pos + 2 ) ) * 4 +
935 Unsigned_8( B( Pos + 3 ) ) * 8 +
936 Unsigned_8( B( Pos + 4 ) ) * 16 +
937 Unsigned_8( B( Pos + 5 ) ) * 32 +
938 Unsigned_8( B( Pos + 6 ) ) * 64 +
939 Unsigned_8( B( Pos + 7 ) ) * 128;
940 Pos := Pos + 8;
941 end loop;
942 end ToOctets;
943
944 procedure ToBitstream(O: in Raw_Types.Octets; B: out Keccak.Bitstream ) is
945 V : Unsigned_8;
946 Pos : Natural;
947 begin
948 Pos := B'First;
949 for I in O'Range loop
950 V := O( I );
951 B( Pos ) := Keccak.Bit( V and 1 );
952 B( Pos + 1 ) := Keccak.Bit( Shift_Right( V, 1 ) and 1 );
953 B( Pos + 2 ) := Keccak.Bit( Shift_Right( V, 2 ) and 1 );
954 B( Pos + 3 ) := Keccak.Bit( Shift_Right( V, 3 ) and 1 );
955 B( Pos + 4 ) := Keccak.Bit( Shift_Right( V, 4 ) and 1 );
956 B( Pos + 5 ) := Keccak.Bit( Shift_Right( V, 5 ) and 1 );
957 B( Pos + 6 ) := Keccak.Bit( Shift_Right( V, 6 ) and 1 );
958 B( Pos + 7 ) := Keccak.Bit( Shift_Right( V, 7 ) and 1 );
959
960 Pos := Pos + 8;
961 end loop;
962 end ToBitstream;
963
964 end OAEP;
-(0 . 0)(1 . 87)
969 -- Implementation of TMSR's OAEP with Keccak as hash function
970 -- NB: this uses Eulora's protocol constants (esp. RSA key length) and types.
971 --
972 -- S.MG, 2018
973
974 with Keccak; -- Keccak is used as hash function
975 with Raw_Types; -- Eulora's protocol raw types and constant values
976
977 with Interfaces; use Interfaces; -- for Unsigned_8 type and bit-level ops
978
979 package OAEP is
980 pragma Pure( OAEP ); -- stateless, no side effects -> can cache calls
981
982 -- constants for OAEP
983 OAEP_LENGTH_OCTETS : constant := Raw_Types.RSA_KEY_OCTETS;
984 OAEP_LENGTH_BITS : constant := OAEP_LENGTH_OCTETS * 8;
985 OAEP_HALF_OCTETS : constant := OAEP_LENGTH_OCTETS / 2;
986 TMSR_STR : constant String := "TMSR-RSA";
987 -- "TMSR-RSA" as unsigned_8 values:
988 TMSR : constant Raw_Types.Octets := (84,77,83,82,45,82,83,65);
989 MAX_LEN_MSG : constant Natural := OAEP_HALF_OCTETS -
990 TMSR_STR'Length - 3;
991
992 -- subtypes for OAEP encrypt/decrypt
993 subtype OAEP_Block is Raw_Types.Octets( 1 .. OAEP_LENGTH_OCTETS );
994 subtype OAEP_HALF is Raw_Types.Octets( 1 .. OAEP_HALF_OCTETS );
995
996 -- padding & formatting of maximum MAX_LEN_MSG octets of the given input
997 -- uses TMSR's OAEP schema:
998 -- 1.format M00 as: [random octet][sz1][sz2]"TMSR-RSA"[random]*Message
999 -- where sz1 and sz2 store the length of the message in bits
1000 -- the random octets before message are padding to make OAEP_LENGTH_OCTETS
1001 -- 2. R = OAEP_HALF_OCTETS random bits
1002 -- 3. X = M00 xor hash(R)
1003 -- 4. Y = R xor hash(X)
1004 -- 5. Result is X || Y
1005 -- NB: the Entropy parameter should be random octets from which this method
1006 -- will use as many as required for the OAEP encryption of given Msg
1007 -- NB: at MOST MAX_LEN_MSG octets of Msg! (Msg at most MAX_LEN_MSG*8 bits!)
1008 procedure OAEP_Encrypt( Msg : in Raw_Types.Octets;
1009 Entropy : in OAEP_Block;
1010 Output : out OAEP_Block);
1011
1012
1013 -- This is the opposite of OAEP_Encrypt above.
1014 -- @param Encr - an OAEP block previously obtained from OAEP_Encrypt
1015 -- @param Len - this will hold the length of the obtained message (in bits!)
1016 -- @param Output - the first Len octets of this are the recovered message
1017 -- @param Success - set to TRUE if message was recovered, false otherwise
1018 -- NB: when Success is FALSE, both Len and Output have undefined values
1019 procedure OAEP_Decrypt( Encr : in OAEP_Block;
1020 Len : out Natural;
1021 Output : out OAEP_HALF;
1022 Success : out Boolean);
1023
1024 private
1025 -- gnat-specific methods for bit-level operations
1026 function Shift_Right( Value : Unsigned_8;
1027 Amount : Natural )
1028 return Unsigned_8;
1029 pragma Import(Intrinsic, Shift_Right);
1030
1031 function Shift_Left( Value : Unsigned_8;
1032 Amount : Natural )
1033 return Unsigned_8;
1034 pragma Import(Intrinsic, Shift_Left);
1035
1036 -- helper method: xor 2 half-oaep blocks
1037 function XOR_Octets(A : in OAEP_HALF;
1038 B : in OAEP_HALF)
1039 return OAEP_HALF;
1040
1041 -- conversions between bitstream and string
1042 -- NB: caller has to ensure correct size of output parameter! no checks here.
1043 procedure ToOctets ( B : in Keccak.Bitstream;
1044 O : out Raw_Types.Octets );
1045
1046 procedure ToBitstream( O : in Raw_Types.Octets;
1047 B : out Keccak.Bitstream );
1048
1049 -- wrapper for Sponge to use Octets for input/output
1050 procedure HashKeccak( Input : in Raw_Types.Octets;
1051 Output : out Raw_Types.Octets;
1052 Block_Len : in Keccak.Keccak_Rate :=
1053 Keccak.Default_Bitrate);
1054
1055 end OAEP;
- 8B32DFA8A36C4CB27171B299D329919B9CD3677DE408D9474768641CF8FC1A4F60C236E6AA3005AA50B9379BBB78A06B214B38345E2D6255452E46F529AFDB71(13 . 6)(13 . 16)-
1060 Pragma Pure(Raw_Types);
1061
1062 -- constants from SMG.COMMS standard specification
1063
1064 -- RSA key size in octets
1065 -- NB: this should MATCH the size of RSA key
1066 -- as defined in the rsa implementation in C!
1067 -- NOT imported here because:
1068 -- a. it's C code that should import this, not the other way around.
1069 -- b. it needs to be static here.
1070 RSA_KEY_OCTETS : constant Positive := 490;
1071
1072
1073 -- size of a serpent-encrypted packet and message, in octets
1074 -- note that this corresponds to 1472/16 = 92 Serpent blocks
1075 -- NB: lengths are the same!
(33 . 6)(43 . 10)
1077 subtype Octets_4 is Octets( 1 .. 4 );
1078 subtype Octets_8 is Octets( 1 .. 8 );
1079
1080 -- raw representations of RSA key components
1081 subtype RSA_len is Octets ( 1 .. RSA_KEY_OCTETS);
1082 subtype RSA_half is Octets( 1 .. RSA_KEY_OCTETS/2);
1083
1084 -- RSA packets and contained raw messages
1085 subtype RSA_Pkt is Octets( 1 .. RSA_PKT_OCTETS );
1086 subtype RSA_Msg is Octets( 1 .. RSA_MSG_OCTETS );
(0 . 0)(1 . 22)
1091 -- S.MG, 2018
1092
1093 with Ada.Exceptions; use Ada.Exceptions;
1094
1095 package body RNG is
1096
1097 procedure Get_Octets( O: out Raw_Types.Octets ) is
1098 F : Octet_IO.File_Type;
1099 begin
1100 begin
1101 Octet_IO.Open( File => F, Mode => Octet_IO.In_File, Name => RNG_PATH );
1102 for I in O'Range loop
1103 Octet_IO.Read( F, O(I) );
1104 end loop;
1105 Octet_IO.Close(F);
1106 exception
1107 when others => Raise_Exception(FG_Failure'Identity,
1108 "Failed to access default RNG source!");
1109 end;
1110 end Get_Octets;
1111
1112 end RNG;
-(0 . 0)(1 . 22)
1117 -- True Random octets generator reading from an FG and using Raw_Types.
1118 -- S.MG, 2018
1119
1120 with Ada.Sequential_IO;
1121 with Interfaces;
1122 with Raw_Types;
1123
1124 package RNG is
1125
1126 -- for reading from the FG one Octet at a time
1127 package Octet_IO is new Ada.Sequential_IO(Element_Type =>
1128 Interfaces.Unsigned_8);
1129
1130 -- path to the FG; NB: the FG has to be initialized prior to using SMG Comms!
1131 RNG_PATH: constant String := "/dev/ttyUSB0";
1132
1133 -- exception raised when FG is not accessible / read fails
1134 FG_Failure : exception;
1135
1136 -- reads O'Length octets from the FG at RNG_PATH
1137 procedure Get_Octets( O: out Raw_Types.Octets );
1138 end RNG;
-(0 . 0)(1 . 173)
1143 -- S.MG, 2018
1144
1145 with Interfaces; use Interfaces;
1146 with OAEP;
1147 with RNG;
1148
1149 package body RSA_OAEP is
1150
1151 -- OAEP + RSA with given public key.
1152 -- Steps:
1153 -- 1. repeat oaep.encrypt of Plain
1154 -- until the result has first octet < than first octet of Key's modulus.
1155 -- 2. RSA.encrypt with Key on the result from 1.
1156 procedure Encrypt( Plain: in Raw_Types.Octets;
1157 Key : in RSA_pkey;
1158 Encr : out Raw_Types.RSA_len ) is
1159 -- block obtained through OAEP padding of given input Plain
1160 Blk : OAEP.OAEP_Block := ( others => 0 );
1161 Entropy : OAEP.OAEP_Block;
1162 Len : constant Natural := entropy'Length;
1163 begin
1164 -- loop cond: 1st octet of oaep block is < 1st octet of key's modulus
1165 loop
1166 -- get random bits via RNG (FG)
1167 RNG.Get_Octets( Entropy );
1168
1169 -- oaep encrypt
1170 OAEP.OAEP_Encrypt( Plain, Entropy, Blk );
1171
1172 -- check that the oaep block is suitable i.e. comparison of 1st octet
1173 if Blk(Blk'First) < Key.n(Key.n'First) then exit; end if;
1174
1175 end loop; -- oaep block < modulus
1176
1177 -- RSA encrypt
1178 Public_RSA( Blk, Key, Encr );
1179 end; --Encrypt (OAEP+RSA)
1180
1181 -- RSA+OAEP Decrypt
1182 -- Steps:
1183 -- 1. RSA Decrypt (secret key)
1184 -- 2. OAEP Decrypt
1185 procedure Decrypt( Encr : in Raw_Types.RSA_len;
1186 Key : in RSA_skey;
1187 Plain: out Raw_Types.Octets;
1188 Plain_Len: out Natural;
1189 Success: out Boolean) is
1190 Blk : OAEP.OAEP_Block;
1191 Msg : OAEP.OAEP_HALF;
1192 Msg_Len : Natural;
1193 begin
1194 -- RSA decrypt with provided secret key
1195 -- NB: result HAS TO BE AN OAEP BLOCK HERE! Even if - potentially - 0 led!
1196 Private_RSA( Encr, Key, Blk );
1197
1198 -- OAEP decrypt
1199 OAEP.OAEP_Decrypt(Blk, Msg_Len, Msg, Success);
1200 -- switch to Length in OCTETS!
1201 Msg_Len := Msg_Len / 8;
1202
1203 -- check that result FITS in given output array - otherwise, fail
1204 if Msg_Len > Plain'Length then
1205 Success := FALSE;
1206 Plain_Len := Msg_Len; --to give a clue to caller
1207 else
1208 Plain_Len := Msg_Len;
1209 Plain( Plain'First ..
1210 Plain'First + Plain_Len-1) := Msg( Msg'First ..
1211 Msg'First + Plain_Len -1 );
1212 end if;
1213 end Decrypt;
1214
1215 -- helper methods
1216 -- encrypt with public RSA key given as struct, Ada style
1217 procedure Public_RSA( Plain: in Raw_Types.Octets;
1218 Key : in RSA_pkey;
1219 Encr : out Raw_Types.RSA_len) is
1220 Encr_char : char_array( size_t(Encr'First) .. size_t(Encr'Last));
1221 Plain_char : char_array( size_t(Plain'First) .. size_t(Plain'Last));
1222 N_char : char_array( size_t(Key.n'First) .. size_t(Key.n'Last));
1223 E_char : char_array( size_t(Key.e'First) .. size_t(Key.e'Last));
1224 out_len : Integer;
1225 begin
1226 -- convert to char array
1227 Octets_To_Char_Array( Plain, Plain_char );
1228 Octets_To_Char_Array( Key.n, N_char );
1229 Octets_To_Char_Array( Key.e, E_char );
1230 -- call C imported function
1231 out_len := Public_RSA_C( Encr_char , Encr'Length,
1232 Plain_char , Plain'Length,
1233 N_char , Key.n'Length,
1234 E_char , Key.e'Length);
1235 -- convert back to octets
1236 Char_Array_To_Octets( Encr_char, Encr );
1237 -- C code trims leading 0s -> need to move octets if out_len<Encr'Length
1238 if out_len < Encr'Length then
1239 Encr(Encr'Last - out_len + 1 .. Encr'Last) := Encr(Encr'First ..
1240 Encr'First+out_len-1);
1241 Encr(Encr'First .. Encr'Last-out_len) := (others=>0);
1242 end if;
1243 -- no need to return anything!
1244 end Public_RSA;
1245
1246 procedure Private_RSA( Encr : in Raw_Types.RSA_len;
1247 Key : in RSA_skey;
1248 Plain : out Raw_Types.Octets) is
1249 Plain_Char : char_array( size_t(Plain'First) .. size_t(Plain'Last) );
1250 Plain_Len : Integer;
1251 Encr_Char : char_array( size_t(Encr'First) .. size_t(Encr'Last) );
1252 N_Char : char_array( size_t(Key.n'First) .. size_t(Key.n'Last) );
1253 E_Char : char_array( size_t(Key.e'First) .. size_t(Key.e'Last) );
1254 D_Char : char_array( size_t(Key.d'First) .. size_t(Key.d'Last) );
1255 P_Char : char_array( size_t(Key.p'First) .. size_t(Key.p'Last) );
1256 Q_Char : char_array( size_t(Key.q'First) .. size_t(Key.q'Last) );
1257 U_Char : char_array( size_t(Key.u'First) .. size_t(Key.u'Last) );
1258 begin
1259 -- convert key and encrypted message to C char_arrays
1260 Octets_To_Char_Array( Encr, Encr_Char );
1261 Octets_To_Char_Array( Key.n, N_Char );
1262 Octets_To_Char_Array( Key.e, E_Char );
1263 Octets_To_Char_Array( Key.d, D_Char );
1264 Octets_To_Char_Array( Key.p, P_Char );
1265 Octets_To_Char_Array( Key.q, Q_Char );
1266 Octets_To_Char_Array( Key.u, U_Char );
1267 -- call RSA decrypt via C_Wrappers
1268 Plain_Len := Private_RSA_C( Plain_Char, Plain'Length,
1269 Encr_Char , Encr'Length,
1270 N_Char , Key.n'Length,
1271 E_Char , Key.e'Length,
1272 D_Char , Key.d'Length,
1273 P_Char , Key.p'Length,
1274 Q_Char , Key.q'Length,
1275 U_Char , Key.u'Length);
1276 -- convert result back to Octets
1277 Char_Array_To_Octets( Plain_Char, Plain );
1278 -- if length < OAEP_Block'Length,it's 0-led and got trimmed, so move it
1279 if Plain_Len < Plain'Length then
1280 Plain(Plain'Last-Plain_Len+1..Plain'Last):= Plain(Plain'First ..
1281 Plain'First + Plain_Len -1);
1282 Plain(Plain'First .. Plain'Last-Plain_Len) := (others => 0);
1283 end if;
1284 -- no need to return anything!
1285 end Private_RSA;
1286
1287 procedure Octets_To_Char_Array( O : in Raw_Types.Octets;
1288 A : out Interfaces.C.char_array) is
1289 begin
1290 -- check that lengths ARE THE SAME!
1291 if A'Length /= O'Length then
1292 raise Mismatched_Lengths_Error;
1293 end if;
1294 -- copy values over octet by octet
1295 for I in 0 .. O'Length-1 loop
1296 A( A'First + Interfaces.C.size_t( I )) :=
1297 Interfaces.C.Char( Character'Val(O(O'First + I)));
1298 end loop;
1299 end Octets_To_Char_Array;
1300
1301 procedure Char_Array_To_Octets( A : in Interfaces.C.char_array;
1302 O : out Raw_Types.Octets) is
1303 begin
1304 -- check that lengths ARE THE SAME!
1305 if A'Length /= O'Length then
1306 raise Mismatched_Lengths_Error;
1307 end if;
1308 -- copy values over octet by octet
1309 for I in 0..O'Length -1 loop
1310 O( O'First + I ) := Character'Pos( Character(
1311 A( A'First + Interfaces.C.size_t( I )) ));
1312 end loop;
1313 end Char_Array_To_Octets;
1314
1315 end RSA_OAEP;
-(0 . 0)(1 . 129)
1320 -- Ada implementation of RSA with OAEP according to TMSR and Eulora spec
1321 -- Uses:
1322 -- - Eulora's raw types (Ada, raw_types.ads)
1323 -- - Keccak hashes (Ada, keccak.ads/adb)
1324 -- - OAEP schema (Ada, oaep.ads/adb)
1325 -- - RNG (Ada, rng.ads/adb) for true random padding
1326 -- - C wrappers lib (C, c_wrappers/) for:
1327 -- - MPI (C, mpi/)
1328 -- - RSA (C, rsa/rsa.c)
1329 --
1330 -- S.MG, 2018
1331
1332 with Raw_Types;
1333 with Interfaces.C; use Interfaces.C;
1334
1335 package RSA_OAEP is
1336 -- exception for mismatched lengths when converting octets <-> char arrays
1337 Mismatched_Lengths_Error: exception;
1338
1339 -- public RSA key with n,e stored as raw octets
1340 type RSA_pkey is
1341 record
1342 n : Raw_Types.RSA_len; --public modulus
1343 e : Raw_Types.RSA_half; --public exponent
1344 end record; --RSA_pkey
1345
1346 -- private (secret) RSA key with components stored as raw octets
1347 type RSA_skey is
1348 record
1349 n : Raw_Types.RSA_len; --public modulus
1350 e : Raw_Types.RSA_half; --public exponent
1351 d : Raw_Types.RSA_len; --secret exponent e*d=1 mod phi; phi=(p-1)*(q-1)
1352 p : Raw_Types.RSA_half; --prime p
1353 q : Raw_Types.RSA_half; --prime q
1354 u : Raw_Types.RSA_half; --inverse of p mod q; for faster calculations
1355 end record; --RSA_skey
1356
1357 -- Encryption RSA+OAEP (i.e. using public key)
1358 -- NB: at most OAEP.MAX_LEN_MSG octets from Plain will be encrypted!
1359 -- Relies directly on:
1360 -- oaep.adb/ads
1361 -- c_wrappers.c ( RSA )
1362 -- rng.adb/ads ( random padding )
1363 procedure Encrypt( Plain: in Raw_Types.Octets;
1364 Key : in RSA_pkey;
1365 Encr : out Raw_Types.RSA_len );
1366
1367 -- Decryption RSA+OAEP (i.e. using private/secret key)
1368 -- The opposite of Encrypt above.
1369 -- NB: Plain has to have ENOUGH space for result!
1370 -- Result can be at most OAEP.MAX_LEN_MSG octets.
1371 -- Relies directly on:
1372 -- oaep.adb/ads
1373 -- c_wrappers.c (RSA)
1374 -- Plain_Len gives the length in OCTETS of the decrypted message.
1375 procedure Decrypt( Encr : in Raw_Types.RSA_len;
1376 Key : in RSA_skey;
1377 Plain : out Raw_Types.Octets;
1378 Plain_Len : out Natural;
1379 Success : out Boolean);
1380
1381 --helper methods:
1382 -- mainly conversions to/from C's char* and imports from C_wrappers
1383 -- encrypt with public RSA key given as struct, Ada style
1384 -- NB: result is potentially 0-led (i.e. at end of Encr not at start!)
1385 procedure Public_RSA( Plain: in Raw_Types.Octets;
1386 Key : in RSA_pkey;
1387 Encr : out Raw_Types.RSA_len);
1388
1389 -- encrypt with public RSA key given as char arrays, via C_Wrappers
1390 -- this returns the length of result because C functions trim leading 0s!
1391 function Public_RSA_C( Encr : out Interfaces.C.char_array;
1392 Encr_Len : in Integer;
1393 Plain : in Interfaces.C.char_array;
1394 Plain_Len : in Integer;
1395 RSA_N : in Interfaces.C.char_array;
1396 N_Len : in Integer;
1397 RSA_E : in Interfaces.C.char_array;
1398 E_Len : in Integer)
1399 return Integer;
1400 pragma Import(C, Public_RSA_C, "public_rsa_octets");
1401
1402 -- decrypt with private RSA key given as struct, Ada style
1403 -- NB: Plain has to have ENOUGH space!
1404 -- NB: Result is potentially 0-led (i.e. at the end of Plain, not at start!)
1405 -- @return actual length of result
1406 procedure Private_RSA( Encr : in Raw_Types.RSA_len;
1407 Key : in RSA_skey;
1408 Plain : out Raw_Types.Octets);
1409
1410 -- encrypt with private/secret RSA key given as char arrays (via C_wrappers)
1411 -- this returns length because C methods trim leading 0s
1412 function Private_RSA_C( Plain : out Interfaces.C.char_array;
1413 Plain_Len : in Integer;
1414 Encr : in Interfaces.C.char_array;
1415 Encr_Len : in Integer;
1416 RSA_N : in Interfaces.C.char_array;
1417 N_Len : in Integer;
1418 RSA_E : in Interfaces.C.char_array;
1419 E_Len : in Integer;
1420 RSA_D : in Interfaces.C.char_array;
1421 D_Len : in Integer;
1422 RSA_P : in Interfaces.C.char_array;
1423 P_Len : in Integer;
1424 RSA_Q : in Interfaces.C.char_array;
1425 Q_Len : in Integer;
1426 RSA_U : in Interfaces.C.char_array;
1427 U_Len : in Integer)
1428 return Integer;
1429 pragma Import( C, Private_RSA_C, "private_rsa_octets" );
1430
1431 -- convert from Ada's Octets (array of octets) to C's char* (char_array)
1432
1433 -- This copies the octets from O to the beginning of A
1434 -- NB: there are NO checks or memory allocations here!
1435 -- Caller has to make sure that:
1436 -- A has allocated space for at least O'Length octets!
1437 procedure Octets_To_Char_Array( O : in Raw_Types.Octets;
1438 A : out Interfaces.C.char_array);
1439
1440
1441 -- This copies first O'Length characters from A to O
1442 -- NB: this does NOT allocate /check memory!
1443 -- Caller has to ensure that:
1444 -- A has space at least O'Length characters
1445 procedure Char_Array_To_Octets( A : in Interfaces.C.char_array;
1446 O : out Raw_Types.Octets);
1447
1448 end RSA_OAEP;
-(0 . 0)(1 . 227)
1453 --S.MG, 2018
1454
1455 with Interfaces; use Interfaces;
1456 with Interfaces.C; use Interfaces.C;
1457 with RSA_OAEP; use RSA_OAEP;
1458 with OAEP; use OAEP;
1459 with Raw_Types; use Raw_Types;
1460 with RNG; use RNG;
1461 with Keccak; use Keccak;
1462
1463 with Ada.Text_IO; use Ada.Text_IO;
1464
1465 package body Test_RSA_OAEP is
1466
1467 procedure test_char_array is
1468 S : String := OAEP.TMSR_STR;
1469 O : Octets := OAEP.TMSR;
1470 A : char_array(0..O'Length-1) := (others => '0');
1471 B : Octets(0..O'Length -1) := (others => 0);
1472 Fail : Boolean := FALSE;
1473 begin
1474 Octets_To_Char_Array(O, A);
1475 Char_Array_To_Octets(A, B);
1476
1477 if B /= O then
1478 Put_Line("FAIL: char_array_to_octets");
1479 else
1480 Put_Line("PASS: char_array_to_octets");
1481 end if;
1482
1483 for I in 0..S'Length-1 loop
1484 declare
1485 C : Character := Character(A(A'First + size_t(I)));
1486 E : Character := S(S'First + I);
1487 begin
1488 if C /= E then
1489 Fail := TRUE;
1490 Put("Error at pos " & Integer'Image(I) & ": ");
1491 Put(Integer'Image(Character'Pos(C)));
1492 Put_Line(" instead of " & Integer'Image(Character'Pos(E)));
1493 end if;
1494 end;
1495 end loop;
1496 if FAIL then
1497 Put_Line("FAIL: test octets_to_char_array");
1498 else
1499 Put_Line("PASS: test octets_to_char_array");
1500 end if;
1501 end test_char_array;
1502
1503 -- test OAEP encrypt + decrypt
1504 procedure test_oaep is
1505 Plain: Octets(1..MAX_LEN_MSG);
1506 Short: Octets(0..10);
1507 Encr : OAEP_Block;
1508 Decr : OAEP_HALF;
1509 Len : Natural;
1510 Entropy: OAEP_Block;
1511 Success : Boolean;
1512 begin
1513 RNG.Get_Octets(Plain);
1514 RNG.Get_Octets(Entropy);
1515 RNG.Get_Octets(Short);
1516
1517 -- test full length message
1518 OAEP_Encrypt(Plain, Entropy, Encr);
1519 OAEP_Decrypt(Encr, Len, Decr, Success);
1520
1521 if not Success or Len/8 /= Plain'Length then
1522 Put_Line("FAIL: oaep encrypt/decrypt on max len message.");
1523 else
1524 if Decr(Decr'First..Decr'First+Len/8-1) /=
1525 Plain(Plain'First..Plain'First+Len/8-1) then
1526 Put_Line("FAIL: oaep encrypt/decrypt on max len message - " &
1527 "result different from expected.");
1528 else
1529 Put_Line("PASS: oaep encrypt/decrypt on max len message.");
1530 end if;
1531 end if;
1532
1533 -- test short message
1534 OAEP_Encrypt(Short, Entropy, Encr);
1535 OAEP_Decrypt(Encr, Len, Decr, Success);
1536 if not Success or Len/8 /= Short'Length then
1537 Put_Line("FAIL: oaep encrypt/decrypt on short message.");
1538 else
1539 if Decr(Decr'First..Decr'First+Len/8-1) /=
1540 Short(Short'First..Short'First+Len/8-1) then
1541 Put_Line("FAIL: oaep encrypt/decrypt on short message - " &
1542 "result different from expected.");
1543 else
1544 Put_Line("PASS: oaep encrypt/decrypt on short message.");
1545 end if;
1546 end if;
1547
1548 end test_oaep;
1549
1550 -- test JUST RSA (i.e. without oaep) with RSA key pair previously generated
1551 procedure test_rsa is
1552 n: String := "C6579F8646180EED0DC1F02E0DDD2B43EABB3F702D79D9928E2CDA5E1D42DF5D9ED7773F80B1F8D9B0DB7D4D00F55647640D70768F63D3CED56A39C681D08D6191F318BB79DC969B470A7364D53335C8318EF35E39D5DF706AB6F2393C6DD2128C142DBAB1806EB35E26C908F0A48419313D2D0F33DD430655DBFEC722899EC21C238E8DB7003430BBC39BAD990F9887F6B03E1344F537EC97389B78DBC656718ACD7B0FDC13DD24534F417BC7A18F077A0C4227354CEA19670331B6CAA3DFC17BBA7E70C14510D9EB3B63F3014994EC87BD23E868C0AE6E9EC55027577F62C0280B2D7DD1135001844923E5455C4566E066B3FDE968C6BC4DC672F229FCE366440403D7A4F4A8BFBA5679B7D0844BA1231277D13A77C9E2B5A1CB138C1B7AB5B4D4832448723A3DE70ED2E86D5FC5174F949A02DE8E404304BEB95F9BF40F3AA3CA15622D2776294BE7E19233406FF563CB8C25A1CB5AADBC1899DA3F2AE38533931FE032EE3232C2CD4F219FADF95B91635C0762A476A4DE5013F4384093F0FB715028D97F93B2E6F057B99EE344D83ADF2686FD5C9C793928BEF3182E568C4339C36C744C8E9CA7D4B9A16AA039CBF6F38CC97B12D87644E94C9DBD6BC93A93A03ED61ECC5874586E3A310E958F858735E30019D345C62E5127B80652C8A970A14B31F03B3A157CD5";
1553 e: String := "F74D78E382FC19B064411C6C20E0FDB2985F843007A54C7D8400BB459468624126E7D175F397E55C57AF25858EAE2D2952FB7998C119A6103606733EB5E1D27FCA1FACF14ADE94101D383D1B25DA511805569BC344EAD384EDBF3F3A541B34887FE199D99D7F62E6E9D516F88D6F5AD3E020DF04D402A02CC628A0064362FE8516CF7CD6040E9521407AB90EE6B5AFFF9EA9EBB16A7D3407CE81FD3844F519880556AB94AB349C1F3BBB6FDB4C4B377FE4C091EBDC2C3A1BD3AA56382D8D80E7742B5C751008FD6ECDD2EC3B2E3B6C566F698ED672000B403766DD63C3ACBDE16A14FB02E83A2EB6AA018BFC0020401E790DEE24E9";
1554 d: String := "698DA05DA25B230211EEF0CBA12083A1457B749A11937AC9993859F69A3BF38D575E5166AF2EC88D77F1DF04E68AEA358EACF7659FD4722A4F5A1C8BA7676DA97A9FBA75451152F8F68887D3451A9CCFFFE9EB80979786E37495B17687A6212F77FA616E4C0CD8A8EB7AEB88EA6CCABB7F3E854FB94B35394A09F95F0D6F997947E865CC0606F437C30FE8C48D96FBF5E2F52807BC9E9ED7BBEB23D5C45EDDCD16FE2BF410A9A1E5EF879E71C0D41FAE270C0C5D442860103F8C3944E802F33DB38432F11F763A7AF593656108E4A98A44A8549913CE5DCEC1A6500F280E3190991B2B938561CFACD8BC5183AAC9A4914BFE52C3BE39BB83688E1DE52479107EF8E087DCDB409432FC954C6349407E81DDFB11AE92BABB32A31868597958C9C76E0B4156F380955F0E09C1F3B98BB4CDD59E1B5C7D8CC2AA7491B0D319D219CF459A527CE1AA2729DEC53269653BF0ED3E0253F4451168437E3B069E48350CA4C3EC82134E87135624C768D1330B0D70C6E447FD9945BF06FCB91AA334C0FD8EEF1ADBC15928B3DB62077B537F7E9F468CC95CD5AAFEAE1F760A863B48D07B163F670E2E5B550BB3E960230BA9FDAED9903AE2E669A7F3C4D1F1E25B8E8EDB8CC6E6FD2164E66F4E64ED77BEF1EC9E6CEA5624FD84C0680248746DC1C8187145F3CD2411659DAEAD11D";
1555 p: String := "CDD6F7673A501FB24C44D56CA1D434F6CB3334E193E02F8E906241906BCB7412DD2159825B24C22002F373E647C2DA62A854F3841C00FD5985D03227CA9B54A69380BA9D63BE738BDF9E65C247E43E1220EEDD9281DCA78B32A4E1B786B7697ED0C3195D5AF2990881B11D6FC9EC9F940067B2DEA2A516FAA5F269C98F0B67628A6D2708515A4A58041AA17A93E4C4DD95C85BC38351DDA1DCF3DFD91C505B22383132649CF9F9233852C7207075BCF43C71038F043F1EC53E9787FB051B7927D020903233C16897B993C8089D8464451F086E756CF20E46CE6ED4A6AC5C327A0AAFBECBAAFD177969E7C952C76A4F4E7C85BF7F63";
1556 q: String := "F6ACF0790A250802C8D45DAC549CDBEF7806D5877A5DF0069136A458FAC4F0B0858060A873DA6355A965A064A0BC1BBB874872CD7ED89674AD407533041E74BCA317EC73597D335115523F61A05071E5ED81EE2A05331F65D4DC7A25AD7938B124CF03F49154B6693FB0B598B33ABDEF85C599A57A9B7347EAFF82638E1CBC28FCDFFF1FF04A18C2DBF3938395C2F8D1782B43D3A25EF7633B5DDAC89EFD3BAA64D976425A0891E00B876E9DE9FE4B6492B0EA8DFC7C8DEEC61721356EC816295B1BD9CD9DA3E30D2D90DC9CB3987F4BE042104900E036F3044A016749EF910CCFB9F377A90849B4CCCF4471A74E67EF6C814C9467";
1557 u: String := "854B89ED10F52258D00D6B3FA7F1FD22752804668F51FF7806DB82E22CB8B3AA8448D9B8E9DB14D31A36AEC2BCFA89E341B7334D494E97ED8051244136192233332C4612D963E7B6AF2535FDB7FE97E28DDFEBDFB3E1AFC29D05DBDF37106A817D3AB1864C7F7F247982897EDA6A92BED47D9C68305CD170C7301ACEB05F8A6382E73CC7614B2D8D758669B3A99AB64114809254B0BE21F40341A5B48B9B032603B14875B87EB5E16603FD16552E146A0FC6964958DFC25AA9FFCCD1ED1F4DEAF9FBAA0D7357F5FF0803FEB9BA78E74AC6B3070F417CEC6CFC7A3CF1E305FC7B76B7ED71893999AF797B2EBDE41FE90F076CCEDBFB";
1558 Plain: OAEP_Block := (others => 0);
1559 Decr : OAEP_Block := (others => 0);
1560 Encr : RSA_len;
1561 pkey: RSA_pkey;
1562 skey: RSA_skey;
1563 begin
1564 -- initialize with RSA pair previously generated
1565 Hex2Octets( n, skey.n );
1566 Hex2Octets( e, skey.e );
1567 Hex2Octets( d, skey.d );
1568 Hex2Octets( p, skey.p );
1569 Hex2Octets( q, skey.q );
1570 Hex2Octets( u, skey.u );
1571 -- copy n and e for public key
1572 pkey.n := skey.n;
1573 pkey.e := skey.e;
1574 -- get random data
1575 RNG.Get_Octets(Plain);
1576 -- make first octet < RSA key's modulus first octet
1577 Plain(Plain'First) := 16#00#;
1578 -- naked rsa encrypt/decrypt
1579 Put_Line("Encrypting with RSA public key...");
1580 Public_RSA( Plain, pkey, Encr );
1581 Put_Line("Decrypting with RSA private key...");
1582 Private_RSA( Encr, skey, Decr );
1583 Put_Line("Checking...");
1584
1585 -- check result
1586 if Decr /= Plain then
1587 Put_Line("FAIL: RSA encrypt/decrypt result doesn't match plain.");
1588 else
1589 Put_Line("PASS: RSA encrypt/decrypt");
1590 end if;
1591 end test_rsa;
1592
1593 -- test rsa+oaep with RSA key pair previously generated
1594 procedure test_rsa_oaep is
1595 n: String := "C6579F8646180EED0DC1F02E0DDD2B43EABB3F702D79D9928E2CDA5E1D42DF5D9ED7773F80B1F8D9B0DB7D4D00F55647640D70768F63D3CED56A39C681D08D6191F318BB79DC969B470A7364D53335C8318EF35E39D5DF706AB6F2393C6DD2128C142DBAB1806EB35E26C908F0A48419313D2D0F33DD430655DBFEC722899EC21C238E8DB7003430BBC39BAD990F9887F6B03E1344F537EC97389B78DBC656718ACD7B0FDC13DD24534F417BC7A18F077A0C4227354CEA19670331B6CAA3DFC17BBA7E70C14510D9EB3B63F3014994EC87BD23E868C0AE6E9EC55027577F62C0280B2D7DD1135001844923E5455C4566E066B3FDE968C6BC4DC672F229FCE366440403D7A4F4A8BFBA5679B7D0844BA1231277D13A77C9E2B5A1CB138C1B7AB5B4D4832448723A3DE70ED2E86D5FC5174F949A02DE8E404304BEB95F9BF40F3AA3CA15622D2776294BE7E19233406FF563CB8C25A1CB5AADBC1899DA3F2AE38533931FE032EE3232C2CD4F219FADF95B91635C0762A476A4DE5013F4384093F0FB715028D97F93B2E6F057B99EE344D83ADF2686FD5C9C793928BEF3182E568C4339C36C744C8E9CA7D4B9A16AA039CBF6F38CC97B12D87644E94C9DBD6BC93A93A03ED61ECC5874586E3A310E958F858735E30019D345C62E5127B80652C8A970A14B31F03B3A157CD5";
1596 e: String := "F74D78E382FC19B064411C6C20E0FDB2985F843007A54C7D8400BB459468624126E7D175F397E55C57AF25858EAE2D2952FB7998C119A6103606733EB5E1D27FCA1FACF14ADE94101D383D1B25DA511805569BC344EAD384EDBF3F3A541B34887FE199D99D7F62E6E9D516F88D6F5AD3E020DF04D402A02CC628A0064362FE8516CF7CD6040E9521407AB90EE6B5AFFF9EA9EBB16A7D3407CE81FD3844F519880556AB94AB349C1F3BBB6FDB4C4B377FE4C091EBDC2C3A1BD3AA56382D8D80E7742B5C751008FD6ECDD2EC3B2E3B6C566F698ED672000B403766DD63C3ACBDE16A14FB02E83A2EB6AA018BFC0020401E790DEE24E9";
1597 d: String := "698DA05DA25B230211EEF0CBA12083A1457B749A11937AC9993859F69A3BF38D575E5166AF2EC88D77F1DF04E68AEA358EACF7659FD4722A4F5A1C8BA7676DA97A9FBA75451152F8F68887D3451A9CCFFFE9EB80979786E37495B17687A6212F77FA616E4C0CD8A8EB7AEB88EA6CCABB7F3E854FB94B35394A09F95F0D6F997947E865CC0606F437C30FE8C48D96FBF5E2F52807BC9E9ED7BBEB23D5C45EDDCD16FE2BF410A9A1E5EF879E71C0D41FAE270C0C5D442860103F8C3944E802F33DB38432F11F763A7AF593656108E4A98A44A8549913CE5DCEC1A6500F280E3190991B2B938561CFACD8BC5183AAC9A4914BFE52C3BE39BB83688E1DE52479107EF8E087DCDB409432FC954C6349407E81DDFB11AE92BABB32A31868597958C9C76E0B4156F380955F0E09C1F3B98BB4CDD59E1B5C7D8CC2AA7491B0D319D219CF459A527CE1AA2729DEC53269653BF0ED3E0253F4451168437E3B069E48350CA4C3EC82134E87135624C768D1330B0D70C6E447FD9945BF06FCB91AA334C0FD8EEF1ADBC15928B3DB62077B537F7E9F468CC95CD5AAFEAE1F760A863B48D07B163F670E2E5B550BB3E960230BA9FDAED9903AE2E669A7F3C4D1F1E25B8E8EDB8CC6E6FD2164E66F4E64ED77BEF1EC9E6CEA5624FD84C0680248746DC1C8187145F3CD2411659DAEAD11D";
1598 p: String := "CDD6F7673A501FB24C44D56CA1D434F6CB3334E193E02F8E906241906BCB7412DD2159825B24C22002F373E647C2DA62A854F3841C00FD5985D03227CA9B54A69380BA9D63BE738BDF9E65C247E43E1220EEDD9281DCA78B32A4E1B786B7697ED0C3195D5AF2990881B11D6FC9EC9F940067B2DEA2A516FAA5F269C98F0B67628A6D2708515A4A58041AA17A93E4C4DD95C85BC38351DDA1DCF3DFD91C505B22383132649CF9F9233852C7207075BCF43C71038F043F1EC53E9787FB051B7927D020903233C16897B993C8089D8464451F086E756CF20E46CE6ED4A6AC5C327A0AAFBECBAAFD177969E7C952C76A4F4E7C85BF7F63";
1599 q: String := "F6ACF0790A250802C8D45DAC549CDBEF7806D5877A5DF0069136A458FAC4F0B0858060A873DA6355A965A064A0BC1BBB874872CD7ED89674AD407533041E74BCA317EC73597D335115523F61A05071E5ED81EE2A05331F65D4DC7A25AD7938B124CF03F49154B6693FB0B598B33ABDEF85C599A57A9B7347EAFF82638E1CBC28FCDFFF1FF04A18C2DBF3938395C2F8D1782B43D3A25EF7633B5DDAC89EFD3BAA64D976425A0891E00B876E9DE9FE4B6492B0EA8DFC7C8DEEC61721356EC816295B1BD9CD9DA3E30D2D90DC9CB3987F4BE042104900E036F3044A016749EF910CCFB9F377A90849B4CCCF4471A74E67EF6C814C9467";
1600 u: String := "854B89ED10F52258D00D6B3FA7F1FD22752804668F51FF7806DB82E22CB8B3AA8448D9B8E9DB14D31A36AEC2BCFA89E341B7334D494E97ED8051244136192233332C4612D963E7B6AF2535FDB7FE97E28DDFEBDFB3E1AFC29D05DBDF37106A817D3AB1864C7F7F247982897EDA6A92BED47D9C68305CD170C7301ACEB05F8A6382E73CC7614B2D8D758669B3A99AB64114809254B0BE21F40341A5B48B9B032603B14875B87EB5E16603FD16552E146A0FC6964958DFC25AA9FFCCD1ED1F4DEAF9FBAA0D7357F5FF0803FEB9BA78E74AC6B3070F417CEC6CFC7A3CF1E305FC7B76B7ED71893999AF797B2EBDE41FE90F076CCEDBFB";
1601 Plain: Octets(1..MAX_LEN_MSG) := (others=>20);
1602 Short: Octets(1..10);
1603 Decr : RSA_len;
1604 Encr : RSA_len;
1605 pkey: RSA_pkey;
1606 skey: RSA_skey;
1607 Success: Boolean;
1608 Len : Natural;
1609 begin
1610 -- initialize with RSA pair previously generated
1611 Hex2Octets( n, skey.n );
1612 Hex2Octets( e, skey.e );
1613 Hex2Octets( d, skey.d );
1614 Hex2Octets( p, skey.p );
1615 Hex2Octets( q, skey.q );
1616 Hex2Octets( u, skey.u );
1617 -- copy n and e for public key
1618 pkey.n := skey.n;
1619 pkey.e := skey.e;
1620
1621 -- test with 0 message of length Plain'Length
1622 RSA_OAEP.Encrypt(Plain, pkey, Encr);
1623 RSA_OAEP.Decrypt(Encr, skey, Decr, Len, Success);
1624 if (not Success) or Len /= Plain'Length
1625 or Plain /= Decr(Decr'First..Decr'First+Plain'Length-1) then
1626 Put_Line("FAIL: RSA_OAEP on max len message 20-filled.");
1627 else
1628 Put_Line("PASS: RSA_OAEP on max len message 20-filled.");
1629 end if;
1630
1631 -- get random data for "plain" message
1632 RNG.Get_Octets(Plain);
1633 RSA_OAEP.Encrypt(Plain, pkey, Encr);
1634 RSA_OAEP.Decrypt(Encr, skey, Decr, Len, Success);
1635 if (not Success) or Len /= Plain'Length
1636 or Plain /= Decr(Decr'First..Decr'First+Plain'Length-1) then
1637 Put_Line("FAIL: RSA_OAEP on random data of max length.");
1638 else
1639 Put_Line("PASS: RSA_OAEP on random data of max length.");
1640 end if;
1641
1642 -- get random data for "short" message
1643 RNG.Get_Octets(Short);
1644 RSA_OAEP.Encrypt(Short, pkey, Encr);
1645 RSA_OAEP.Decrypt(Encr, skey, Decr, Len, Success);
1646 if (not Success) or Len /= Short'Length
1647 or Short /= Decr(Decr'First..Decr'First+Short'Length-1) then
1648 Put_Line("FAIL: RSA_OAEP on random data of short length.");
1649 else
1650 Put_Line("PASS: RSA_OAEP on random data of short length.");
1651 end if;
1652
1653 end test_rsa_oaep;
1654
1655 -- helper methods
1656 procedure Hex2Octets( Hex: in String; O: out Raw_Types.Octets ) is
1657 S : String := "16#AA#";
1658 -- to make sure that input String has EVEN number of chars (ie full octets)
1659 H : String(1..Hex'Length+Hex'Length mod 2) := (others=>'0');
1660 begin
1661 -- first char is 0 if needed to cover full octet...
1662 H(H'Length-Hex'Length+1..H'Length) := Hex;
1663 O := (others => 0);
1664 for I in 0 .. H'Length/2-1 loop
1665 S := "16#" & H(H'First + I*2 .. H'First + I*2 + 1) & "#";
1666 O(O'Last - H'Length/2 + 1 + I) := Unsigned_8'Value(S);
1667 end loop;
1668 end Hex2Octets;
1669
1670 procedure PrintOctets( O: in Raw_Types.Octets; Title: in String ) is
1671 begin
1672 Put_Line(Title);
1673 for V of O loop
1674 Put(Unsigned_8'Image(V) & " ");
1675 end loop;
1676 New_Line;
1677 end PrintOctets;
1678
1679 end Test_RSA_OAEP;
-(0 . 0)(1 . 13)
1684 -- S.MG, 2018
1685
1686 with Raw_Types;
1687
1688 package Test_RSA_OAEP is
1689 procedure test_char_array;
1690 procedure test_oaep; -- test oaep only
1691 procedure test_rsa; -- test rsa only
1692 procedure test_rsa_oaep; -- test rsa+oaep
1693
1694 procedure Hex2Octets( Hex: in String; O: out Raw_Types.Octets );
1695 procedure PrintOctets( O: in Raw_Types.Octets; Title: in String );
1696 end Test_RSA_OAEP;
- D2F582FFA3714E9756AD5A412EA1CACBA2BBD0B4E9BBA295217333AE4FC9B7B21AFED99A5DB413A3800E77DC407A500265DE7140466342A9992403A351A1B68D(2 . 9)(2 . 14)
1701
1702 with Test_Serpent;
1703 with Test_Packing;
1704 with Test_RSA_OAEP;
1705
1706 procedure testall is
1707 begin
1708 Test_Serpent.Selftest;
1709 Test_Packing.Test_Pack_Unpack;
1710 Test_RSA_OAEP.test_char_array;
1711 Test_RSA_OAEP.test_oaep;
1712 Test_RSA_OAEP.test_rsa;
1713 Test_RSA_OAEP.test_rsa_oaep;
1714 end testall;