summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorLéo Lam <leo@innovatetechnologi.es>2018-05-20 20:04:19 +0200
committerGitHub <noreply@github.com>2018-05-20 20:04:19 +0200
commita974c690586d3842297a730865e4ceafa3ac3d75 (patch)
treeb1779dc4371e040de85c01742c8121de343fe30e /Source/Core
parent46cc57ba33f551a4ee4c79987023e4ace15604f9 (diff)
parent67ce7e34e979e139c0854a73351a44a344eafa32 (diff)
Merge pull request #6866 from leoetlino/ec-cleanup
ec: General cleanup
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Common/Crypto/bn.cpp71
-rw-r--r--Source/Core/Common/Crypto/bn.h12
-rw-r--r--Source/Core/Common/Crypto/ec.cpp484
-rw-r--r--Source/Core/Common/Crypto/ec.h14
-rw-r--r--Source/Core/Core/IOS/IOSC.cpp14
5 files changed, 245 insertions, 350 deletions
diff --git a/Source/Core/Common/Crypto/bn.cpp b/Source/Core/Common/Crypto/bn.cpp
index 78ea444384..339b269d39 100644
--- a/Source/Core/Common/Crypto/bn.cpp
+++ b/Source/Core/Common/Crypto/bn.cpp
@@ -3,61 +3,43 @@
// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
#include <cstdio>
-#include <string.h>
+#include <cstring>
#include "Common/CommonTypes.h"
#include "Common/Crypto/bn.h"
-static void bn_zero(u8* d, u32 n)
+static void bn_zero(u8* d, int n)
{
- memset(d, 0, n);
+ std::memset(d, 0, n);
}
-static void bn_copy(u8* d, const u8* a, u32 n)
+static void bn_copy(u8* d, const u8* a, int n)
{
- memcpy(d, a, n);
+ std::memcpy(d, a, n);
}
-int bn_compare(const u8* a, const u8* b, u32 n)
+int bn_compare(const u8* a, const u8* b, int n)
{
- u32 i;
-
- for (i = 0; i < n; i++)
- {
- if (a[i] < b[i])
- return -1;
- if (a[i] > b[i])
- return 1;
- }
-
- return 0;
+ return std::memcmp(a, b, n);
}
-void bn_sub_modulus(u8* a, const u8* N, u32 n)
+void bn_sub_modulus(u8* a, const u8* N, int n)
{
- u32 i;
- u32 dig;
- u8 c;
-
- c = 0;
- for (i = n - 1; i < n; i--)
+ u8 c = 0;
+ for (int i = n - 1; i >= 0; --i)
{
- dig = N[i] + c;
+ u32 dig = N[i] + c;
c = (a[i] < dig);
a[i] -= dig;
}
}
-void bn_add(u8* d, const u8* a, const u8* b, const u8* N, u32 n)
+void bn_add(u8* d, const u8* a, const u8* b, const u8* N, int n)
{
- u32 i;
- u32 dig;
- u8 c;
-
- c = 0;
- for (i = n - 1; i < n; i--)
+ u8 c = 0;
+ for (int i = n - 1; i >= 0; --i)
{
- dig = a[i] + b[i] + c;
+ u32 dig = a[i] + b[i] + c;
c = (dig >= 0x100);
d[i] = dig;
}
@@ -69,32 +51,30 @@ void bn_add(u8* d, const u8* a, const u8* b, const u8* N, u32 n)
bn_sub_modulus(d, N, n);
}
-void bn_mul(u8* d, const u8* a, const u8* b, const u8* N, u32 n)
+void bn_mul(u8* d, const u8* a, const u8* b, const u8* N, int n)
{
- u32 i;
- u8 mask;
-
bn_zero(d, n);
- for (i = 0; i < n; i++)
- for (mask = 0x80; mask != 0; mask >>= 1)
+ for (int i = 0; i < n; i++)
+ {
+ for (u8 mask = 0x80; mask != 0; mask >>= 1)
{
bn_add(d, d, d, N, n);
if ((a[i] & mask) != 0)
bn_add(d, d, b, N, n);
}
+ }
}
-void bn_exp(u8* d, const u8* a, const u8* N, u32 n, const u8* e, u32 en)
+void bn_exp(u8* d, const u8* a, const u8* N, int n, const u8* e, int en)
{
u8 t[512];
- u32 i;
- u8 mask;
bn_zero(d, n);
d[n - 1] = 1;
- for (i = 0; i < en; i++)
- for (mask = 0x80; mask != 0; mask >>= 1)
+ for (int i = 0; i < en; i++)
+ {
+ for (u8 mask = 0x80; mask != 0; mask >>= 1)
{
bn_mul(t, d, d, N, n);
if ((e[i] & mask) != 0)
@@ -102,10 +82,11 @@ void bn_exp(u8* d, const u8* a, const u8* N, u32 n, const u8* e, u32 en)
else
bn_copy(d, t, n);
}
+ }
}
// only for prime N -- stupid but lazy, see if I care
-void bn_inv(u8* d, const u8* a, const u8* N, u32 n)
+void bn_inv(u8* d, const u8* a, const u8* N, int n)
{
u8 t[512], s[512];
diff --git a/Source/Core/Common/Crypto/bn.h b/Source/Core/Common/Crypto/bn.h
index 5c0c85b157..7ab2ab3fb1 100644
--- a/Source/Core/Common/Crypto/bn.h
+++ b/Source/Core/Common/Crypto/bn.h
@@ -8,9 +8,9 @@
// bignum arithmetic
-int bn_compare(const u8* a, const u8* b, u32 n);
-void bn_sub_modulus(u8* a, const u8* N, u32 n);
-void bn_add(u8* d, const u8* a, const u8* b, const u8* N, u32 n);
-void bn_mul(u8* d, const u8* a, const u8* b, const u8* N, u32 n);
-void bn_inv(u8* d, const u8* a, const u8* N, u32 n); // only for prime N
-void bn_exp(u8* d, const u8* a, const u8* N, u32 n, const u8* e, u32 en);
+int bn_compare(const u8* a, const u8* b, int n);
+void bn_sub_modulus(u8* a, const u8* N, int n);
+void bn_add(u8* d, const u8* a, const u8* b, const u8* N, int n);
+void bn_mul(u8* d, const u8* a, const u8* b, const u8* N, int n);
+void bn_inv(u8* d, const u8* a, const u8* N, int n); // only for prime N
+void bn_exp(u8* d, const u8* a, const u8* N, int n, const u8* e, int en);
diff --git a/Source/Core/Common/Crypto/ec.cpp b/Source/Core/Common/Crypto/ec.cpp
index 5fe7e9bb2b..9906ccd5e9 100644
--- a/Source/Core/Common/Crypto/ec.cpp
+++ b/Source/Core/Common/Crypto/ec.cpp
@@ -6,6 +6,7 @@
// Licensed under the terms of the GNU GPL, version 2
// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
+#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <ctime>
@@ -20,314 +21,213 @@
#pragma warning(disable : 4505)
#endif
-// y**2 + x*y = x**3 + x + b
-UNUSED static const u8 ec_b[30] = {0x00, 0x66, 0x64, 0x7e, 0xde, 0x6c, 0x33, 0x2c, 0x7f, 0x8c,
- 0x09, 0x23, 0xbb, 0x58, 0x21, 0x3b, 0x33, 0x3b, 0x20, 0xe9,
- 0xce, 0x42, 0x81, 0xfe, 0x11, 0x5f, 0x7d, 0x8f, 0x90, 0xad};
-
-// order of the addition group of points
-static const u8 ec_N[30] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xe9, 0x74, 0xe7, 0x2f,
- 0x8a, 0x69, 0x22, 0x03, 0x1d, 0x26, 0x03, 0xcf, 0xe0, 0xd7};
-
-// base point
-static const u8 ec_G[60] = {0x00, 0xfa, 0xc9, 0xdf, 0xcb, 0xac, 0x83, 0x13, 0xbb, 0x21, 0x39, 0xf1,
- 0xbb, 0x75, 0x5f, 0xef, 0x65, 0xbc, 0x39, 0x1f, 0x8b, 0x36, 0xf8, 0xf8,
- 0xeb, 0x73, 0x71, 0xfd, 0x55, 0x8b, 0x01, 0x00, 0x6a, 0x08, 0xa4, 0x19,
- 0x03, 0x35, 0x06, 0x78, 0xe5, 0x85, 0x28, 0xbe, 0xbf, 0x8a, 0x0b, 0xef,
- 0xf8, 0x67, 0xa7, 0xca, 0x36, 0x71, 0x6f, 0x7e, 0x01, 0xf8, 0x10, 0x52};
-
-static void elt_copy(u8* d, const u8* a)
+namespace Common::ec
{
- memcpy(d, a, 30);
-}
-
-static void elt_zero(u8* d)
-{
- memset(d, 0, 30);
-}
-
-static int elt_is_zero(const u8* d)
-{
- u32 i;
-
- for (i = 0; i < 30; i++)
- if (d[i] != 0)
- return 0;
-
- return 1;
-}
-
-static void elt_add(u8* d, const u8* a, const u8* b)
-{
- u32 i;
+static const u8 square[16] = {0x00, 0x01, 0x04, 0x05, 0x10, 0x11, 0x14, 0x15,
+ 0x40, 0x41, 0x44, 0x45, 0x50, 0x51, 0x54, 0x55};
- for (i = 0; i < 30; i++)
- d[i] = a[i] ^ b[i];
-}
+struct Elt;
+static Elt operator*(const Elt& a, const Elt& b);
-static void elt_mul_x(u8* d, const u8* a)
+struct Elt
{
- u8 carry, x, y;
- u32 i;
-
- carry = a[0] & 1;
-
- x = 0;
- for (i = 0; i < 29; i++)
+ bool IsZero() const
{
- y = a[i + 1];
- d[i] = x ^ (y >> 7);
- x = y << 1;
+ return std::all_of(data.begin(), data.end(), [](u8 b) { return b == 0; });
}
- d[29] = x ^ carry;
-
- d[20] ^= carry << 2;
-}
-
-static void elt_mul(u8* d, const u8* a, const u8* b)
-{
- u32 i, n;
- u8 mask;
-
- elt_zero(d);
- i = 0;
- mask = 1;
- for (n = 0; n < 233; n++)
+ void MulX()
{
- elt_mul_x(d, d);
-
- if ((a[i] & mask) != 0)
- elt_add(d, d, b);
-
- mask >>= 1;
- if (mask == 0)
+ u8 carry = data[0] & 1;
+ u8 x = 0;
+ for (std::size_t i = 0; i < data.size() - 1; i++)
{
- mask = 0x80;
- i++;
+ u8 y = data[i + 1];
+ data[i] = x ^ (y >> 7);
+ x = y << 1;
}
+ data[29] = x ^ carry;
+ data[20] ^= carry << 2;
}
-}
-
-static const u8 square[16] = {0x00, 0x01, 0x04, 0x05, 0x10, 0x11, 0x14, 0x15,
- 0x40, 0x41, 0x44, 0x45, 0x50, 0x51, 0x54, 0x55};
-static void elt_square_to_wide(u8* d, const u8* a)
-{
- u32 i;
-
- for (i = 0; i < 30; i++)
+ Elt Square() const
{
- d[2 * i] = square[a[i] >> 4];
- d[2 * i + 1] = square[a[i] & 15];
- }
-}
+ std::array<u8, 60> wide;
+ for (std::size_t i = 0; i < data.size(); i++)
+ {
+ wide[2 * i] = square[data[i] >> 4];
+ wide[2 * i + 1] = square[data[i] & 15];
+ }
+ for (std::size_t i = 0; i < data.size(); i++)
+ {
+ u8 x = wide[i];
-static void wide_reduce(u8* d)
-{
- u32 i;
- u8 x;
+ wide[i + 19] ^= x >> 7;
+ wide[i + 20] ^= x << 1;
- for (i = 0; i < 30; i++)
- {
- x = d[i];
+ wide[i + 29] ^= x >> 1;
+ wide[i + 30] ^= x << 7;
+ }
- d[i + 19] ^= x >> 7;
- d[i + 20] ^= x << 1;
+ u8 x = wide[30] & ~1;
+ wide[49] ^= x >> 7;
+ wide[50] ^= x << 1;
+ wide[59] ^= x >> 1;
+ wide[30] &= 1;
- d[i + 29] ^= x >> 1;
- d[i + 30] ^= x << 7;
+ Elt result;
+ std::copy(wide.cbegin() + 30, wide.cend(), result.data.begin());
+ return result;
}
- x = d[30] & ~1;
-
- d[49] ^= x >> 7;
- d[50] ^= x << 1;
-
- d[59] ^= x >> 1;
-
- d[30] &= 1;
-}
-
-static void elt_square(u8* d, const u8* a)
-{
- u8 wide[60];
-
- elt_square_to_wide(wide, a);
- wide_reduce(wide);
-
- elt_copy(d, wide + 30);
-}
-
-static void itoh_tsujii(u8* d, const u8* a, const u8* b, u32 j)
-{
- u8 t[30];
+ Elt ItohTsujii(const Elt& b, std::size_t j) const
+ {
+ Elt t = *this;
+ while (j--)
+ t = t.Square();
+ return t * b;
+ }
- elt_copy(t, a);
- while (j--)
+ Elt Inv() const
{
- elt_square(d, t);
- elt_copy(t, d);
+ Elt t = ItohTsujii(*this, 1);
+ Elt s = t.ItohTsujii(*this, 1);
+ t = s.ItohTsujii(s, 3);
+ s = t.ItohTsujii(*this, 1);
+ t = s.ItohTsujii(s, 7);
+ s = t.ItohTsujii(t, 14);
+ t = s.ItohTsujii(*this, 1);
+ s = t.ItohTsujii(t, 29);
+ t = s.ItohTsujii(s, 58);
+ s = t.ItohTsujii(t, 116);
+ return s.Square();
}
- elt_mul(d, t, b);
-}
+ std::array<u8, 30> data{};
+};
-static void elt_inv(u8* d, const u8* a)
+static Elt operator+(const Elt& a, const Elt& b)
{
- u8 t[30];
- u8 s[30];
-
- itoh_tsujii(t, a, a, 1);
- itoh_tsujii(s, t, a, 1);
- itoh_tsujii(t, s, s, 3);
- itoh_tsujii(s, t, a, 1);
- itoh_tsujii(t, s, s, 7);
- itoh_tsujii(s, t, t, 14);
- itoh_tsujii(t, s, a, 1);
- itoh_tsujii(s, t, t, 29);
- itoh_tsujii(t, s, s, 58);
- itoh_tsujii(s, t, t, 116);
- elt_square(d, s);
+ Elt d;
+ for (std::size_t i = 0; i < std::tuple_size<decltype(Elt::data)>{}; i++)
+ d.data[i] = a.data[i] ^ b.data[i];
+ return d;
}
-UNUSED static int point_is_on_curve(u8* p)
+static Elt operator*(const Elt& a, const Elt& b)
{
- u8 s[30], t[30];
- u8 *x, *y;
-
- x = p;
- y = p + 30;
-
- elt_square(t, x);
- elt_mul(s, t, x);
-
- elt_add(s, s, t);
-
- elt_square(t, y);
- elt_add(s, s, t);
-
- elt_mul(t, x, y);
- elt_add(s, s, t);
+ Elt d;
+ std::size_t i = 0;
+ u8 mask = 1;
+ for (std::size_t n = 0; n < 233; n++)
+ {
+ d.MulX();
- elt_add(s, s, ec_b);
+ if ((a.data[i] & mask) != 0)
+ d = d + b;
- return elt_is_zero(s);
+ mask >>= 1;
+ if (mask == 0)
+ {
+ mask = 0x80;
+ i++;
+ }
+ }
+ return d;
}
-static int point_is_zero(const u8* p)
+static Elt operator/(const Elt& dividend, const Elt& divisor)
{
- return elt_is_zero(p) && elt_is_zero(p + 30);
+ return dividend * divisor.Inv();
}
-static void point_double(u8* r, const u8* p)
+struct Point
{
- u8 s[30], t[30];
- const u8 *px, *py;
- u8 *rx, *ry;
-
- px = p;
- py = p + 30;
- rx = r;
- ry = r + 30;
-
- if (elt_is_zero(px))
+ Point() = default;
+ constexpr explicit Point(Elt x, Elt y) : m_data{{std::move(x), std::move(y)}} {}
+ explicit Point(const u8* data) { std::copy_n(data, sizeof(m_data), Data()); }
+
+ bool IsZero() const { return X().IsZero() && Y().IsZero(); }
+ Elt& X() { return m_data[0]; }
+ Elt& Y() { return m_data[1]; }
+ u8* Data() { return m_data[0].data.data(); }
+ const Elt& X() const { return m_data[0]; }
+ const Elt& Y() const { return m_data[1]; }
+ const u8* Data() const { return m_data[0].data.data(); }
+
+ Point Double() const
{
- elt_zero(rx);
- elt_zero(ry);
-
- return;
+ Point r;
+ if (X().IsZero())
+ return r;
+
+ const auto s = Y() / X() + X();
+ r.X() = s.Square() + s;
+ r.X().data[29] ^= 1;
+ r.Y() = s * r.X() + r.X() + X().Square();
+ return r;
}
- elt_inv(t, px);
- elt_mul(s, py, t);
- elt_add(s, s, px);
+private:
+ std::array<Elt, 2> m_data{};
+ static_assert(sizeof(decltype(m_data)) == 60, "Wrong size for m_data");
+};
- elt_square(t, px);
+// y**2 + x*y = x**3 + x + b
+UNUSED static const u8 ec_b[30] = {0x00, 0x66, 0x64, 0x7e, 0xde, 0x6c, 0x33, 0x2c, 0x7f, 0x8c,
+ 0x09, 0x23, 0xbb, 0x58, 0x21, 0x3b, 0x33, 0x3b, 0x20, 0xe9,
+ 0xce, 0x42, 0x81, 0xfe, 0x11, 0x5f, 0x7d, 0x8f, 0x90, 0xad};
- elt_square(rx, s);
- elt_add(rx, rx, s);
- rx[29] ^= 1;
+// order of the addition group of points
+static const u8 ec_N[30] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xe9, 0x74, 0xe7, 0x2f,
+ 0x8a, 0x69, 0x22, 0x03, 0x1d, 0x26, 0x03, 0xcf, 0xe0, 0xd7};
- elt_mul(ry, s, rx);
- elt_add(ry, ry, rx);
- elt_add(ry, ry, t);
-}
+// base point
+constexpr Point ec_G{
+ {{{0x00, 0xfa, 0xc9, 0xdf, 0xcb, 0xac, 0x83, 0x13, 0xbb, 0x21, 0x39, 0xf1, 0xbb, 0x75, 0x5f,
+ 0xef, 0x65, 0xbc, 0x39, 0x1f, 0x8b, 0x36, 0xf8, 0xf8, 0xeb, 0x73, 0x71, 0xfd, 0x55, 0x8b}}},
+ {{{0x01, 0x00, 0x6a, 0x08, 0xa4, 0x19, 0x03, 0x35, 0x06, 0x78, 0xe5, 0x85, 0x28, 0xbe, 0xbf,
+ 0x8a, 0x0b, 0xef, 0xf8, 0x67, 0xa7, 0xca, 0x36, 0x71, 0x6f, 0x7e, 0x01, 0xf8, 0x10, 0x52}}}};
-static void point_add(u8* r, const u8* p, const u8* q)
+static Point operator+(const Point& a, const Point& b)
{
- u8 s[30], t[30], u[30];
- const u8 *px, *py, *qx, *qy;
- u8 *rx, *ry;
-
- px = p;
- py = p + 30;
- qx = q;
- qy = q + 30;
- rx = r;
- ry = r + 30;
-
- if (point_is_zero(p))
- {
- elt_copy(rx, qx);
- elt_copy(ry, qy);
- return;
- }
+ if (a.IsZero())
+ return b;
+ if (b.IsZero())
+ return a;
- if (point_is_zero(q))
+ Elt u = a.X() + b.X();
+ if (u.IsZero())
{
- elt_copy(rx, px);
- elt_copy(ry, py);
- return;
+ u = a.Y() + b.Y();
+ if (u.IsZero())
+ return a.Double();
+ return Point{};
}
- elt_add(u, px, qx);
-
- if (elt_is_zero(u))
- {
- elt_add(u, py, qy);
- if (elt_is_zero(u))
- point_double(r, p);
- else
- {
- elt_zero(rx);
- elt_zero(ry);
- }
-
- return;
- }
+ const Elt s = (a.Y() + b.Y()) / u;
+ Elt t = s.Square() + s + b.X();
+ t.data[29] ^= 1;
- elt_inv(t, u);
- elt_add(u, py, qy);
- elt_mul(s, t, u);
-
- elt_square(t, s);
- elt_add(t, t, s);
- elt_add(t, t, qx);
- t[29] ^= 1;
-
- elt_mul(u, s, t);
- elt_add(s, u, py);
- elt_add(rx, t, px);
- elt_add(ry, s, rx);
+ const Elt rx = t + a.X();
+ const Elt ry = s * t + a.Y() + rx;
+ return Point{rx, ry};
}
-void point_mul(u8* d, const u8* a, const u8* b) // a is bignum
+static Point operator*(const u8* a, const Point& b)
{
- u32 i;
- u8 mask;
-
- elt_zero(d);
- elt_zero(d + 30);
-
- for (i = 0; i < 30; i++)
- for (mask = 0x80; mask != 0; mask >>= 1)
+ Point d;
+ for (std::size_t i = 0; i < 30; i++)
+ {
+ for (u8 mask = 0x80; mask != 0; mask >>= 1)
{
- point_double(d, d);
+ d = d.Double();
if ((a[i] & mask) != 0)
- point_add(d, d, b);
+ d = d + b;
}
+ }
+ return d;
}
static void silly_random(u8* rndArea, u8 count)
@@ -341,19 +241,13 @@ static void silly_random(u8* rndArea, u8 count)
}
}
-void generate_ecdsa(u8* R, u8* S, const u8* k, const u8* hash)
+std::array<u8, 60> Sign(const u8* key, const u8* hash)
{
- u8 e[30];
- u8 kk[30];
- u8 m[30];
- u8 minv[30];
- u8 mG[60];
- // FILE *fp;
-
- elt_zero(e);
+ u8 e[30]{};
memcpy(e + 10, hash, 20);
// Changing random number generator to a lame one...
+ u8 m[30];
silly_random(m, sizeof(m));
// fp = fopen("/dev/random", "rb");
// if (fread(m, sizeof m, 1, fp) != 1)
@@ -361,55 +255,65 @@ void generate_ecdsa(u8* R, u8* S, const u8* k, const u8* hash)
// fclose(fp);
m[0] = 0;
- // R = (mG).x
-
- point_mul(mG, m, ec_G);
- elt_copy(R, mG);
- if (bn_compare(R, ec_N, 30) >= 0)
- bn_sub_modulus(R, ec_N, 30);
+ Elt r = (m * ec_G).X();
+ if (bn_compare(r.data.data(), ec_N, 30) >= 0)
+ bn_sub_modulus(r.data.data(), ec_N, 30);
// S = m**-1*(e + Rk) (mod N)
- elt_copy(kk, k);
- if (bn_compare(kk, ec_N, 30) >= 0)
- bn_sub_modulus(kk, ec_N, 30);
- bn_mul(S, R, kk, ec_N, 30);
- bn_add(kk, S, e, ec_N, 30);
- bn_inv(minv, m, ec_N, 30);
- bn_mul(S, minv, kk, ec_N, 30);
+ u8 kk[30];
+ std::copy_n(key, sizeof(kk), kk);
+ if (bn_compare(kk, ec_N, sizeof(kk)) >= 0)
+ bn_sub_modulus(kk, ec_N, sizeof(kk));
+ Elt s;
+ bn_mul(s.data.data(), r.data.data(), kk, ec_N, 30);
+ bn_add(kk, s.data.data(), e, ec_N, sizeof(kk));
+ u8 minv[30];
+ bn_inv(minv, m, ec_N, sizeof(minv));
+ bn_mul(s.data.data(), minv, kk, ec_N, 30);
+
+ std::array<u8, 60> signature;
+ std::copy(r.data.cbegin(), r.data.cend(), signature.begin());
+ std::copy(s.data.cbegin(), s.data.cend(), signature.begin() + 30);
+ return signature;
}
UNUSED static int check_ecdsa(u8* Q, u8* R, u8* S, const u8* hash)
{
u8 Sinv[30];
- u8 e[30];
- u8 w1[30], w2[30];
- u8 r1[60], r2[60];
bn_inv(Sinv, S, ec_N, 30);
-
- elt_zero(e);
+ u8 e[30]{};
memcpy(e + 10, hash, 20);
+ u8 w1[30], w2[30];
bn_mul(w1, e, Sinv, ec_N, 30);
bn_mul(w2, R, Sinv, ec_N, 30);
- point_mul(r1, w1, ec_G);
- point_mul(r2, w2, Q);
-
- point_add(r1, r1, r2);
+ Point r1 = w1 * ec_G + w2 * Point{Q};
+ auto& rx = r1.X().data;
+ if (bn_compare(rx.data(), ec_N, 30) >= 0)
+ bn_sub_modulus(rx.data(), ec_N, 30);
- if (bn_compare(r1, ec_N, 30) >= 0)
- bn_sub_modulus(r1, ec_N, 30);
-
- return (bn_compare(r1, R, 30) == 0);
+ return (bn_compare(rx.data(), R, 30) == 0);
}
-void ec_priv_to_pub(const u8* k, u8* Q)
+std::array<u8, 60> PrivToPub(const u8* key)
{
- point_mul(Q, k, ec_G);
+ const Point data = key * ec_G;
+ std::array<u8, 60> result;
+ std::copy_n(data.Data(), result.size(), result.begin());
+ return result;
}
+std::array<u8, 60> ComputeSharedSecret(const u8* private_key, const u8* public_key)
+{
+ std::array<u8, 60> shared_secret;
+ const Point data = private_key * Point{public_key};
+ std::copy_n(data.Data(), shared_secret.size(), shared_secret.begin());
+ return shared_secret;
+}
#ifdef _MSC_VER
#pragma warning(pop)
#endif
+} // namespace Common::ec
diff --git a/Source/Core/Common/Crypto/ec.h b/Source/Core/Common/Crypto/ec.h
index 3bf8b9904f..18b0d48d98 100644
--- a/Source/Core/Common/Crypto/ec.h
+++ b/Source/Core/Common/Crypto/ec.h
@@ -4,10 +4,18 @@
#pragma once
+#include <array>
+
#include "Common/CommonTypes.h"
-void generate_ecdsa(u8* R, u8* S, const u8* k, const u8* hash);
+namespace Common::ec
+{
+/// Generate a signature using ECDSA.
+std::array<u8, 60> Sign(const u8* key, const u8* hash);
-void ec_priv_to_pub(const u8* k, u8* Q);
+/// Compute a shared secret from a private key (30 bytes) and public key (60 bytes).
+std::array<u8, 60> ComputeSharedSecret(const u8* private_key, const u8* public_key);
-void point_mul(u8* d, const u8* a, const u8* b);
+/// Convert a ECC private key (30 bytes) to a public key (60 bytes).
+std::array<u8, 60> PrivToPub(const u8* key);
+} // namespace Common::ec
diff --git a/Source/Core/Core/IOS/IOSC.cpp b/Source/Core/Core/IOS/IOSC.cpp
index 7f47421ca8..569568395d 100644
--- a/Source/Core/Core/IOS/IOSC.cpp
+++ b/Source/Core/Core/IOS/IOSC.cpp
@@ -250,8 +250,8 @@ ReturnCode IOSC::ComputeSharedKey(Handle dest_handle, Handle private_handle, Han
}
// Calculate the ECC shared secret.
- std::array<u8, 0x3c> shared_secret;
- point_mul(shared_secret.data(), private_entry->data.data(), public_entry->data.data());
+ const std::array<u8, 0x3c> shared_secret =
+ Common::ec::ComputeSharedSecret(private_entry->data.data(), public_entry->data.data());
std::array<u8, 20> sha1;
mbedtls_sha1(shared_secret.data(), shared_secret.size() / 2, sha1.data());
@@ -425,7 +425,8 @@ static Certificate MakeBlankSigECCert(const char* signer, const char* name, cons
std::strncpy(reinterpret_cast<char*>(cert_out.data()) + 0xc4, name, 0x40);
const u32 swapped_key_id = Common::swap32(key_id);
std::memcpy(cert_out.data() + 0x104, &swapped_key_id, sizeof(swapped_key_id));
- ec_priv_to_pub(private_key, cert_out.data() + 0x108);
+ const std::array<u8, 60> public_key = Common::ec::PrivToPub(private_key);
+ std::copy(public_key.cbegin(), public_key.cend(), cert_out.begin() + 0x108);
return cert_out;
}
@@ -454,11 +455,12 @@ void IOSC::Sign(u8* sig_out, u8* ap_cert_out, u64 title_id, const u8* data, u32
std::copy(cert.begin(), cert.end(), ap_cert_out);
mbedtls_sha1(ap_cert_out + 0x80, 0x100, hash.data());
- generate_ecdsa(ap_cert_out + 4, ap_cert_out + 34, m_key_entries[HANDLE_CONSOLE_KEY].data.data(),
- hash.data());
+ auto signature = Common::ec::Sign(m_key_entries[HANDLE_CONSOLE_KEY].data.data(), hash.data());
+ std::copy(signature.cbegin(), signature.cend(), ap_cert_out + 4);
mbedtls_sha1(data, data_size, hash.data());
- generate_ecdsa(sig_out, sig_out + 30, ap_priv.data(), hash.data());
+ signature = Common::ec::Sign(ap_priv.data(), hash.data());
+ std::copy(signature.cbegin(), signature.cend(), sig_out);
}
constexpr std::array<u8, 512> ROOT_PUBLIC_KEY = {