mirror of
https://github.com/zoogie/TADpole.git
synced 2025-06-18 19:45:41 -04:00
Port from Python to C
- add crc16 fixing for banner.bin - remove keyy error correct, will probably be added back in time
This commit is contained in:
parent
bdf6cbd764
commit
de9eeebc0c
352
LICENSE
352
LICENSE
@ -1,21 +1,339 @@
|
||||
MIT License
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (c) 2018 zoogie
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
Preamble
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
|
156
Makefile
Normal file
156
Makefile
Normal file
@ -0,0 +1,156 @@
|
||||
#---------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# the prefix on the compiler executables
|
||||
#---------------------------------------------------------------------------------
|
||||
PREFIX :=
|
||||
|
||||
export CC := $(PREFIX)gcc
|
||||
export CXX := $(PREFIX)g++
|
||||
export AS := $(PREFIX)as
|
||||
export AR := $(PREFIX)ar
|
||||
export OBJCOPY := $(PREFIX)objcopy
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.a:
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $@)
|
||||
@rm -f $@
|
||||
$(AR) -rc $@ $^
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.o: %.cpp
|
||||
@echo $(notdir $<)
|
||||
$(CXX) -MMD -MP -MF $(DEPSDIR)/$*.d $(CXXFLAGS) -c $< -o $@
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.o: %.c
|
||||
@echo $(notdir $<)
|
||||
$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d $(CFLAGS) -c $< -o $@
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.o: %.s
|
||||
@echo $(notdir $<)
|
||||
$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d -x assembler-with-cpp $(ASFLAGS) -c $< -o $@
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.o: %.S
|
||||
@echo $(notdir $<)
|
||||
$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d -x assembler-with-cpp $(ASFLAGS) -c $< -o $@
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# SOURCES is a list of directories containing source code
|
||||
# INCLUDES is a list of directories containing extra header files
|
||||
# MAXMOD_SOUNDBANK contains a directory of music and sound effect files
|
||||
#---------------------------------------------------------------------------------
|
||||
TARGET := $(shell basename $(CURDIR))
|
||||
BUILD := build
|
||||
SOURCES := source
|
||||
#DATA := data
|
||||
INCLUDES := include
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
CFLAGS := -Wall -O3
|
||||
|
||||
CFLAGS += $(INCLUDE)
|
||||
CXXFLAGS := $(CFLAGS)
|
||||
|
||||
ASFLAGS := -g
|
||||
LDFLAGS = -g
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# any extra libraries we wish to link with the project (order is important)
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBS := -lcrypto
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
# include and lib
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBDIRS := C:\Users\Snake-DellPC\Desktop\HAX\seedminer\stage3\CPU_Conventional\openssl
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
# rules for different file extensions
|
||||
#---------------------------------------------------------------------------------
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
#---------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(CPPFILES)),)
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CC)
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
#---------------------------------------------------------------------------------
|
||||
export LD := $(CXX)
|
||||
#---------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
export OFILES := $(addsuffix .o,$(BINFILES)) \
|
||||
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||
|
||||
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
-I$(CURDIR)/$(BUILD)
|
||||
|
||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||
|
||||
.PHONY: $(BUILD) clean
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
$(BUILD):
|
||||
@[ -d $@ ] || mkdir -p $@
|
||||
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -fr $(BUILD) $(TARGET)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
else
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#---------------------------------------------------------------------------------
|
||||
$(OUTPUT) : $(OFILES)
|
||||
@echo linking $(notdir $@)
|
||||
@$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%.bin.o : %.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
$(bin2o)
|
||||
|
||||
-include $(DEPSDIR)/*.d
|
||||
|
||||
#---------------------------------------------------------------------------------------
|
||||
endif
|
||||
#---------------------------------------------------------------------------------------
|
48
README.md
48
README.md
@ -1,13 +1,9 @@
|
||||
# Notice
|
||||
You can use [DSIHaxInjector](https://jenkins.nelthorya.net/job/DSIHaxInjector/build?delay=0sec) for seedminer instead of this program. This is a cloud based version of TADpole and it's easier to use because of its user-friendly web interface.
|
||||
# What is this?
|
||||
A program that allows you to dump the contents of a 3ds dsiware export, modify them, and rebuild to an importable .bin file.
|
||||
# Requirements
|
||||
* Windows - adapting to Linux is possible
|
||||
* Python 2.x.x or 3.x.x - [official download](https://www.python.org/downloads)
|
||||
* Pycryptodomex - install with `pip install pycryptodomex`
|
||||
* A DSiWare export from your target console - must be DSihax injectable (see [list of injectable games](https://3ds.hacks.guide/installing-boot9strap-(dsiware-game-injection-list))). EA Sudoku is recommended for US/EU -- if you don't have one already on the list.
|
||||
* A `movable.sed` from your target console - see README in [latest seedminer release](https://github.com/zoogie/seedminer/releases/latest)
|
||||
* A valid `ctcert.bin` with private key attached from a CFW console - see [instructions below](#obtaining-ctcertbin-plus-private-key) for guidance. You might also be able to find one online, but it may not be valid. I can confirm the one with SHA256 dc2a92d2c2f7cf444ff1343ecf1224c4e9e49daff79ae02d72585b850af0ad4e is valid, though.
|
||||
* Sudokuhax injection files for TADpole - download appropriate set from [this link](https://github.com/YYoshi241/Sudokuhax-4-TADpole/releases/latest)
|
||||
* Windows - compiling to Linux & Mac should be easy given there are no dependancies here though
|
||||
* A DSiWare export from your target console - one the utilizes a save file is preferable. The filename must be in the format: <8 digit hex>.bin Ex. 484E4441.bin)
|
||||
* A `movable.sed` from your target console placed in your /resources folder
|
||||
|
||||
# Usage
|
||||
Basic Command Line usage is:
|
||||
@ -17,38 +13,16 @@ python TADpole.py (8-digit hex).bin d
|
||||
Rebuild
|
||||
python TADpole.py (8-digit hex).bin r
|
||||
```
|
||||
Seedminer Instructions:
|
||||
1. Download and extract latest release of [TADpole](https://github.com/zoogie/TADpole/releases/latest)
|
||||
2. Copy the injectable DSiWare game from System Memory to your SD card via 3DS System Settings
|
||||
3. Copy the exported DSiWare game from your SD card (in `your-sd-card/Nintendo 3DS/ID0/ID1/Nintendo DSiWare/`) to the extracted TADpole folder on your PC. It might look like `4b4c4455.bin`, for example. The hex number will be different of course.
|
||||
4. Place `movable.sed` in `.../TADpole/resources/`
|
||||
5. Place `ctcert.bin` in `.../TADpole/resources/`
|
||||
6. Dump the exported DSiWare .bin by drag n dropping it on dump.bat.
|
||||
7. Place both sudokuhax injection files (`public.sav.inject` and `srl.nds.inject`) inside the generated game folder
|
||||
8. Rebuild the modified game folder by drag n dropping the DSiWare .bin on rebuild.bat
|
||||
9. Copy the built `.patched` file to the `.../Nintendo DSiWare/` folder in your SD card and replace the original DSiWare export with it by removing `.patched` from the filename
|
||||
10. Proceed to import the DSiWare to your system memory from your SD card
|
||||
11. Download [b9sTool](https://github.com/zoogie/b9sTool/releases/latest) and place the boot.nds on your SD root
|
||||
12. Proceed with steps in [Section VI of 3ds.guide](https://3ds.hacks.guide/installing-boot9strap-(dsiware-game-injection))
|
||||
|
||||
**Note: more detailed instructions with screenshots can be found [here](http://gbatemp.net/threads/seedminer-single-system-dsiware-injection.495685/page-41#post-7830489)** (may be deprecated)
|
||||
|
||||
# Obtaining `ctcert.bin` plus private key - (can also be found online - no hints!)
|
||||
**Warning: the following steps require access to a 3DS with Custom Firmware (an already hacked 3DS)**
|
||||
1. Install the `seedstarter.cia` found in the [seedminer release](https://github.com/zoogie/seedminer/releases/latest) section
|
||||
2. Place [`ctcertifier.firm`](https://github.com/zoogie/seedminer_toolbox/tree/master/ctcertifier) in `/luma/payloads/` of your SD card if you have [Luma3DS](https://github.com/AuroraWright/Luma3DS/wiki/Optional-features#firm-payload-chainloader) installed or else somewhere where you can execute it via a chainloader
|
||||
3. Turn on your 3DS and run `seedstarter.cia`
|
||||
4. Press `Y` to dump `ctcert.bin` (missing private key) to `sdmc:/seedstarter/ctcert.bin`
|
||||
5. Turn off your 3DS
|
||||
6. Run `ctcertifier.firm` by holding `Start` and turning the 3DS on when you have Luma3DS installed
|
||||
7. Copy `ctcert.bin` from `sdmc:/seedstarter/ctcert.bin` to your TADpole location, and put it in the `resources/` folder
|
||||
8. Done
|
||||
|
||||
# Additional Notes
|
||||
* If you perform a System Transfer from console A to console B, the `movable.sed` from console A (pre-transfer) will be identical to the `movable.sed` for console B (post-transfer).
|
||||
* The release archives include an `.exe` if you want to avoid installing python2, python3, or python in general.
|
||||
|
||||
# Thanks
|
||||
* **yellows8** for [ctr-dsiwaretool](https://github.com/zoogie/ctr-dsiwaretool) and 3dbrew [documentation](https://www.3dbrew.org/wiki/DSiWare_Exports)
|
||||
* **booto** for [sav-adjust](https://github.com/booto/dsi/tree/master/save_adjust) (ecc code) and 3dbrew [documentation](https://www.3dbrew.org/wiki/DSiWare_Exports) (general dsiware export info)
|
||||
* **jason0597** for about 75% of the [TAD crypto code](https://github.com/jason0597/TADPole-3DS/)
|
||||
* **d0k3** for inspiring the creation of this tool with this [commit](https://github.com/d0k3/GodMode9/commit/ec861a7bf7c162c605aea353c0b9cebe7fa80e71)
|
||||
|
||||
# Libraries used
|
||||
* [Texas Instruments AES-128 CBC and AES CMAC functions](https://github.com/flexibity-team/AES-CMAC-RFC)
|
||||
* [ECDSA sect233r1 code (along with BigNum code)](http://git.infradead.org/?p=users/segher/wii.git)
|
||||
* [Nintendo 3DS key scrambler function](https://github.com/luigoalma/3ds_keyscrambler/blob/master/src/UnScrambler.c#L50)
|
322
TADpole.py
322
TADpole.py
@ -1,322 +0,0 @@
|
||||
from __future__ import print_function
|
||||
from Cryptodome.Hash import CMAC
|
||||
from Cryptodome.Cipher import AES
|
||||
import os,sys,random,hashlib
|
||||
from binascii import hexlify
|
||||
|
||||
keyx=0x6FBB01F872CAF9C01834EEC04065EE53
|
||||
keyy=0x0 #get this from movable.sed - console unique
|
||||
F128=0xffffffffffffffffffffffffffffffff
|
||||
C =0x1FF9E9AAC5FE0408024591DC5D52768A
|
||||
cmac_keyx=0xB529221CDDB5DB5A1BF26EFF2041E875
|
||||
|
||||
DIR="decrypted_sections/"
|
||||
BM=0x20 #block metadata size https://www.3dbrew.org/wiki/DSiWare_Exports (a bunch of info in this script is sourced here)
|
||||
BANNER=0x0
|
||||
BANNER_SIZE=0x4000
|
||||
HEADER=BANNER+BANNER_SIZE+BM
|
||||
HEADER_SIZE=0xF0
|
||||
FOOTER=HEADER+HEADER_SIZE+BM
|
||||
FOOTER_SIZE=0x4E0
|
||||
TMD=FOOTER+FOOTER_SIZE+BM
|
||||
content_sizelist=[0]*11
|
||||
content_namelist=["tmd","srl.nds","2.bin","3.bin","4.bin","5.bin","6.bin","7.bin","8.bin","public.sav","banner.sav"]
|
||||
|
||||
if (len(sys.argv) != 3):
|
||||
print("Usage: python TADpole.py <dsiware export> <dump or rebuild (d or r)>\n")
|
||||
|
||||
with open(sys.argv[1],"rb+") as f:
|
||||
tad=f.read()
|
||||
if(len(tad)<0x20000):
|
||||
print("Error: input dsiware %s is way too small, is this really a dsiware.bin?" % sys.argv[1])
|
||||
sys.exit(1)
|
||||
|
||||
tad_sections=[b""]*14
|
||||
|
||||
if sys.version_info[0] >= 3:
|
||||
# Python 3
|
||||
def bytechr(c):
|
||||
return bytes([c])
|
||||
else:
|
||||
# Python 2
|
||||
bytechr = chr
|
||||
|
||||
def get_keyy():
|
||||
global keyy
|
||||
realseed=0
|
||||
with open("resources/movable.sed","rb") as f:
|
||||
msedlen=len(f.read())
|
||||
if(msedlen != 0x140 and msedlen != 0x120):
|
||||
print("Error: movable.sed is the wrong size - are you sure this is a movable.sed?")
|
||||
sys.exit(1)
|
||||
f.seek(0)
|
||||
if(f.read(4)==b"SEED"):
|
||||
realseed=1
|
||||
f.seek(0)
|
||||
f.seek(0x110)
|
||||
temp=f.read(0x10)
|
||||
keyy=int(hexlify(temp), 16)
|
||||
if(realseed):
|
||||
print("Real movable.sed detected, cleaning non-keyy contents for safety")
|
||||
print("DO NOT import this to a real 3DS!")
|
||||
with open("resources/movable.sed","wb") as f:
|
||||
f.write((b"\x00"*0x110)+temp+(b"\x00"*0x20))
|
||||
|
||||
def int16bytes(n):
|
||||
if sys.version_info[0] >= 3:
|
||||
return n.to_bytes(16, 'big') # Python 3
|
||||
else:
|
||||
s=b"" # Python 2
|
||||
for i in range(16):
|
||||
s=chr(n & 0xFF)+s
|
||||
n=n>>8
|
||||
return s
|
||||
|
||||
def int2bytes(n):
|
||||
s=bytearray(4)
|
||||
for i in range(4):
|
||||
s[i]=n & 0xFF
|
||||
n=n>>8
|
||||
return s
|
||||
|
||||
def bytes2int(s):
|
||||
n=0
|
||||
for i in range(4):
|
||||
n+=ord(s[i:i+1])<<(i*8)
|
||||
return n
|
||||
|
||||
def endian(n, size):
|
||||
new=0
|
||||
for i in range(size):
|
||||
new <<= 8
|
||||
new |= (n & 0xFF)
|
||||
n >>= 8
|
||||
return new
|
||||
|
||||
def add_128(a, b):
|
||||
return (a+b) & F128
|
||||
|
||||
def rol_128(n, shift):
|
||||
for i in range(shift):
|
||||
left_bit=(n & 1<<127)>>127
|
||||
shift_result=n<<1 & F128
|
||||
n=shift_result | left_bit
|
||||
return n
|
||||
|
||||
def normalkey(x,y): #3ds aes engine - curtesy of rei's pastebin google doc, curtesy of plutoo from 32c3
|
||||
n=rol_128(x,2) ^ y #F(KeyX, KeyY) = (((KeyX <<< 2) ^ KeyY) + 1FF9E9AAC5FE0408024591DC5D52768A) <<< 87
|
||||
n=add_128(n,C) #https://pastebin.com/ucqXGq6E
|
||||
n=rol_128(n,87) #https://smealum.github.io/3ds/32c3/#/113
|
||||
return n
|
||||
|
||||
def decrypt(message, key, iv):
|
||||
cipher = AES.new(key, AES.MODE_CBC, iv )
|
||||
return cipher.decrypt(message)
|
||||
|
||||
def encrypt(message, key, iv):
|
||||
cipher = AES.new(key, AES.MODE_CBC, iv )
|
||||
return cipher.encrypt(message)
|
||||
|
||||
def dump_section(data_offset, size, filename):
|
||||
iv=tad[data_offset+size+0x10:data_offset+size+0x20]
|
||||
key=normalkey(keyx,keyy)
|
||||
result=decrypt(tad[data_offset:data_offset+size],int16bytes(key),iv)
|
||||
with open(filename,"wb") as f:
|
||||
f.write(result)
|
||||
print("%08X %08X %s" % (data_offset, size, filename))
|
||||
|
||||
def check_keyy(keyy_offset):
|
||||
global keyy
|
||||
tempy=endian(keyy,16)
|
||||
tempy=tempy+(keyy_offset<<64)
|
||||
tempy=endian(tempy,16)
|
||||
iv=tad[HEADER+HEADER_SIZE+0x10:HEADER+HEADER_SIZE+0x20]
|
||||
key=normalkey(keyx, tempy)
|
||||
result=decrypt(tad[HEADER:HEADER+HEADER_SIZE],int16bytes(key),iv)
|
||||
if(b"\x33\x46\x44\x54" not in result[:4]):
|
||||
print("wrong -- keyy offset: %d" % (keyy_offset))
|
||||
return 1
|
||||
keyy=tempy
|
||||
print("correct! -- keyy offset: %d" % (keyy_offset))
|
||||
return 0
|
||||
#print("%08X %08X %s" % (data_offset, size, filename))
|
||||
|
||||
def fix_movable():
|
||||
temp=b""
|
||||
print("correcting movable.sed ...")
|
||||
with open("resources/movable.sed","rb+") as f:
|
||||
bak=f.read()
|
||||
f.seek(0)
|
||||
f.write(b"\x00"*0x110+int16bytes(keyy)+b"\x00"*0x20)
|
||||
with open("resources/movable_bak.sed","wb") as f:
|
||||
f.write(bak)
|
||||
print("your original movable.sed has been overwritten and a new movable_bak.sed created with the old data\n")
|
||||
|
||||
def get_content_sizes():
|
||||
with open(DIR+"header.bin","rb") as f:
|
||||
f.seek(0x48)
|
||||
temp=f.read(0x2C)
|
||||
for i in range(11):
|
||||
offset=i*4
|
||||
content_sizelist[i]=bytes2int(temp[offset:offset+4])
|
||||
if(i==0):
|
||||
pad=16-(content_sizelist[i] % 16)
|
||||
content_sizelist[i]+=pad
|
||||
#this is padding the tmd section for aes-cbc blocks (16B block align)
|
||||
|
||||
def get_content_block(buff):
|
||||
global cmac_keyx
|
||||
hash=hashlib.sha256(buff).digest()
|
||||
key = int16bytes(normalkey(cmac_keyx, keyy))
|
||||
cipher = CMAC.new(key, ciphermod=AES)
|
||||
result = cipher.update(hash)
|
||||
return result.digest() + b''.join(bytechr(random.randint(0,255)) for _ in range(16))
|
||||
|
||||
def sign_footer():
|
||||
ret=0
|
||||
print("-----------Handing off to ctr-dsiwaretool...\n")
|
||||
if(sys.platform=="win32"):
|
||||
print("Windows ctr-dsiwaretool selected")
|
||||
sys.stdout.flush()
|
||||
ret=os.system("resources\ctr-dsiwaretool.exe "+DIR+"footer.bin resources/ctcert.bin --write")
|
||||
else:
|
||||
print("Linux ctr-dsiwaretool selected")
|
||||
sys.stdout.flush() #fix out-of-order text output on unix platforms (ctr-dsiwaretool before before python)
|
||||
ret=os.system("resources/ctr-dsiwaretool "+DIR+"footer.bin resources/ctcert.bin --write")
|
||||
print("\n-----------Returning to TADpole...")
|
||||
if (ret==1):
|
||||
print("Error: file handling issue with %sfooter.bin" % DIR)
|
||||
sys.exit(1)
|
||||
elif(ret==2):
|
||||
print("Error: file handling issue with resources/ctcert.bin")
|
||||
sys.exit(1)
|
||||
elif(ret==3):
|
||||
print("Error: resources/ctcert.bin is invalid")
|
||||
sys.exit(1)
|
||||
elif(ret!=0):
|
||||
print("Error: unknown code "+str(ret))
|
||||
sys.exit(1)
|
||||
|
||||
def fix_hashes_and_sizes():
|
||||
sizes=[0]*11
|
||||
hashes=[""]*13
|
||||
footer_namelist=["banner.bin","header.bin"]+content_namelist
|
||||
for i in range(11):
|
||||
if(os.path.exists(DIR+content_namelist[i])):
|
||||
sizes[i] = os.path.getsize(DIR+content_namelist[i])
|
||||
else:
|
||||
sizes[i] = 0
|
||||
if(sizes[0]%16==0):
|
||||
sizes[0]-=0xC
|
||||
for i in range(13):
|
||||
if(os.path.exists(DIR+footer_namelist[i])):
|
||||
with open(DIR+footer_namelist[i],"rb") as f:
|
||||
hashes[i] = hashlib.sha256(f.read()).digest()
|
||||
else:
|
||||
hashes[i] = b"\x00"*0x20
|
||||
|
||||
with open(DIR+"header.bin","rb+") as f:
|
||||
offset=0x48
|
||||
for i in range(11):
|
||||
f.seek(offset)
|
||||
f.write(int2bytes(sizes[i]))
|
||||
offset+=4
|
||||
f.seek(0)
|
||||
hashes[1] = hashlib.sha256(f.read()).digest() #we need to recalulate header hash in case there's a size change in any section. sneaky bug.
|
||||
print("header.bin fixed")
|
||||
|
||||
with open(DIR+"footer.bin","rb+") as f:
|
||||
offset=0
|
||||
for i in range(13):
|
||||
f.seek(offset)
|
||||
f.write(hashes[i])
|
||||
offset+=0x20
|
||||
print("footer.bin fixed")
|
||||
|
||||
def rebuild_tad():
|
||||
global keyy
|
||||
full_namelist=["banner.bin","header.bin","footer.bin"]+content_namelist
|
||||
section=""
|
||||
content_block=""
|
||||
key=normalkey(keyx,keyy)
|
||||
for i in range(len(full_namelist)):
|
||||
if(os.path.exists(DIR+full_namelist[i])):
|
||||
print("encrypting "+DIR+full_namelist[i])
|
||||
with open(DIR+full_namelist[i],"rb") as f:
|
||||
section=f.read()
|
||||
content_block=get_content_block(section)
|
||||
tad_sections[i]=encrypt(section, int16bytes(key), content_block[0x10:])+content_block
|
||||
with open(sys.argv[1]+".patched","wb") as f:
|
||||
f.write(b''.join(tad_sections))
|
||||
print("Rebuilt to "+sys.argv[1]+".patched")
|
||||
print("Done.")
|
||||
|
||||
def inject_binary(path):
|
||||
if(os.path.exists(path+".inject")):
|
||||
print(path+".inject found, injecting to "+path+"...")
|
||||
with open(path,"rb+") as f, open(path+".inject","rb") as g:
|
||||
if(len(g.read()) > len(f.read())):
|
||||
print("WARNING: injection binary size greater than target, import may fail")
|
||||
f.seek(0)
|
||||
g.seek(0)
|
||||
f.write(g.read())
|
||||
|
||||
print("|TADpole by zoogie|")
|
||||
print("|_______v1.5______|")
|
||||
abspath = os.path.abspath(__file__)
|
||||
dname = os.path.dirname(abspath)
|
||||
os.chdir(dname)
|
||||
|
||||
wkdir=sys.argv[1].upper().replace(".BIN","/",1)
|
||||
if(wkdir.count('.')==0 and wkdir.count('/')==1):
|
||||
DIR=wkdir
|
||||
print("Using workdir: "+DIR)
|
||||
|
||||
if(sys.argv[2]=="dump" or sys.argv[2]=="d"):
|
||||
if not os.path.exists(DIR):
|
||||
os.makedirs(DIR)
|
||||
get_keyy()
|
||||
print("checking keyy...")
|
||||
if(check_keyy(0)):
|
||||
print("Initial keyy failed to decrypt dsiware, trying adjacent keyys...")
|
||||
decrypted=0
|
||||
dec_error_msg=\
|
||||
"\nWARNING!!!: Your input movable.sed keyy was wrong, but a nearby keyy worked!"\
|
||||
"\nWARNING!!!: This means either you brute forced the wrong id0 or decrypted a dsiware.bin from the wrong id0"\
|
||||
"\nWARNING!!!: The former will probably work while the latter will likely fail to import to the 3ds."
|
||||
for i in range(1,21):
|
||||
if(check_keyy(i)==0):
|
||||
print(dec_error_msg)
|
||||
decrypted=1
|
||||
break
|
||||
elif(check_keyy(-i)==0):
|
||||
print(dec_error_msg)
|
||||
decrypted=1
|
||||
break
|
||||
if(decrypted==0):
|
||||
print("Error: decryption failed - movable.sed keyy is wrong!")
|
||||
sys.exit(1)
|
||||
else:
|
||||
fix_movable()
|
||||
|
||||
print("Dumping sections...")
|
||||
print("Offset Size Filename")
|
||||
dump_section(BANNER, BANNER_SIZE, DIR+"banner.bin")
|
||||
dump_section(HEADER, HEADER_SIZE, DIR+"header.bin")
|
||||
dump_section(FOOTER, FOOTER_SIZE, DIR+"footer.bin")
|
||||
get_content_sizes()
|
||||
tad_offset=TMD
|
||||
for i in range(11):
|
||||
if(content_sizelist[i]):
|
||||
dump_section(tad_offset, content_sizelist[i], DIR+content_namelist[i])
|
||||
tad_offset+=(content_sizelist[i]+BM)
|
||||
elif(sys.argv[2]=="rebuild" or sys.argv[2]=="r"):
|
||||
print("Rebuilding export...")
|
||||
get_keyy()
|
||||
inject_binary(DIR+"srl.nds")
|
||||
inject_binary(DIR+"public.sav")
|
||||
fix_hashes_and_sizes()
|
||||
sign_footer()
|
||||
rebuild_tad()
|
||||
else:
|
||||
print("ERROR: please recheck Usage above")
|
@ -1,2 +1,2 @@
|
||||
py -2 tadpole.py %~nx1 r
|
||||
tadpole.exe %~nx1 r
|
||||
pause
|
||||
|
44
include/TI_aes_128.h
Normal file
44
include/TI_aes_128.h
Normal file
@ -0,0 +1,44 @@
|
||||
/* --COPYRIGHT--,BSD
|
||||
* Copyright (c) 2011, Texas Instruments Incorporated
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of Texas Instruments Incorporated nor the names of
|
||||
* its contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* --/COPYRIGHT--*/
|
||||
/*
|
||||
* TI_aes_128.h
|
||||
*
|
||||
* Created on: Nov 3, 2011
|
||||
* Author: Eric Peeters
|
||||
*/
|
||||
|
||||
#ifndef TI_OPT_AES_H_
|
||||
#define TI_OPT_AES_H_
|
||||
|
||||
void aes_enc_dec(unsigned char *state, unsigned char *key, unsigned char dir);
|
||||
|
||||
#endif /* TI_OPT_AES_H_ */
|
57
include/aes-cbc-cmac.h
Normal file
57
include/aes-cbc-cmac.h
Normal file
@ -0,0 +1,57 @@
|
||||
/**
|
||||
* File: cmac.h
|
||||
* Created on: 21 авг. 2015 г.
|
||||
* Description:
|
||||
*
|
||||
*
|
||||
* Author: Roman Savrulin <romeo.deepmind@gmail.com>
|
||||
* Copyright: 2015 Roman Savrulin
|
||||
* Copying permission statement:
|
||||
*
|
||||
* This file is part of AES-CMAC.
|
||||
*
|
||||
* AES-CMAC is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
#ifndef AES_CBC_CMAC_H_
|
||||
#define AES_CBC_CMAC_H_
|
||||
|
||||
#define BLOCK_SIZE 16
|
||||
#define LAST_INDEX (BLOCK_SIZE - 1)
|
||||
|
||||
int AES_CBC_ENC(const unsigned char *IV, const unsigned char *key,
|
||||
const unsigned char *input, int inputLength, unsigned char *output,
|
||||
int outputLength);
|
||||
|
||||
int AES_CBC_DEC(const unsigned char *IV, const unsigned char *key,
|
||||
const unsigned char *input, int inputLength, unsigned char *output,
|
||||
int outputLength);
|
||||
|
||||
void AES_CMAC(const unsigned char *key, const unsigned char *input, int length,
|
||||
unsigned char *mac);
|
||||
|
||||
int AES_CMAC_CHECK(const unsigned char *key, const unsigned char *input,
|
||||
int length, const unsigned char *mac);
|
||||
|
||||
void xor_128(const unsigned char *a, const unsigned char *b, unsigned char *out);
|
||||
void AES_128_DEC(unsigned const char *key, unsigned const char* msg, unsigned char *cipher);
|
||||
|
||||
#ifdef DEBUG_CMAC
|
||||
void print_hex(const char *str, const unsigned char *buf, int len);
|
||||
void print128(const unsigned char *bytes);
|
||||
void print96(const unsigned char *bytes);
|
||||
#endif
|
||||
|
||||
#endif /* AES_CBC_CMAC_H_ */
|
15
include/bn.h
Normal file
15
include/bn.h
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright 2010 booto
|
||||
// Licensed under the terms of the GNU GPL, version 2
|
||||
// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
|
||||
#ifndef bn_h
|
||||
#define bn_h
|
||||
#include "types.h"
|
||||
|
||||
int bn_compare(u8 *a, u8 *b, u32 n);
|
||||
void bn_sub_modulus(u8 *a, u8 *N, u32 n);
|
||||
void bn_add(u8 *d, u8 *a, u8 *b, u8 *N, u32 n);
|
||||
void bn_mul(u8 *d, u8 *a, u8 *b, u8 *N, u32 n);
|
||||
void bn_exp(u8 *d, u8 *a, u8 *N, u32 n, u8 *e, u32 en);
|
||||
void bn_inv(u8 *d, u8 *a, u8 *N, u32 n);
|
||||
void bn_shiftr(u8 *in, u32 size, u32 shiftn);
|
||||
#endif
|
9
include/crypto.h
Normal file
9
include/crypto.h
Normal file
@ -0,0 +1,9 @@
|
||||
#include "types.h"
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
void encryptAES(u8 *plaintext, u32 size, u8 *key, u8 *iv, u8 *output);
|
||||
void decryptAES(u8 *ciphertext, u32 size, u8 *key, u8 *iv, u8 *output);
|
||||
void calculateCMAC(u8 *input, u32 size, u8 *key, u8 *output);
|
||||
void calculateSha256(u8 *input, u32 size, u8 *output);
|
||||
void keyScrambler(u8 *Y, bool cmacYN, u8 *normal_key);
|
11
include/ec.h
Normal file
11
include/ec.h
Normal file
@ -0,0 +1,11 @@
|
||||
// Copyright 2010 booto
|
||||
// Licensed under the terms of the GNU GPL, version 2
|
||||
// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
|
||||
#ifndef ec_h
|
||||
#define ec_h
|
||||
|
||||
void ec_priv_to_pub(u8 *k, u8 *Q);
|
||||
int check_ecdsa(u8 *Q, u8 *R, u8 *S, u8 *hash);
|
||||
int generate_ecdsa(u8 *R, u8 *S, u8 *k, u8 *hash, bool randsig);
|
||||
|
||||
#endif
|
2
include/hash_stash.h
Normal file
2
include/hash_stash.h
Normal file
@ -0,0 +1,2 @@
|
||||
u8 frogcertXL_hash[] = {0x35,0x1D,0x39,0xF4,0xD3,0x1C,0x6A,0xA8,0xF7,0x29,0x90,0x73,0x3D,0x6C,0xC5,0x54,0x30,0x15,0xA8,0x06,0xD7,0xEB,0x75,0x92,0x5D,0x86,0xE0,0xCD,0x0C,0x20,0x7D,0x60}; //resources for flipnote injected DS dlp TAD
|
||||
u8 dlpcertXL_hash[] = {0xCB,0xD6,0x3F,0xB2,0x64,0xA4,0x12,0x33,0xE4,0x61,0x0E,0x98,0x49,0x4E,0x21,0xE9,0x70,0x3F,0x9D,0x36,0x68,0x03,0xBE,0x27,0xCE,0x0E,0xD7,0x6D,0x05,0xB4,0x6E,0xC1}; //resources for clean DS dlp TAD
|
34
include/sha256.h
Normal file
34
include/sha256.h
Normal file
@ -0,0 +1,34 @@
|
||||
/*********************************************************************
|
||||
* Filename: sha256.h
|
||||
* Author: Brad Conte (brad AT bradconte.com)
|
||||
* Copyright:
|
||||
* Disclaimer: This code is presented "as is" without any guarantees.
|
||||
* Details: Defines the API for the corresponding SHA1 implementation.
|
||||
*********************************************************************/
|
||||
|
||||
#ifndef SHA256_H
|
||||
#define SHA256_H
|
||||
|
||||
/*************************** HEADER FILES ***************************/
|
||||
#include <stddef.h>
|
||||
|
||||
/****************************** MACROS ******************************/
|
||||
#define SHA256_BLOCK_SIZE 32 // SHA256 outputs a 32 byte digest
|
||||
|
||||
/**************************** DATA TYPES ****************************/
|
||||
typedef unsigned char BYTE; // 8-bit byte
|
||||
typedef unsigned int WORD; // 32-bit word, change to "long" for 16-bit machines
|
||||
|
||||
typedef struct {
|
||||
BYTE data[64];
|
||||
WORD datalen;
|
||||
unsigned long long bitlen;
|
||||
WORD state[8];
|
||||
} SHA256_CTX;
|
||||
|
||||
/*********************** FUNCTION DECLARATIONS **********************/
|
||||
void sha256_init(SHA256_CTX *ctx);
|
||||
void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len);
|
||||
void sha256_final(SHA256_CTX *ctx, BYTE hash[]);
|
||||
|
||||
#endif // SHA256_H
|
58
include/tadpole.h
Normal file
58
include/tadpole.h
Normal file
@ -0,0 +1,58 @@
|
||||
|
||||
#define SIZE_FOOTER 0x4E0
|
||||
#define SIZE_CTCERTBIN 0x19E
|
||||
|
||||
typedef u8 sha256_hash[0x20];
|
||||
|
||||
typedef struct ecc_point_t
|
||||
{
|
||||
uint8_t r[0x1e];
|
||||
uint8_t s[0x1e];
|
||||
} __attribute__((packed)) ecc_point_t;
|
||||
|
||||
typedef struct ecc_cert_t
|
||||
{
|
||||
struct {
|
||||
uint32_t type;
|
||||
ecc_point_t val;
|
||||
uint8_t padding[0x40];
|
||||
} sig;
|
||||
char issuer[0x40];
|
||||
uint32_t key_type;
|
||||
char key_id[0x40];
|
||||
uint32_t unk;
|
||||
ecc_point_t pubkey;
|
||||
uint8_t padding2[0x3c];
|
||||
} __attribute__((packed)) ecc_cert_t;
|
||||
|
||||
typedef struct footer_t
|
||||
{
|
||||
sha256_hash banner_hash;
|
||||
sha256_hash hdr_hash;
|
||||
sha256_hash tmd_hash;
|
||||
sha256_hash content_hash[8];
|
||||
sha256_hash savedata_hash;
|
||||
sha256_hash bannersav_hash;
|
||||
ecc_point_t sig;
|
||||
ecc_cert_t ap;
|
||||
ecc_cert_t ct;
|
||||
} footer_t;
|
||||
|
||||
typedef struct header_t
|
||||
{
|
||||
u32 magic;
|
||||
u16 group_id;
|
||||
u16 version;
|
||||
u8 sha256_ivs[0x20];
|
||||
u8 aes_zeroblock[0x10];
|
||||
u64 tid;
|
||||
u64 installed_size;
|
||||
u32 content[11];
|
||||
u8 padding[0x7C]; //not totally padding, but no idea what some values in the middle are
|
||||
|
||||
|
||||
} header_t;
|
||||
|
||||
Result doSigning(u8 *ctcert_bin, footer_t *footer);
|
||||
void getSection(u8 *dsiware_pointer, u32 section_size, u8 *key, u8 *output);
|
||||
void placeSection(u8 *dsiware_pointer, u8 *section, u32 section_size, u8 *key, u8 *key_cmac);
|
19
include/types.h
Normal file
19
include/types.h
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2010 booto
|
||||
// Licensed under the terms of the GNU GPL, version 2
|
||||
// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
|
||||
#ifndef types_h
|
||||
#define types_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef int8_t s8;
|
||||
typedef uint8_t u8;
|
||||
typedef int16_t s16;
|
||||
typedef uint16_t u16;
|
||||
typedef int32_t s32;
|
||||
typedef uint32_t u32;
|
||||
typedef int64_t s64;
|
||||
typedef uint64_t u64;
|
||||
typedef int32_t Result;
|
||||
|
||||
#endif
|
BIN
resources/ctcert.bin
Normal file
BIN
resources/ctcert.bin
Normal file
Binary file not shown.
Binary file not shown.
227
source/TI_aes_128.cpp
Normal file
227
source/TI_aes_128.cpp
Normal file
@ -0,0 +1,227 @@
|
||||
/* --COPYRIGHT--,BSD
|
||||
* Copyright (c) 2011, Texas Instruments Incorporated
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of Texas Instruments Incorporated nor the names of
|
||||
* its contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* --/COPYRIGHT--*/
|
||||
/*
|
||||
* TI_aes_128.c
|
||||
*
|
||||
* Created on: Nov 3, 2011
|
||||
* Author: Eric Peeters
|
||||
*
|
||||
* Description: Implementation of the AES-128 as defined by the FIPS PUB 197:
|
||||
* the official AES standard
|
||||
*/
|
||||
|
||||
|
||||
// foreward sbox
|
||||
const unsigned char sbox[256] = {
|
||||
//0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, //0
|
||||
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, //1
|
||||
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, //2
|
||||
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, //3
|
||||
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, //4
|
||||
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, //5
|
||||
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, //6
|
||||
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, //7
|
||||
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, //8
|
||||
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, //9
|
||||
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, //A
|
||||
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, //B
|
||||
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, //C
|
||||
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, //D
|
||||
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, //E
|
||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; //F
|
||||
|
||||
// inverse sbox
|
||||
const unsigned char rsbox[256] =
|
||||
{ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb
|
||||
, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb
|
||||
, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e
|
||||
, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25
|
||||
, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92
|
||||
, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84
|
||||
, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06
|
||||
, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b
|
||||
, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73
|
||||
, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e
|
||||
, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b
|
||||
, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4
|
||||
, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f
|
||||
, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef
|
||||
, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61
|
||||
, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d };
|
||||
|
||||
// round constant
|
||||
const unsigned char Rcon[10] = {
|
||||
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36};
|
||||
|
||||
|
||||
// multiply by 2 in the galois field
|
||||
unsigned char galois_mul2(unsigned char value)
|
||||
{
|
||||
if (value>>7)
|
||||
{
|
||||
return ((value << 1)^0x1b);
|
||||
} else
|
||||
return (value << 1);
|
||||
}
|
||||
|
||||
// AES encryption and decryption function
|
||||
// The code was optimized for memory (flash and ram)
|
||||
// Combining both encryption and decryption resulted in a slower implementation
|
||||
// but much smaller than the 2 functions separated
|
||||
// This function only implements AES-128 encryption and decryption (AES-192 and
|
||||
// AES-256 are not supported by this code)
|
||||
void aes_enc_dec(unsigned char *state, unsigned char *key, unsigned char dir)
|
||||
{
|
||||
unsigned char buf1, buf2, buf3, buf4, round, i;
|
||||
|
||||
// In case of decryption
|
||||
if (dir) {
|
||||
// compute the last key of encryption before starting the decryption
|
||||
for (round = 0 ; round < 10; round++) {
|
||||
//key schedule
|
||||
key[0] = sbox[key[13]]^key[0]^Rcon[round];
|
||||
key[1] = sbox[key[14]]^key[1];
|
||||
key[2] = sbox[key[15]]^key[2];
|
||||
key[3] = sbox[key[12]]^key[3];
|
||||
for (i=4; i<16; i++) {
|
||||
key[i] = key[i] ^ key[i-4];
|
||||
}
|
||||
}
|
||||
|
||||
//first Addroundkey
|
||||
for (i = 0; i <16; i++){
|
||||
state[i]=state[i] ^ key[i];
|
||||
}
|
||||
}
|
||||
|
||||
// main loop
|
||||
for (round = 0; round < 10; round++){
|
||||
if (dir){
|
||||
//Inverse key schedule
|
||||
for (i=15; i>3; --i) {
|
||||
key[i] = key[i] ^ key[i-4];
|
||||
}
|
||||
key[0] = sbox[key[13]]^key[0]^Rcon[9-round];
|
||||
key[1] = sbox[key[14]]^key[1];
|
||||
key[2] = sbox[key[15]]^key[2];
|
||||
key[3] = sbox[key[12]]^key[3];
|
||||
} else {
|
||||
for (i = 0; i <16; i++){
|
||||
// with shiftrow i+5 mod 16
|
||||
state[i]=sbox[state[i] ^ key[i]];
|
||||
}
|
||||
//shift rows
|
||||
buf1 = state[1];
|
||||
state[1] = state[5];
|
||||
state[5] = state[9];
|
||||
state[9] = state[13];
|
||||
state[13] = buf1;
|
||||
|
||||
buf1 = state[2];
|
||||
buf2 = state[6];
|
||||
state[2] = state[10];
|
||||
state[6] = state[14];
|
||||
state[10] = buf1;
|
||||
state[14] = buf2;
|
||||
|
||||
buf1 = state[15];
|
||||
state[15] = state[11];
|
||||
state[11] = state[7];
|
||||
state[7] = state[3];
|
||||
state[3] = buf1;
|
||||
}
|
||||
//mixcol - inv mix
|
||||
if ((round > 0 && dir) || (round < 9 && !dir)) {
|
||||
for (i=0; i <4; i++){
|
||||
buf4 = (i << 2);
|
||||
if (dir){
|
||||
// precompute for decryption
|
||||
buf1 = galois_mul2(galois_mul2(state[buf4]^state[buf4+2]));
|
||||
buf2 = galois_mul2(galois_mul2(state[buf4+1]^state[buf4+3]));
|
||||
state[buf4] ^= buf1; state[buf4+1] ^= buf2; state[buf4+2] ^= buf1; state[buf4+3] ^= buf2;
|
||||
}
|
||||
// in all cases
|
||||
buf1 = state[buf4] ^ state[buf4+1] ^ state[buf4+2] ^ state[buf4+3];
|
||||
buf2 = state[buf4];
|
||||
buf3 = state[buf4]^state[buf4+1]; buf3=galois_mul2(buf3); state[buf4] = state[buf4] ^ buf3 ^ buf1;
|
||||
buf3 = state[buf4+1]^state[buf4+2]; buf3=galois_mul2(buf3); state[buf4+1] = state[buf4+1] ^ buf3 ^ buf1;
|
||||
buf3 = state[buf4+2]^state[buf4+3]; buf3=galois_mul2(buf3); state[buf4+2] = state[buf4+2] ^ buf3 ^ buf1;
|
||||
buf3 = state[buf4+3]^buf2; buf3=galois_mul2(buf3); state[buf4+3] = state[buf4+3] ^ buf3 ^ buf1;
|
||||
}
|
||||
}
|
||||
|
||||
if (dir) {
|
||||
//Inv shift rows
|
||||
// Row 1
|
||||
buf1 = state[13];
|
||||
state[13] = state[9];
|
||||
state[9] = state[5];
|
||||
state[5] = state[1];
|
||||
state[1] = buf1;
|
||||
//Row 2
|
||||
buf1 = state[10];
|
||||
buf2 = state[14];
|
||||
state[10] = state[2];
|
||||
state[14] = state[6];
|
||||
state[2] = buf1;
|
||||
state[6] = buf2;
|
||||
//Row 3
|
||||
buf1 = state[3];
|
||||
state[3] = state[7];
|
||||
state[7] = state[11];
|
||||
state[11] = state[15];
|
||||
state[15] = buf1;
|
||||
|
||||
for (i = 0; i <16; i++){
|
||||
// with shiftrow i+5 mod 16
|
||||
state[i]=rsbox[state[i]] ^ key[i];
|
||||
}
|
||||
} else {
|
||||
//key schedule
|
||||
key[0] = sbox[key[13]]^key[0]^Rcon[round];
|
||||
key[1] = sbox[key[14]]^key[1];
|
||||
key[2] = sbox[key[15]]^key[2];
|
||||
key[3] = sbox[key[12]]^key[3];
|
||||
for (i=4; i<16; i++) {
|
||||
key[i] = key[i] ^ key[i-4];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!dir) {
|
||||
//last Addroundkey
|
||||
for (i = 0; i <16; i++){
|
||||
// with shiftrow i+5 mod 16
|
||||
state[i]=state[i] ^ key[i];
|
||||
} // enf for
|
||||
} // end if (!dir)
|
||||
} // end function
|
273
source/aes-cbc-cmac.cpp
Normal file
273
source/aes-cbc-cmac.cpp
Normal file
@ -0,0 +1,273 @@
|
||||
/**
|
||||
* File: cmac.c
|
||||
* Created on: 21 авг. 2015 г.
|
||||
* Description:
|
||||
*
|
||||
*
|
||||
* Author: Roman Savrulin <romeo.deepmind@gmail.com>
|
||||
* Copyright: 2015 Roman Savrulin
|
||||
* Copying permission statement:
|
||||
*
|
||||
* This file is part of AES-CMAC.
|
||||
*
|
||||
* AES-CMAC is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/****************************************************************/
|
||||
/* AES-CMAC with AES-128 bit */
|
||||
/* CMAC Algorithm described in SP800-38B */
|
||||
/* Author: Junhyuk Song (junhyuk.song@samsung.com) */
|
||||
/* Jicheol Lee (jicheol.lee@samsung.com) */
|
||||
/****************************************************************/
|
||||
|
||||
#include "TI_aes_128.h"
|
||||
#include "aes-cbc-cmac.h"
|
||||
#include <string.h>
|
||||
|
||||
#ifdef DEBUG_CMAC
|
||||
#include <stdio.h>
|
||||
void print_hex(const char *str, const unsigned char *buf, int len) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if ((i % BLOCK_SIZE) == 0 && i != 0)
|
||||
printf("%s", str);
|
||||
printf("%02x", buf[i]);
|
||||
if ((i % 4) == 3)
|
||||
printf(" ");
|
||||
if ((i % BLOCK_SIZE) == LAST_INDEX)
|
||||
printf("\n");
|
||||
}
|
||||
if ((i % BLOCK_SIZE) != 0)
|
||||
printf("\n");
|
||||
}
|
||||
void print128(const unsigned char *bytes) {
|
||||
int j;
|
||||
for (j = 0; j < BLOCK_SIZE; j++) {
|
||||
printf("%02x", bytes[j]);
|
||||
if ((j % 4) == 3)
|
||||
printf(" ");
|
||||
}
|
||||
}
|
||||
|
||||
void print96(const unsigned char *bytes) {
|
||||
int j;
|
||||
for (j = 0; j < 12; j++) {
|
||||
printf("%02x", bytes[j]);
|
||||
if ((j % 4) == 3)
|
||||
printf(" ");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* For CMAC Calculation */
|
||||
static unsigned const char const_Rb[BLOCK_SIZE] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 };
|
||||
static unsigned const char const_Zero[BLOCK_SIZE] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
int AES_CMAC_CHECK(const unsigned char *key, const unsigned char *input, int length,
|
||||
const unsigned char *mac){
|
||||
unsigned char T[BLOCK_SIZE];
|
||||
AES_CMAC(key, input, length, T);
|
||||
/*print128(T);
|
||||
printf("\n");
|
||||
print128(mac);*/
|
||||
return memcmp(mac, T, BLOCK_SIZE);
|
||||
}
|
||||
|
||||
static void AES_128_ENC(unsigned const char *key, unsigned const char* msg, unsigned char *cipher){
|
||||
unsigned char key_copy[BLOCK_SIZE];
|
||||
memcpy(cipher, msg, BLOCK_SIZE);
|
||||
memcpy(key_copy, key, BLOCK_SIZE);
|
||||
aes_enc_dec(cipher, key_copy, 0);
|
||||
}
|
||||
|
||||
void AES_128_DEC(unsigned const char *key, unsigned const char* msg, unsigned char *cipher){
|
||||
unsigned char key_copy[BLOCK_SIZE];
|
||||
memcpy(cipher, msg, BLOCK_SIZE);
|
||||
memcpy(key_copy, key, BLOCK_SIZE);
|
||||
aes_enc_dec(cipher, key_copy, 1);
|
||||
}
|
||||
|
||||
void xor_128(const unsigned char *a, const unsigned char *b, unsigned char *out) {
|
||||
int i;
|
||||
for (i = 0; i < BLOCK_SIZE; i++) {
|
||||
out[i] = a[i] ^ b[i];
|
||||
}
|
||||
}
|
||||
|
||||
static void padding_AES(const unsigned char *lastb, unsigned char *pad, int length) {
|
||||
int j;
|
||||
length = length % BLOCK_SIZE;
|
||||
|
||||
if(length == 0){
|
||||
memcpy(pad, lastb, BLOCK_SIZE);
|
||||
return;
|
||||
}
|
||||
|
||||
/* original last block */
|
||||
for (j = 0; j < BLOCK_SIZE; j++) {
|
||||
if (j < length) {
|
||||
pad[j] = lastb[j];
|
||||
} else {
|
||||
pad[j] = 0x00;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int AES_CBC_ENC(const unsigned char *IV, const unsigned char *key, const unsigned char *input, int inputLength, unsigned char *output, int outputLength){
|
||||
unsigned char X[BLOCK_SIZE], Y[BLOCK_SIZE], M_last[BLOCK_SIZE];
|
||||
|
||||
if (inputLength <= 0)
|
||||
return 0; //nothing to encode
|
||||
|
||||
int n = (inputLength + LAST_INDEX) / BLOCK_SIZE; //TODO: last
|
||||
|
||||
memcpy(X, IV, BLOCK_SIZE);
|
||||
padding_AES(&input[BLOCK_SIZE * (n - 1)], M_last, inputLength);
|
||||
|
||||
for (int i = 0; (i < n) && outputLength > 0; i++) {
|
||||
unsigned const char * text = &input[BLOCK_SIZE * i];
|
||||
if(i == n - 1){
|
||||
text = M_last;
|
||||
}
|
||||
int outLen = (BLOCK_SIZE < outputLength)?BLOCK_SIZE:outputLength;
|
||||
xor_128(X, text, Y);
|
||||
AES_128_ENC(key, Y, X);
|
||||
memcpy(output, X, outLen);
|
||||
outputLength -= outLen;
|
||||
output += outLen;
|
||||
}
|
||||
|
||||
return n * BLOCK_SIZE;
|
||||
}
|
||||
|
||||
int AES_CBC_DEC(const unsigned char *IV, const unsigned char *key, const unsigned char *input, int inputLength, unsigned char *output, int outputLength){
|
||||
unsigned char X[BLOCK_SIZE], text[BLOCK_SIZE], Z[BLOCK_SIZE];
|
||||
|
||||
if (inputLength <= 0)
|
||||
return 0; //nothing to encode
|
||||
|
||||
inputLength = ( inputLength / BLOCK_SIZE ) * BLOCK_SIZE;
|
||||
|
||||
int n = (inputLength + LAST_INDEX) / BLOCK_SIZE;
|
||||
|
||||
memcpy(Z, IV, BLOCK_SIZE);
|
||||
for (int i = 0; (i < n) && outputLength > 0; i++) {
|
||||
unsigned const char * cipher = &input[BLOCK_SIZE * i];
|
||||
AES_128_DEC(key, cipher, X);
|
||||
xor_128(Z, X, text);
|
||||
memcpy(Z, cipher, BLOCK_SIZE);
|
||||
memcpy(output, text, BLOCK_SIZE);
|
||||
outputLength -= BLOCK_SIZE;
|
||||
output += BLOCK_SIZE;
|
||||
}
|
||||
|
||||
return n * BLOCK_SIZE;
|
||||
}
|
||||
|
||||
/* AES-CMAC Generation Function */
|
||||
|
||||
static void leftshift_onebit(const unsigned char *input, unsigned char *output) {
|
||||
int i;
|
||||
unsigned char overflow = 0;
|
||||
|
||||
for (i = LAST_INDEX; i >= 0; i--) {
|
||||
output[i] = input[i] << 1;
|
||||
output[i] |= overflow;
|
||||
overflow = (input[i] & 0x80) ? 1 : 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void generate_subkey(const unsigned char *key, unsigned char *K1, unsigned
|
||||
char *K2) {
|
||||
unsigned char L[BLOCK_SIZE];
|
||||
unsigned char tmp[BLOCK_SIZE];
|
||||
|
||||
AES_128_ENC(key, const_Zero, L);
|
||||
|
||||
if ((L[0] & 0x80) == 0) { /* If MSB(L) = 0, then K1 = L << 1 */
|
||||
leftshift_onebit(L, K1);
|
||||
} else { /* Else K1 = ( L << 1 ) (+) Rb */
|
||||
|
||||
leftshift_onebit(L, tmp);
|
||||
xor_128(tmp, const_Rb, K1);
|
||||
}
|
||||
|
||||
if ((K1[0] & 0x80) == 0) {
|
||||
leftshift_onebit(K1, K2);
|
||||
} else {
|
||||
leftshift_onebit(K1, tmp);
|
||||
xor_128(tmp, const_Rb, K2);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void padding(const unsigned char *lastb, unsigned char *pad, int length) {
|
||||
int j;
|
||||
|
||||
/* original last block */
|
||||
for (j = 0; j < BLOCK_SIZE; j++) {
|
||||
if (j < length) {
|
||||
pad[j] = lastb[j];
|
||||
} else if (j == length) {
|
||||
pad[j] = 0x80;
|
||||
} else {
|
||||
pad[j] = 0x00;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AES_CMAC(const unsigned char *key, const unsigned char *input, int length,
|
||||
unsigned char *mac) {
|
||||
unsigned char X[BLOCK_SIZE], Y[BLOCK_SIZE], M_last[BLOCK_SIZE], padded[BLOCK_SIZE];
|
||||
unsigned char K1[BLOCK_SIZE], K2[BLOCK_SIZE];
|
||||
int n, i, flag;
|
||||
generate_subkey(key, K1, K2);
|
||||
|
||||
n = (length + LAST_INDEX) / BLOCK_SIZE; /* n is number of rounds */
|
||||
|
||||
if (n == 0) {
|
||||
n = 1;
|
||||
flag = 0;
|
||||
} else {
|
||||
if ((length % BLOCK_SIZE) == 0) { /* last block is a complete block */
|
||||
flag = 1;
|
||||
} else { /* last block is not complete block */
|
||||
flag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag) { /* last block is complete block */
|
||||
xor_128(&input[BLOCK_SIZE * (n - 1)], K1, M_last);
|
||||
} else {
|
||||
padding(&input[BLOCK_SIZE * (n - 1)], padded, length % BLOCK_SIZE);
|
||||
xor_128(padded, K2, M_last);
|
||||
}
|
||||
|
||||
memset(X, 0, BLOCK_SIZE);
|
||||
for (i = 0; i < n - 1; i++) {
|
||||
xor_128(X, &input[BLOCK_SIZE * i], Y); /* Y := Mi (+) X */
|
||||
AES_128_ENC(key, Y, X); /* X := AES-128(KEY, Y); */
|
||||
}
|
||||
|
||||
xor_128(X, M_last, Y);
|
||||
AES_128_ENC(key, Y, X);
|
||||
|
||||
memcpy(mac, X, BLOCK_SIZE);
|
||||
}
|
137
source/bn.cpp
Normal file
137
source/bn.cpp
Normal file
@ -0,0 +1,137 @@
|
||||
// Copyright 2007,2008 Segher Boessenkool <segher@kernel.crashing.org>
|
||||
// Licensed under the terms of the GNU GPL, version 2
|
||||
// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
|
||||
// obtained from http://git.infradead.org/?p=users/segher/wii.git
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "types.h"
|
||||
|
||||
#if 0
|
||||
static void bn_print(char *name, u8 *a, u32 n)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
printf("%s = ", name);
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
printf("%02x", a[i]);
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
static void bn_zero(u8 *d, u32 n)
|
||||
{
|
||||
memset(d, 0, n);
|
||||
}
|
||||
|
||||
static void bn_copy(u8 *d, u8 *a, u32 n)
|
||||
{
|
||||
memcpy(d, a, n);
|
||||
}
|
||||
|
||||
int bn_compare(u8 *a, u8 *b, u32 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;
|
||||
}
|
||||
|
||||
void bn_sub_modulus(u8 *a, u8 *N, u32 n)
|
||||
{
|
||||
u32 i;
|
||||
u32 dig;
|
||||
u8 c;
|
||||
|
||||
c = 0;
|
||||
for (i = n - 1; i < n; i--) {
|
||||
dig = N[i] + c;
|
||||
c = (a[i] < dig);
|
||||
a[i] -= dig;
|
||||
}
|
||||
}
|
||||
|
||||
void bn_add(u8 *d, u8 *a, u8 *b, u8 *N, u32 n)
|
||||
{
|
||||
u32 i;
|
||||
u32 dig;
|
||||
u8 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(u8 *d, u8 *a, u8 *b, u8 *N, u32 n)
|
||||
{
|
||||
u32 i;
|
||||
u8 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(u8 *d, u8 *a, u8 *N, u32 n, u8 *e, u32 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) {
|
||||
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(u8 *d, u8 *a, u8 *N, u32 n)
|
||||
{
|
||||
u8 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);
|
||||
}
|
||||
|
||||
void bn_shiftr(u8 *in, u32 size, u32 shiftn){ //this is to help convert sha1 ecdsa to sha256. this curve is limited to 233 bits so the 256 bit hash needs to be shifted right 23 bits.
|
||||
u8 carry=0;
|
||||
u8 temp=0;
|
||||
for(u32 j=0;j<shiftn;j++){
|
||||
for(u32 i=0;i<size;i++){
|
||||
temp=*(in+i) & 1;
|
||||
*(in+i)=(*(in+i) >> 1 ) | carry<<7;
|
||||
carry=temp;
|
||||
}
|
||||
carry=0; temp=0;
|
||||
}
|
||||
}
|
60
source/crypto.cpp
Normal file
60
source/crypto.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
#include "types.h"
|
||||
#include "aes-cbc-cmac.h"
|
||||
#include "crypto.h"
|
||||
#include "sha256.h"
|
||||
|
||||
|
||||
void encryptAES(u8 *plaintext, u32 size, u8 *key, u8 *iv, u8 *output) {
|
||||
AES_CBC_ENC(iv, key, plaintext, size, output, size);
|
||||
}
|
||||
|
||||
void decryptAES(u8 *ciphertext, u32 size, u8 *key, u8 *iv, u8 *output) {
|
||||
AES_CBC_DEC(iv, key, ciphertext, size, output, size);
|
||||
}
|
||||
|
||||
void calculateCMAC(u8 *input, u32 size, u8 *key, u8 *output) {
|
||||
AES_CMAC(key, input, size, output);
|
||||
}
|
||||
|
||||
void calculateSha256(u8 *input, u32 size, u8 *output) {
|
||||
//FSUSER_UpdateSha256Context(input, size, output);
|
||||
SHA256_CTX *ctx = (SHA256_CTX*)malloc(sizeof(SHA256_CTX));
|
||||
sha256_init(ctx);
|
||||
sha256_update(ctx, input, size);
|
||||
sha256_final(ctx, output);
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
// Full credit goes to https://github.com/luigoalma/3ds_keyscrambler/blob/master/src/UnScrambler.c#L50
|
||||
void keyScrambler(u8 *Y, bool cmacYN, u8 *normal_key) {
|
||||
u8 C[0x10] = {0x1F, 0xF9, 0xE9, 0xAA, 0xC5, 0xFE, 0x04, 0x08, 0x02, 0x45, 0x91, 0xDC, 0x5D, 0x52, 0x76, 0x8A};
|
||||
u8 X_normal[0x10] = {0x6F, 0xBB, 0x01, 0xF8, 0x72, 0xCA, 0xF9, 0xC0, 0x18, 0x34, 0xEE, 0xC0, 0x40, 0x65, 0xEE, 0x53};
|
||||
u8 X_cmac[0x10] = {0xB5, 0x29, 0x22, 0x1C, 0xDD, 0xB5, 0xDB, 0x5A, 0x1B, 0xF2, 0x6E, 0xFF, 0x20, 0x41, 0xE8, 0x75};
|
||||
u8 *X = (cmacYN) ? X_cmac : X_normal;
|
||||
|
||||
int i;
|
||||
u8 shifted_X[0x10];
|
||||
for(i=0;i<16;i++){
|
||||
//The joke is already dead, but I keep doing it. So, more type casts and masks.
|
||||
if(i!=15) shifted_X[i] = (u8)((((u8)X[i] << (u8)2)&0xFC) + (((u8)X[i+1] >> (u8)6)&0x03))&0xff;
|
||||
else shifted_X[i] = (u8)((((u8)X[i] << (u8)2)&0xFC) + (((u8)X[0] >> (u8)6)&0x03))&0xff;
|
||||
}
|
||||
u8 shifted_X_xor_Y[0x10];
|
||||
for(i=0;i<16;i++){
|
||||
//Do I need to say anything more about the type casts?
|
||||
shifted_X_xor_Y[i] = (u8)((u8)shifted_X[i] ^ (u8)Y[i]);
|
||||
}
|
||||
u8 shifted_X_xor_Y_addition_C[0x10];
|
||||
u8 carry = 0;
|
||||
for(i=0;i<16;i++){
|
||||
//Type casts. Type casts everywhere.
|
||||
shifted_X_xor_Y_addition_C[15-i] = (u8)((u8)shifted_X_xor_Y[15-i] + (u8)carry + (u8)C[15-i]);
|
||||
carry = (u8)(((u16)((u8)shifted_X_xor_Y[15-i] + (u8)carry + (u8)C[15-i])) >> (u8)8);
|
||||
}
|
||||
for(i=0;i<16;i++){
|
||||
//Just make it stop! Oh wait, there's no more type casts and masks after this loop.
|
||||
if(i < 5) normal_key[i] = (u8)((((u8)shifted_X_xor_Y_addition_C[10+i] << (u8)7)&0x80) + (((u8)shifted_X_xor_Y_addition_C[10+i+1] >> (u8)1)&0x7F))&0xff;
|
||||
else if (i == 5) normal_key[i] = (u8)((((u8)shifted_X_xor_Y_addition_C[10+i] << (u8)7)&0x80) + (((u8)shifted_X_xor_Y_addition_C[0] >> (u8)1)&0x7F))&0xff;
|
||||
else normal_key[i] = (u8)((((u8)shifted_X_xor_Y_addition_C[-6+i] << (u8)7)&0x80) + (((u8)shifted_X_xor_Y_addition_C[-6+i+1] >> (u8)1)&0x7F))&0xff;
|
||||
}
|
||||
};
|
402
source/ec.cpp
Normal file
402
source/ec.cpp
Normal file
@ -0,0 +1,402 @@
|
||||
// Copyright 2007,2008 Segher Boessenkool <segher@kernel.crashing.org>
|
||||
// Licensed under the terms of the GNU GPL, version 2
|
||||
// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
|
||||
// obtained from http://git.infradead.org/?p=users/segher/wii.git
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
//#include <openssl/sha.h>
|
||||
#include "bn.h"
|
||||
#include "types.h"
|
||||
|
||||
#if 0
|
||||
// y**2 + x*y = x**3 + x + b
|
||||
static u8 ec_b[30] =
|
||||
"\x00\x66\x64\x7e\xde\x6c\x33\x2c\x7f\x8c\x09\x23\xbb\x58\x21"
|
||||
"\x3b\x33\x3b\x20\xe9\xce\x42\x81\xfe\x11\x5f\x7d\x8f\x90\xad";
|
||||
|
||||
#endif
|
||||
|
||||
// order of the addition group of points
|
||||
static u8 ec_N[31] =
|
||||
"\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
"\x13\xe9\x74\xe7\x2f\x8a\x69\x22\x03\x1d\x26\x03\xcf\xe0\xd7";
|
||||
|
||||
// base point
|
||||
static u8 ec_G[61] =
|
||||
"\x00\xfa\xc9\xdf\xcb\xac\x83\x13\xbb\x21\x39\xf1\xbb\x75\x5f"
|
||||
"\xef\x65\xbc\x39\x1f\x8b\x36\xf8\xf8\xeb\x73\x71\xfd\x55\x8b"
|
||||
"\x01\x00\x6a\x08\xa4\x19\x03\x35\x06\x78\xe5\x85\x28\xbe\xbf"
|
||||
"\x8a\x0b\xef\xf8\x67\xa7\xca\x36\x71\x6f\x7e\x01\xf8\x10\x52";
|
||||
|
||||
#if 0
|
||||
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");
|
||||
}
|
||||
#endif
|
||||
|
||||
static void elt_copy(u8 *d, u8 *a)
|
||||
{
|
||||
memcpy(d, a, 30);
|
||||
}
|
||||
|
||||
static void elt_zero(u8 *d)
|
||||
{
|
||||
memset(d, 0, 30);
|
||||
}
|
||||
|
||||
static int elt_is_zero(u8 *d)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < 30; i++)
|
||||
if (d[i] != 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void elt_add(u8 *d, u8 *a, u8 *b)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < 30; i++)
|
||||
d[i] = a[i] ^ b[i];
|
||||
}
|
||||
|
||||
static void elt_mul_x(u8 *d, u8 *a)
|
||||
{
|
||||
u8 carry, x, y;
|
||||
u32 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(u8 *d, u8 *a, u8 *b)
|
||||
{
|
||||
u32 i, n;
|
||||
u8 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 u8 square[17] =
|
||||
"\x00\x01\x04\x05\x10\x11\x14\x15\x40\x41\x44\x45\x50\x51\x54\x55";
|
||||
|
||||
static void elt_square_to_wide(u8 *d, u8 *a)
|
||||
{
|
||||
u32 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(u8 *d)
|
||||
{
|
||||
u32 i;
|
||||
u8 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(u8 *d, 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, u8 *a, u8 *b, u32 j)
|
||||
{
|
||||
u8 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(u8 *d, u8 *a)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
#if 0
|
||||
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); // t = x*x
|
||||
elt_mul(s, t, x); // s = x*x*x
|
||||
|
||||
elt_add(s, s, t); // s = x*x*x + x*x
|
||||
|
||||
elt_square(t, y); // t = y*y
|
||||
elt_add(s, s, t); // s = x*x*x + x*x + y*y
|
||||
|
||||
elt_mul(t, x, y); // t = x*y
|
||||
elt_add(s, s, t); // s = x*x*x + x*x + y*y + x*y
|
||||
|
||||
elt_add(s, s, ec_b); // s = x*x*x + x*x + y*y + x*y + ec_b
|
||||
|
||||
return elt_is_zero(s);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int point_is_zero(u8 *p)
|
||||
{
|
||||
return elt_is_zero(p) && elt_is_zero(p + 30);
|
||||
}
|
||||
|
||||
static void point_double(u8 *r, u8 *p)
|
||||
{
|
||||
u8 s[30], t[30];
|
||||
u8 *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); // t = 1/px
|
||||
elt_mul(s, py, t); // s = py/px
|
||||
elt_add(s, s, px); // s = py/px + px
|
||||
|
||||
elt_square(t, px); // t = px*px
|
||||
|
||||
elt_square(rx, s); // rx = s*s
|
||||
elt_add(rx, rx, s); // rx = s*s + s
|
||||
rx[29] ^= 1; // rx = s*s + s + 1
|
||||
|
||||
elt_mul(ry, s, rx); // ry = s * rx
|
||||
elt_add(ry, ry, rx); // ry = s*rx + rx
|
||||
elt_add(ry, ry, t); // ry = s*rx + rx + px*px
|
||||
}
|
||||
|
||||
static void point_add(u8 *r, u8 *p, u8 *q)
|
||||
{
|
||||
u8 s[30], t[30], u[30];
|
||||
u8 *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);
|
||||
}
|
||||
|
||||
void point_mul(u8 *d, u8 *a, u8 *b) // a is bignum
|
||||
{
|
||||
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_double(d, d);
|
||||
if ((a[i] & mask) != 0)
|
||||
point_add(d, d, b);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int generate_ecdsa(u8 *R, u8 *S, u8 *k, u8 *hash, bool randsig)
|
||||
{
|
||||
u8 e[30];
|
||||
u8 kk[30];
|
||||
u8 m[30];
|
||||
u8 minv[30];
|
||||
u8 mG[60];
|
||||
srand(time(0));
|
||||
|
||||
elt_zero(e);
|
||||
bn_shiftr(hash, 32, 7);
|
||||
memcpy(e, hash, 30);
|
||||
|
||||
memset(m, 0, 30);
|
||||
|
||||
if(randsig){
|
||||
for(int i=1;i<30;i++){
|
||||
m[i]=rand() & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
m[29]=1;
|
||||
|
||||
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_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);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int check_ecdsa(u8 *Q, u8 *R, u8 *S, 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);
|
||||
bn_shiftr(hash, 32, 7); //shift right 7 bits.
|
||||
memcpy(e, hash, 30); //then shift 16 more bits right by cutting off the last two bytes of 32 byte sha256.
|
||||
//this gets our bignum sha256 hash to fit in the 233 bit limit of this ecdsa curve.
|
||||
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(u8 *k, u8 *Q)
|
||||
{
|
||||
point_mul(Q, k, ec_G);
|
||||
}
|
366
source/main.cpp
Normal file
366
source/main.cpp
Normal file
@ -0,0 +1,366 @@
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include "crypto.h"
|
||||
#include "tadpole.h"
|
||||
#include "types.h"
|
||||
#include "hash_stash.h"
|
||||
|
||||
void error(const char *errormsg, const char *filename, bool fatal) {
|
||||
printf("%s:%s %s\nHit Enter to close\n", fatal ? "ERROR":"WARNING", errormsg, filename);
|
||||
getchar();
|
||||
if(fatal) exit(1);
|
||||
}
|
||||
|
||||
u8 *readAllBytes(const char *filename, u32 &filelen) {
|
||||
FILE *fileptr = fopen(filename, "rb");
|
||||
if (fileptr == NULL) {
|
||||
error("Failed to open ", filename, true);
|
||||
}
|
||||
|
||||
fseek(fileptr, 0, SEEK_END);
|
||||
filelen = ftell(fileptr);
|
||||
rewind(fileptr);
|
||||
|
||||
if(filelen > 0x4000000) filelen=0x4000000; //keep dsiware buffer reasonable
|
||||
|
||||
u8 *buffer = (u8*)malloc(filelen);
|
||||
|
||||
fread(buffer, filelen, 1, fileptr);
|
||||
fclose(fileptr);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void writeAllBytes(const char *filename, u8 *filedata, u32 filelen) {
|
||||
FILE *fileptr = fopen(filename, "wb");
|
||||
fwrite(filedata, 1, filelen, fileptr);
|
||||
fclose(fileptr);
|
||||
}
|
||||
|
||||
void dumpMsedData(u8 *msed){
|
||||
u32 keyy[4]={0};
|
||||
int mdata[3]={33,33,33};
|
||||
memcpy(keyy, msed+0x110, 0x10);
|
||||
mdata[0]=(keyy[0]&0xFFFFFF00) | 0x80;
|
||||
keyy[3]&=0x7FFFFFFF;
|
||||
|
||||
mdata[1]=(keyy[0]/5) - keyy[3];
|
||||
if(keyy[1]==2) mdata[2]=3;
|
||||
else if(keyy[1]==0) mdata[2]=2;
|
||||
|
||||
writeAllBytes("msed_data.bin", (u8*)mdata, 12);
|
||||
}
|
||||
|
||||
u16 crc16(u8 *data, u32 N) //https://modbus.control.com/thread/1381836105#1381859471
|
||||
{
|
||||
u16 reg, bit, yy, flag;
|
||||
|
||||
yy = 0;
|
||||
reg = 0xffff;
|
||||
|
||||
while( N-- > 0 )
|
||||
{
|
||||
reg = reg ^ data[yy];
|
||||
yy = yy + 1;
|
||||
|
||||
for ( bit = 0; bit <= 7; bit++ )
|
||||
{
|
||||
flag = reg & 0x0001;
|
||||
reg = reg >> 1;
|
||||
if ( flag == 1 )
|
||||
reg = reg ^ 0xa001;
|
||||
}
|
||||
}
|
||||
return ( reg );
|
||||
}
|
||||
|
||||
void fixcrc16(u16 *checksum, u8 *message, u32 len){
|
||||
u16 original=*checksum;
|
||||
u16 calculated=crc16(message, len);
|
||||
printf("orig:%04X calc:%04X ", original, calculated);
|
||||
if(original != calculated){
|
||||
*checksum=calculated;
|
||||
printf("fixed\n");
|
||||
return;
|
||||
}
|
||||
printf("good\n");
|
||||
}
|
||||
|
||||
void dumpTad(char *filename, char *dname) {
|
||||
u8 *dsiware, *wbuff, *contents, *banner, *header, *footer, *movable;
|
||||
u32 dsiware_size, movable_size, banner_size=0x4000, header_size=0xF0, footer_size=0x4E0; //the 3ds currently uses the 11 content sections version of dsiware exports. this is all we should encounter.
|
||||
u32 banner_off=0, header_off=0x4020, footer_off=0x4130, tmd_off=0x4630; //0x4000+0x20+0xF0+0x20+0x4E0+0x20
|
||||
u32 content_size[11]={0};
|
||||
const char *content_namelist[]={"tmd","srl.nds","2.bin","3.bin","4.bin","5.bin","6.bin","7.bin","8.bin","public.sav","banner.sav"};
|
||||
u32 content_off=tmd_off;
|
||||
u32 checked_size=0;
|
||||
//u8 header_hash[0x20] = {0}, srl_hash[0x20] = {0}, tmp_hash[0x20] = {0}, tmd_hash[0x20]={0}, banner_hash[0x20]={0};
|
||||
u8 normalKey[0x10] = {0}, normalKey_CMAC[0x10] = {0};
|
||||
header_t header_out;
|
||||
memset(&header_out, 0, 0xF0);
|
||||
|
||||
printf("Reading %s\n", filename);
|
||||
dsiware = readAllBytes(filename, dsiware_size);
|
||||
if (dsiware_size > 0x4000000) {
|
||||
error("Provided dsiware seems to be way too large!","", true);
|
||||
}
|
||||
|
||||
printf("Reading resources/movable.sed\n");
|
||||
movable = readAllBytes("resources/movable.sed", movable_size);
|
||||
if (movable_size != 320 && movable_size != 288) {
|
||||
error("Provided movable.sed is not 320 or 288 bytes of size","", true);
|
||||
}
|
||||
|
||||
printf("Dumping msed_data.bin\n");
|
||||
dumpMsedData(movable);
|
||||
|
||||
printf("Scrambling keys\n");
|
||||
keyScrambler((movable + 0x110), false, normalKey);
|
||||
keyScrambler((movable + 0x110), true, normalKey_CMAC);
|
||||
|
||||
wbuff=(u8*)malloc(tmd_off);
|
||||
|
||||
banner=wbuff;
|
||||
header=wbuff+header_off;
|
||||
footer=wbuff+footer_off;
|
||||
|
||||
// === HEADER ===
|
||||
printf("Decrypting header\n");
|
||||
getSection((dsiware + header_off), header_size, normalKey, header);
|
||||
|
||||
if (memcmp("3FDT", header, 4)) {
|
||||
error("Decryption failed","", true);
|
||||
}
|
||||
|
||||
memcpy(content_size, header+0x48, 11*4);
|
||||
content_size[0]+=0xC; //tmd padding adjust
|
||||
|
||||
printf("Verifying input dsiware size\n");
|
||||
for(int i=0;i<11;i++){
|
||||
if(content_size[i]){
|
||||
checked_size+=(content_size[i]+0x20);
|
||||
}
|
||||
}
|
||||
checked_size+=tmd_off;
|
||||
|
||||
|
||||
printf("checked %08X actual %08X\n",checked_size, dsiware_size);
|
||||
if(checked_size != dsiware_size){
|
||||
error("Input dsiware size does not agree with its header!","", true);
|
||||
}
|
||||
|
||||
getSection((dsiware + banner_off), banner_size, normalKey, banner);
|
||||
getSection((dsiware + footer_off), footer_size, normalKey, footer);
|
||||
|
||||
chdir(dname);
|
||||
printf("Dumping %s/banner.bin\n", dname);
|
||||
writeAllBytes("banner.bin", banner, banner_size);
|
||||
printf("Dumping %s/header.bin\n", dname);
|
||||
writeAllBytes("header.bin", header, header_size);
|
||||
printf("Dumping %s/footer.bin\n", dname);
|
||||
writeAllBytes("footer.bin", footer, footer_size);
|
||||
|
||||
contents=(u8*)malloc(dsiware_size);
|
||||
|
||||
for(int i=0;i<11;i++){
|
||||
if(content_size[i]){
|
||||
printf("Dumping %s/%s\n", dname, content_namelist[i]);
|
||||
getSection((dsiware + content_off), content_size[i], normalKey, contents);
|
||||
writeAllBytes(content_namelist[i], contents, content_size[i]);
|
||||
content_off+=0x20;
|
||||
}
|
||||
content_off+=content_size[i];
|
||||
}
|
||||
|
||||
printf("Done!\n");
|
||||
|
||||
printf("Cleaning up\n");
|
||||
free(contents);
|
||||
free(dsiware);
|
||||
free(wbuff);
|
||||
free(movable);
|
||||
printf("Done!\n");
|
||||
}
|
||||
|
||||
void rebuildTad(char *filename, char *dname) {
|
||||
u8 *dsiware, *ctcert, *banner, *header, *footer, *movable;
|
||||
u32 ctcert_size, header_size, footer_size, movable_size, banner_size;
|
||||
u8 banner_hash[0x20]={0}, header_hash[0x20] = {0};
|
||||
u8 content_hash[11][0x20]={0};
|
||||
u32 banner_off=0, header_off=0x4020, footer_off=0x4130, tmd_off=0x4630; //0x4000+0x20+0xF0+0x20+0x4E0+0x20
|
||||
u32 content_off=tmd_off;
|
||||
u32 checked_size=tmd_off;
|
||||
u32 content_size[11]={0};
|
||||
const char *content_namelist[]={"tmd","srl.nds","2.bin","3.bin","4.bin","5.bin","6.bin","7.bin","8.bin","public.sav","banner.sav"};
|
||||
u8 *contents[11];
|
||||
u8 normalKey[0x10] = {0}, normalKey_CMAC[0x10] = {0};
|
||||
char outname[64]={0};
|
||||
memset(content_hash, 0, 11*0x20);
|
||||
|
||||
printf("Reading resources/movable.sed\n");
|
||||
movable = readAllBytes("resources/movable.sed", movable_size);
|
||||
if (movable_size != 320 && movable_size != 288) {
|
||||
error("Provided movable.sed is not 320 or 288 bytes of size","", true);
|
||||
}
|
||||
|
||||
printf("Reading resources/ctcert.bin\n");
|
||||
ctcert = readAllBytes("resources/ctcert.bin", ctcert_size);
|
||||
|
||||
chdir(dname);
|
||||
|
||||
printf("Reading %s/banner.bin\n", dname);
|
||||
banner = readAllBytes("banner.bin", banner_size);
|
||||
|
||||
printf("Reading %s/header.bin\n", dname);
|
||||
header = readAllBytes("header.bin", header_size);
|
||||
|
||||
printf("Reading %s/footer.bin\n", dname);
|
||||
footer = readAllBytes("footer.bin", footer_size);
|
||||
|
||||
printf("Fixing banner crc16s\n");
|
||||
fixcrc16((u16*)(banner+0x2), banner+0x20, 0x820);
|
||||
fixcrc16((u16*)(banner+0x4), banner+0x20, 0x920);
|
||||
fixcrc16((u16*)(banner+0x6), banner+0x20, 0xA20);
|
||||
fixcrc16((u16*)(banner+0x8), banner+0x1240, 0x1180);
|
||||
|
||||
printf("Scrambling keys\n");
|
||||
keyScrambler((movable + 0x110), false, normalKey);
|
||||
keyScrambler((movable + 0x110), true, normalKey_CMAC);
|
||||
|
||||
printf("Getting content section sizes and hashes\n");
|
||||
for(int i=0;i<11;i++){
|
||||
if( access( content_namelist[i], F_OK ) != -1 ) {
|
||||
if (i==1 && access( "srl.nds.inject", F_OK ) != -1 ) contents[i] = readAllBytes("srl.nds.inject", content_size[i]);
|
||||
else if (i==9 && access( "public.sav.inject", F_OK ) != -1 ) contents[i] = readAllBytes("public.sav.inject", content_size[i]);
|
||||
else contents[i] = readAllBytes(content_namelist[i], content_size[i]);
|
||||
|
||||
checked_size+=(content_size[i]+0x20);
|
||||
calculateSha256(contents[i],content_size[i], content_hash[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if(*(u32*)(header+0x48+4) < content_size[1]){
|
||||
*(u32*)(header+0x40)=(content_size[1]+0x20000)&0xFFFF8000;
|
||||
}
|
||||
|
||||
content_size[0]-=0xC;
|
||||
memcpy(header+0x48, content_size, 11*4);
|
||||
|
||||
printf("Getting banner and header hashes\n");
|
||||
calculateSha256(banner, banner_size, banner_hash);
|
||||
calculateSha256(header, header_size, header_hash);
|
||||
|
||||
printf("Writing final footer hashes\n");
|
||||
|
||||
memset(footer, 0, 13*0x20);
|
||||
memcpy(footer, banner_hash, 0x20);
|
||||
memcpy(footer+0x20, header_hash, 0x20);
|
||||
|
||||
for(int i=0;i<11;i++){
|
||||
if(content_size[i]){
|
||||
memcpy(footer+0x40+(i*0x20), content_hash[i], 0x20);
|
||||
}
|
||||
}
|
||||
|
||||
printf("Signing the footer!\n");
|
||||
Result res = doSigning(ctcert, (footer_t*)footer);
|
||||
if (res < 0) {
|
||||
error("Signing failed","", true);
|
||||
}
|
||||
|
||||
printf("Copying all sections to output buffer\n");
|
||||
|
||||
dsiware=(u8*)malloc(checked_size);
|
||||
printf("Writing banner\n"); placeSection((dsiware + banner_off), banner, banner_size, normalKey, normalKey_CMAC);
|
||||
printf("Writing header\n"); placeSection((dsiware + header_off), header, header_size, normalKey, normalKey_CMAC);
|
||||
printf("Writing TMD\n"); placeSection((dsiware + footer_off), footer, footer_size, normalKey, normalKey_CMAC);
|
||||
|
||||
content_size[0]+=0xC;
|
||||
for(int i=0;i<11;i++){
|
||||
if(content_size[i]){
|
||||
printf("Writing %s\n", content_namelist[i]);
|
||||
placeSection((dsiware + content_off), contents[i], content_size[i], normalKey, normalKey_CMAC);
|
||||
content_off+=(content_size[i]+0x20);
|
||||
free(contents[i]);
|
||||
}
|
||||
}
|
||||
|
||||
snprintf(outname, 32, "../%s.bin.patched", dname);
|
||||
|
||||
printf("Writing %s.bin.patched\n", dname);
|
||||
writeAllBytes(outname, dsiware, checked_size);
|
||||
printf("Done!\n");
|
||||
|
||||
printf("Cleaning up\n");
|
||||
free(banner);
|
||||
free(header);
|
||||
free(footer);
|
||||
free(dsiware);
|
||||
free(movable);
|
||||
free(ctcert);
|
||||
printf("Done!\n");
|
||||
}
|
||||
|
||||
void usage(){
|
||||
printf("TADpole <8-digitHex.bin(dsiware export)> <d|r>\n");
|
||||
printf("ex. TADpole 484E4441.bin d (this dumps the dsiware export)\n");
|
||||
printf("ex. TADpole 484E4441.bin r (this rebuilds the dsiware export)\n");
|
||||
}
|
||||
|
||||
int ishex(char *in, u32 size){
|
||||
const char hex[]="0123456789ABCDEFabcdef";
|
||||
u32 match=0;
|
||||
u32 i,c;
|
||||
for(i=0;i<size;i++){
|
||||
for(c=0;c<22;c++){
|
||||
if(in[i]==hex[c]){
|
||||
match=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(match==0) return 1;
|
||||
match=0;
|
||||
if(c>15) in[i]-=0x20; //toupper()
|
||||
//printf("%d\n",(int)c);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
char dname[64]={0};
|
||||
int len=strlen(argv[1]);
|
||||
|
||||
if(len<8 || argc!=3){
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(memcmp(argv[2], "d", 1) && memcmp(argv[2], "r", 1) && memcmp(argv[2], "D", 1) && memcmp(argv[2], "R", 1)){
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
memcpy(dname, argv[1], 8);
|
||||
//printf("hex check %d %s\n", len,dname);
|
||||
|
||||
if(ishex(dname,8)){
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
mkdir(dname);
|
||||
|
||||
printf("|TADpole by zoogie|\n");
|
||||
printf("|_______v2.0______|\n");
|
||||
|
||||
if (!memcmp(argv[2], "d", 1) || !memcmp(argv[2], "D", 1)) dumpTad(argv[1], dname);
|
||||
else if(!memcmp(argv[2], "r", 1) || !memcmp(argv[2], "R", 1)) rebuildTad(argv[1], dname);
|
||||
printf("\nJob completed\n");
|
||||
|
||||
return 0;
|
||||
}
|
160
source/sha256.cpp
Normal file
160
source/sha256.cpp
Normal file
@ -0,0 +1,160 @@
|
||||
/*********************************************************************
|
||||
* Filename: sha256.c
|
||||
* Author: Brad Conte (brad AT bradconte.com)
|
||||
* Copyright:
|
||||
* Disclaimer: This code is presented "as is" without any guarantees.
|
||||
* Details: Implementation of the SHA-256 hashing algorithm.
|
||||
SHA-256 is one of the three algorithms in the SHA2
|
||||
specification. The others, SHA-384 and SHA-512, are not
|
||||
offered in this implementation.
|
||||
Algorithm specification can be found here:
|
||||
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf
|
||||
This implementation uses little endian byte order.
|
||||
*********************************************************************/
|
||||
|
||||
/*************************** HEADER FILES ***************************/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
//#include <memory.h>
|
||||
#include "sha256.h"
|
||||
|
||||
/****************************** MACROS ******************************/
|
||||
#define ROTLEFT(a,b) (((a) << (b)) | ((a) >> (32-(b))))
|
||||
#define ROTRIGHT(a,b) (((a) >> (b)) | ((a) << (32-(b))))
|
||||
|
||||
#define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z)))
|
||||
#define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
|
||||
#define EP0(x) (ROTRIGHT(x,2) ^ ROTRIGHT(x,13) ^ ROTRIGHT(x,22))
|
||||
#define EP1(x) (ROTRIGHT(x,6) ^ ROTRIGHT(x,11) ^ ROTRIGHT(x,25))
|
||||
#define SIG0(x) (ROTRIGHT(x,7) ^ ROTRIGHT(x,18) ^ ((x) >> 3))
|
||||
#define SIG1(x) (ROTRIGHT(x,17) ^ ROTRIGHT(x,19) ^ ((x) >> 10))
|
||||
|
||||
/**************************** VARIABLES *****************************/
|
||||
static const WORD k[64] = {
|
||||
0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
|
||||
0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
|
||||
0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
|
||||
0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
|
||||
0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
|
||||
0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
|
||||
0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
|
||||
0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
|
||||
};
|
||||
|
||||
/*********************** FUNCTION DEFINITIONS ***********************/
|
||||
void sha256_transform(SHA256_CTX *ctx, const BYTE data[])
|
||||
{
|
||||
WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64];
|
||||
|
||||
for (i = 0, j = 0; i < 16; ++i, j += 4)
|
||||
m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]);
|
||||
for ( ; i < 64; ++i)
|
||||
m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];
|
||||
|
||||
a = ctx->state[0];
|
||||
b = ctx->state[1];
|
||||
c = ctx->state[2];
|
||||
d = ctx->state[3];
|
||||
e = ctx->state[4];
|
||||
f = ctx->state[5];
|
||||
g = ctx->state[6];
|
||||
h = ctx->state[7];
|
||||
|
||||
for (i = 0; i < 64; ++i) {
|
||||
t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i];
|
||||
t2 = EP0(a) + MAJ(a,b,c);
|
||||
h = g;
|
||||
g = f;
|
||||
f = e;
|
||||
e = d + t1;
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
a = t1 + t2;
|
||||
}
|
||||
|
||||
ctx->state[0] += a;
|
||||
ctx->state[1] += b;
|
||||
ctx->state[2] += c;
|
||||
ctx->state[3] += d;
|
||||
ctx->state[4] += e;
|
||||
ctx->state[5] += f;
|
||||
ctx->state[6] += g;
|
||||
ctx->state[7] += h;
|
||||
}
|
||||
|
||||
void sha256_init(SHA256_CTX *ctx)
|
||||
{
|
||||
ctx->datalen = 0;
|
||||
ctx->bitlen = 0;
|
||||
ctx->state[0] = 0x6a09e667;
|
||||
ctx->state[1] = 0xbb67ae85;
|
||||
ctx->state[2] = 0x3c6ef372;
|
||||
ctx->state[3] = 0xa54ff53a;
|
||||
ctx->state[4] = 0x510e527f;
|
||||
ctx->state[5] = 0x9b05688c;
|
||||
ctx->state[6] = 0x1f83d9ab;
|
||||
ctx->state[7] = 0x5be0cd19;
|
||||
}
|
||||
|
||||
void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len)
|
||||
{
|
||||
WORD i;
|
||||
|
||||
for (i = 0; i < len; ++i) {
|
||||
ctx->data[ctx->datalen] = data[i];
|
||||
ctx->datalen++;
|
||||
if (ctx->datalen == 64) {
|
||||
sha256_transform(ctx, ctx->data);
|
||||
ctx->bitlen += 512;
|
||||
ctx->datalen = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sha256_final(SHA256_CTX *ctx, BYTE hash[])
|
||||
{
|
||||
WORD i;
|
||||
|
||||
i = ctx->datalen;
|
||||
|
||||
// Pad whatever data is left in the buffer.
|
||||
if (ctx->datalen < 56) {
|
||||
ctx->data[i++] = 0x80;
|
||||
while (i < 56)
|
||||
ctx->data[i++] = 0x00;
|
||||
}
|
||||
else {
|
||||
ctx->data[i++] = 0x80;
|
||||
while (i < 64)
|
||||
ctx->data[i++] = 0x00;
|
||||
sha256_transform(ctx, ctx->data);
|
||||
memset(ctx->data, 0, 56);
|
||||
}
|
||||
|
||||
// Append to the padding the total message's length in bits and transform.
|
||||
ctx->bitlen += ctx->datalen * 8;
|
||||
ctx->data[63] = ctx->bitlen;
|
||||
ctx->data[62] = ctx->bitlen >> 8;
|
||||
ctx->data[61] = ctx->bitlen >> 16;
|
||||
ctx->data[60] = ctx->bitlen >> 24;
|
||||
ctx->data[59] = ctx->bitlen >> 32;
|
||||
ctx->data[58] = ctx->bitlen >> 40;
|
||||
ctx->data[57] = ctx->bitlen >> 48;
|
||||
ctx->data[56] = ctx->bitlen >> 56;
|
||||
sha256_transform(ctx, ctx->data);
|
||||
|
||||
// Since this implementation uses little endian byte ordering and SHA uses big endian,
|
||||
// reverse all the bytes when copying the final state to the output hash.
|
||||
for (i = 0; i < 4; ++i) {
|
||||
hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff;
|
||||
hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff;
|
||||
hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff;
|
||||
hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff;
|
||||
hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff;
|
||||
hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff;
|
||||
hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff;
|
||||
hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff;
|
||||
}
|
||||
}
|
132
source/tadpole.cpp
Normal file
132
source/tadpole.cpp
Normal file
@ -0,0 +1,132 @@
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include "crypto.h"
|
||||
#include "tadpole.h"
|
||||
#include "ec.h"
|
||||
#include "types.h"
|
||||
|
||||
void getSection(u8 *dsiware_pointer, u32 section_size, u8 *key, u8 *output) {
|
||||
decryptAES(dsiware_pointer, section_size, key, (dsiware_pointer + section_size + 0x10), output);
|
||||
}
|
||||
|
||||
void placeSection(u8 *dsiware_pointer, u8 *section, u32 section_size, u8 *key, u8 *key_cmac) {
|
||||
u8 allzero[0x10]= {0};
|
||||
|
||||
encryptAES(section, section_size, key, allzero, dsiware_pointer);
|
||||
|
||||
u8 section_hash[0x20] = {0};
|
||||
calculateSha256(section, section_size, section_hash);
|
||||
u8 section_cmac[0x20] = {0};
|
||||
calculateCMAC(section_hash, 0x20, key_cmac, section_cmac);
|
||||
|
||||
memcpy((dsiware_pointer + section_size), section_cmac, 0x10);
|
||||
memset((dsiware_pointer + section_size + 0x10), 0, 0x10);
|
||||
}
|
||||
|
||||
static void elt_print(const char *name, u8 *a)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
printf("%s = ", name);
|
||||
|
||||
for (i = 0; i < 30; i++)
|
||||
printf("%02x", a[i]);
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
Result doSigning(u8 *ctcert_bin, footer_t *footer) {
|
||||
Result res;
|
||||
u8 ct_priv[0x1E], ap_priv[0x1E], tmp_pub[0x3C], tmp_hash[0x20];
|
||||
memset(ap_priv, 0, 0x1E);
|
||||
ecc_cert_t ct_cert, ap_cert;
|
||||
ap_priv[0x1D]=1;
|
||||
|
||||
printf("loading keys from ctcert.bin...\n");
|
||||
memcpy(&ct_cert, ctcert_bin, 0x180);
|
||||
memcpy(ct_priv, (ctcert_bin + 0x180), 0x1E);
|
||||
|
||||
ec_priv_to_pub(ct_priv, tmp_pub);
|
||||
if (memcmp(tmp_pub, &ct_cert.pubkey, sizeof(tmp_pub)) != 0) {
|
||||
printf("error: ecc priv key does not correspond to the cert\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("using zeroed AP privkey to generate AP cert...\n");
|
||||
memset(&ap_cert, 0, sizeof(ap_cert));
|
||||
memcpy(&ap_cert.key_id, &footer->ap.key_id, 0x40);
|
||||
|
||||
snprintf(ap_cert.issuer, sizeof(ap_cert.issuer), "%s-%s", ct_cert.issuer, ct_cert.key_id);
|
||||
|
||||
ap_cert.key_type = 0x02000000; // key type
|
||||
ec_priv_to_pub(ap_priv, ap_cert.pubkey.r);// pub key
|
||||
ap_cert.sig.type = 0x05000100;// sig
|
||||
|
||||
srand(time(0));
|
||||
int check=rand();
|
||||
printf("%08X\n",check);
|
||||
int sanity=100;
|
||||
bool randsig=false;
|
||||
|
||||
do{
|
||||
printf("signing ap...\n"); // actually sign it
|
||||
calculateSha256((u8*)ap_cert.issuer, 0x100, tmp_hash);
|
||||
//calculateSha256((u8*)&check, 4, tmp_hash);
|
||||
res = generate_ecdsa(ap_cert.sig.val.r, ap_cert.sig.val.s, ct_priv, tmp_hash, randsig);
|
||||
if (res < 0) {
|
||||
printf("error: problem signing AP\n");
|
||||
}
|
||||
printf("re-verifying ap sig... ");
|
||||
calculateSha256((u8*)ap_cert.issuer, sizeof(ecc_cert_t)-sizeof(ap_cert.sig), tmp_hash);
|
||||
//calculateSha256((u8*)&check, 4, tmp_hash);
|
||||
res = check_ecdsa(ct_cert.pubkey.r, ap_cert.sig.val.r, ap_cert.sig.val.s, tmp_hash);
|
||||
if (res == 1) {
|
||||
printf("GOOD!\n");
|
||||
} else {
|
||||
printf("BAD\n");
|
||||
randsig=true;
|
||||
}
|
||||
elt_print("R", ap_cert.sig.val.r);
|
||||
elt_print("S", ap_cert.sig.val.s);
|
||||
elt_print("H", tmp_hash);
|
||||
sanity--;
|
||||
} while(res !=1 && sanity >=0);
|
||||
|
||||
sanity=100;
|
||||
randsig=false;
|
||||
|
||||
do{
|
||||
printf("signing footer...\n");
|
||||
calculateSha256((u8*)footer, 0x1A0, tmp_hash);
|
||||
//calculateSha256((u8*)&check, 4, tmp_hash);
|
||||
res = generate_ecdsa(footer->sig.r, footer->sig.s, ap_priv, tmp_hash, randsig);
|
||||
if (res < 0) {
|
||||
printf("error: problem signing footer\n");
|
||||
}
|
||||
printf("re-verifying footer sig... ");
|
||||
calculateSha256((u8*)footer, 0x1A0, tmp_hash);
|
||||
//calculateSha256((u8*)&check, 4, tmp_hash);
|
||||
res = check_ecdsa(ap_cert.pubkey.r, footer->sig.r, footer->sig.s, tmp_hash);
|
||||
if (res == 1) {
|
||||
printf("GOOD!\n");
|
||||
} else {
|
||||
printf("BAD\n");
|
||||
randsig=true;
|
||||
}
|
||||
elt_print("R", ap_cert.sig.val.r);
|
||||
elt_print("S", ap_cert.sig.val.s);
|
||||
elt_print("H", tmp_hash);
|
||||
sanity--;
|
||||
} while(res !=1 && sanity >=0);
|
||||
|
||||
|
||||
memcpy(&footer->ap, &ap_cert, 0x180);
|
||||
memcpy(&footer->ct, &ct_cert, 0x180);
|
||||
|
||||
printf("done signing\n");
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user