goc25519sm_test.go 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. // Copyright 2021 Jeffrey H. Johnson <trnsz@pobox.com>.
  2. // Copyright 2021 Gridfinity, LLC.
  3. // Copyright 2020 Frank Denis <j at pureftpd dot org>.
  4. // Copyright 2012 The Go Authors.
  5. //
  6. // All rights reserved.
  7. //
  8. // Use of this source code is governed by the BSD-style
  9. // license that can be found in the LICENSE file.
  10. package goc25519sm_test
  11. import (
  12. crand "crypto/rand"
  13. csubtle "crypto/subtle"
  14. "fmt"
  15. "testing"
  16. goc25519sm "github.com/johnsonjh/goc25519sm"
  17. u "github.com/johnsonjh/leaktestfe"
  18. )
  19. const (
  20. expectedHex = "89161fde887b2b53de549af483940106ecc114d6982daa98256de23bdf77661a"
  21. )
  22. var lowOrderPoints = [][goc25519sm.X25519Size]byte{
  23. {
  24. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  25. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  26. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  27. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  28. },
  29. {
  30. 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  31. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  32. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  33. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  34. },
  35. {
  36. 0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae,
  37. 0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a,
  38. 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd,
  39. 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x00,
  40. },
  41. {
  42. 0x5f, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24,
  43. 0xb1, 0xd0, 0xb1, 0x55, 0x9c, 0x83, 0xef, 0x5b,
  44. 0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c, 0x8e, 0x86,
  45. 0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0x57,
  46. },
  47. {
  48. 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  49. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  50. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  51. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
  52. },
  53. {
  54. 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  55. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  56. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  57. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
  58. },
  59. {
  60. 0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  61. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  62. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  63. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
  64. },
  65. }
  66. var curved25519Expected = [goc25519sm.X25519Size]byte{
  67. 0xac, 0xce, 0x24, 0xb1, 0xd4, 0xa2, 0x36, 0x21,
  68. 0x15, 0xe2, 0x3e, 0x84, 0x3c, 0x23, 0x2b, 0x5f,
  69. 0x95, 0x6c, 0xc0, 0x7b, 0x95, 0x82, 0xd7, 0x93,
  70. 0xd5, 0x19, 0xb6, 0xf1, 0xfb, 0x96, 0xd6, 0x04,
  71. }
  72. func TestTestVectors(
  73. t *testing.T,
  74. ) {
  75. defer u.Leakplug(
  76. t,
  77. )
  78. t.Run(
  79. "PureGo",
  80. func(
  81. t *testing.T,
  82. ) {
  83. testTestVectors(
  84. t,
  85. goc25519sm.OldScalarMultGeneric,
  86. )
  87. },
  88. )
  89. t.Run(
  90. "Native",
  91. func(
  92. t *testing.T,
  93. ) {
  94. testTestVectors(
  95. t,
  96. goc25519sm.OldScalarMult,
  97. )
  98. },
  99. )
  100. }
  101. func testTestVectors(
  102. t *testing.T,
  103. OldScalarMult func(
  104. dst,
  105. scalar,
  106. point *[goc25519sm.X25519Size]byte,
  107. ) error,
  108. ) {
  109. defer u.Leakplug(
  110. t,
  111. )
  112. for _, tv := range testVectors {
  113. var got [goc25519sm.X25519Size]byte
  114. err := goc25519sm.OldScalarMult(
  115. &got,
  116. &tv.In,
  117. &tv.Base,
  118. )
  119. if csubtle.ConstantTimeCompare(
  120. got[:],
  121. tv.Expect[:],
  122. ) != 1 || err != nil {
  123. t.Logf(
  124. " in = %v",
  125. tv.In,
  126. )
  127. t.Logf(
  128. " base = %v",
  129. tv.Base,
  130. )
  131. t.Logf(
  132. " got = %v",
  133. got,
  134. )
  135. t.Logf(
  136. "expect = %v",
  137. tv.Expect,
  138. )
  139. t.Logf(
  140. " err = %v",
  141. err,
  142. )
  143. t.Fail()
  144. }
  145. }
  146. }
  147. // TestHighBitIgnored tests the following requirement in RFC-7748:
  148. // "When receiving such an array, implementations of X25519
  149. // ... MUST mask the most significant bit in the final byte."
  150. func TestHighBitIgnored(
  151. t *testing.T,
  152. ) {
  153. defer u.Leakplug(
  154. t,
  155. )
  156. var err error
  157. var s, u [goc25519sm.X25519Size]byte
  158. _, err = crand.Read(
  159. s[:],
  160. )
  161. if err != nil {
  162. t.Errorf(
  163. "\ngoc25519sm_test.TestHighBitIgnored.crand.Read(s[:]) FAILURE:\n %v",
  164. err,
  165. )
  166. }
  167. _, err = crand.Read(
  168. u[:],
  169. )
  170. if err != nil {
  171. t.Errorf(
  172. "\ngoc25519sm_test.TestHighBitIgnored.crand.Read(u[:]) FAILURE:\n %v",
  173. err,
  174. )
  175. }
  176. var hi0, hi1 [goc25519sm.X25519Size]byte
  177. u[31] &= 0x7f
  178. err = goc25519sm.OldScalarMult(
  179. &hi0,
  180. &s,
  181. &u,
  182. )
  183. if err != nil {
  184. t.Errorf(
  185. "\ngoc25519sm_test.TestHighBitIgnored.OldScalarMult FAILURE:\n hi0=%v\n s=%v\n u=%v\n %v",
  186. hi0,
  187. s,
  188. u,
  189. err,
  190. )
  191. }
  192. u[31] |= 0x80
  193. err = goc25519sm.OldScalarMult(
  194. &hi1,
  195. &s,
  196. &u,
  197. )
  198. if err != nil {
  199. t.Errorf(
  200. "\ngoc25519sm_test.TestHighBitIgnored.OldScalarMult FAILURE:\n hi1=%v\n s=%v\n u=%v\n %v",
  201. hi1,
  202. s,
  203. u,
  204. err,
  205. )
  206. }
  207. if csubtle.ConstantTimeCompare(
  208. hi0[:],
  209. hi1[:],
  210. ) != 1 {
  211. t.Errorf(
  212. "\ngoc25519sm_test.TestHighBitIgnored FAILURE:\n ERROR: high bit of group erronously point affecting result",
  213. )
  214. }
  215. }
  216. func TestOldScalarBaseMult1024(
  217. t *testing.T,
  218. ) {
  219. defer u.Leakplug(
  220. t,
  221. )
  222. var err error
  223. csk := [2][goc25519sm.X25519Size]byte{
  224. {255},
  225. }
  226. for i := 0; i < 1024; i++ {
  227. err = goc25519sm.OldScalarBaseMult(
  228. &csk[(i&1)^1],
  229. &csk[i&1],
  230. )
  231. if err != nil {
  232. t.Errorf(
  233. "\ngoc25519sm_test.TestOldScalarBaseMult1024.OldScalarBaseMult FAILURE:\n csk[(%v&1)^1]=%v\n csk[%v&1]=%v\n %v",
  234. i,
  235. csk[(i&1)^1],
  236. i,
  237. csk[i&1],
  238. err,
  239. )
  240. }
  241. }
  242. if csubtle.ConstantTimeCompare(
  243. curved25519Expected[:],
  244. csk[0][:],
  245. ) != 1 {
  246. t.Fatal(
  247. "\ngoc25519sm_test.TestOldScalarBaseMult1024 FAILURE:\n ERROR: ((|255| * basepoint) * basepoint)... 1024 did not match",
  248. )
  249. }
  250. }
  251. func TestBasepointMolestation(
  252. t *testing.T,
  253. ) {
  254. defer u.Leakplug(
  255. t,
  256. )
  257. var err error
  258. oBasepoint := goc25519sm.Basepoint
  259. err = goc25519sm.OldScalarVerifyBasepoint(
  260. goc25519sm.Basepoint,
  261. )
  262. if err != nil {
  263. t.Fatal(
  264. fmt.Sprintf(
  265. "\ngoc25519sm_test.TestBasepointMolestation.OldScalarVerifyBasepoint FAILURE\n ERROR: falsely detected molestation of pristine Basepoint\n wanted %v\n got %v",
  266. goc25519sm.Basepoint,
  267. err,
  268. ),
  269. )
  270. }
  271. goc25519sm.Basepoint = [goc25519sm.X25519Size]byte{
  272. 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
  273. 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
  274. 0x17, 0x18, 0x19, 0x20, 0x21, 0x22, 0x23, 0x24,
  275. 0x25, 0x26, 0x27, 0x28, 0x29, 0x30, 0x31, 0x32,
  276. }
  277. err = goc25519sm.OldScalarVerifyBasepoint(
  278. goc25519sm.Basepoint,
  279. )
  280. if err == nil {
  281. t.Fatal(
  282. fmt.Sprintf(
  283. "\ngoc25519sm_test.TestBasepointMolestation.OldScalarVerifyBasepoint FAILURE:\n ERROR: failed to detect Basepoint molestation\n wanted %v\n got %v",
  284. oBasepoint,
  285. goc25519sm.Basepoint,
  286. ),
  287. )
  288. }
  289. goc25519sm.Basepoint = oBasepoint
  290. }
  291. func TestOldScalarBaseMult200(
  292. t *testing.T,
  293. ) {
  294. defer u.Leakplug(
  295. t,
  296. )
  297. var err error
  298. var a, b [goc25519sm.X25519Size]byte
  299. in := &a
  300. out := &b
  301. a[0] = 2
  302. for i := 0; i < 200; i++ {
  303. err = goc25519sm.OldScalarBaseMult(
  304. out,
  305. in,
  306. )
  307. if err != nil {
  308. t.Fatal(
  309. fmt.Sprintf(
  310. "\ngoc25519sm_test.TestOldScalarBaseMult200.OldScalarBaseMult FAILURE:\n in=%v\n out=%v\n %v",
  311. *in,
  312. *out,
  313. err,
  314. ),
  315. )
  316. }
  317. in, out = out, in
  318. }
  319. result := fmt.Sprintf(
  320. "%x",
  321. in[:],
  322. )
  323. if result != expectedHex {
  324. t.Errorf(
  325. "\ngoc25519sm_test.TestOldScalarBaseMult200 FAILURE:\n wanted %v\n got %v",
  326. expectedHex,
  327. result,
  328. )
  329. }
  330. }
  331. func TestLowOrderPoints(
  332. t *testing.T,
  333. ) {
  334. defer u.Leakplug(
  335. t,
  336. )
  337. var x [goc25519sm.X25519Size]byte
  338. var err error
  339. scalar := make(
  340. []byte,
  341. goc25519sm.X25519Size,
  342. )
  343. tscalar := scalar
  344. copy(
  345. x[:],
  346. tscalar,
  347. )
  348. if _, err = crand.Read(
  349. tscalar,
  350. ); err != nil {
  351. t.Fatal(
  352. fmt.Sprintf(
  353. "\ngoc25519sm_test.TestLowOrderPoints.crand.Read FAILURE:\n %v",
  354. err,
  355. ),
  356. )
  357. }
  358. for i, p := range lowOrderPoints {
  359. var out [goc25519sm.X25519Size]byte
  360. err = goc25519sm.OldScalarMult(
  361. &out,
  362. &x,
  363. &p,
  364. )
  365. if err == nil {
  366. t.Errorf(
  367. "\ngoc25519sm_test.TestLowOrderPoints.OldScalarMult FAILURE:\n %v expected an error\n got %v",
  368. i,
  369. err,
  370. )
  371. }
  372. var allZeroOutput [goc25519sm.X25519Size]byte
  373. if out != allZeroOutput {
  374. t.Errorf(
  375. "\ngoc25519sm_test.TestLowOrderPoints.OldScalarMult FAILURE:\n %v expected all zero output\n got %v",
  376. i,
  377. out,
  378. )
  379. }
  380. }
  381. }