From 99dcef42f1266b1a6db49d41392f327866413c51 Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Wed, 29 Jun 2016 17:37:34 -0700 Subject: [PATCH] Remove EC and BN code in preparation due to licensing issues --- CMakeLists.txt | 8 +- Doxyfile | 2 +- include/athena/DNAYaml.hpp | 4 +- include/athena/IStreamReader.hpp | 34 ++- include/athena/IStreamWriter.hpp | 11 +- include/athena/MemoryWriter.hpp | 86 +++--- include/athena/Types.hpp | 57 +--- include/bn.h | 15 - include/ec.h | 10 - src/athena/MemoryWriter.cpp | 4 +- src/athena/WiiSaveReader.cpp | 3 +- src/athena/WiiSaveWriter.cpp | 2 + src/bn.cpp | 122 --------- src/ec.cpp | 451 ------------------------------- 14 files changed, 105 insertions(+), 704 deletions(-) delete mode 100644 include/bn.h delete mode 100644 include/ec.h delete mode 100644 src/bn.cpp delete mode 100644 src/ec.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index b9609e7..0f442c6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -100,8 +100,8 @@ add_library(athena-wiisave EXCLUDE_FROM_ALL src/athena/WiiSave.cpp src/athena/WiiSaveReader.cpp src/athena/WiiSaveWriter.cpp - src/bn.cpp - src/ec.cpp +# src/bn.cpp +# src/ec.cpp src/md5.cpp src/sha1.cpp src/aes.cpp @@ -113,8 +113,8 @@ add_library(athena-wiisave EXCLUDE_FROM_ALL include/athena/WiiSaveReader.hpp include/athena/WiiSaveWriter.hpp include/aes.hpp - include/bn.h - include/ec.h +# include/bn.h +# include/ec.h include/md5.h include/sha1.h ) diff --git a/Doxyfile b/Doxyfile index 1adc300..18bc731 100644 --- a/Doxyfile +++ b/Doxyfile @@ -768,7 +768,7 @@ WARN_LOGFILE = # spaces. # Note: If this tag is empty the current directory is searched. -INPUT = include/Athena +INPUT = include/athena # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses diff --git a/include/athena/DNAYaml.hpp b/include/athena/DNAYaml.hpp index ae24d69..7aef95e 100644 --- a/include/athena/DNAYaml.hpp +++ b/include/athena/DNAYaml.hpp @@ -195,7 +195,7 @@ template <> inline std::unique_ptr ValToNode(const atInt64& val) { char str[32]; - snprintf(str, 32, "0x%016llX", val); + snprintf(str, 32, "0x%016" PRIX64, val); YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE); ret->m_scalarString = str; return std::unique_ptr(ret); @@ -215,7 +215,7 @@ template <> inline std::unique_ptr ValToNode(const atUint64& val) { char str[32]; - snprintf(str, 32, "0x%016llX", val); + snprintf(str, 32, "0x%016" PRIX64, val); YAMLNode* ret = new YAMLNode(YAML_SCALAR_NODE); ret->m_scalarString = str; return std::unique_ptr(ret); diff --git a/include/athena/IStreamReader.hpp b/include/athena/IStreamReader.hpp index d8d9dae..b05f387 100644 --- a/include/athena/IStreamReader.hpp +++ b/include/athena/IStreamReader.hpp @@ -10,6 +10,11 @@ namespace athena { namespace io { +/** @brief The IStreamReader class defines a basic API for reading from streams, Implementors are provided with one pure virtual + * function that must be implemented in order to interact with the stream. + * + * Most implementing classes will only need to implement IStreamReader::readUBytesToBuf(void*, atUint64) for basic stream intearaction + */ class IStreamReader : public IStream { public: @@ -26,7 +31,7 @@ public: * * @return The current Stream Endianness */ - inline Endian endian() const + inline Endian endian() const {return m_endian;} /** @brief Returns whether the stream is BigEndian @@ -51,10 +56,18 @@ public: */ virtual void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current)=0; + /** @brief Sets the buffer's position relative to the next 64-byte aligned position.
+ */ + inline void seekAlign64() {seek(ROUND_UP_64(position()), SeekOrigin::Begin);} + /** @brief Sets the buffers position relative to the next 32-byte aligned position.
*/ inline void seekAlign32() {seek(ROUND_UP_32(position()), SeekOrigin::Begin);} + /** @brief Sets the buffer's position relative to the next 16-byte aligned position.
+ */ + inline void seekAlign16() {seek(ROUND_UP_16(position()), SeekOrigin::Begin); } + /** @brief Returns whether or not the stream is at the end. * * @return True if at end; False otherwise. @@ -68,9 +81,9 @@ public: */ virtual atUint64 position() const=0; - /** @brief Returns whether or not the stream is at the end. + /** @brief Returns the length of the file. * - * @return True if at end; False otherwise. + * @return True length of the file. */ virtual atUint64 length() const=0; @@ -117,7 +130,7 @@ public: /** @brief Reads a byte at the current position and advances the current position. * - * @return The buffer at the current position from the given length. + * @return The buffer at the current position from the given length. */ inline std::unique_ptr readUBytes(atUint64 length) { @@ -126,7 +139,20 @@ public: return std::unique_ptr(buf); } + /** @brief Attempts to read a fixed length of data into a pre-allocated buffer. + * @param buf The buffer to read into + * @param len The length of the buffer + * @return How much data was actually read, useful for detecting read errors. + */ inline atUint64 readBytesToBuf(void* buf, atUint64 len) {return readUBytesToBuf(buf, len);} + + + /** @brief Attempts to read a fixed length of data into a pre-allocated buffer, this function is client defined + * and must be implemented. + * @param buf The buffer to read into + * @param len The length of the buffer + * @return How much data was actually read, useful for detecting read errors. + */ virtual atUint64 readUBytesToBuf(void* buf, atUint64 len)=0; /** @brief Reads a Int16 and swaps to endianness specified by setEndian depending on platform diff --git a/include/athena/IStreamWriter.hpp b/include/athena/IStreamWriter.hpp index 579b551..137f173 100644 --- a/include/athena/IStreamWriter.hpp +++ b/include/athena/IStreamWriter.hpp @@ -3,6 +3,7 @@ #include "utf8proc.h" #include "IStream.hpp" +#include namespace athena { @@ -1032,7 +1033,15 @@ public: inline void writeValBig(const std::wstring& val) {writeWStringBig(val);} inline void fill(atUint8 val, atUint64 length) - {for (atUint64 l=0 ; l tmp(new atUint8[length]); + memset(tmp.get(), val, length); + writeUBytes(tmp.get(), length); + } + inline void fill(atInt8 val, atUint64 length) {fill((atUint8)val, length);} diff --git a/include/athena/MemoryWriter.hpp b/include/athena/MemoryWriter.hpp index 2ad2c2a..0ae1e62 100644 --- a/include/athena/MemoryWriter.hpp +++ b/include/athena/MemoryWriter.hpp @@ -11,13 +11,13 @@ namespace athena namespace io { -/*! \class MemoryWriter - * \brief A Stream class for writing data to a memory position +/*! @class MemoryWriter + * @brief A Stream class for writing data to a memory position * * A Class for writing binary data to a file or memory stream, * all work is done using a memory buffer, and not written directly to the disk * this allows for fast, flexible code as well as the ability to quickly modify data - * \sa Stream + * @sa Stream */ class MemoryWriter : public IStreamWriter { @@ -25,78 +25,78 @@ public: virtual ~MemoryWriter(); - /*! \brief This constructor references an existing buffer to write to in-place. + /*! @brief This constructor references an existing buffer to write to in-place. * - * \param data The existing buffer - * \param length The length of the existing buffer + * @param data The existing buffer + * @param length The length of the existing buffer */ explicit MemoryWriter(atUint8* data, atUint64 length, bool takeOwnership = false); - /*! \brief Sets the buffers position relative to the specified position.
+ /*! @brief Sets the buffers position relative to the specified position.
* It seeks relative to the current position by default. - * \param position where in the buffer to seek - * \param origin The Origin to seek \sa SeekOrigin + * @param position where in the buffer to seek + * @param origin The Origin to seek @sa SeekOrigin */ void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current); - /*! \brief Returns the current position in the stream. + /*! @brief Returns the current position in the stream. * - * \return Int64 The current position in the stream. + * @return Int64 The current position in the stream. */ inline atUint64 position() const {return m_position;} - /*! \brief Returns whether or not the stream is at the end. + /*! @brief Returns whether or not the stream is at the end. * - * \return bool True if at end; False otherwise. + * @return bool True if at end; False otherwise. */ inline atUint64 length() const {return m_length;} inline bool isOpen() const {return true;} - /*! \brief Sets the buffer to the given one, deleting the current one if it owns it.
- * \param data The new buffer. - * \param length The length of the new buffer. - * \param takeOwnership Whether the Stream now owns the buffer. - * \throw IOException + /** @brief Sets the buffer to the given one, deleting the current one if it owns it.
+ * @param data The new buffer. + * @param length The length of the new buffer. + * @param takeOwnership Whether the Stream now owns the buffer. */ void setData(atUint8* data, atUint64 length, bool takeOwnership = false); - /*! \brief Returns a copy of the current buffer.
+ /*! @brief Returns a copy of the current buffer.
* Changes to the copy do not affect the buffer so it's perfectly safe to * directly edit the buffer and use setData to set the new information.
- * \return Uint8* The copy of the buffer. + * @return Uint8* The copy of the buffer. */ atUint8* data() const; - /*! \brief Sets the target file + /*! @brief Sets the target file * - * \param filepath The path to write to. + * @param filepath The path to write to. */ inline void setFilepath(const std::string& filepath) {m_filepath = filepath;} - /*! \brief + /*! @brief * Returns the target file */ inline std::string filepath() const {return m_filepath;} - /*! \brief Saves the file to the specified file. + /*! @brief Saves the file to the specified file. * - * \param filename If not empty, the filename to save to + * @param filename If not empty, the filename to save to */ void save(const std::string& filename = ""); - /*! \brief Writes the given buffer with the specified length, buffers can be bigger than the length + /*! @brief Writes the given buffer with the specified length, buffers can be bigger than the length * however it's undefined behavior to try and write a buffer which is smaller than the given length. + * If you are needing to fill in an area please use IStreamWriter::fill(atUint64) instead. * - * \param data The buffer to write - * \param length The amount to write + * @param data The buffer to write + * @param length The amount to write */ void writeUBytes(const atUint8* data, atUint64 len); @@ -113,42 +113,42 @@ class MemoryCopyWriter : public MemoryWriter { public: - /*! \brief This constructor copies an existing buffer to write to. + /*! @brief This constructor copies an existing buffer to write to. * - * \param data The existing buffer - * \param length The length of the existing buffer + * @param data The existing buffer + * @param length The length of the existing buffer */ explicit MemoryCopyWriter(atUint8* data=nullptr, atUint64 length=0x10); - /*! \brief This constructor creates an instance from a file on disk. + /*! @brief This constructor creates an instance from a file on disk. * - * \param filename The file to create the stream from + * @param filename The file to create the stream from */ MemoryCopyWriter(const std::string& filename); - /*! \brief Sets the buffers position relative to the specified position.
+ /*! @brief Sets the buffers position relative to the specified position.
* It seeks relative to the current position by default. - * \param position where in the buffer to seek - * \param origin The Origin to seek \sa SeekOrigin + * @param position where in the buffer to seek + * @param origin The Origin to seek @sa SeekOrigin */ void seek(atInt64 pos, SeekOrigin origin = SeekOrigin::Current); - /*! \brief Sets the buffer to the given one, deleting the current one.
+ /*! @brief Sets the buffer to the given one, deleting the current one.
* BEWARE: As this deletes the current buffer it WILL cause a loss of data * if that was not the intent.
* Once you pass the data to setData DO NOT delete the buffer * as Stream now owns the address, this is done to keep memory usage down. - * \param data The new buffer. - * \param length The length of the new buffer. - * \throw IOException + * @param data The new buffer. + * @param length The length of the new buffer. + * @throw IOException */ void setData(const atUint8* data, atUint64 length); - /*! \brief Writes the given buffer with the specified length, buffers can be bigger than the length + /*! @brief Writes the given buffer with the specified length, buffers can be bigger than the length * however it's undefined behavior to try and write a buffer which is smaller than the given length. * - * \param data The buffer to write - * \param length The amount to write + * @param data The buffer to write + * @param length The amount to write */ void writeUBytes(const atUint8* data, atUint64 len); diff --git a/include/athena/Types.hpp b/include/athena/Types.hpp index bc6454d..4398c84 100644 --- a/include/athena/Types.hpp +++ b/include/athena/Types.hpp @@ -1,45 +1,15 @@ #ifndef TYPES_HPP #define TYPES_HPP -#include +#include -// 8 bits integer types -#if UCHAR_MAX == 0xFF -typedef signed char atInt8; -typedef unsigned char atUint8; -#else -#error No 8 bits integer type for this platform -#endif - -// 16 bits integer types -#if USHRT_MAX == 0xFFFF -typedef signed short atInt16; -typedef unsigned short atUint16; -#elif UINT_MAX == 0xFFFF -typedef signed int atInt16; -typedef unsigned int atUint16; -#elif ULONG_MAX == 0xFFFF -typedef signed long atInt16; -typedef unsigned long atUint16; -#else -#error No 16 bits integer type for this platform -#endif - -// 32 bits integer types -#if USHRT_MAX == 0xFFFFFFFF -typedef signed short atInt32; -typedef unsigned short atUint32; -#elif UINT_MAX == 0xFFFFFFFF -typedef signed int atInt32; -typedef unsigned int atUint32; -#elif ULONG_MAX == 0xFFFFFFFF -typedef signed long atInt32; -typedef unsigned long atUint32; -#else -#error No 32 bits integer type for this platform -#endif - -typedef signed long long atInt64; -typedef unsigned long long atUint64; +using atInt8 = int8_t; +using atUint8 = uint8_t; +using atInt16 = int16_t; +using atUint16 = uint16_t; +using atInt32 = int32_t; +using atUint32 = uint32_t; +using atInt64 = int64_t; +using atUint64 = uint64_t; // Vector types #if __SSE__ @@ -124,15 +94,6 @@ typedef union alignas(16) double vec[4]; } atVec4d; - -#ifndef NULL -#ifdef __cplusplus -#define NULL 0 -#else // __cplusplus -#define NULL (void*)0 -#endif -#endif // NULL - #ifndef UNUSED #define UNUSED(x) ((void)x) #endif // UNUSED diff --git a/include/bn.h b/include/bn.h deleted file mode 100644 index a93a2a5..0000000 --- a/include/bn.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef BN_H -#define BN_H - -#ifndef __DOXYGEN_IGNORE__ - -#include "athena/Types.hpp" -int bn_compare(atUint8* a, atUint8* b, atUint32 n); -void bn_sub_modulus(atUint8* a, atUint8* N, atUint32 n); -void bn_add(atUint8* d, atUint8* a, atUint8* b, atUint8* N, atUint32 n); -void bn_mul(atUint8* d, atUint8* a, atUint8* b, atUint8* N, atUint32 n); -void bn_exp(atUint8* d, atUint8* a, atUint8* N, atUint32 n, atUint8* e, atUint32 en); -void bn_inv(atUint8* d, atUint8* a, atUint8* N, atUint32 n); - -#endif // __DOXYGEN_IGNORE__ -#endif // BN_H diff --git a/include/ec.h b/include/ec.h deleted file mode 100644 index e37cc4f..0000000 --- a/include/ec.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef EC_H -#define EC_H -#include "athena/Types.hpp" - -bool check_ec(atUint8* ng, atUint8* ap, atUint8* sig, atUint8* sig_hash); -void make_ec_cert(atUint8* cert, atUint8* sig, char* signer, char* name, atUint8* priv, atUint32 key_id); -void generate_ecdsa(atUint8* R, atUint8* S, atUint8* k, atUint8* hash); - -#endif // EC_H - diff --git a/src/athena/MemoryWriter.cpp b/src/athena/MemoryWriter.cpp index d8fd6c0..a3df929 100644 --- a/src/athena/MemoryWriter.cpp +++ b/src/athena/MemoryWriter.cpp @@ -280,7 +280,7 @@ void MemoryWriter::writeUBytes(const atUint8* data, atUint64 length) return; } - memcpy((atInt8*)(m_data + m_position), data, length); + memcpy(reinterpret_cast(m_data + m_position), data, length); m_position += length; } @@ -297,7 +297,7 @@ void MemoryCopyWriter::writeUBytes(const atUint8* data, atUint64 length) if (m_position + length > m_length) resize(m_position + length); - memcpy((atInt8*)(m_data + m_position), data, length); + memcpy(reinterpret_cast(m_data + m_position), data, length); m_position += length; } diff --git a/src/athena/WiiSaveReader.cpp b/src/athena/WiiSaveReader.cpp index c25cb56..74ef4ff 100644 --- a/src/athena/WiiSaveReader.cpp +++ b/src/athena/WiiSaveReader.cpp @@ -306,10 +306,11 @@ void WiiSaveReader::readCerts(atUint32 totalSize) hash = getSha1(data.get(), dataSize); atUint8* hash2 = getSha1(hash, 20); - +#if 0 std::cout << "validating..." << std::endl; std::cout << (check_ec(ngCert.get(), apCert.get(), sig.get(), hash2) ? "ok" : "invalid") << "..."; std::cout << "done" << std::endl; +#endif } WiiFile* WiiSaveReader::buildTree(std::vector files) diff --git a/src/athena/WiiSaveWriter.cpp b/src/athena/WiiSaveWriter.cpp index 0f8bc6d..8fce1e2 100644 --- a/src/athena/WiiSaveWriter.cpp +++ b/src/athena/WiiSaveWriter.cpp @@ -194,6 +194,7 @@ void WiiSaveWriter::writeImage(WiiImage* image) void WiiSaveWriter::writeCerts(atUint32 filesSize, atUint32 ngId, atUint8* ngPriv, atUint8* ngSig, atUint32 ngKeyId) { +#if 0 atUint8 sig[0x40]; atUint8 ngCert[0x180]; atUint8 apCert[0x180]; @@ -245,6 +246,7 @@ void WiiSaveWriter::writeCerts(atUint32 filesSize, atUint32 ngId, atUint8* ngPri base::writeBytes((atInt8*)sig, 0x40); base::writeBytes((atInt8*)ngCert, 0x180); base::writeBytes((atInt8*)apCert, 0x180); +#endif } } // io diff --git a/src/bn.cpp b/src/bn.cpp deleted file mode 100644 index 7c7a45f..0000000 --- a/src/bn.cpp +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright 2007,2008 Segher Boessenkool -// Licensed under the terms of the GNU GPL, version 2 -// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt - -#include -#include - -#include "bn.h" - -static void bn_zero(atUint8* d, atUint32 n) -{ - memset(d, 0, n); -} - -static void bn_copy(atUint8* d, atUint8* a, atUint32 n) -{ - memcpy(d, a, n); -} - -int bn_compare(atUint8* a, atUint8* b, atUint32 n) -{ - atUint32 i; - - for (i = 0; i < n; i++) - { - if (a[i] < b[i]) - return -1; - - if (a[i] > b[i]) - return 1; - } - - return 0; -} - -void bn_sub_modulus(atUint8* a, atUint8* N, atUint32 n) -{ - atUint32 i; - atUint32 dig; - atUint8 c; - - c = 0; - - for (i = n - 1; i < n; i--) - { - dig = N[i] + c; - c = (a[i] < dig); - a[i] -= dig; - } -} - -void bn_add(atUint8* d, atUint8* a, atUint8* b, atUint8* N, atUint32 n) -{ - atUint32 i; - atUint32 dig; - atUint8 c; - - c = 0; - - for (i = n - 1; i < n; i--) - { - dig = a[i] + b[i] + c; - c = (dig >= 0x100); - d[i] = dig; - } - - if (c) - bn_sub_modulus(d, N, n); - - if (bn_compare(d, N, n) >= 0) - bn_sub_modulus(d, N, n); -} - -void bn_mul(atUint8* d, atUint8* a, atUint8* b, atUint8* N, atUint32 n) -{ - atUint32 i; - atUint8 mask; - - bn_zero(d, n); - - for (i = 0; i < n; i++) - for (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(atUint8* d, atUint8* a, atUint8* N, atUint32 n, atUint8* e, atUint32 en) -{ - atUint8 t[512]; - atUint32 i; - atUint8 mask; - - bn_zero(d, n); - d[n - 1] = 1; - - for (i = 0; i < en; i++) - for (mask = 0x80; mask != 0; mask >>= 1) - { - bn_mul(t, d, d, N, n); - - if ((e[i] & mask) != 0) - bn_mul(d, t, a, N, n); - else - bn_copy(d, t, n); - } -} - -// only for prime N -- stupid but lazy, see if I care -void bn_inv(atUint8* d, atUint8* a, atUint8* N, atUint32 n) -{ - atUint8 t[512], s[512]; - - bn_copy(t, N, n); - bn_zero(s, n); - s[n - 1] = 2; - bn_sub_modulus(t, s, n); - bn_exp(d, a, N, n, t, n); -} diff --git a/src/ec.cpp b/src/ec.cpp deleted file mode 100644 index 066f9d8..0000000 --- a/src/ec.cpp +++ /dev/null @@ -1,451 +0,0 @@ -// Copyright 2007,2008 Segher Boessenkool -// Licensed under the terms of the GNU GPL, version 2 -// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt - - -// TODO: Clean this code up and prune -// NOTE: It's pretty much been gutted from it's original form, does the original license even apply anymore? - -// Not all of these headers are necessary, figure out which ones are actually used and prune those that are irrelevant. -#include -#include "athena/Utility.hpp" - -#include "bn.h" -#include "ec.h" -#include "sha1.h" - -// y**2 + x*y = x**3 + x + b -/*static 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 atUint8 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 atUint8 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_print(char *name, u8 *a) -{ - u32 i; - - printf("%s = ", name); - - for (i = 0; i < 30; i++) - printf("%02x", a[i]); - - printf("\n"); -} -*/ -static void elt_copy(atUint8* d, atUint8* a) -{ - memcpy(d, a, 30); -} - -static void elt_zero(atUint8* d) -{ - memset(d, 0, 30); -} - -static int elt_is_zero(atUint8* d) -{ - atUint32 i; - - for (i = 0; i < 30; i++) - if (d[i] != 0) - return 0; - - return 1; -} - -static void elt_add(atUint8* d, atUint8* a, atUint8* b) -{ - atUint32 i; - - for (i = 0; i < 30; i++) - d[i] = a[i] ^ b[i]; -} - -static void elt_mul_x(atUint8* d, atUint8* a) -{ - atUint8 carry, x, y; - atUint32 i; - - carry = a[0] & 1; - - x = 0; - - for (i = 0; i < 29; i++) - { - y = a[i + 1]; - d[i] = x ^ (y >> 7); - x = y << 1; - } - - d[29] = x ^ carry; - - d[20] ^= carry << 2; -} - -static void elt_mul(atUint8* d, atUint8* a, atUint8* b) -{ - atUint32 i, n; - atUint8 mask; - - elt_zero(d); - - i = 0; - mask = 1; - - for (n = 0; n < 233; n++) - { - elt_mul_x(d, d); - - if ((a[i] & mask) != 0) - elt_add(d, d, b); - - mask >>= 1; - - if (mask == 0) - { - mask = 0x80; - i++; - } - } -} - -static const atUint8 square[16] = { 0x00, 0x01, 0x04, 0x05, 0x10, 0x11, 0x14, 0x15, 0x40, 0x41, 0x44, 0x45, 0x50, 0x51, 0x54, 0x55 }; - -static void elt_square_to_wide(atUint8* d, atUint8* a) -{ - atUint32 i; - - for (i = 0; i < 30; i++) - { - d[2 * i] = square[a[i] >> 4]; - d[2 * i + 1] = square[a[i] & 15]; - } -} - -static void wide_reduce(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 elt_square(atUint8* d, atUint8* a) -{ - atUint8 wide[60]; - - elt_square_to_wide(wide, a); - wide_reduce(wide); - - elt_copy(d, wide + 30); -} - -static void itoh_tsujii(atUint8* d, atUint8* a, atUint8* b, atUint32 j) -{ - atUint8 t[30]; - - elt_copy(t, a); - - while (j--) - { - elt_square(d, t); - elt_copy(t, d); - } - - elt_mul(d, t, b); -} - -static void elt_inv(atUint8* d, atUint8* a) -{ - atUint8 t[30]; - atUint8 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); -} -/* -static int point_is_on_curve(u8 *p) -{ - 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_add(s, s, ec_b); - - return elt_is_zero(s); -} -*/ -static int point_is_zero(atUint8* p) -{ - return elt_is_zero(p) && elt_is_zero(p + 30); -} - -static void point_double(atUint8* r, atUint8* p) -{ - atUint8 s[30], t[30]; - atUint8* px, *py, *rx, *ry; - - px = p; - py = p + 30; - rx = r; - ry = r + 30; - - if (elt_is_zero(px)) - { - elt_zero(rx); - elt_zero(ry); - - return; - } - - elt_inv(t, px); - elt_mul(s, py, t); - elt_add(s, s, px); - - elt_square(t, px); - - elt_square(rx, s); - elt_add(rx, rx, s); - rx[29] ^= 1; - - elt_mul(ry, s, rx); - elt_add(ry, ry, rx); - elt_add(ry, ry, t); -} - -static void point_add(atUint8* r, atUint8* p, atUint8* q) -{ - atUint8 s[30], t[30], u[30]; - atUint8* px, *py, *qx, *qy, *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 (point_is_zero(q)) - { - elt_copy(rx, px); - elt_copy(ry, py); - return; - } - - 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; - } - - 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); -} - -static void point_mul(atUint8* d, atUint8* a, atUint8* b) // a is bignum -{ - atUint32 i; - atUint8 mask; - - elt_zero(d); - elt_zero(d + 30); - - for (i = 0; i < 30; i++) - for (mask = 0x80; mask != 0; mask >>= 1) - { - point_double(d, d); - - if ((a[i] & mask) != 0) - point_add(d, d, b); - } -} - -void generate_ecdsa(atUint8* R, atUint8* S, atUint8* k, atUint8* hash) -{ - atUint8 e[30]; - atUint8 kk[30]; - atUint8 m[30]; - atUint8 minv[30]; - atUint8 mG[60]; - //FILE *fp; - - elt_zero(e); - memcpy(e + 10, hash, 20); - - athena::utility::fillRandom(m, sizeof(m)); - 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); - - // 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); -} - -bool check_ecdsa(atUint8* Q, atUint8* R, atUint8* S, atUint8* hash) -{ - atUint8 Sinv[30]; - atUint8 e[30]; - atUint8 w1[30], w2[30]; - atUint8 r1[60], r2[60]; - - bn_inv(Sinv, S, ec_N, 30); - - elt_zero(e); - memcpy(e + 10, hash, 20); - - 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); - - if (bn_compare(r1, ec_N, 30) >= 0) - bn_sub_modulus(r1, ec_N, 30); - - return (bn_compare(r1, R, 30) == 0); -} - -void ec_priv_to_pub(atUint8* k, atUint8* Q) -{ - point_mul(Q, k, ec_G); -} - -bool check_ec(atUint8* ng, atUint8* ap, atUint8* sig, atUint8* sig_hash) -{ - atUint8* ap_hash; - atUint8* ng_Q, *ap_R, *ap_S; - atUint8* ap_Q, *sig_R, *sig_S; - - ng_Q = ng + 0x0108; - ap_R = ap + 0x04; - ap_S = ap + 0x22; - - - ap_hash = getSha1(ap + 0x80, 0x100); - ap_Q = ap + 0x0108; - sig_R = sig; - sig_S = sig + 30; - - return check_ecdsa(ng_Q, ap_R, ap_S, ap_hash) - && check_ecdsa(ap_Q, sig_R, sig_S, sig_hash); -} - -void make_ec_cert(atUint8* cert, atUint8* sig, char* signer, char* name, atUint8* priv, atUint32 key_id) -{ - 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) = key_id; - - if (!athena::utility::isSystemBigEndian()) - *(atUint32*)(cert + 0x104) = athena::utility::swapU32(*(atUint32*)(cert + 0x104)); - - ec_priv_to_pub(priv, cert + 0x108); -}