diff --git a/.gitignore b/.gitignore index 28d6b50e6..4672f1b6d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,28 @@ +# Built application files +build/ +app/.externalNativeBuild/ + +# Crashlytics configuations +com_crashlytics_export_strings.xml + +# Local configuration file (sdk path, etc) +local.properties + +# Gradle generated files +.gradle/ + +# Signing files +.signing/ + +# User-specific configurations +.idea/ *.iml -.gradle -/local.properties -/.idea/* + +# OS-specific files .DS_Store -/build -/captures -/ndk/libs -/ndk/obj -/app/build -/app/libs -/app/app.iml +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db diff --git a/.idea/compiler.xml b/.idea/compiler.xml deleted file mode 100644 index 96cc43efa..000000000 --- a/.idea/compiler.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml deleted file mode 100644 index c7d1c5a83..000000000 --- a/.idea/copyright/profiles_settings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml deleted file mode 100644 index 97626ba45..000000000 --- a/.idea/encodings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml deleted file mode 100644 index 681d7d03a..000000000 --- a/.idea/gradle.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 5d1998103..000000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index a50469e4d..000000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml deleted file mode 100644 index 7f68460d8..000000000 --- a/.idea/runConfigurations.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7f4..000000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 949ac880c..f9e66c7d4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -59,6 +59,11 @@ android { sourceSets.main { jniLibs.srcDir '../ndk/libs' } + externalNativeBuild { + ndkBuild { + path '../ndk/jni/Android.mk' + } + } } dependencies { diff --git a/app/src/main/java/com/hiddenramblings/tagmo/AmiiboDictionary.java b/app/src/main/java/com/hiddenramblings/tagmo/AmiiboDictionary.java index 8bb6aa42f..20efa8a4b 100644 --- a/app/src/main/java/com/hiddenramblings/tagmo/AmiiboDictionary.java +++ b/app/src/main/java/com/hiddenramblings/tagmo/AmiiboDictionary.java @@ -4,9 +4,12 @@ /** Data from https://docs.google.com/spreadsheets/d/1WJ4HxS9hkLquq-ATt1Rq9mioH6RDgP3qQrtYVaOdimM by /u/MacGuffen + or from : https://docs.google.com/spreadsheets/d/19E7pMhKN6x583uB6bWVBeaTMyBPtEAC-Bk59Y6cfgxA/ by N3evin & CheatFreak */ public class AmiiboDictionary { + // Last 4 bits of the 2nd byte are the game series identifier + // -------- ----XXXX static final HashMap seriesNames = new HashMap(); static { @@ -23,8 +26,12 @@ public class AmiiboDictionary { seriesNames.put(0x0C02, "Kirby"); seriesNames.put(0x0D02, "Pokkén Tournament"); seriesNames.put(0x0F02, "Monster Hunter Stories"); + seriesNames.put(0x0E02, "Mario Sports Superstars"); + } + // Same as above but with short names + // TODO: Useless IMO static final HashMap seriesShortNames = new HashMap(); static { @@ -41,8 +48,12 @@ public class AmiiboDictionary { seriesShortNames.put(0x0C02, "KIR"); seriesShortNames.put(0x0D02, "POK"); seriesShortNames.put(0x0F02, "MON"); + seriesShortNames.put(0x0E02, "MSS"); + } + // First 4 bits of the 2nd byte are the variant of the character + // -------- XXXX---- static final HashMap idList = new HashMap(); static { @@ -626,11 +637,111 @@ public class AmiiboDictionary { idList.put(0x031D, "Chelsea (ACCS)"); idList.put(0x031E, "Toby (ACCS)"); idList.put(0x034B, "Link (Ocarina of Time) (LOZ)"); + idList.put(0x034C, "Link (Majora's Mask) (LOZ)"); + idList.put(0x034D, "Link (Twilight Princess) (LOZ)"); + idList.put(0x034E, "Link (Skyward Sword) (LOZ)"); idList.put(0x034F, "8-bit Link (The Legend of Zelda) (LOZ)"); idList.put(0x0350, "Toon Link (The Wind Waker) (LOZ)"); idList.put(0x0352, "Toon Zelda (The Wind Waker) (LOZ)"); + idList.put(0x0353, "Link (Archer) (BOTW)"); + idList.put(0x0354, "Link (Rider) (BOTW)"); + idList.put(0x0355, "Guardian (BOTW)"); + idList.put(0x0356, "Zelda (BOTW)"); + idList.put(0x035C, "Bokoblin (BOTW)"); + idList.put(0x0269,"Mario - Soccer (MSS)"); + idList.put(0x026A,"Mario - Baseball (MSS)"); + idList.put(0x026B,"Mario - Tennis (MSS)"); + idList.put(0x026C,"Mario - Golf (MSS)"); + idList.put(0x026D,"Mario - Horse Racing (MSS)"); + idList.put(0x026E,"Luigi - Soccer (MSS)"); + idList.put(0x026F,"Luigi - Baseball (MSS)"); + idList.put(0x0270,"Luigi - Tennis (MSS)"); + idList.put(0x0271,"Luigi - Golf (MSS)"); + idList.put(0x0272,"Luigi - Horse Racing (MSS)"); + idList.put(0x0273,"Peach - Soccer (MSS)"); + idList.put(0x0274,"Peach - Baseball (MSS)"); + idList.put(0x0275,"Peach - Tennis (MSS)"); + idList.put(0x0276,"Peach - Golf (MSS)"); + idList.put(0x0277,"Peach - Horse Racing (MSS)"); + idList.put(0x0278,"Daisy - Soccer (MSS)"); + idList.put(0x0279,"Daisy - Baseball (MSS)"); + idList.put(0x027A,"Daisy - Tennis (MSS)"); + idList.put(0x027B,"Daisy - Golf (MSS)"); + idList.put(0x027C,"Daisy - Horse Racing (MSS)"); + idList.put(0x027D,"Yoshi - Soccer (MSS)"); + idList.put(0x027E,"Yoshi - Baseball (MSS)"); + idList.put(0x027F,"Yoshi - Tennis (MSS)"); + idList.put(0x0280,"Yoshi - Golf (MSS)"); + idList.put(0x0281,"Yoshi - Horse Racing (MSS)"); + idList.put(0x0282,"Wario - Soccer (MSS)"); + idList.put(0x0283,"Wario - Baseball (MSS)"); + idList.put(0x0284,"Wario - Tennis (MSS)"); + idList.put(0x0285,"Wario - Golf (MSS)"); + idList.put(0x0286,"Wario - Horse Racing (MSS)"); + idList.put(0x0287,"Waluigi - Soccer (MSS)"); + idList.put(0x0288,"Waluigi - Baseball (MSS)"); + idList.put(0x0289,"Waluigi - Tennis (MSS)"); + idList.put(0x028A,"Waluigi - Golf (MSS)"); + idList.put(0x028B,"Waluigi - Horse Racing (MSS)"); + idList.put(0x028C,"Donkey Kong - Soccer (MSS)"); + idList.put(0x028D,"Donkey Kong - Baseball (MSS)"); + idList.put(0x028E,"Donkey Kong - Tennis (MSS)"); + idList.put(0x028F,"Donkey Kong - Golf (MSS)"); + idList.put(0x0290,"Donkey Kong - Horse Racing (MSS)"); + idList.put(0x0291,"Diddy Kong - Soccer (MSS)"); + idList.put(0x0292,"Diddy Kong - Baseball (MSS)"); + idList.put(0x0293,"Diddy Kong - Tennis (MSS)"); + idList.put(0x0294,"Diddy Kong - Golf (MSS)"); + idList.put(0x0295,"Diddy Kong - Horse Racing (MSS)"); + idList.put(0x0296,"Bowser - Soccer (MSS)"); + idList.put(0x0297,"Bowser - Baseball (MSS)"); + idList.put(0x0298,"Bowser - Tennis (MSS)"); + idList.put(0x0299,"Bowser - Golf (MSS)"); + idList.put(0x029A,"Bowser - Horse Racing (MSS)"); + idList.put(0x029B,"Bowser Jr. - Soccer (MSS)"); + idList.put(0x029C,"Bowser Jr. - Baseball (MSS)"); + idList.put(0x029D,"Bowser Jr. - Tennis (MSS)"); + idList.put(0x029E,"Bowser Jr. - Golf (MSS)"); + idList.put(0x029F,"Bowser Jr. - Horse Racing (MSS)"); + idList.put(0x02A0,"Boo - Soccer (MSS)"); + idList.put(0x02A1,"Boo - Baseball (MSS)"); + idList.put(0x02A2,"Boo - Tennis (MSS)"); + idList.put(0x02A3,"Boo - Golf (MSS)"); + idList.put(0x02A4,"Boo - Horse Racing (MSS)"); + idList.put(0x02A5,"Baby Mario - Soccer (MSS)"); + idList.put(0x02A6,"Baby Mario - Baseball (MSS)"); + idList.put(0x02A7,"Baby Mario - Tennis (MSS)"); + idList.put(0x02A8,"Baby Mario - Golf (MSS)"); + idList.put(0x02A9,"Baby Mario - Horse Racing (MSS)"); + idList.put(0x02AA,"Baby Luigi - Soccer (MSS)"); + idList.put(0x02AB,"Baby Luigi - Baseball (MSS)"); + idList.put(0x02AC,"Baby Luigi - Tennis (MSS)"); + idList.put(0x02AD,"Baby Luigi - Golf (MSS)"); + idList.put(0x02AE,"Baby Luigi - Horse Racing (MSS)"); + idList.put(0x02AF,"Birdo - Soccer (MSS)"); + idList.put(0x02B0,"Birdo - Baseball (MSS)"); + idList.put(0x02B1,"Birdo - Tennis (MSS)"); + idList.put(0x02B2,"Birdo - Golf (MSS)"); + idList.put(0x02B3,"Birdo - Horse Racing (MSS)"); + idList.put(0x02B4,"Rosalina - Soccer (MSS)"); + idList.put(0x02B5,"Rosalina - Baseball (MSS)"); + idList.put(0x02B6,"Rosalina - Tennis (MSS)"); + idList.put(0x02B7,"Rosalina - Golf (MSS)"); + idList.put(0x02B8,"Rosalina - Horse Racing (MSS)"); + idList.put(0x02B9,"Metal Mario - Soccer (MSS)"); + idList.put(0x02BA,"Metal Mario - Baseball (MSS)"); + idList.put(0x02BB,"Metal Mario - Tennis (MSS)"); + idList.put(0x02BC,"Metal Mario - Golf (MSS)"); + idList.put(0x02BD,"Metal Mario - Horse Racing (MSS)"); + idList.put(0x02BE,"Pink Gold Peach - Soccer (MSS)"); + idList.put(0x02BF,"Pink Gold Peach - Baseball (MSS)"); + idList.put(0x02C0,"Pink Gold Peach - Tennis (MSS)"); + idList.put(0x02C1,"Pink Gold Peach - Golf (MSS)"); + idList.put(0x02C2,"Pink Gold Peach - Horse Racing (MSS)"); } + // 1st byte is the character identifier + // XXXXXXXX -------- static final HashMap charList = new HashMap(); static { @@ -653,7 +764,7 @@ public class AmiiboDictionary { charList.put(0x00130000, "Daisy"); charList.put(0x00140000, "Waluigi"); charList.put(0x00170000, "Boo"); - charList.put(0x01000000, "Link (Ocarina of Time)"); + charList.put(0x01000000, "Link"); charList.put(0x01000100, "Toon Link (The Wind Waker)"); charList.put(0x01010000, "Toon Zelda (The Wind Waker)"); charList.put(0x01010100, "Sheik"); @@ -1188,6 +1299,101 @@ public class AmiiboDictionary { charList.put(0x35C00000, "Shovel Knight"); charList.put(0x38400000, "Cloud Strife"); // TODO last two digits for this and next charList.put(0x39800000, "Bayonetta"); + charList.put(0x01000000, "Link (Archer)"); + charList.put(0x01000000, "Link (Rider)"); + charList.put(0x01400000, "Guardian"); + charList.put(0x01010000, "Zelda"); + charList.put(0x01410000, "Bokoblin"); + charList.put(0x09C00101, "Mario - Soccer"); + charList.put(0x09C00201, "Mario - Baseball"); + charList.put(0x09C00301, "Mario - Tennis"); + charList.put(0x09C00401, "Mario - Golf"); + charList.put(0x09C00501, "Mario - Horse Racing"); + charList.put(0x09C10101, "Luigi - Soccer"); + charList.put(0x09C10201, "Luigi - Baseball"); + charList.put(0x09C10301, "Luigi - Tennis"); + charList.put(0x09C10401, "Luigi - Golf"); + charList.put(0x09C10501, "Luigi - Horse Racing"); + charList.put(0x09C20101, "Peach - Soccer"); + charList.put(0x09C20201, "Peach - Baseball"); + charList.put(0x09C20301, "Peach - Tennis"); + charList.put(0x09C20401, "Peach - Golf"); + charList.put(0x09C20501, "Peach - Horse Racing"); + charList.put(0x09C30101, "Daisy - Soccer"); + charList.put(0x09C30201, "Daisy - Baseball"); + charList.put(0x09C30301, "Daisy - Tennis"); + charList.put(0x09C30401, "Daisy - Golf"); + charList.put(0x09C30501, "Daisy - Horse Racing"); + charList.put(0x09C40101, "Yoshi - Soccer"); + charList.put(0x09C40201, "Yoshi - Baseball"); + charList.put(0x09C40301, "Yoshi - Tennis"); + charList.put(0x09C40401, "Yoshi - Golf"); + charList.put(0x09C40501, "Yoshi - Horse Racing"); + charList.put(0x09C50101, "Wario - Soccer"); + charList.put(0x09C50201, "Wario - Baseball"); + charList.put(0x09C50301, "Wario - Tennis"); + charList.put(0x09C50401, "Wario - Golf"); + charList.put(0x09C50501, "Wario - Horse Racing"); + charList.put(0x09C60101, "Waluigi - Soccer"); + charList.put(0x09C60201, "Waluigi - Baseball"); + charList.put(0x09C60301, "Waluigi - Tennis"); + charList.put(0x09C60401, "Waluigi - Golf"); + charList.put(0x09C60501, "Waluigi - Horse Racing"); + charList.put(0x09C70101, "Donkey Kong - Soccer"); + charList.put(0x09C70201, "Donkey Kong - Baseball"); + charList.put(0x09C70301, "Donkey Kong - Tennis"); + charList.put(0x09C70401, "Donkey Kong - Golf"); + charList.put(0x09C70501, "Donkey Kong - Horse Racing"); + charList.put(0x09C80101, "Diddy Kong - Soccer"); + charList.put(0x09C80201, "Diddy Kong - Baseball"); + charList.put(0x09C80301, "Diddy Kong - Tennis"); + charList.put(0x09C80401, "Diddy Kong - Golf"); + charList.put(0x09C80501, "Diddy Kong - Horse Racing"); + charList.put(0x09C90101, "Bowser - Soccer"); + charList.put(0x09C90201, "Bowser - Baseball"); + charList.put(0x09C90301, "Bowser - Tennis"); + charList.put(0x09C90401, "Bowser - Golf"); + charList.put(0x09C90501, "Bowser - Horse Racing"); + charList.put(0x09CA0101, "Bowser Jr. - Soccer"); + charList.put(0x09CA0201, "Bowser Jr. - Baseball"); + charList.put(0x09CA0301, "Bowser Jr. - Tennis"); + charList.put(0x09CA0401, "Bowser Jr. - Golf"); + charList.put(0x09CA0501, "Bowser Jr. - Horse Racing"); + charList.put(0x09CB0101, "Boo - Soccer"); + charList.put(0x09CB0201, "Boo - Baseball"); + charList.put(0x09CB0301, "Boo - Tennis"); + charList.put(0x09CB0401, "Boo - Golf"); + charList.put(0x09CB0501, "Boo - Horse Racing"); + charList.put(0x09CC0101, "Baby Mario - Soccer"); + charList.put(0x09CC0201, "Baby Mario - Baseball"); + charList.put(0x09CC0301, "Baby Mario - Tennis"); + charList.put(0x09CC0401, "Baby Mario - Golf"); + charList.put(0x09CC0501, "Baby Mario - Horse Racing"); + charList.put(0x09CD0101, "Baby Luigi - Soccer"); + charList.put(0x09CD0201, "Baby Luigi - Baseball"); + charList.put(0x09CD0301, "Baby Luigi - Tennis"); + charList.put(0x09CD0401, "Baby Luigi - Golf"); + charList.put(0x09CD0501, "Baby Luigi - Horse Racing"); + charList.put(0x09CE0101, "Birdo - Soccer"); + charList.put(0x09CE0201, "Birdo - Baseball"); + charList.put(0x09CE0301, "Birdo - Tennis"); + charList.put(0x09CE0401, "Birdo - Golf"); + charList.put(0x09CE0501, "Birdo - Horse Racing"); + charList.put(0x09CF0101, "Rosalina - Soccer"); + charList.put(0x09CF0201, "Rosalina - Baseball"); + charList.put(0x09CF0301, "Rosalina - Tennis"); + charList.put(0x09CF0401, "Rosalina - Golf"); + charList.put(0x09CF0501, "Rosalina - Horse Racing"); + charList.put(0x09D00101, "Metal Mario - Soccer"); + charList.put(0x09D00201, "Metal Mario - Baseball"); + charList.put(0x09D00301, "Metal Mario - Tennis"); + charList.put(0x09D00401, "Metal Mario - Golf"); + charList.put(0x09D00501, "Metal Mario - Horse Racing"); + charList.put(0x09D10101, "Pink Gold Peach - Soccer"); + charList.put(0x09D10201, "Pink Gold Peach - Baseball"); + charList.put(0x09D10301, "Pink Gold Peach - Tennis"); + charList.put(0x09D10401, "Pink Gold Peach - Golf"); + charList.put(0x09D10501, "Pink Gold Peach - Horse Racing"); } diff --git a/app/src/main/java/com/hiddenramblings/tagmo/EditorSSB.java b/app/src/main/java/com/hiddenramblings/tagmo/EditorSSB.java index 633156545..dfa5b9c9b 100644 --- a/app/src/main/java/com/hiddenramblings/tagmo/EditorSSB.java +++ b/app/src/main/java/com/hiddenramblings/tagmo/EditorSSB.java @@ -3,13 +3,8 @@ import android.app.Activity; import android.content.Intent; import android.support.v7.app.AppCompatActivity; -import android.os.Bundle; import android.util.Log; -import android.view.View; -import android.widget.AdapterView; import android.widget.ArrayAdapter; -import android.widget.NumberPicker; -import android.widget.SeekBar; import android.widget.Spinner; import android.widget.TextView; @@ -82,7 +77,7 @@ void afterViews() { tagData = TagUtil.decrypt(keyManager, tagData); this.loadData(tagData); } catch (Exception e) { - Log.d(TAG, "Error decyrpting data", e); + Log.d(TAG, "Error decrypting data", e); finish(); } } @@ -176,9 +171,9 @@ int readLevel(byte[] data) { } void writeLevel(byte[] data, int level) { - int oldlevel = readLevel(data); - if (oldlevel == level) - return; //level is a granular value as such we dont want to overwrite it in case its halfway through a level + int oldLevel = readLevel(data); + if (oldLevel == level) + return; //level is a granular value as such we don't want to overwrite it in case its halfway through a level int value = LEVEL_THRESHOLDS[level - 1]; diff --git a/app/src/main/java/com/hiddenramblings/tagmo/HexViewerActivity.java b/app/src/main/java/com/hiddenramblings/tagmo/HexViewerActivity.java index b7388c80b..87f565dcb 100644 --- a/app/src/main/java/com/hiddenramblings/tagmo/HexViewerActivity.java +++ b/app/src/main/java/com/hiddenramblings/tagmo/HexViewerActivity.java @@ -1,25 +1,20 @@ package com.hiddenramblings.tagmo; import android.content.Context; -import android.content.res.Resources; import android.graphics.Color; import android.support.v7.app.AppCompatActivity; -import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ListView; -import android.widget.Spinner; import android.widget.TextView; import org.androidannotations.annotations.AfterViews; import org.androidannotations.annotations.EActivity; import org.androidannotations.annotations.ViewById; -import java.util.List; - @EActivity(R.layout.activity_hex_viewer) public class HexViewerActivity extends AppCompatActivity { private static final String TAG = "HexViewerActivity"; @@ -43,7 +38,6 @@ void afterViews() { void loadData(byte[] tagData) { int rows = (int)Math.ceil((float)tagData.length / 0x10); - String[] data = new String[rows]; for(int i=0; i< rows; i++) { @@ -80,7 +74,6 @@ public HexDumpAdapter(Context context, String[] data) { @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { - final Context context = getContext(); convertView = LayoutInflater.from(getContext()).inflate(R.layout.hexdump_line, parent, false); convertView.setTag(convertView.findViewById(R.id.textView2)); } diff --git a/app/src/main/java/com/hiddenramblings/tagmo/KeyManager.java b/app/src/main/java/com/hiddenramblings/tagmo/KeyManager.java index eadc71d16..e4f40f3c3 100644 --- a/app/src/main/java/com/hiddenramblings/tagmo/KeyManager.java +++ b/app/src/main/java/com/hiddenramblings/tagmo/KeyManager.java @@ -4,13 +4,10 @@ import android.net.Uri; import android.util.Log; -import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; -import java.net.URL; -import java.security.Key; /** * Created by MAS on 31/01/2016. diff --git a/app/src/main/java/com/hiddenramblings/tagmo/MainActivity.java b/app/src/main/java/com/hiddenramblings/tagmo/MainActivity.java index d4f556af5..23ad37baf 100644 --- a/app/src/main/java/com/hiddenramblings/tagmo/MainActivity.java +++ b/app/src/main/java/com/hiddenramblings/tagmo/MainActivity.java @@ -1,6 +1,5 @@ package com.hiddenramblings.tagmo; -import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; @@ -37,7 +36,6 @@ import java.io.InputStream; import java.util.Arrays; import java.util.Calendar; -import java.util.jar.Manifest; @EActivity(R.layout.activity_main) @@ -189,9 +187,9 @@ void updateStatus() { try { if (this.currentTagData != null) { byte[] charIdData = TagUtil.charIdDataFromTag(this.currentTagData); - String charid = AmiiboDictionary.getDisplayName(charIdData); + String charId = AmiiboDictionary.getDisplayName(charIdData); String uid = Util.bytesToHex(TagUtil.uidFromPages(this.currentTagData)); - txtTagId.setText("TagId: " + charid + " / " + uid); + txtTagId.setText("TagId: " + charId + " / " + uid); } else { txtTagId.setText("TagId: "); } @@ -296,7 +294,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { Log.d(TAG, "onActivityResult"); - String action = null; + String action; switch (requestCode) { case EDIT_TAG: @@ -335,7 +333,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { private void showFileChooser(String title, String mimeType, int resultCode) { Intent intent = new Intent(Intent.ACTION_GET_CONTENT); - intent.setType("*/*"); //all files + intent.setType(mimeType); intent.addCategory(Intent.CATEGORY_OPENABLE); try { @@ -404,17 +402,17 @@ protected void writeTagToFile(byte[] tagdata) { try { byte[] charIdData = TagUtil.charIdDataFromTag(this.currentTagData); - String charid = AmiiboDictionary.getDisplayName(charIdData).replace("/", "-"); //prevent invalid filenames + String charId = AmiiboDictionary.getDisplayName(charIdData).replace("/", "-"); //prevent invalid filenames - byte[] uid = Arrays.copyOfRange(tagdata, 0, 9); - String uids = Util.bytesToHex(uid); - String fname = String.format("%1$s [%2$s] %3$ty%3$tm%3$te_%3$tH%3$tM%3$tS%4$s.bin", charid, uids, Calendar.getInstance(), (valid ? "" : "_corrupted_")); + byte[] uId = Arrays.copyOfRange(tagdata, 0, 9); + String uIds = Util.bytesToHex(uId); + String fName = String.format("%1$s [%2$s] %3$ty%3$tm%3$te_%3$tH%3$tM%3$tS%4$s.bin", charId, uIds, Calendar.getInstance(), (valid ? "" : "_corrupted_")); File dir = new File(Environment.getExternalStorageDirectory(), DATA_DIR); if (!dir.isDirectory()) dir.mkdir(); - File file = new File(dir.getAbsolutePath(), fname); + File file = new File(dir.getAbsolutePath(), fName); Log.d(TAG, file.toString()); FileOutputStream fos = new FileOutputStream(file); @@ -428,7 +426,7 @@ protected void writeTagToFile(byte[] tagdata) { } catch (Exception e) { Log.e(TAG, "Failed to refresh media scanner", e); } - LogMessage("Wrote to file " + fname + " in tagmo directory."); + LogMessage("Wrote to file " + fName + " in tagmo directory."); } catch (Exception e) { LogError("Error writing to file: " + e.getMessage()); } diff --git a/app/src/main/java/com/hiddenramblings/tagmo/NfcActivity.java b/app/src/main/java/com/hiddenramblings/tagmo/NfcActivity.java index 80a86cc41..d42d86a97 100644 --- a/app/src/main/java/com/hiddenramblings/tagmo/NfcActivity.java +++ b/app/src/main/java/com/hiddenramblings/tagmo/NfcActivity.java @@ -1,7 +1,6 @@ package com.hiddenramblings.tagmo; import android.app.Activity; -import android.app.Notification; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; @@ -11,23 +10,19 @@ import android.nfc.Tag; import android.nfc.tech.MifareUltralight; import android.support.v7.app.AppCompatActivity; -import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.widget.ImageView; -import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; import org.androidannotations.annotations.AfterViews; import org.androidannotations.annotations.Background; import org.androidannotations.annotations.EActivity; -import org.androidannotations.annotations.OptionsMenu; import org.androidannotations.annotations.UiThread; import org.androidannotations.annotations.ViewById; -import org.androidannotations.annotations.res.AnimationRes; @EActivity(R.layout.activity_nfc) public class NfcActivity extends AppCompatActivity { @@ -149,8 +144,6 @@ void onTagDiscovered(Intent intent) { try { Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); Log.d(TAG, tag.toString()); - if (tag == null) - showError("Error getting tag data"); MifareUltralight mifare = MifareUltralight.get(tag); if (mifare == null) throw new Exception("Error getting tag data. Possibly not a NTAG215"); @@ -159,7 +152,7 @@ void onTagDiscovered(Intent intent) { int resultCode = Activity.RESULT_CANCELED; try { Log.d(TAG, mode); - byte[] data = null; + byte[] data; switch (mode) { case ACTION_WRITE_TAG_RAW: data = commandIntent.getByteArrayExtra(EXTRA_TAG_DATA); diff --git a/app/src/main/java/com/hiddenramblings/tagmo/TagCreateDialog.java b/app/src/main/java/com/hiddenramblings/tagmo/TagCreateDialog.java index 56d1f6170..479a89c3c 100644 --- a/app/src/main/java/com/hiddenramblings/tagmo/TagCreateDialog.java +++ b/app/src/main/java/com/hiddenramblings/tagmo/TagCreateDialog.java @@ -9,7 +9,6 @@ import android.util.Log; import android.view.LayoutInflater; import android.view.View; -import android.webkit.WebView; import android.widget.ArrayAdapter; import android.widget.Spinner; diff --git a/app/src/main/java/com/hiddenramblings/tagmo/TagUtil.java b/app/src/main/java/com/hiddenramblings/tagmo/TagUtil.java index e9961f70a..78b9fe5e0 100644 --- a/app/src/main/java/com/hiddenramblings/tagmo/TagUtil.java +++ b/app/src/main/java/com/hiddenramblings/tagmo/TagUtil.java @@ -1,7 +1,5 @@ package com.hiddenramblings.tagmo; -import android.util.Log; - import java.util.Arrays; public class TagUtil { diff --git a/app/src/main/java/com/hiddenramblings/tagmo/TagWriter.java b/app/src/main/java/com/hiddenramblings/tagmo/TagWriter.java index 0c031dded..2fc9a5363 100644 --- a/app/src/main/java/com/hiddenramblings/tagmo/TagWriter.java +++ b/app/src/main/java/com/hiddenramblings/tagmo/TagWriter.java @@ -4,7 +4,6 @@ import android.util.Log; import java.io.IOException; -import java.util.Arrays; /** * Created by MAS on 01/02/2016. @@ -107,32 +106,29 @@ static boolean compareRange(byte[] data, byte[] data2, int data2offset, int len) public static final int BULK_READ_PAGE_COUNT = 4; public static byte[] readFromTag(MifareUltralight tag) throws Exception { - byte[] tagdata = new byte[TagUtil.TAG_FILE_SIZE]; + byte[] tagData = new byte[TagUtil.TAG_FILE_SIZE]; + int pageCount = TagUtil.TAG_FILE_SIZE / TagUtil.PAGE_SIZE; - int pagecount = TagUtil.TAG_FILE_SIZE / TagUtil.PAGE_SIZE; - int readcount = (int)Math.ceil((double)TagUtil.TAG_FILE_SIZE / (pagecount * BULK_READ_PAGE_COUNT)); - - for(int i=0; i #include #define HMAC_POS_DATA 0x008 #define HMAC_POS_TAG 0x1B4 -void bzero(void *s, size_t n);; - void nfc3d_amiibo_calc_seed(const uint8_t * dump, uint8_t * key) { memcpy(key + 0x00, dump + 0x029, 0x02); - bzero(key + 0x02, 0x0E); + memset(key + 0x02, 0x00, 0x0E); memcpy(key + 0x10, dump + 0x1D4, 0x08); memcpy(key + 0x18, dump + 0x1D4, 0x08); memcpy(key + 0x20, dump + 0x1E8, 0x20); @@ -89,9 +88,22 @@ bool nfc3d_amiibo_unpack(const nfc3d_amiibo_keys * amiiboKeys, const uint8_t * t // Decrypt nfc3d_amiibo_cipher(&dataKeys, internal, plain); - // Check integrity. Note: order matters, data HMAC depends on tag HMAC! - sha256hmac(tagKeys.hmacKey, sizeof(tagKeys.hmacKey), plain + 0x1D4, 0x34, plain + HMAC_POS_TAG); - sha256hmac(dataKeys.hmacKey, sizeof(dataKeys.hmacKey), plain + 0x029, 0x1DF, plain + HMAC_POS_DATA); + // Init OpenSSL HMAC context + HMAC_CTX hmacCtx; + HMAC_CTX_init(&hmacCtx); + + // Regenerate tag HMAC. Note: order matters, data HMAC depends on tag HMAC! + HMAC_Init_ex(&hmacCtx, tagKeys.hmacKey, sizeof(tagKeys.hmacKey), EVP_sha256(), NULL); + HMAC_Update(&hmacCtx, plain + 0x1D4, 0x34); + HMAC_Final(&hmacCtx, plain + HMAC_POS_TAG, NULL); + + // Regenerate data HMAC + HMAC_Init_ex(&hmacCtx, dataKeys.hmacKey, sizeof(dataKeys.hmacKey), EVP_sha256(), NULL); + HMAC_Update(&hmacCtx, plain + 0x029, 0x1DF); + HMAC_Final(&hmacCtx, plain + HMAC_POS_DATA, NULL); + + // HMAC cleanup + HMAC_CTX_cleanup(&hmacCtx); return memcmp(plain + HMAC_POS_DATA, internal + HMAC_POS_DATA, 32) == 0 && @@ -107,16 +119,27 @@ void nfc3d_amiibo_pack(const nfc3d_amiibo_keys * amiiboKeys, const uint8_t * pla nfc3d_amiibo_keygen(&amiiboKeys->tag, plain, &tagKeys); nfc3d_amiibo_keygen(&amiiboKeys->data, plain, &dataKeys); - uint8_t plain2[NFC3D_AMIIBO_SIZE]; - memcpy(plain2, plain, NFC3D_AMIIBO_SIZE); + // Init OpenSSL HMAC context + HMAC_CTX hmacCtx; + HMAC_CTX_init(&hmacCtx); + + // Generate tag HMAC + HMAC_Init_ex(&hmacCtx, tagKeys.hmacKey, sizeof(tagKeys.hmacKey), EVP_sha256(), NULL); + HMAC_Update(&hmacCtx, plain + 0x1D4, 0x34); + HMAC_Final(&hmacCtx, cipher + HMAC_POS_TAG, NULL); + + // Generate data HMAC + HMAC_Init_ex(&hmacCtx, dataKeys.hmacKey, sizeof(dataKeys.hmacKey), EVP_sha256(), NULL); + HMAC_Update(&hmacCtx, plain + 0x029, 0x18B); // Data + HMAC_Update(&hmacCtx, cipher + HMAC_POS_TAG, 0x20); // Tag HMAC + HMAC_Update(&hmacCtx, plain + 0x1D4, 0x34); // Here be dragons + HMAC_Final(&hmacCtx, cipher + HMAC_POS_DATA, NULL); - // Generate HMAC //tag hmac is used by data hmac - sha256hmac(tagKeys.hmacKey, sizeof(tagKeys.hmacKey), plain2 + 0x1D4, 0x34, plain2 + HMAC_POS_TAG); - sha256hmac(tagKeys.hmacKey, sizeof(tagKeys.hmacKey), plain2 + 0x1D4, 0x34, cipher + HMAC_POS_TAG); - sha256hmac(dataKeys.hmacKey, sizeof(dataKeys.hmacKey), plain2 + 0x029, 0x1DF, cipher + HMAC_POS_DATA); + // HMAC cleanup + HMAC_CTX_cleanup(&hmacCtx); // Encrypt - nfc3d_amiibo_cipher(&dataKeys, plain2, cipher); + nfc3d_amiibo_cipher(&dataKeys, plain, cipher); // Convert back to hardware nfc3d_amiibo_internal_to_tag(cipher, tag); diff --git a/ndk/jni/include/nfc3d/amiibo.h b/ndk/jni/include/nfc3d/amiibo.h index 1dd5c3017..8433fffaa 100644 --- a/ndk/jni/include/nfc3d/amiibo.h +++ b/ndk/jni/include/nfc3d/amiibo.h @@ -38,4 +38,6 @@ typedef struct { bool nfc3d_amiibo_unpack(const nfc3d_amiibo_keys * amiiboKeys, const uint8_t * tag, uint8_t * plain); void nfc3d_amiibo_pack(const nfc3d_amiibo_keys * amiiboKeys, const uint8_t * plain, uint8_t * tag); +bool nfc3d_amiibo_load_keys(nfc3d_amiibo_keys * amiiboKeys, const char * path); + #endif diff --git a/ndk/jni/keygen.c b/ndk/jni/keygen.c index ceb757ccf..16fb43e39 100644 --- a/ndk/jni/keygen.c +++ b/ndk/jni/keygen.c @@ -22,17 +22,11 @@ #include "nfc3d/drbg.h" #include "nfc3d/keygen.h" +#include "util.h" #include #include #include -char * stpncpy (char *dst, const char *src, size_t len) { - size_t n = strlen (src); - if (n > len) - n = len; - return strncpy (dst, src, len) + n; -} - void nfc3d_keygen_prepare_seed(const nfc3d_keygen_masterkeys * baseKeys, const uint8_t * baseSeed, uint8_t * output, size_t * outputSize) { assert(baseKeys != NULL); assert(baseSeed != NULL); @@ -42,7 +36,7 @@ void nfc3d_keygen_prepare_seed(const nfc3d_keygen_masterkeys * baseKeys, const u uint8_t * start = output; // 1: Copy whole type string - output = (uint8_t *) stpncpy((char *) output, baseKeys->typeString, sizeof(baseKeys->typeString)) + 1; + output = memccpy(output, baseKeys->typeString, '\0', sizeof(baseKeys->typeString)); // 2: Append (16 - magicBytesSize) from the input seed size_t leadingSeedBytes = 16 - baseKeys->magicBytesSize;