fprime.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /* Arithmetic in prime fields
  2. * Daniel Beer <dlbeer@gmail.com>, 10 Jan 2014
  3. *
  4. * This file is in the public domain.
  5. */
  6. #include "fprime.h"
  7. static void raw_add(uint8_t *x, const uint8_t *p)
  8. {
  9. uint16_t c = 0;
  10. int i;
  11. for (i = 0; i < FPRIME_SIZE; i++) {
  12. c += ((uint16_t)x[i]) + ((uint16_t)p[i]);
  13. x[i] = c;
  14. c >>= 8;
  15. }
  16. }
  17. static void raw_try_sub(uint8_t *x, const uint8_t *p)
  18. {
  19. uint8_t minusp[FPRIME_SIZE];
  20. uint16_t c = 0;
  21. int i;
  22. for (i = 0; i < FPRIME_SIZE; i++) {
  23. c = ((uint16_t)x[i]) - ((uint16_t)p[i]) - c;
  24. minusp[i] = c;
  25. c = (c >> 8) & 1;
  26. }
  27. fprime_select(x, minusp, x, c);
  28. }
  29. /* Warning: this function is variable-time */
  30. static int prime_msb(const uint8_t *p)
  31. {
  32. int i;
  33. uint8_t x;
  34. for (i = FPRIME_SIZE - 1; i >= 0; i--)
  35. if (p[i])
  36. break;
  37. x = p[i];
  38. i <<= 3;
  39. while (x) {
  40. x >>= 1;
  41. i++;
  42. }
  43. return i - 1;
  44. }
  45. /* Warning: this function may be variable-time in the argument n */
  46. static void shift_n_bits(uint8_t *x, int n)
  47. {
  48. uint16_t c = 0;
  49. int i;
  50. for (i = 0; i < FPRIME_SIZE; i++) {
  51. c |= ((uint16_t)x[i]) << n;
  52. x[i] = c;
  53. c >>= 8;
  54. }
  55. }
  56. static inline int min_int(int a, int b)
  57. {
  58. return a < b ? a : b;
  59. }
  60. void fprime_from_bytes(uint8_t *n,
  61. const uint8_t *x, size_t len,
  62. const uint8_t *modulus)
  63. {
  64. const int preload_total = min_int(prime_msb(modulus) - 1, len << 3);
  65. const int preload_bytes = preload_total >> 3;
  66. const int preload_bits = preload_total & 7;
  67. const int rbits = (len << 3) - preload_total;
  68. int i;
  69. memset(n, 0, FPRIME_SIZE);
  70. for (i = 0; i < preload_bytes; i++)
  71. n[i] = x[len - preload_bytes + i];
  72. if (preload_bits) {
  73. shift_n_bits(n, preload_bits);
  74. n[0] |= x[len - preload_bytes - 1] >> (8 - preload_bits);
  75. }
  76. for (i = rbits - 1; i >= 0; i--) {
  77. const uint8_t bit = (x[i >> 3] >> (i & 7)) & 1;
  78. shift_n_bits(n, 1);
  79. n[0] |= bit;
  80. raw_try_sub(n, modulus);
  81. }
  82. }
  83. void fprime_select(uint8_t *dst,
  84. const uint8_t *zero, const uint8_t *one,
  85. uint8_t condition)
  86. {
  87. const uint8_t mask = -condition;
  88. int i;
  89. for (i = 0; i < FPRIME_SIZE; i++)
  90. dst[i] = zero[i] ^ (mask & (one[i] ^ zero[i]));
  91. }
  92. void fprime_add(uint8_t *r, const uint8_t *a, const uint8_t *modulus)
  93. {
  94. raw_add(r, a);
  95. raw_try_sub(r, modulus);
  96. }
  97. void fprime_mul(uint8_t *r, const uint8_t *a, const uint8_t *b,
  98. const uint8_t *modulus)
  99. {
  100. int i;
  101. memset(r, 0, FPRIME_SIZE);
  102. for (i = prime_msb(modulus); i >= 0; i--) {
  103. const uint8_t bit = (b[i >> 3] >> (i & 7)) & 1;
  104. uint8_t plusa[FPRIME_SIZE];
  105. shift_n_bits(r, 1);
  106. raw_try_sub(r, modulus);
  107. fprime_copy(plusa, r);
  108. fprime_add(plusa, a, modulus);
  109. fprime_select(r, r, plusa, bit);
  110. }
  111. }