cbd.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. // cbd.go - Centered binomial distribution.
  2. //
  3. // To the extent possible under law, Yawning Angel has waived all copyright
  4. // and related or neighboring rights to the software, using the Creative
  5. // Commons "CC0" public domain dedication. See LICENSE or
  6. // <http://creativecommons.org/publicdomain/zero/1.0/> for full details.
  7. package kyber
  8. // Load bytes into a 64-bit integer in little-endian order.
  9. func loadLittleEndian(x []byte, bytes int) uint64 {
  10. var r uint64
  11. for i, v := range x[:bytes] {
  12. r |= uint64(v) << (8 * uint(i))
  13. }
  14. return r
  15. }
  16. // Given an array of uniformly random bytes, compute polynomial with
  17. // coefficients distributed according to a centered binomial distribution
  18. // with parameter eta.
  19. func (p *poly) cbd(buf []byte, eta int) {
  20. hardwareAccelImpl.cbdFn(p, buf, eta)
  21. }
  22. func cbdRef(p *poly, buf []byte, eta int) {
  23. switch eta {
  24. case 3:
  25. var a, b [4]uint32
  26. for i := 0; i < kyberN/4; i++ {
  27. t := loadLittleEndian(buf[3*i:], 3)
  28. var d uint32
  29. for j := 0; j < 3; j++ {
  30. d += uint32((t >> uint(j)) & 0x249249)
  31. }
  32. a[0] = d & 0x7
  33. b[0] = (d >> 3) & 0x7
  34. a[1] = (d >> 6) & 0x7
  35. b[1] = (d >> 9) & 0x7
  36. a[2] = (d >> 12) & 0x7
  37. b[2] = (d >> 15) & 0x7
  38. a[3] = (d >> 18) & 0x7
  39. b[3] = (d >> 21)
  40. p.coeffs[4*i+0] = uint16(a[0] + kyberQ - b[0])
  41. p.coeffs[4*i+1] = uint16(a[1] + kyberQ - b[1])
  42. p.coeffs[4*i+2] = uint16(a[2] + kyberQ - b[2])
  43. p.coeffs[4*i+3] = uint16(a[3] + kyberQ - b[3])
  44. }
  45. case 4:
  46. var a, b [4]uint32
  47. for i := 0; i < kyberN/4; i++ {
  48. t := loadLittleEndian(buf[4*i:], 4)
  49. var d uint32
  50. for j := 0; j < 4; j++ {
  51. d += uint32((t >> uint(j)) & 0x11111111)
  52. }
  53. a[0] = d & 0xf
  54. b[0] = (d >> 4) & 0xf
  55. a[1] = (d >> 8) & 0xf
  56. b[1] = (d >> 12) & 0xf
  57. a[2] = (d >> 16) & 0xf
  58. b[2] = (d >> 20) & 0xf
  59. a[3] = (d >> 24) & 0xf
  60. b[3] = (d >> 28)
  61. p.coeffs[4*i+0] = uint16(a[0] + kyberQ - b[0])
  62. p.coeffs[4*i+1] = uint16(a[1] + kyberQ - b[1])
  63. p.coeffs[4*i+2] = uint16(a[2] + kyberQ - b[2])
  64. p.coeffs[4*i+3] = uint16(a[3] + kyberQ - b[3])
  65. }
  66. case 5:
  67. var a, b [4]uint64
  68. for i := 0; i < kyberN/4; i++ {
  69. t := loadLittleEndian(buf[5*i:], 5)
  70. var d uint64
  71. for j := 0; j < 5; j++ {
  72. d += (t >> uint(j)) & 0x0842108421
  73. }
  74. a[0] = d & 0x1f
  75. b[0] = (d >> 5) & 0x1f
  76. a[1] = (d >> 10) & 0x1f
  77. b[1] = (d >> 15) & 0x1f
  78. a[2] = (d >> 20) & 0x1f
  79. b[2] = (d >> 25) & 0x1f
  80. a[3] = (d >> 30) & 0x1f
  81. b[3] = (d >> 35)
  82. p.coeffs[4*i+0] = uint16(a[0] + kyberQ - b[0])
  83. p.coeffs[4*i+1] = uint16(a[1] + kyberQ - b[1])
  84. p.coeffs[4*i+2] = uint16(a[2] + kyberQ - b[2])
  85. p.coeffs[4*i+3] = uint16(a[3] + kyberQ - b[3])
  86. }
  87. default:
  88. panic("kyber: eta must be in {3,4,5}")
  89. }
  90. }