1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-07-01 11:32:48 -05:00

Merge 0.81 branch.

This commit is contained in:
Simon Tatham
2024-04-15 19:42:50 +01:00
20 changed files with 925 additions and 215 deletions

View File

@ -90,6 +90,9 @@ def le_integer(x, nbits):
assert nbits % 8 == 0
return bytes([0xFF & (x >> (8*n)) for n in range(nbits//8)])
def be_integer(x, nbits):
return bytes(reversed(le_integer(x, nbits)))
@contextlib.contextmanager
def queued_random_data(nbytes, seed):
hashsize = 512 // 8
@ -2075,6 +2078,244 @@ culpa qui officia deserunt mollit anim id est laborum.
self.assertFalse(ssh_key_verify(pubkey, badsig0, "hello, again"))
self.assertFalse(ssh_key_verify(pubkey, badsigq, "hello, again"))
def testRFC6979(self):
# The test case described in detail in RFC 6979 section A.1.
# We can't actually do the _signature_ for this, because it's
# based on ECDSA over a finite field of characteristic 2, and
# we only support prime-order fields. But we don't need to do
# full ECDSA, only generate the same deterministic nonce that
# the test case expects.
k = rfc6979('sha256',
0x4000000000000000000020108A2E0CC0D99F8A5EF,
0x09A4D6792295A7F730FC3F2B49CBC0F62E862272F, "sample")
self.assertEqual(int(k), 0x23AF4074C90A02B3FE61D286D5C87F425E6BDD81B)
# Selected test cases from the rest of Appendix A.
#
# We can only use test cases for which we have the appropriate
# hash function, so I've left out the test cases based on
# SHA-224. (We could easily implement that, but I don't think
# it's worth it just for adding further tests of this one
# function.) Similarly, I've omitted test cases relating to
# ECDSA curves we don't implement: P192, P224, and all the
# curves over power-of-2 finite fields.
#
# Where possible, we also test the actual signature algorithm,
# to make sure it delivers the same entire signature as the
# test case. This demonstrates that the rfc6979() function is
# being called in the right way and the results are being used
# as they should be. Here I've had to cut down the test cases
# even further, because the RFC specifies test cases with a
# cross product of DSA group and hash function, whereas we
# have a fixed hash (specified by SSH) for each signature
# algorithm. And the RFC is clear that you use the same hash
# for nonce generation and actual signing.
# A.2.1: 1024-bit DSA
q = 0x996F967F6C8E388D9E28D01E205FBA957A5698B1
x = 0x411602CB19A6CCC34494D79D98EF1E7ED5AF25F7
k = rfc6979('sha1', q, x, "sample")
self.assertEqual(int(k), 0x7BDB6B0FF756E1BB5D53583EF979082F9AD5BD5B)
k = rfc6979('sha256', q, x, "sample")
self.assertEqual(int(k), 0x519BA0546D0C39202A7D34D7DFA5E760B318BCFB)
k = rfc6979('sha384', q, x, "sample")
self.assertEqual(int(k), 0x95897CD7BBB944AA932DBC579C1C09EB6FCFC595)
k = rfc6979('sha512', q, x, "sample")
self.assertEqual(int(k), 0x09ECE7CA27D0F5A4DD4E556C9DF1D21D28104F8B)
k = rfc6979('sha1', q, x, "test")
self.assertEqual(int(k), 0x5C842DF4F9E344EE09F056838B42C7A17F4A6433)
k = rfc6979('sha256', q, x, "test")
self.assertEqual(int(k), 0x5A67592E8128E03A417B0484410FB72C0B630E1A)
k = rfc6979('sha384', q, x, "test")
self.assertEqual(int(k), 0x220156B761F6CA5E6C9F1B9CF9C24BE25F98CD89)
k = rfc6979('sha512', q, x, "test")
self.assertEqual(int(k), 0x65D2C2EEB175E370F28C75BFCDC028D22C7DBE9C)
# The rest of the public key, for signature testing
p = 0x86F5CA03DCFEB225063FF830A0C769B9DD9D6153AD91D7CE27F787C43278B447E6533B86B18BED6E8A48B784A14C252C5BE0DBF60B86D6385BD2F12FB763ED8873ABFD3F5BA2E0A8C0A59082EAC056935E529DAF7C610467899C77ADEDFC846C881870B7B19B2B58F9BE0521A17002E3BDD6B86685EE90B3D9A1B02B782B1779
g = 0x07B0F92546150B62514BB771E2A0C0CE387F03BDA6C56B505209FF25FD3C133D89BBCD97E904E09114D9A7DEFDEADFC9078EA544D2E401AEECC40BB9FBBF78FD87995A10A1C27CB7789B594BA7EFB5C4326A9FE59A070E136DB77175464ADCA417BE5DCE2F40D10A46A3A3943F26AB7FD9C0398FF8C76EE0A56826A8A88F1DBD
y = 0x5DF5E01DED31D0297E274E1691C192FE5868FEF9E19A84776454B100CF16F65392195A38B90523E2542EE61871C0440CB87C322FC4B4D2EC5E1E7EC766E1BE8D4CE935437DC11C3C8FD426338933EBFE739CB3465F4D3668C5E473508253B1E682F65CBDC4FAE93C2EA212390E54905A86E2223170B44EAA7DA5DD9FFCFB7F3B
pubblob = ssh_string(b"ssh-dss") + b"".join(map(ssh2_mpint, [p,q,g,y]))
privblob = ssh2_mpint(x)
pubkey = ssh_key_new_pub('dsa', pubblob)
privkey = ssh_key_new_priv('dsa', pubblob, privblob)
sig = ssh_key_sign(privkey, b"sample", 0)
# Expected output using SHA-1 as the hash in nonce
# construction.
r = 0x2E1A0C2562B2912CAAF89186FB0F42001585DA55
s = 0x29EFB6B0AFF2D7A68EB70CA313022253B9A88DF5
ref_sig = ssh_string(b"ssh-dss") + ssh_string(
be_integer(r, 160) + be_integer(s, 160))
self.assertEqual(sig, ref_sig)
# And the other test string.
sig = ssh_key_sign(privkey, b"test", 0)
r = 0x42AB2052FD43E123F0607F115052A67DCD9C5C77
s = 0x183916B0230D45B9931491D4C6B0BD2FB4AAF088
ref_sig = ssh_string(b"ssh-dss") + ssh_string(
be_integer(r, 160) + be_integer(s, 160))
self.assertEqual(sig, ref_sig)
# A.2.2: 2048-bit DSA
q = 0xF2C3119374CE76C9356990B465374A17F23F9ED35089BD969F61C6DDE9998C1F
x = 0x69C7548C21D0DFEA6B9A51C9EAD4E27C33D3B3F180316E5BCAB92C933F0E4DBC
k = rfc6979('sha1', q, x, "sample")
self.assertEqual(int(k), 0x888FA6F7738A41BDC9846466ABDB8174C0338250AE50CE955CA16230F9CBD53E)
k = rfc6979('sha256', q, x, "sample")
self.assertEqual(int(k), 0x8926A27C40484216F052F4427CFD5647338B7B3939BC6573AF4333569D597C52)
k = rfc6979('sha384', q, x, "sample")
self.assertEqual(int(k), 0xC345D5AB3DA0A5BCB7EC8F8FB7A7E96069E03B206371EF7D83E39068EC564920)
k = rfc6979('sha512', q, x, "sample")
self.assertEqual(int(k), 0x5A12994431785485B3F5F067221517791B85A597B7A9436995C89ED0374668FC)
k = rfc6979('sha1', q, x, "test")
self.assertEqual(int(k), 0x6EEA486F9D41A037B2C640BC5645694FF8FF4B98D066A25F76BE641CCB24BA4F)
k = rfc6979('sha256', q, x, "test")
self.assertEqual(int(k), 0x1D6CE6DDA1C5D37307839CD03AB0A5CBB18E60D800937D67DFB4479AAC8DEAD7)
k = rfc6979('sha384', q, x, "test")
self.assertEqual(int(k), 0x206E61F73DBE1B2DC8BE736B22B079E9DACD974DB00EEBBC5B64CAD39CF9F91C)
k = rfc6979('sha512', q, x, "test")
self.assertEqual(int(k), 0xAFF1651E4CD6036D57AA8B2A05CCF1A9D5A40166340ECBBDC55BE10B568AA0AA)
# The rest of the public key, for signature testing
p = 0x9DB6FB5951B66BB6FE1E140F1D2CE5502374161FD6538DF1648218642F0B5C48C8F7A41AADFA187324B87674FA1822B00F1ECF8136943D7C55757264E5A1A44FFE012E9936E00C1D3E9310B01C7D179805D3058B2A9F4BB6F9716BFE6117C6B5B3CC4D9BE341104AD4A80AD6C94E005F4B993E14F091EB51743BF33050C38DE235567E1B34C3D6A5C0CEAA1A0F368213C3D19843D0B4B09DCB9FC72D39C8DE41F1BF14D4BB4563CA28371621CAD3324B6A2D392145BEBFAC748805236F5CA2FE92B871CD8F9C36D3292B5509CA8CAA77A2ADFC7BFD77DDA6F71125A7456FEA153E433256A2261C6A06ED3693797E7995FAD5AABBCFBE3EDA2741E375404AE25B
g = 0x5C7FF6B06F8F143FE8288433493E4769C4D988ACE5BE25A0E24809670716C613D7B0CEE6932F8FAA7C44D2CB24523DA53FBE4F6EC3595892D1AA58C4328A06C46A15662E7EAA703A1DECF8BBB2D05DBE2EB956C142A338661D10461C0D135472085057F3494309FFA73C611F78B32ADBB5740C361C9F35BE90997DB2014E2EF5AA61782F52ABEB8BD6432C4DD097BC5423B285DAFB60DC364E8161F4A2A35ACA3A10B1C4D203CC76A470A33AFDCBDD92959859ABD8B56E1725252D78EAC66E71BA9AE3F1DD2487199874393CD4D832186800654760E1E34C09E4D155179F9EC0DC4473F996BDCE6EED1CABED8B6F116F7AD9CF505DF0F998E34AB27514B0FFE7
y = 0x667098C654426C78D7F8201EAC6C203EF030D43605032C2F1FA937E5237DBD949F34A0A2564FE126DC8B715C5141802CE0979C8246463C40E6B6BDAA2513FA611728716C2E4FD53BC95B89E69949D96512E873B9C8F8DFD499CC312882561ADECB31F658E934C0C197F2C4D96B05CBAD67381E7B768891E4DA3843D24D94CDFB5126E9B8BF21E8358EE0E0A30EF13FD6A664C0DCE3731F7FB49A4845A4FD8254687972A2D382599C9BAC4E0ED7998193078913032558134976410B89D2C171D123AC35FD977219597AA7D15C1A9A428E59194F75C721EBCBCFAE44696A499AFA74E04299F132026601638CB87AB79190D4A0986315DA8EEC6561C938996BEADF
pubblob = ssh_string(b"ssh-dss") + b"".join(map(ssh2_mpint, [p,q,g,y]))
privblob = ssh2_mpint(x)
pubkey = ssh_key_new_pub('dsa', pubblob)
privkey = ssh_key_new_priv('dsa', pubblob, privblob)
sig = ssh_key_sign(privkey, b"sample", 0)
# Expected output using SHA-1 as the hash in nonce
# construction, which is how SSH does things. RFC6979 lists
# the following 256-bit values for r and s, but we end up only
# using the low 160 bits of each.
r = 0x3A1B2DBD7489D6ED7E608FD036C83AF396E290DBD602408E8677DAABD6E7445A
s = 0xD26FCBA19FA3E3058FFC02CA1596CDBB6E0D20CB37B06054F7E36DED0CDBBCCF
ref_sig = ssh_string(b"ssh-dss") + ssh_string(
be_integer(r, 160) + be_integer(s, 160))
self.assertEqual(sig, ref_sig)
# And the other test string.
sig = ssh_key_sign(privkey, b"test", 0)
r = 0xC18270A93CFC6063F57A4DFA86024F700D980E4CF4E2CB65A504397273D98EA0
s = 0x414F22E5F31A8B6D33295C7539C1C1BA3A6160D7D68D50AC0D3A5BEAC2884FAA
ref_sig = ssh_string(b"ssh-dss") + ssh_string(
be_integer(r, 160) + be_integer(s, 160))
self.assertEqual(sig, ref_sig)
# A.2.5: ECDSA with NIST P256
q = 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551
x = 0xC9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721
k = rfc6979('sha1', q, x, "sample")
self.assertEqual(int(k), 0x882905F1227FD620FBF2ABF21244F0BA83D0DC3A9103DBBEE43A1FB858109DB4)
k = rfc6979('sha256', q, x, "sample")
self.assertEqual(int(k), 0xA6E3C57DD01ABE90086538398355DD4C3B17AA873382B0F24D6129493D8AAD60)
k = rfc6979('sha384', q, x, "sample")
self.assertEqual(int(k), 0x09F634B188CEFD98E7EC88B1AA9852D734D0BC272F7D2A47DECC6EBEB375AAD4)
k = rfc6979('sha512', q, x, "sample")
self.assertEqual(int(k), 0x5FA81C63109BADB88C1F367B47DA606DA28CAD69AA22C4FE6AD7DF73A7173AA5)
k = rfc6979('sha1', q, x, "test")
self.assertEqual(int(k), 0x8C9520267C55D6B980DF741E56B4ADEE114D84FBFA2E62137954164028632A2E)
k = rfc6979('sha256', q, x, "test")
self.assertEqual(int(k), 0xD16B6AE827F17175E040871A1C7EC3500192C4C92677336EC2537ACAEE0008E0)
k = rfc6979('sha384', q, x, "test")
self.assertEqual(int(k), 0x16AEFFA357260B04B1DD199693960740066C1A8F3E8EDD79070AA914D361B3B8)
k = rfc6979('sha512', q, x, "test")
self.assertEqual(int(k), 0x6915D11632ACA3C40D5D51C08DAF9C555933819548784480E93499000D9F0B7F)
# The public key, for signature testing
Ux = 0x60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6
Uy = 0x7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299
pubblob = ssh_string(b"ecdsa-sha2-nistp256") + ssh_string(b"nistp256") + ssh_string(b'\x04' + be_integer(Ux, 256) + be_integer(Uy, 256))
privblob = ssh2_mpint(x)
pubkey = ssh_key_new_pub('p256', pubblob)
privkey = ssh_key_new_priv('p256', pubblob, privblob)
sig = ssh_key_sign(privkey, b"sample", 0)
# Expected output using SHA-256
r = 0xEFD48B2AACB6A8FD1140DD9CD45E81D69D2C877B56AAF991C34D0EA84EAF3716
s = 0xF7CB1C942D657C41D436C7A1B6E29F65F3E900DBB9AFF4064DC4AB2F843ACDA8
ref_sig = ssh_string(b"ecdsa-sha2-nistp256") + ssh_string(ssh2_mpint(r) + ssh2_mpint(s))
self.assertEqual(sig, ref_sig)
# And the other test string
sig = ssh_key_sign(privkey, b"test", 0)
r = 0xF1ABB023518351CD71D881567B1EA663ED3EFCF6C5132B354F28D3B0B7D38367
s = 0x019F4113742A2B14BD25926B49C649155F267E60D3814B4C0CC84250E46F0083
ref_sig = ssh_string(b"ecdsa-sha2-nistp256") + ssh_string(ssh2_mpint(r) + ssh2_mpint(s))
self.assertEqual(sig, ref_sig)
# A.2.5: ECDSA with NIST P384
q = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973
x = 0x6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D896D5724E4C70A825F872C9EA60D2EDF5
k = rfc6979('sha1', q, x, "sample")
self.assertEqual(int(k), 0x4471EF7518BB2C7C20F62EAE1C387AD0C5E8E470995DB4ACF694466E6AB096630F29E5938D25106C3C340045A2DB01A7)
k = rfc6979('sha256', q, x, "sample")
self.assertEqual(int(k), 0x180AE9F9AEC5438A44BC159A1FCB277C7BE54FA20E7CF404B490650A8ACC414E375572342863C899F9F2EDF9747A9B60)
k = rfc6979('sha384', q, x, "sample")
self.assertEqual(int(k), 0x94ED910D1A099DAD3254E9242AE85ABDE4BA15168EAF0CA87A555FD56D10FBCA2907E3E83BA95368623B8C4686915CF9)
k = rfc6979('sha512', q, x, "sample")
self.assertEqual(int(k), 0x92FC3C7183A883E24216D1141F1A8976C5B0DD797DFA597E3D7B32198BD35331A4E966532593A52980D0E3AAA5E10EC3)
k = rfc6979('sha1', q, x, "test")
self.assertEqual(int(k), 0x66CC2C8F4D303FC962E5FF6A27BD79F84EC812DDAE58CF5243B64A4AD8094D47EC3727F3A3C186C15054492E30698497)
k = rfc6979('sha256', q, x, "test")
self.assertEqual(int(k), 0x0CFAC37587532347DC3389FDC98286BBA8C73807285B184C83E62E26C401C0FAA48DD070BA79921A3457ABFF2D630AD7)
k = rfc6979('sha384', q, x, "test")
self.assertEqual(int(k), 0x015EE46A5BF88773ED9123A5AB0807962D193719503C527B031B4C2D225092ADA71F4A459BC0DA98ADB95837DB8312EA)
k = rfc6979('sha512', q, x, "test")
self.assertEqual(int(k), 0x3780C4F67CB15518B6ACAE34C9F83568D2E12E47DEAB6C50A4E4EE5319D1E8CE0E2CC8A136036DC4B9C00E6888F66B6C)
# The public key, for signature testing
Ux = 0xEC3A4E415B4E19A4568618029F427FA5DA9A8BC4AE92E02E06AAE5286B300C64DEF8F0EA9055866064A254515480BC13
Uy = 0x8015D9B72D7D57244EA8EF9AC0C621896708A59367F9DFB9F54CA84B3F1C9DB1288B231C3AE0D4FE7344FD2533264720
pubblob = ssh_string(b"ecdsa-sha2-nistp384") + ssh_string(b"nistp384") + ssh_string(b'\x04' + be_integer(Ux, 384) + be_integer(Uy, 384))
privblob = ssh2_mpint(x)
pubkey = ssh_key_new_pub('p384', pubblob)
privkey = ssh_key_new_priv('p384', pubblob, privblob)
sig = ssh_key_sign(privkey, b"sample", 0)
# Expected output using SHA-384
r = 0x94EDBB92A5ECB8AAD4736E56C691916B3F88140666CE9FA73D64C4EA95AD133C81A648152E44ACF96E36DD1E80FABE46
s = 0x99EF4AEB15F178CEA1FE40DB2603138F130E740A19624526203B6351D0A3A94FA329C145786E679E7B82C71A38628AC8
ref_sig = ssh_string(b"ecdsa-sha2-nistp384") + ssh_string(ssh2_mpint(r) + ssh2_mpint(s))
self.assertEqual(sig, ref_sig)
# And the other test string
sig = ssh_key_sign(privkey, b"test", 0)
r = 0x8203B63D3C853E8D77227FB377BCF7B7B772E97892A80F36AB775D509D7A5FEB0542A7F0812998DA8F1DD3CA3CF023DB
s = 0xDDD0760448D42D8A43AF45AF836FCE4DE8BE06B485E9B61B827C2F13173923E06A739F040649A667BF3B828246BAA5A5
ref_sig = ssh_string(b"ecdsa-sha2-nistp384") + ssh_string(ssh2_mpint(r) + ssh2_mpint(s))
self.assertEqual(sig, ref_sig)
# A.2.6: ECDSA with NIST P521
q = 0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409
x = 0x0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538
k = rfc6979('sha1', q, x, "sample")
self.assertEqual(int(k), 0x089C071B419E1C2820962321787258469511958E80582E95D8378E0C2CCDB3CB42BEDE42F50E3FA3C71F5A76724281D31D9C89F0F91FC1BE4918DB1C03A5838D0F9)
k = rfc6979('sha256', q, x, "sample")
self.assertEqual(int(k), 0x0EDF38AFCAAECAB4383358B34D67C9F2216C8382AAEA44A3DAD5FDC9C32575761793FEF24EB0FC276DFC4F6E3EC476752F043CF01415387470BCBD8678ED2C7E1A0)
k = rfc6979('sha384', q, x, "sample")
self.assertEqual(int(k), 0x1546A108BC23A15D6F21872F7DED661FA8431DDBD922D0DCDB77CC878C8553FFAD064C95A920A750AC9137E527390D2D92F153E66196966EA554D9ADFCB109C4211)
k = rfc6979('sha512', q, x, "sample")
self.assertEqual(int(k), 0x1DAE2EA071F8110DC26882D4D5EAE0621A3256FC8847FB9022E2B7D28E6F10198B1574FDD03A9053C08A1854A168AA5A57470EC97DD5CE090124EF52A2F7ECBFFD3)
k = rfc6979('sha1', q, x, "test")
self.assertEqual(int(k), 0x0BB9F2BF4FE1038CCF4DABD7139A56F6FD8BB1386561BD3C6A4FC818B20DF5DDBA80795A947107A1AB9D12DAA615B1ADE4F7A9DC05E8E6311150F47F5C57CE8B222)
k = rfc6979('sha256', q, x, "test")
self.assertEqual(int(k), 0x01DE74955EFAABC4C4F17F8E84D881D1310B5392D7700275F82F145C61E843841AF09035BF7A6210F5A431A6A9E81C9323354A9E69135D44EBD2FCAA7731B909258)
k = rfc6979('sha384', q, x, "test")
self.assertEqual(int(k), 0x1F1FC4A349A7DA9A9E116BFDD055DC08E78252FF8E23AC276AC88B1770AE0B5DCEB1ED14A4916B769A523CE1E90BA22846AF11DF8B300C38818F713DADD85DE0C88)
k = rfc6979('sha512', q, x, "test")
self.assertEqual(int(k), 0x16200813020EC986863BEDFC1B121F605C1215645018AEA1A7B215A564DE9EB1B38A67AA1128B80CE391C4FB71187654AAA3431027BFC7F395766CA988C964DC56D)
# The public key, for signature testing
Ux = 0x1894550D0785932E00EAA23B694F213F8C3121F86DC97A04E5A7167DB4E5BCD371123D46E45DB6B5D5370A7F20FB633155D38FFA16D2BD761DCAC474B9A2F5023A4
Uy = 0x0493101C962CD4D2FDDF782285E64584139C2F91B47F87FF82354D6630F746A28A0DB25741B5B34A828008B22ACC23F924FAAFBD4D33F81EA66956DFEAA2BFDFCF5
pubblob = ssh_string(b"ecdsa-sha2-nistp521") + ssh_string(b"nistp521") + ssh_string(b'\x04' + be_integer(Ux, 528) + be_integer(Uy, 528))
privblob = ssh2_mpint(x)
pubkey = ssh_key_new_pub('p521', pubblob)
privkey = ssh_key_new_priv('p521', pubblob, privblob)
sig = ssh_key_sign(privkey, b"sample", 0)
# Expected output using SHA-512
r = 0x0C328FAFCBD79DD77850370C46325D987CB525569FB63C5D3BC53950E6D4C5F174E25A1EE9017B5D450606ADD152B534931D7D4E8455CC91F9B15BF05EC36E377FA
s = 0x0617CCE7CF5064806C467F678D3B4080D6F1CC50AF26CA209417308281B68AF282623EAA63E5B5C0723D8B8C37FF0777B1A20F8CCB1DCCC43997F1EE0E44DA4A67A
ref_sig = ssh_string(b"ecdsa-sha2-nistp521") + ssh_string(ssh2_mpint(r) + ssh2_mpint(s))
self.assertEqual(sig, ref_sig)
# And the other test string
sig = ssh_key_sign(privkey, b"test", 0)
r = 0x13E99020ABF5CEE7525D16B69B229652AB6BDF2AFFCAEF38773B4B7D08725F10CDB93482FDCC54EDCEE91ECA4166B2A7C6265EF0CE2BD7051B7CEF945BABD47EE6D
s = 0x1FBD0013C674AA79CB39849527916CE301C66EA7CE8B80682786AD60F98F7E78A19CA69EFF5C57400E3B3A0AD66CE0978214D13BAF4E9AC60752F7B155E2DE4DCE3
ref_sig = ssh_string(b"ecdsa-sha2-nistp521") + ssh_string(ssh2_mpint(r) + ssh2_mpint(s))
self.assertEqual(sig, ref_sig)
def testBLAKE2b(self):
# The standard test vectors for BLAKE2b (in the separate class
# below) don't satisfy me because they only test one hash
@ -2381,10 +2622,10 @@ culpa qui officia deserunt mollit anim id est laborum.
test_keys = [
('ed25519', 'AAAAC3NzaC1lZDI1NTE5AAAAIM7jupzef6CD0ps2JYxJp9IlwY49oorOseV5z5JFDFKn', 'AAAAIAf4/WRtypofgdNF2vbZOUFE1h4hvjw4tkGJZyOzI7c3', 255, b'0xf4d6e7f6f4479c23f0764ef43cea1711dbfe02aa2b5a32ff925c7c1fbf0f0db,0x27520c4592cf79e5b1ce8aa23d8ec125d2a7498c25369bd283a07fde9cbae3ce', [(0, 'AAAAC3NzaC1lZDI1NTE5AAAAQN73EqfyA4WneqDhgZ98TlRj9V5Wg8zCrMxTLJN1UtyfAnPUJDtfG/U0vOsP8PrnQxd41DDDnxrAXuqJz8rOagc=')]),
('ed448', 'AAAACXNzaC1lZDQ0OAAAADnRI0CQDym5IqUidLNDcSdHe54bYEwqjpjBlab8uKGoe6FRqqejha7+5U/VAHy7BmE23+ju26O9XgA=', 'AAAAObP9klqyiJSJsdFJf+xwZQdkbZGUqXE07K6e5plfRTGjYYkyWJFUNFH4jzIn9xH1TX9z9EGycPaXAA==', 448, b'0x4bf4a2b6586c60d8cdb52c2b45b897f6d2224bc37987489c0d70febb449e8c82964ed5785827be808e44d31dd31e6ff7c99f43e49f419928,0x5ebda3dbeee8df366106bb7c00d54fe5feae85a3a7aa51a17ba8a1b8fca695c1988e2a4c601b9e7b47277143b37422a522b9290f904023d1', [(0, 'AAAACXNzaC1lZDQ0OAAAAHLkSVioGMvLesZp3Tn+Z/sSK0Hl7RHsHP4q9flLzTpZG5h6JDH3VmZBEjTJ6iOLaa0v4FoNt0ng4wAB53WrlQC4h3iAusoGXnPMAKJLmqzplKOCi8HKXk8Xl8fsXbaoyhatv1OZpwJcffmh1x+x+LSgNQA=')]),
('p256', 'AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHkYQ0sQoq5LbJI1VMWhw3bV43TSYi3WVpqIgKcBKK91TcFFlAMZgceOHQ0xAFYcSczIttLvFu+xkcLXrRd4N7Q=', 'AAAAIQCV/1VqiCsHZm/n+bq7lHEHlyy7KFgZBEbzqYaWtbx48Q==', 256, b'nistp256,0x7918434b10a2ae4b6c923554c5a1c376d5e374d2622dd6569a8880a70128af75,0x4dc14594031981c78e1d0d3100561c49ccc8b6d2ef16efb191c2d7ad177837b4', [(0, 'AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAABIAAAAIAryzHDGi/TcCnbdxZkIYR5EGR6SNYXr/HlQRF8le+/IAAAAIERfzn6eHuBbqWIop2qL8S7DWRB3lenN1iyL10xYQPKw')]),
('p384', 'AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBMYK8PUtfAlJwKaBTIGEuCzH0vqOMa4UbcjrBbTbkGVSUnfo+nuC80NCdj9JJMs1jvfF8GzKLc5z8H3nZyM741/BUFjV7rEHsQFDek4KyWvKkEgKiTlZid19VukNo1q2Hg==', 'AAAAMGsfTmdB4zHdbiQ2euTSdzM6UKEOnrVjMAWwHEYvmG5qUOcBnn62fJDRJy67L+QGdg==', 384, b'nistp384,0xc60af0f52d7c0949c0a6814c8184b82cc7d2fa8e31ae146dc8eb05b4db9065525277e8fa7b82f34342763f4924cb358e,0xf7c5f06cca2dce73f07de767233be35fc15058d5eeb107b101437a4e0ac96bca90480a89395989dd7d56e90da35ab61e', [(0, 'AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAABpAAAAMDmHrtXCADzLvkkWG/duBAHlf6B1mVvdt6F0uzXfsf8Yub8WXNUNVnYq6ovrWPzLggAAADEA9izzwoUuFcXYRJeKcRLZEGMmSDDPzUZb7oZR0UgD1jsMQXs8UfpO31Qur/FDSCRK')]),
('p521', 'AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAFrGthlKM152vu2Ghk+R7iO9/M6e+hTehNZ6+FBwof4HPkPB2/HHXj5+w5ynWyUrWiX5TI2riuJEIrJErcRH5LglADnJDX2w4yrKZ+wDHSz9lwh9p2F+B5R952es6gX3RJRkGA+qhKpKup8gKx78RMbleX8wgRtIu+4YMUnKb1edREiRg==', 'AAAAQgFh7VNJFUljWhhyAEiL0z+UPs/QggcMTd3Vv2aKDeBdCRl5di8r+BMm39L7bRzxRMEtW5NSKlDtE8MFEGdIE9khsw==', 521, b'nistp521,0x16b1ad86528cd79dafbb61a193e47b88ef7f33a7be8537a1359ebe141c287f81cf90f076fc71d78f9fb0e729d6c94ad6897e53236ae2b89108ac912b7111f92e094,0xe72435f6c38cab299fb00c74b3f65c21f69d85f81e51f79d9eb3a817dd125190603eaa12a92aea7c80ac7bf1131b95e5fcc2046d22efb860c52729bd5e75112246', [(0, 'AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAACMAAAAQgCLgvftvwM3CUaigrW0yzmCHoYjC6GLtO+6S91itqpgMEtWPNlaTZH6QQqkgscijWdXx98dDkQao/gcAKVmOZKPXgAAAEIB1PIrsDF1y6poJ/czqujB7NSUWt31v+c2t6UA8m2gTA1ARuVJ9XBGLMdceOTB00Hi9psC2RYFLpaWREOGCeDa6ow=')]),
('dsa', 'AAAAB3NzaC1kc3MAAABhAJyWZzjVddGdyc5JPu/WPrC07vKRAmlqO6TUi49ah96iRcM7/D1aRMVAdYBepQ2mf1fsQTmvoC9KgQa79nN3kHhz0voQBKOuKI1ZAodfVOgpP4xmcXgjaA73Vjz22n4newAAABUA6l7/vIveaiA33YYv+SKcKLQaA8cAAABgbErc8QLw/WDz7mhVRZrU+9x3Tfs68j3eW+B/d7Rz1ZCqMYDk7r/F8dlBdQlYhpQvhuSBgzoFa0+qPvSSxPmutgb94wNqhHlVIUb9ZOJNloNr2lXiPP//Wu51TxXAEvAAAAAAYQCcQ9mufXtZa5RyfwT4NuLivdsidP4HRoLXdlnppfFAbNdbhxE0Us8WZt+a/443bwKnYxgif8dgxv5UROnWTngWu0jbJHpaDcTc9lRyTeSUiZZK312s/Sl7qDk3/Du7RUI=', 'AAAAFGx3ft7G8AQzFsjhle7PWardUXh3', 768, b'0x9c966738d575d19dc9ce493eefd63eb0b4eef29102696a3ba4d48b8f5a87dea245c33bfc3d5a44c54075805ea50da67f57ec4139afa02f4a8106bbf67377907873d2fa1004a3ae288d5902875f54e8293f8c66717823680ef7563cf6da7e277b,0xea5effbc8bde6a2037dd862ff9229c28b41a03c7,0x6c4adcf102f0fd60f3ee6855459ad4fbdc774dfb3af23dde5be07f77b473d590aa3180e4eebfc5f1d94175095886942f86e481833a056b4faa3ef492c4f9aeb606fde3036a8479552146fd64e24d96836bda55e23cffff5aee754f15c012f000,0x9c43d9ae7d7b596b94727f04f836e2e2bddb2274fe074682d77659e9a5f1406cd75b87113452cf1666df9aff8e376f02a76318227fc760c6fe5444e9d64e7816bb48db247a5a0dc4dcf654724de49489964adf5dacfd297ba83937fc3bbb4542', [(0, 'AAAAB3NzaC1kc3MAAAAo0T2t6dr8Qr5DK2B0ETwUa3BhxMLPjLY0ZtlOACmP/kUt3JgByLv+3g==')]),
('p256', 'AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHkYQ0sQoq5LbJI1VMWhw3bV43TSYi3WVpqIgKcBKK91TcFFlAMZgceOHQ0xAFYcSczIttLvFu+xkcLXrRd4N7Q=', 'AAAAIQCV/1VqiCsHZm/n+bq7lHEHlyy7KFgZBEbzqYaWtbx48Q==', 256, b'nistp256,0x7918434b10a2ae4b6c923554c5a1c376d5e374d2622dd6569a8880a70128af75,0x4dc14594031981c78e1d0d3100561c49ccc8b6d2ef16efb191c2d7ad177837b4', [(0, 'AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAABIAAAAIFrd1bjr4GHfWsM9RNJ+y4Z0eVwpRRv3IvNE2moaA1x3AAAAIFWcwwCE69kS4oybMFEUP4r7qFAY8tSb1o8ItSFcSe2+')]),
('p384', 'AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBMYK8PUtfAlJwKaBTIGEuCzH0vqOMa4UbcjrBbTbkGVSUnfo+nuC80NCdj9JJMs1jvfF8GzKLc5z8H3nZyM741/BUFjV7rEHsQFDek4KyWvKkEgKiTlZid19VukNo1q2Hg==', 'AAAAMGsfTmdB4zHdbiQ2euTSdzM6UKEOnrVjMAWwHEYvmG5qUOcBnn62fJDRJy67L+QGdg==', 384, b'nistp384,0xc60af0f52d7c0949c0a6814c8184b82cc7d2fa8e31ae146dc8eb05b4db9065525277e8fa7b82f34342763f4924cb358e,0xf7c5f06cca2dce73f07de767233be35fc15058d5eeb107b101437a4e0ac96bca90480a89395989dd7d56e90da35ab61e', [(0, 'AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAABoAAAAMFqCJ+gBP4GGc7yCy9F5e4EjkDlvYBYsYWMYFg3Md/ml7Md8pIrN7I0+8bFb99rZjQAAADAsM2kI+QOcgK+oVDaP0qkLRRbWDO1dSU5I2YfETyHVLYFNdRmgdWo6002XTO9jAsk=')]),
('p521', 'AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAFrGthlKM152vu2Ghk+R7iO9/M6e+hTehNZ6+FBwof4HPkPB2/HHXj5+w5ynWyUrWiX5TI2riuJEIrJErcRH5LglADnJDX2w4yrKZ+wDHSz9lwh9p2F+B5R952es6gX3RJRkGA+qhKpKup8gKx78RMbleX8wgRtIu+4YMUnKb1edREiRg==', 'AAAAQgFh7VNJFUljWhhyAEiL0z+UPs/QggcMTd3Vv2aKDeBdCRl5di8r+BMm39L7bRzxRMEtW5NSKlDtE8MFEGdIE9khsw==', 521, b'nistp521,0x16b1ad86528cd79dafbb61a193e47b88ef7f33a7be8537a1359ebe141c287f81cf90f076fc71d78f9fb0e729d6c94ad6897e53236ae2b89108ac912b7111f92e094,0xe72435f6c38cab299fb00c74b3f65c21f69d85f81e51f79d9eb3a817dd125190603eaa12a92aea7c80ac7bf1131b95e5fcc2046d22efb860c52729bd5e75112246', [(0, 'AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAACLAAAAQVBkbaCKivgvc+68CULCdPayjzRUYZdj1G2pLyiPWTdmJKVKF/W1oDAtjMZlP53tqCpGxDdrLoJH2A39k6g5MgNjAAAAQgGrNcesPBw/HMopBQ1JqOG1cSlAzjiFT34FvM68ZhdIjbQ0eHFuYs97RekQ8dpxmkuM88e63ATbZy4yDX06pKgmuQ==')]),
('dsa', 'AAAAB3NzaC1kc3MAAABhAJyWZzjVddGdyc5JPu/WPrC07vKRAmlqO6TUi49ah96iRcM7/D1aRMVAdYBepQ2mf1fsQTmvoC9KgQa79nN3kHhz0voQBKOuKI1ZAodfVOgpP4xmcXgjaA73Vjz22n4newAAABUA6l7/vIveaiA33YYv+SKcKLQaA8cAAABgbErc8QLw/WDz7mhVRZrU+9x3Tfs68j3eW+B/d7Rz1ZCqMYDk7r/F8dlBdQlYhpQvhuSBgzoFa0+qPvSSxPmutgb94wNqhHlVIUb9ZOJNloNr2lXiPP//Wu51TxXAEvAAAAAAYQCcQ9mufXtZa5RyfwT4NuLivdsidP4HRoLXdlnppfFAbNdbhxE0Us8WZt+a/443bwKnYxgif8dgxv5UROnWTngWu0jbJHpaDcTc9lRyTeSUiZZK312s/Sl7qDk3/Du7RUI=', 'AAAAFGx3ft7G8AQzFsjhle7PWardUXh3', 768, b'0x9c966738d575d19dc9ce493eefd63eb0b4eef29102696a3ba4d48b8f5a87dea245c33bfc3d5a44c54075805ea50da67f57ec4139afa02f4a8106bbf67377907873d2fa1004a3ae288d5902875f54e8293f8c66717823680ef7563cf6da7e277b,0xea5effbc8bde6a2037dd862ff9229c28b41a03c7,0x6c4adcf102f0fd60f3ee6855459ad4fbdc774dfb3af23dde5be07f77b473d590aa3180e4eebfc5f1d94175095886942f86e481833a056b4faa3ef492c4f9aeb606fde3036a8479552146fd64e24d96836bda55e23cffff5aee754f15c012f000,0x9c43d9ae7d7b596b94727f04f836e2e2bddb2274fe074682d77659e9a5f1406cd75b87113452cf1666df9aff8e376f02a76318227fc760c6fe5444e9d64e7816bb48db247a5a0dc4dcf654724de49489964adf5dacfd297ba83937fc3bbb4542', [(0, 'AAAAB3NzaC1kc3MAAAAoyCVHLG2QqdMx7NiCWaThx6tDA5mf7UGl+8By0IzmSldBujsGKNs20g==')]),
('rsa', 'AAAAB3NzaC1yc2EAAAABJQAAAGEA2ChX9+mQD/NULFkBrxLDI8d1PHgrInC2u11U4Grqu4oVzKvnFROo6DZeCu6sKhFJE5CnIL7evAthQ9hkXVHDhQ7xGVauzqyHGdIU4/pHRScAYWBv/PZOlNMrSoP/PP91', 'AAAAYCMNdgyGvWpez2EjMLSbQj0nQ3GW8jzvru3zdYwtA3hblNUU9QpWNxDmOMOApkwCzUgsdIPsBxctIeWT2h+v8sVOH+d66LCaNmNR0lp+dQ+iXM67hcGNuxJwRdMupD9ZbQAAADEA7XMrMAb4WuHaFafoTfGrf6Jhdy9Ozjqi1fStuld7Nj9JkoZluiL2dCwIrxqOjwU5AAAAMQDpC1gYiGVSPeDRILr2oxREtXWOsW+/ZZTfZNX7lvoufnp+qvwZPqvZnXQFHyZ8qB0AAAAwQE0wx8TPgcvRVEVv8Wt+o1NFlkJZayWD5hqpe/8AqUMZbqfg/aiso5mvecDLFgfV', 768, b'0x25,0xd82857f7e9900ff3542c5901af12c323c7753c782b2270b6bb5d54e06aeabb8a15ccabe71513a8e8365e0aeeac2a11491390a720bedebc0b6143d8645d51c3850ef11956aeceac8719d214e3fa4745270061606ffcf64e94d32b4a83ff3cff75', [(0, 'AAAAB3NzaC1yc2EAAABgrLSC4635RCsH1b3en58NqLsrH7PKRZyb3YmRasOyr8xIZMSlKZyxNg+kkn9OgBzbH9vChafzarfHyVwtJE2IMt3uwxTIWjwgwH19tc16k8YmNfDzujmB6OFOArmzKJgJ'), (2, 'AAAADHJzYS1zaGEyLTI1NgAAAGAJszr04BZlVBEdRLGOv1rTJwPiid/0I6/MycSH+noahvUH2wjrRhqDuv51F4nKYF5J9vBsEotTSrSF/cnLsliCdvVkEfmvhdcn/jx2LWF2OfjqETiYSc69Dde9UFmAPds='), (4, 'AAAADHJzYS1zaGEyLTUxMgAAAGBxfZ2m+WjvZ5YV5RFm0+w84CgHQ95EPndoAha0PCMc93AUHBmoHnezsJvEGuLovUm35w/0POmUNHI7HzM9PECwXrV0rO6N/HL/oFxJuDYmeqCpjMVmN8QXka+yxs2GEtA=')]),
]

142
test/dsa_nonce_recover.py Executable file
View File

@ -0,0 +1,142 @@
#!/usr/bin/env python3
'''
Recover the nonce value k used in integer DSA or NIST-style ECDSA,
starting from the private key and the signature.
_Without_ the private key, recovering the nonce is equivalent to
recovering the private key itself. But with it, it's a trivial piece
of modular arithmetic.
This script generates a load of test signatures from various keys,
recovers the nonces used, and prints them. This allows an eyeball
check of whether they're evenly distributed.
'''
import argparse
from base64 import b64decode as b64
from eccref import *
from testcrypt import *
from ssh import *
from agenttest import agent_query
def recover_nonce(order, hashalg, privint, transform_hash, r, s, message):
w = int(mp_invert(s, order))
h = ssh_hash_new(hashalg)
ssh_hash_update(h, message)
z = int(mp_from_bytes_be(ssh_hash_final(h)))
z = int(transform_hash(z))
return w * (z + r * privint) % order
def dsa_decode_sig(signature):
_, signature = ssh_decode_string(signature, return_rest=True)
signature = ssh_decode_string(signature)
assert len(signature) == 40
r = int(mp_from_bytes_be(signature[:20]))
s = int(mp_from_bytes_be(signature[20:]))
return r, s
def ecdsa_decode_sig(signature):
_, signature = ssh_decode_string(signature, return_rest=True)
signature = ssh_decode_string(signature)
r, signature = ssh_decode_string(signature, return_rest=True)
s, signature = ssh_decode_string(signature, return_rest=True)
r = int(mp_from_bytes_be(r))
s = int(mp_from_bytes_be(s))
return r, s
class SignerBase:
def test(self, privkey, decode_sig, transform_hash, order, hashalg,
algid, obits):
print("----", algid)
print("k=0x{{:0{}b}}".format(obits).format(order))
privblob = ssh_key_private_blob(privkey)
privint = int(mp_from_bytes_be(ssh_decode_string(privblob)))
self.setup_key(privkey)
for message in (f"msg{i}".encode('ASCII') for i in range(100)):
signature = self.sign(privkey, message)
r, s = decode_sig(signature)
nonce = recover_nonce(order, hashalg, privint, transform_hash,
r, s, message)
print("k=0x{{:0{}b}}".format(obits).format(nonce))
self.cleanup_key(privkey)
def test_dsa(self, pubblob, privblob):
privkey = ssh_key_new_priv('dsa', pubblob, privblob)
_, buf = ssh_decode_string(pubblob, return_rest=True)
p, buf = ssh_decode_string(buf, return_rest=True)
q, buf = ssh_decode_string(buf, return_rest=True)
g, buf = ssh_decode_string(buf, return_rest=True)
p = int(mp_from_bytes_be(p))
q = int(mp_from_bytes_be(q))
g = int(mp_from_bytes_be(g))
transform_hash = lambda h: h
self.test(privkey, dsa_decode_sig, transform_hash, q, 'sha1', 'dsa',
160)
def test_ecdsa(self, algid, curve, hashalg, pubblob, privblob):
privkey = ssh_key_new_priv(algid, pubblob, privblob)
obits = int(mp_get_nbits(curve.G_order))
def transform_hash(z):
shift = max(0, mp_get_nbits(z) - obits)
return mp_rshift_safe(z, shift)
self.test(privkey, ecdsa_decode_sig, transform_hash, curve.G_order,
hashalg, algid, obits)
class TestcryptSigner(SignerBase):
def setup_key(self, key):
pass
def cleanup_key(self, key):
pass
def sign(self, key, message):
return ssh_key_sign(key, message, 0)
class AgentSigner(SignerBase):
def setup_key(self, key):
alg = ssh_decode_string(key.public_blob())
msg = (ssh_byte(SSH2_AGENTC_ADD_IDENTITY) +
ssh_string(alg) +
key.openssh_blob() +
ssh_string(b"dsa_nonce_recover test key"))
result = agent_query(msg)
assert result == ssh_byte(SSH_AGENT_SUCCESS)
def cleanup_key(self, key):
msg = (ssh_byte(SSH2_AGENTC_REMOVE_IDENTITY) +
ssh_string(key.public_blob()))
result = agent_query(msg)
assert result == ssh_byte(SSH_AGENT_SUCCESS)
def sign(self, key, message):
msg = (ssh_byte(SSH2_AGENTC_SIGN_REQUEST) +
ssh_string(key.public_blob()) +
ssh_string(message))
rsp = agent_query(msg)
t, rsp = ssh_decode_byte(rsp, True)
assert t == SSH2_AGENT_SIGN_RESPONSE
sig, rsp = ssh_decode_string(rsp, True)
assert len(rsp) == 0
return sig
def main():
parser = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument("--agent", action="store_true",
help="Test an SSH agent instead of testcrypt. "
"(Still needs testcrypt.)")
args = parser.parse_args()
signer = AgentSigner() if args.agent else TestcryptSigner()
signer.test_dsa(b64('AAAAB3NzaC1kc3MAAABhAJyWZzjVddGdyc5JPu/WPrC07vKRAmlqO6TUi49ah96iRcM7/D1aRMVAdYBepQ2mf1fsQTmvoC9KgQa79nN3kHhz0voQBKOuKI1ZAodfVOgpP4xmcXgjaA73Vjz22n4newAAABUA6l7/vIveaiA33YYv+SKcKLQaA8cAAABgbErc8QLw/WDz7mhVRZrU+9x3Tfs68j3eW+B/d7Rz1ZCqMYDk7r/F8dlBdQlYhpQvhuSBgzoFa0+qPvSSxPmutgb94wNqhHlVIUb9ZOJNloNr2lXiPP//Wu51TxXAEvAAAAAAYQCcQ9mufXtZa5RyfwT4NuLivdsidP4HRoLXdlnppfFAbNdbhxE0Us8WZt+a/443bwKnYxgif8dgxv5UROnWTngWu0jbJHpaDcTc9lRyTeSUiZZK312s/Sl7qDk3/Du7RUI='), b64('AAAAFGx3ft7G8AQzFsjhle7PWardUXh3'))
signer.test_ecdsa('p256', p256, 'sha256', b64('AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHkYQ0sQoq5LbJI1VMWhw3bV43TSYi3WVpqIgKcBKK91TcFFlAMZgceOHQ0xAFYcSczIttLvFu+xkcLXrRd4N7Q='), b64('AAAAIQCV/1VqiCsHZm/n+bq7lHEHlyy7KFgZBEbzqYaWtbx48Q=='))
signer.test_ecdsa('p384', p384, 'sha384', b64('AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBMYK8PUtfAlJwKaBTIGEuCzH0vqOMa4UbcjrBbTbkGVSUnfo+nuC80NCdj9JJMs1jvfF8GzKLc5z8H3nZyM741/BUFjV7rEHsQFDek4KyWvKkEgKiTlZid19VukNo1q2Hg=='), b64('AAAAMGsfTmdB4zHdbiQ2euTSdzM6UKEOnrVjMAWwHEYvmG5qUOcBnn62fJDRJy67L+QGdg=='))
signer.test_ecdsa('p521', p521, 'sha512', b64('AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAFrGthlKM152vu2Ghk+R7iO9/M6e+hTehNZ6+FBwof4HPkPB2/HHXj5+w5ynWyUrWiX5TI2riuJEIrJErcRH5LglADnJDX2w4yrKZ+wDHSz9lwh9p2F+B5R952es6gX3RJRkGA+qhKpKup8gKx78RMbleX8wgRtIu+4YMUnKb1edREiRg=='), b64('AAAAQgFh7VNJFUljWhhyAEiL0z+UPs/QggcMTd3Vv2aKDeBdCRl5di8r+BMm39L7bRzxRMEtW5NSKlDtE8MFEGdIE9khsw=='))
if __name__ == '__main__':
main()

View File

@ -214,6 +214,14 @@ static void wrap_malloc_pre(void *wrapctx, void **user_data)
*user_data = drwrap_get_arg(wrapctx, 0);
dr_fprintf(outfile, "malloc %"PRIuMAX"\n", (uintmax_t)*user_data);
}
static void wrap_aligned_alloc_pre(void *wrapctx, void **user_data)
{
logging_paused++;
size_t align = (size_t) drwrap_get_arg(wrapctx, 0);
*user_data = drwrap_get_arg(wrapctx, 1);
dr_fprintf(outfile, "aligned_alloc align=%zu size=%"PRIuMAX"\n",
align, (uintmax_t)*user_data);
}
static void wrap_free_pre(void *wrapctx, void **user_data)
{
logging_paused++;
@ -239,71 +247,7 @@ static void wrap_alloc_post(void *wrapctx, void *user_data)
}
/*
* We wrap the C library function memset, because I've noticed that at
* least one optimised implementation of it diverges control flow
* internally based on what appears to be the _alignment_ of the input
* pointer - and that alignment check can vary depending on the
* addresses of allocated blocks. So I can't guarantee no divergence
* of control flow inside memset if malloc doesn't return the same
* values, and instead I just have to trust that memset isn't reading
* the contents of the block and basing control flow decisions on that.
*/
static void wrap_memset_pre(void *wrapctx, void **user_data)
{
uint was_already_paused = logging_paused++;
if (outfile == INVALID_FILE || was_already_paused)
return;
const void *addr = drwrap_get_arg(wrapctx, 0);
size_t size = (size_t)drwrap_get_arg(wrapctx, 2);
struct allocation *alloc = find_allocation(addr);
if (!alloc) {
dr_fprintf(outfile, "memset %"PRIuMAX" @ %"PRIxMAX"\n",
(uintmax_t)size, (uintmax_t)addr);
} else {
dr_fprintf(outfile, "memset %"PRIuMAX" @ allocations[%"PRIuPTR"]"
" + %"PRIxMAX"\n", (uintmax_t)size, alloc->index,
(uintmax_t)(addr - alloc->start));
}
}
/*
* Similarly to the above, wrap some versions of memmove.
*/
static void wrap_memmove_pre(void *wrapctx, void **user_data)
{
uint was_already_paused = logging_paused++;
if (outfile == INVALID_FILE || was_already_paused)
return;
const void *daddr = drwrap_get_arg(wrapctx, 0);
const void *saddr = drwrap_get_arg(wrapctx, 1);
size_t size = (size_t)drwrap_get_arg(wrapctx, 2);
struct allocation *alloc;
dr_fprintf(outfile, "memmove %"PRIuMAX" ", (uintmax_t)size);
if (!(alloc = find_allocation(daddr))) {
dr_fprintf(outfile, "to %"PRIxMAX" ", (uintmax_t)daddr);
} else {
dr_fprintf(outfile, "to allocations[%"PRIuPTR"] + %"PRIxMAX" ",
alloc->index, (uintmax_t)(daddr - alloc->start));
}
if (!(alloc = find_allocation(saddr))) {
dr_fprintf(outfile, "from %"PRIxMAX"\n", (uintmax_t)saddr);
} else {
dr_fprintf(outfile, "from allocations[%"PRIuPTR"] + %"PRIxMAX"\n",
alloc->index, (uintmax_t)(saddr - alloc->start));
}
}
/*
* Common post-wrapper function for memset and free, whose entire
* function is to unpause the logging.
* Common post-wrapper function to unpause the logging.
*/
static void unpause_post(void *wrapctx, void *user_data)
{
@ -594,10 +538,9 @@ static void load_module(
TRY_WRAP("dry_run_real", NULL, wrap_dryrun);
if (libc) {
TRY_WRAP("malloc", wrap_malloc_pre, wrap_alloc_post);
TRY_WRAP("aligned_alloc", wrap_aligned_alloc_pre, wrap_alloc_post);
TRY_WRAP("realloc", wrap_realloc_pre, wrap_alloc_post);
TRY_WRAP("free", wrap_free_pre, unpause_post);
TRY_WRAP("memset", wrap_memset_pre, unpause_post);
TRY_WRAP("memmove", wrap_memmove_pre, unpause_post);
/*
* More strangely named versions of standard C library
@ -616,10 +559,6 @@ static void load_module(
TRY_WRAP("__libc_malloc", wrap_malloc_pre, wrap_alloc_post);
TRY_WRAP("__GI___libc_realloc", wrap_realloc_pre, wrap_alloc_post);
TRY_WRAP("__GI___libc_free", wrap_free_pre, unpause_post);
TRY_WRAP("__memset_sse2_unaligned", wrap_memset_pre, unpause_post);
TRY_WRAP("__memset_sse2", wrap_memset_pre, unpause_post);
TRY_WRAP("__memmove_avx_unaligned_erms", wrap_memmove_pre,
unpause_post);
TRY_WRAP("cfree", wrap_free_pre, unpause_post);
}
}

View File

@ -327,6 +327,12 @@ FUNC(opt_val_string, key_components_nth_str,
FUNC(opt_val_mpint, key_components_nth_mp, ARG(val_keycomponents, kc),
ARG(uint, n))
/*
* DSA nonce generation.
*/
FUNC(opt_val_mpint, rfc6979, ARG(hashalg, hash), ARG(val_mpint, modulus),
ARG(val_mpint, private_key), ARG(val_string_ptrlen, message))
/*
* The ssh_cipher abstraction. The in-place encrypt and decrypt
* functions are wrapped to replace them with versions that take one

View File

@ -431,6 +431,8 @@ VOLATILE_WRAPPED_DEFN(static, size_t, looplimit, (size_t x))
X(argon2) \
X(primegen_probabilistic) \
X(ntru) \
X(rfc6979_setup) \
X(rfc6979_attempt) \
/* end of list */
static void test_mp_get_nbits(void)
@ -1565,6 +1567,7 @@ static void test_hash(const ssh_hashalg *halg)
test_skipped = true;
return;
}
ssh_hash_free(h);
size_t datalen = 256;
uint8_t *data = snewn(datalen, uint8_t);
@ -1574,16 +1577,14 @@ static void test_hash(const ssh_hashalg *halg)
random_read(data, datalen);
log_start();
h = ssh_hash_new(halg);
put_data(h, data, datalen);
ssh_hash_final(h, hash);
log_end();
h = ssh_hash_new(halg);
}
sfree(data);
sfree(hash);
ssh_hash_free(h);
}
#define HASH_TESTFN(Y_unused, hash) \
@ -1744,6 +1745,63 @@ static void test_ntru(void)
strbuf_free(buffer);
}
static void test_rfc6979_setup(void)
{
mp_int *q = mp_new(512);
mp_int *x = mp_new(512);
strbuf *message = strbuf_new();
strbuf_append(message, 123);
RFC6979 *s = rfc6979_new(&ssh_sha256, q, x);
for (size_t i = 0; i < looplimit(20); i++) {
random_read(message->u, message->len);
mp_random_fill(q);
mp_random_fill(x);
log_start();
rfc6979_setup(s, ptrlen_from_strbuf(message));
log_end();
}
rfc6979_free(s);
mp_free(q);
mp_free(x);
strbuf_free(message);
}
static void test_rfc6979_attempt(void)
{
mp_int *q = mp_new(512);
mp_int *x = mp_new(512);
strbuf *message = strbuf_new();
strbuf_append(message, 123);
RFC6979 *s = rfc6979_new(&ssh_sha256, q, x);
for (size_t i = 0; i < looplimit(5); i++) {
random_read(message->u, message->len);
mp_random_fill(q);
mp_random_fill(x);
rfc6979_setup(s, ptrlen_from_strbuf(message));
for (size_t j = 0; j < looplimit(10); j++) {
log_start();
RFC6979Result result = rfc6979_attempt(s);
mp_free(result.k);
log_end();
}
}
rfc6979_free(s);
mp_free(q);
mp_free(x);
strbuf_free(message);
}
static const struct test tests[] = {
#define STRUCT_TEST(X) { #X, test_##X },
TESTLIST(STRUCT_TEST)