mirror of https://github.com/libAthena/athena.git
Restore certificate check with re-written ECC code
This commit is contained in:
parent
26407b49e2
commit
ba92629900
|
@ -1,3 +0,0 @@
|
||||||
[submodule "easy-ecc"]
|
|
||||||
path = extern/easy-ecc
|
|
||||||
url = https://github.com/libAthena/easy-ecc.git
|
|
|
@ -19,7 +19,7 @@ set(ATHENA_VERSION
|
||||||
|
|
||||||
add_subdirectory(extern)
|
add_subdirectory(extern)
|
||||||
|
|
||||||
include_directories(include ${LZO_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR} ${EASYECC_INCLUDE_DIR})
|
include_directories(include ${LZO_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR})
|
||||||
|
|
||||||
if (NOT MSVC)
|
if (NOT MSVC)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
|
||||||
|
@ -103,8 +103,8 @@ add_library(athena-wiisave EXCLUDE_FROM_ALL
|
||||||
src/athena/WiiSave.cpp
|
src/athena/WiiSave.cpp
|
||||||
src/athena/WiiSaveReader.cpp
|
src/athena/WiiSaveReader.cpp
|
||||||
src/athena/WiiSaveWriter.cpp
|
src/athena/WiiSaveWriter.cpp
|
||||||
# src/bn.cpp
|
src/bn.cpp
|
||||||
# src/ec.cpp
|
src/ec.cpp
|
||||||
src/md5.cpp
|
src/md5.cpp
|
||||||
src/sha1.cpp
|
src/sha1.cpp
|
||||||
src/aes.cpp
|
src/aes.cpp
|
||||||
|
@ -116,8 +116,8 @@ add_library(athena-wiisave EXCLUDE_FROM_ALL
|
||||||
include/athena/WiiSaveReader.hpp
|
include/athena/WiiSaveReader.hpp
|
||||||
include/athena/WiiSaveWriter.hpp
|
include/athena/WiiSaveWriter.hpp
|
||||||
include/aes.hpp
|
include/aes.hpp
|
||||||
# include/bn.h
|
include/bn.hpp
|
||||||
# include/ec.h
|
include/ec.hpp
|
||||||
include/md5.h
|
include/md5.h
|
||||||
include/sha1.h
|
include/sha1.h
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
add_subdirectory(lzo)
|
add_subdirectory(lzo)
|
||||||
add_subdirectory(zlib)
|
add_subdirectory(zlib)
|
||||||
add_subdirectory(yaml)
|
add_subdirectory(yaml)
|
||||||
add_subdirectory(easy-ecc)
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit da2748507cbe429d3e1be918c54cfba3be06d4b2
|
|
|
@ -21,7 +21,7 @@ namespace io
|
||||||
* all work is done using a memory buffer, and not read directly from the disk.
|
* all work is done using a memory buffer, and not read directly from the disk.
|
||||||
* \sa BinaryReader
|
* \sa BinaryReader
|
||||||
*/
|
*/
|
||||||
class WiiSaveReader : protected MemoryCopyReader
|
class WiiSaveReader : public MemoryCopyReader
|
||||||
{
|
{
|
||||||
MEMORYCOPYREADER_BASE();
|
MEMORYCOPYREADER_BASE();
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
#ifndef BN_H
|
||||||
|
#define BN_H
|
||||||
|
|
||||||
|
#include "athena/Types.hpp"
|
||||||
|
namespace bignum
|
||||||
|
{
|
||||||
|
int compare(const atUint8* a, const atUint8* b, atUint32 n);
|
||||||
|
void subModulus(atUint8* a, const atUint8* N, atUint32 n);
|
||||||
|
void add(atUint8* d, atUint8* a, const atUint8* b, const atUint8* N, atUint32 n);
|
||||||
|
void mul(atUint8* d, atUint8* a, const atUint8* b, const atUint8* N, atUint32 n);
|
||||||
|
void exp(atUint8* d, const atUint8* a, const atUint8* N, atUint32 n, atUint8* e, atUint32 en);
|
||||||
|
void inv(atUint8* d, atUint8* a, const atUint8* N, atUint32 n);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // BN_H
|
|
@ -0,0 +1,13 @@
|
||||||
|
#ifndef EC_H
|
||||||
|
#define EC_H
|
||||||
|
#include "athena/Types.hpp"
|
||||||
|
|
||||||
|
namespace ecc
|
||||||
|
{
|
||||||
|
void checkEC(atUint8* ng, atUint8* ap, atUint8* sig, atUint8* sigHash, bool& apValid, bool& ngValid);
|
||||||
|
void makeECCert(atUint8* cert, atUint8* sig, const char* signer, const char* name, atUint8* priv, atUint32 keyId);
|
||||||
|
void createECDSA(atUint8* R, atUint8* S, atUint8* k, atUint8* hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // EC_H
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include "athena/FileWriter.hpp"
|
#include "athena/FileWriter.hpp"
|
||||||
#include "md5.h"
|
#include "md5.h"
|
||||||
#include "aes.hpp"
|
#include "aes.hpp"
|
||||||
#include "ecc.h"
|
#include "ec.hpp"
|
||||||
#include "sha1.h"
|
#include "sha1.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
@ -294,7 +294,6 @@ WiiFile* WiiSaveReader::readFile()
|
||||||
|
|
||||||
void WiiSaveReader::readCerts(atUint32 totalSize)
|
void WiiSaveReader::readCerts(atUint32 totalSize)
|
||||||
{
|
{
|
||||||
#if 0
|
|
||||||
std::cout << "Reading certs..." << std::endl;
|
std::cout << "Reading certs..." << std::endl;
|
||||||
atUint32 dataSize = totalSize - 0x340;
|
atUint32 dataSize = totalSize - 0x340;
|
||||||
std::unique_ptr<atUint8[]> sig = base::readUBytes(0x40);
|
std::unique_ptr<atUint8[]> sig = base::readUBytes(0x40);
|
||||||
|
@ -307,22 +306,14 @@ void WiiSaveReader::readCerts(atUint32 totalSize)
|
||||||
std::cout << "validating..." << std::endl;
|
std::cout << "validating..." << std::endl;
|
||||||
hash = getSha1(data.get(), dataSize);
|
hash = getSha1(data.get(), dataSize);
|
||||||
atUint8* hash2 = getSha1(hash, 20);
|
atUint8* hash2 = getSha1(hash, 20);
|
||||||
bool failed = false;
|
bool ngValid = false;
|
||||||
|
bool apValid = false;
|
||||||
|
ecc::checkEC(ngCert.get(), apCert.get(), sig.get(), hash2, apValid, ngValid);
|
||||||
|
|
||||||
if (!ecdsa_verify(ngCert.get(), hash, sig.get()))
|
if (apValid)
|
||||||
{
|
std::cout << "AP Certificate ok" << std::endl;
|
||||||
std::cout << "NGCert failure" << std::endl;
|
if (ngValid)
|
||||||
failed = true;
|
std::cout << "NG Certificate ok" << std::endl;
|
||||||
}
|
|
||||||
if (!ecdsa_verify(apCert.get(), hash2, sig.get()))
|
|
||||||
{
|
|
||||||
std::cout << "APCert failure" << std::endl;
|
|
||||||
failed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!failed)
|
|
||||||
std::cout << "certificates ok" << std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WiiFile* WiiSaveReader::buildTree(std::vector<WiiFile*> files)
|
WiiFile* WiiSaveReader::buildTree(std::vector<WiiFile*> files)
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#include "athena/Utility.hpp"
|
#include "athena/Utility.hpp"
|
||||||
|
|
||||||
#include "aes.hpp"
|
#include "aes.hpp"
|
||||||
#include "ecc.h"
|
#include "ec.hpp"
|
||||||
#include "md5.h"
|
#include "md5.h"
|
||||||
#include "sha1.h"
|
#include "sha1.h"
|
||||||
|
|
||||||
|
@ -194,7 +194,6 @@ void WiiSaveWriter::writeImage(WiiImage* image)
|
||||||
|
|
||||||
void WiiSaveWriter::writeCerts(atUint32 filesSize, atUint32 ngId, atUint8* ngPriv, atUint8* ngSig, atUint32 ngKeyId)
|
void WiiSaveWriter::writeCerts(atUint32 filesSize, atUint32 ngId, atUint8* ngPriv, atUint8* ngSig, atUint32 ngKeyId)
|
||||||
{
|
{
|
||||||
#if 0
|
|
||||||
atUint8 sig[0x40];
|
atUint8 sig[0x40];
|
||||||
atUint8 ngCert[0x180];
|
atUint8 ngCert[0x180];
|
||||||
atUint8 apCert[0x180];
|
atUint8 apCert[0x180];
|
||||||
|
@ -208,7 +207,7 @@ void WiiSaveWriter::writeCerts(atUint32 filesSize, atUint32 ngId, atUint8* ngPri
|
||||||
|
|
||||||
sprintf(signer, "Root-CA00000001-MS00000002");
|
sprintf(signer, "Root-CA00000001-MS00000002");
|
||||||
sprintf(name, "NG%08x", ngId);
|
sprintf(name, "NG%08x", ngId);
|
||||||
make_ec_cert(ngCert, ngSig, signer, name, ngPriv, ngKeyId);
|
ecc::makeECCert(ngCert, ngSig, signer, name, ngPriv, ngKeyId);
|
||||||
|
|
||||||
memset(apPriv, 0, 30);
|
memset(apPriv, 0, 30);
|
||||||
apPriv[10] = 1;
|
apPriv[10] = 1;
|
||||||
|
@ -217,11 +216,11 @@ void WiiSaveWriter::writeCerts(atUint32 filesSize, atUint32 ngId, atUint8* ngPri
|
||||||
|
|
||||||
sprintf(signer, "Root-CA00000001-MS00000002-NG%08x", ngId);
|
sprintf(signer, "Root-CA00000001-MS00000002-NG%08x", ngId);
|
||||||
sprintf(name, "AP%08x%08x", 1, 2);
|
sprintf(name, "AP%08x%08x", 1, 2);
|
||||||
make_ec_cert(apCert, apSig, signer, name, apPriv, 0);
|
ecc::makeECCert(apCert, apSig, signer, name, apPriv, 0);
|
||||||
|
|
||||||
hash = getSha1(apCert + 0x80, 0x100);
|
hash = getSha1(apCert + 0x80, 0x100);
|
||||||
generate_ecdsa(apSig, apSig + 30, ngPriv, hash);
|
ecc::createECDSA(apSig, apSig + 30, ngPriv, hash);
|
||||||
make_ec_cert(apCert, apSig, signer, name, apPriv, 0);
|
ecc::makeECCert(apCert, apSig, signer, name, apPriv, 0);
|
||||||
delete[] hash;
|
delete[] hash;
|
||||||
|
|
||||||
dataSize = filesSize + 0x80;
|
dataSize = filesSize + 0x80;
|
||||||
|
@ -234,7 +233,7 @@ void WiiSaveWriter::writeCerts(atUint32 filesSize, atUint32 ngId, atUint8* ngPri
|
||||||
delete[] hash;
|
delete[] hash;
|
||||||
delete[] data;
|
delete[] data;
|
||||||
|
|
||||||
generate_ecdsa(sig, sig + 30, apPriv, hash2);
|
ecc::createECDSA(sig, sig + 30, apPriv, hash2);
|
||||||
int stuff = 0x2f536969;
|
int stuff = 0x2f536969;
|
||||||
|
|
||||||
if (!utility::isSystemBigEndian())
|
if (!utility::isSystemBigEndian())
|
||||||
|
@ -246,7 +245,6 @@ void WiiSaveWriter::writeCerts(atUint32 filesSize, atUint32 ngId, atUint8* ngPri
|
||||||
base::writeBytes((atInt8*)sig, 0x40);
|
base::writeBytes((atInt8*)sig, 0x40);
|
||||||
base::writeBytes((atInt8*)ngCert, 0x180);
|
base::writeBytes((atInt8*)ngCert, 0x180);
|
||||||
base::writeBytes((atInt8*)apCert, 0x180);
|
base::writeBytes((atInt8*)apCert, 0x180);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // io
|
} // io
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "bn.hpp"
|
||||||
|
|
||||||
|
namespace bignum
|
||||||
|
{
|
||||||
|
|
||||||
|
void subModulus(atUint8* a, const atUint8* N, atUint32 n)
|
||||||
|
{
|
||||||
|
atUint8 c = 0;
|
||||||
|
|
||||||
|
for (atUint32 i = n - 1; i < n; i--)
|
||||||
|
{
|
||||||
|
atUint32 dig = N[i] + c;
|
||||||
|
c = (a[i] < dig);
|
||||||
|
a[i] -= dig;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(atUint8* d, atUint8* a, const atUint8* b, const atUint8* N, atUint32 n)
|
||||||
|
{
|
||||||
|
atUint8 c = 0;
|
||||||
|
|
||||||
|
for (atUint32 i = n - 1; i < n; i--)
|
||||||
|
{
|
||||||
|
atUint32 dig = a[i] + b[i] + c;
|
||||||
|
c = (dig >= 0x100);
|
||||||
|
d[i] = dig;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c)
|
||||||
|
subModulus(d, N, n);
|
||||||
|
|
||||||
|
if (compare(d, N, n) >= 0)
|
||||||
|
subModulus(d, N, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mul(atUint8* d, atUint8* a, const atUint8* b, const atUint8* N, atUint32 n)
|
||||||
|
{
|
||||||
|
memset(d, 0, n);
|
||||||
|
|
||||||
|
for (atUint32 i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
for (atUint8 mask = 0x80; mask != 0; mask >>= 1)
|
||||||
|
{
|
||||||
|
add(d, d, d, N, n);
|
||||||
|
|
||||||
|
if ((a[i] & mask) != 0)
|
||||||
|
add(d, d, b, N, n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void exp(atUint8* d, const atUint8* a, const atUint8* N, atUint32 n, atUint8* e, atUint32 en)
|
||||||
|
{
|
||||||
|
atUint8 t[512];
|
||||||
|
memset(d, 0, n);
|
||||||
|
d[n - 1] = 1;
|
||||||
|
|
||||||
|
for (atUint32 i = 0; i < en; i++)
|
||||||
|
{
|
||||||
|
for (atUint8 mask = 0x80; mask != 0; mask >>= 1)
|
||||||
|
{
|
||||||
|
mul(t, d, d, N, n);
|
||||||
|
|
||||||
|
if ((e[i] & mask) != 0)
|
||||||
|
mul(d, t, a, N, n);
|
||||||
|
else
|
||||||
|
memcpy(d, t, n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void inv(atUint8* d, atUint8* a, const atUint8* N, atUint32 n)
|
||||||
|
{
|
||||||
|
atUint8 t[512], s[512];
|
||||||
|
|
||||||
|
memcpy(t, N, n);
|
||||||
|
memset(s, 0, n);
|
||||||
|
s[n - 1] = 2;
|
||||||
|
subModulus(t, s, n);
|
||||||
|
exp(d, a, N, n, t, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
int compare(const atUint8* a, const atUint8* b, atUint32 n)
|
||||||
|
{
|
||||||
|
for (atUint32 i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
if (a[i] < b[i])
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (a[i] > b[i])
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,320 @@
|
||||||
|
#include <string.h>
|
||||||
|
#include "athena/Utility.hpp"
|
||||||
|
|
||||||
|
#include "bn.hpp"
|
||||||
|
#include "ec.hpp"
|
||||||
|
#include "sha1.h"
|
||||||
|
|
||||||
|
namespace ecc
|
||||||
|
{
|
||||||
|
static int checkZero(const atUint8* d) { return !memcmp(d, d + 1, 29) && d[0] == 0; }
|
||||||
|
|
||||||
|
static void add(atUint8* d, const atUint8* a, const atUint8* b)
|
||||||
|
{
|
||||||
|
for (atUint32 i = 0; i < 30; i++)
|
||||||
|
d[i] = a[i] ^ b[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void multiply(atUint8* d, const atUint8* a, const atUint8* b)
|
||||||
|
{
|
||||||
|
memset(d, 0, 30);
|
||||||
|
for (atUint32 n = 0, i = 0, mask = 1; n < 233; n++)
|
||||||
|
{
|
||||||
|
atUint8 x, y;
|
||||||
|
atUint8 carry = d[0] & 1;
|
||||||
|
x = 0;
|
||||||
|
for (atUint32 i = 0; i < 29; i++)
|
||||||
|
{
|
||||||
|
y = d[i + 1];
|
||||||
|
d[i] = x ^ (y >> 7);
|
||||||
|
x = y << 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
d[29] = x ^ carry;
|
||||||
|
d[20] ^= carry << 2;
|
||||||
|
if ((a[i] & mask) != 0)
|
||||||
|
add(d, d, b);
|
||||||
|
|
||||||
|
mask >>= 1;
|
||||||
|
if (mask == 0)
|
||||||
|
{
|
||||||
|
mask = 0x80;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void squareToWide(atUint8* d, const atUint8* a)
|
||||||
|
{
|
||||||
|
static const atUint8 sq[16] = {0x00, 0x01, 0x04, 0x05, 0x10, 0x11, 0x14, 0x15,
|
||||||
|
0x40, 0x41, 0x44, 0x45, 0x50, 0x51, 0x54, 0x55};
|
||||||
|
for (atUint32 i = 0; i < 30; i++)
|
||||||
|
{
|
||||||
|
d[2 * i] = sq[a[i] >> 4];
|
||||||
|
d[2 * i + 1] = sq[a[i] & 15];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wideReduce(atUint8* d)
|
||||||
|
{
|
||||||
|
atUint32 i;
|
||||||
|
atUint8 x;
|
||||||
|
|
||||||
|
for (i = 0; i < 30; i++)
|
||||||
|
{
|
||||||
|
x = d[i];
|
||||||
|
|
||||||
|
d[i + 19] ^= x >> 7;
|
||||||
|
d[i + 20] ^= x << 1;
|
||||||
|
d[i + 29] ^= x >> 1;
|
||||||
|
d[i + 30] ^= x << 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
x = d[30] & ~1;
|
||||||
|
d[49] ^= x >> 7;
|
||||||
|
d[50] ^= x << 1;
|
||||||
|
d[59] ^= x >> 1;
|
||||||
|
d[30] &= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void square(atUint8* d, const atUint8* a)
|
||||||
|
{
|
||||||
|
atUint8 wide[60];
|
||||||
|
|
||||||
|
squareToWide(wide, a);
|
||||||
|
wideReduce(wide);
|
||||||
|
|
||||||
|
memcpy(d, wide + 30, 30);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void itInvert(atUint8* d, const atUint8* a, const atUint8* b, atUint32 j)
|
||||||
|
{
|
||||||
|
atUint8 t[30];
|
||||||
|
memcpy(t, a, 32);
|
||||||
|
while (j--)
|
||||||
|
{
|
||||||
|
square(d, t);
|
||||||
|
memcpy(t, d, 30);
|
||||||
|
}
|
||||||
|
multiply(d, t, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void invert(atUint8* d, const atUint8* a)
|
||||||
|
{
|
||||||
|
atUint8 t[30];
|
||||||
|
atUint8 s[30];
|
||||||
|
|
||||||
|
itInvert(t, a, a, 1);
|
||||||
|
itInvert(s, t, a, 1);
|
||||||
|
itInvert(t, s, s, 3);
|
||||||
|
itInvert(s, t, a, 1);
|
||||||
|
itInvert(t, s, s, 7);
|
||||||
|
itInvert(s, t, t, 14);
|
||||||
|
itInvert(t, s, a, 1);
|
||||||
|
itInvert(s, t, t, 29);
|
||||||
|
itInvert(t, s, s, 58);
|
||||||
|
itInvert(s, t, t, 116);
|
||||||
|
square(d, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pointDouble(atUint8* r, const atUint8* p)
|
||||||
|
{
|
||||||
|
atUint8 s[30], t[30];
|
||||||
|
const atUint8* px = p;
|
||||||
|
const atUint8* py = p + 30;
|
||||||
|
atUint8* rx = r;
|
||||||
|
atUint8* ry = r + 30;
|
||||||
|
|
||||||
|
if (checkZero(px))
|
||||||
|
{
|
||||||
|
memset(rx, 0, 30);
|
||||||
|
memset(ry, 0, 30);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
invert(t, px);
|
||||||
|
multiply(s, py, t);
|
||||||
|
add(s, s, px);
|
||||||
|
|
||||||
|
square(t, px);
|
||||||
|
|
||||||
|
square(rx, s);
|
||||||
|
add(rx, rx, s);
|
||||||
|
rx[29] ^= 1;
|
||||||
|
|
||||||
|
multiply(ry, s, rx);
|
||||||
|
add(ry, ry, rx);
|
||||||
|
add(ry, ry, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pointAdd(atUint8* r, const atUint8* p, const atUint8* q)
|
||||||
|
{
|
||||||
|
atUint8 s[30], t[30], u[30];
|
||||||
|
const atUint8* px = p;
|
||||||
|
const atUint8* py = p + 30;
|
||||||
|
const atUint8* qx = q;
|
||||||
|
const atUint8* qy = q + 30;
|
||||||
|
atUint8* rx = r;
|
||||||
|
atUint8* ry = r + 30;
|
||||||
|
|
||||||
|
if (checkZero(p) && checkZero(p + 30))
|
||||||
|
{
|
||||||
|
memcpy(rx, qx, 30);
|
||||||
|
memcpy(ry, qy, 30);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checkZero(p) && checkZero(p + 30))
|
||||||
|
{
|
||||||
|
memcpy(rx, px, 30);
|
||||||
|
memcpy(ry, py, 30);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
add(u, px, qx);
|
||||||
|
|
||||||
|
if (checkZero(u))
|
||||||
|
{
|
||||||
|
add(u, py, qy);
|
||||||
|
|
||||||
|
if (checkZero(u))
|
||||||
|
pointDouble(r, p);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memset(rx, 0, 30);
|
||||||
|
memset(ry, 0, 30);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
invert(t, u);
|
||||||
|
add(u, py, qy);
|
||||||
|
multiply(s, t, u);
|
||||||
|
|
||||||
|
square(t, s);
|
||||||
|
add(t, t, s);
|
||||||
|
add(t, t, qx);
|
||||||
|
t[29] ^= 1;
|
||||||
|
|
||||||
|
multiply(u, s, t);
|
||||||
|
add(s, u, py);
|
||||||
|
add(rx, t, px);
|
||||||
|
add(ry, s, rx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pointMultiply(atUint8* d, const atUint8* a, const atUint8* b)
|
||||||
|
{
|
||||||
|
memset(d, 0, 30);
|
||||||
|
memset(d + 30, 0, 30);
|
||||||
|
for (atUint32 i = 0; i < 30; i++)
|
||||||
|
{
|
||||||
|
for (atUint8 mask = 0x80; mask != 0; mask >>= 1)
|
||||||
|
{
|
||||||
|
pointDouble(d, d);
|
||||||
|
|
||||||
|
if ((a[i] & mask) != 0)
|
||||||
|
pointAdd(d, d, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const atUint8 ecG[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 const atUint8 ecN[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};
|
||||||
|
|
||||||
|
bool checkECDSA(atUint8* Q, atUint8* R, atUint8* S, atUint8* hash)
|
||||||
|
{
|
||||||
|
atUint8 Sinv[30];
|
||||||
|
atUint8 e[30];
|
||||||
|
atUint8 w1[30], w2[30];
|
||||||
|
atUint8 r1[60], r2[60];
|
||||||
|
|
||||||
|
bignum::inv(Sinv, S, ecN, 30);
|
||||||
|
|
||||||
|
memset(e, 0, 30);
|
||||||
|
memcpy(e + 10, hash, 20);
|
||||||
|
|
||||||
|
bignum::mul(w1, e, Sinv, ecN, 30);
|
||||||
|
bignum::mul(w2, R, Sinv, ecN, 30);
|
||||||
|
|
||||||
|
pointMultiply(r1, w1, ecG);
|
||||||
|
pointMultiply(r2, w2, Q);
|
||||||
|
|
||||||
|
pointAdd(r1, r1, r2);
|
||||||
|
|
||||||
|
if (bignum::compare(r1, ecN, 30) >= 0)
|
||||||
|
bignum::subModulus(r1, ecN, 30);
|
||||||
|
|
||||||
|
return (bignum::compare(r1, R, 30) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void makeECCert(atUint8* cert, atUint8* sig, const char* signer, const char* name, atUint8* priv, atUint32 keyId)
|
||||||
|
{
|
||||||
|
memset(cert, 0, 0x180);
|
||||||
|
*(atUint32*)(cert) = 0x10002;
|
||||||
|
|
||||||
|
if (!athena::utility::isSystemBigEndian())
|
||||||
|
*(atUint32*)(cert) = athena::utility::swapU32(*(atUint32*)(cert));
|
||||||
|
|
||||||
|
memcpy((char*)cert + 4, sig, 60);
|
||||||
|
strcpy((char*)cert + 0x80, signer);
|
||||||
|
*(atUint32*)(cert + 0xc0) = 2;
|
||||||
|
|
||||||
|
if (!athena::utility::isSystemBigEndian())
|
||||||
|
*(atUint32*)(cert + 0xc0) = athena::utility::swapU32(*(atUint32*)(cert + 0xc0));
|
||||||
|
|
||||||
|
strcpy((char*)cert + 0xc4, name);
|
||||||
|
*(atUint32*)(cert + 0x104) = keyId;
|
||||||
|
|
||||||
|
if (!athena::utility::isSystemBigEndian())
|
||||||
|
*(atUint32*)(cert + 0x104) = athena::utility::swapU32(*(atUint32*)(cert + 0x104));
|
||||||
|
|
||||||
|
pointMultiply(cert + 0x108, priv, ecG);
|
||||||
|
}
|
||||||
|
|
||||||
|
void createECDSA(atUint8* R, atUint8* S, atUint8* k, atUint8* hash)
|
||||||
|
{
|
||||||
|
atUint8 e[30];
|
||||||
|
atUint8 kk[30];
|
||||||
|
atUint8 m[30];
|
||||||
|
atUint8 minv[30];
|
||||||
|
atUint8 mG[60];
|
||||||
|
|
||||||
|
memset(e, 0, 30);
|
||||||
|
memcpy(e + 10, hash, 20);
|
||||||
|
|
||||||
|
athena::utility::fillRandom(m, sizeof(m));
|
||||||
|
m[0] = 0;
|
||||||
|
|
||||||
|
pointMultiply(mG, m, ecG);
|
||||||
|
memcpy(R, mG, 30);
|
||||||
|
|
||||||
|
if (bignum::compare(R, ecN, 30) >= 0)
|
||||||
|
bignum::subModulus(R, ecN, 30);
|
||||||
|
|
||||||
|
memcpy(kk, k, 30);
|
||||||
|
|
||||||
|
if (bignum::compare(kk, ecN, 30) >= 0)
|
||||||
|
bignum::subModulus(kk, ecN, 30);
|
||||||
|
|
||||||
|
bignum::mul(S, R, kk, ecN, 30);
|
||||||
|
bignum::add(kk, S, e, ecN, 30);
|
||||||
|
bignum::inv(minv, m, ecN, 30);
|
||||||
|
bignum::mul(S, minv, kk, ecN, 30);
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkEC(atUint8* ng, atUint8* ap, atUint8* sig, atUint8* sigHash, bool& apValid, bool& ngValid)
|
||||||
|
{
|
||||||
|
atUint8* apHash = getSha1(ap + 0x80, 0x100);
|
||||||
|
ngValid = checkECDSA(ng + 0x0108, ap + 0x04, ap + 0x22, apHash);
|
||||||
|
apValid = checkECDSA(ap + 0x0108, sig, sig + 30, sigHash);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue