Last active
December 15, 2018 07:20
-
-
Save simontime/b5e4516aedb4542516da9ec2fb5ddda6 to your computer and use it in GitHub Desktop.
Nintendo Switch screenshot filename encryptor/decryptor using x86 AES-NI intrinsics
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <string.h> | |
#include <wmmintrin.h> | |
#define u8 unsigned char | |
#define i128 __m128i | |
#define exp(k, rc) expand(k, _mm_aeskeygenassist_si128(k, rc)) | |
#define c(b) b - (b < 58 ? 48 : 55) | |
typedef struct { | |
long long titleid; | |
long long params; | |
} name; | |
u8 key[] = { | |
0xb7, 0xed, 0x7a, 0x66, 0xc8, 0x0b, 0x4b, 0x00, | |
0x8b, 0xaf, 0x7f, 0x05, 0x89, 0xc0, 0x82, 0x24 | |
}; | |
i128 k[20]; | |
i128 expand(i128 key, i128 gen) { | |
gen = _mm_shuffle_epi32(gen, _MM_SHUFFLE(3, 3, 3, 3)); | |
for (int i = 0; i < 3; i++) | |
key = _mm_xor_si128(key, _mm_slli_si128(key, 4)); | |
return _mm_xor_si128(key, gen); | |
} | |
void init(void *key) { | |
k[0] = _mm_loadu_si128((i128 *)key); | |
k[1] = exp(k[0], 0x01); k[2] = exp(k[1], 0x02); | |
k[3] = exp(k[2], 0x04); k[4] = exp(k[3], 0x08); | |
k[5] = exp(k[4], 0x10); k[6] = exp(k[5], 0x20); | |
k[7] = exp(k[6], 0x40); k[8] = exp(k[7], 0x80); | |
k[9] = exp(k[8], 0x1b); k[10] = exp(k[9], 0x36); | |
for (int i = 11; i <= 19; i++) | |
k[i] = _mm_aesimc_si128(k[20 - i]); | |
} | |
void encrypt(void *pt, void *ct) { | |
i128 m = _mm_loadu_si128((i128 *)pt); | |
m = _mm_xor_si128(m, k[0]); | |
for (int i = 1; i <= 9; i++) | |
m = _mm_aesenc_si128(m, k[i]); | |
m = _mm_aesenclast_si128(m, k[10]); | |
_mm_storeu_si128((i128 *)ct, m); | |
} | |
void decrypt(void *ct, void *pt) { | |
i128 m = _mm_loadu_si128((i128 *)ct); | |
m = _mm_xor_si128(m, k[10]); | |
for (int i = 1; i <= 9; i++) | |
m = _mm_aesdec_si128(m, k[10 + i]); | |
m = _mm_aesdeclast_si128(m, k[0]); | |
_mm_storeu_si128((i128 *)pt, m); | |
} | |
void *hex(char *x) { | |
u8 *buf = malloc(strlen(x) >> 1); | |
for (u8 i = 0; i < strlen(x) >> 1; ++i) | |
buf[i] = (c(x[i << 1]) << 4) + (c(x[(i << 1) + 1])); | |
return buf; | |
} | |
int main(int argc, char **argv) { | |
if (argc < 2) { | |
fprintf(stderr, "Usage: %s <Title ID or cipher text> [params]", argv[0]); | |
return 1; | |
} | |
init(key); | |
if (strlen(argv[1]) > 0x10) { | |
name *buf = hex(argv[1]); | |
decrypt(buf, buf); | |
printf("Title ID: %016llx\nParams: 0x%llx", buf->titleid, buf->params); | |
} | |
else { | |
name *buf = calloc(0x10, 1); | |
sscanf(argv[1], "%016llx", &buf->titleid); | |
if (argc > 2) | |
sscanf(argv[2], "%016llx", &buf->params); | |
encrypt(buf, buf); | |
for (int i = 0; i < 0x10; i++) | |
printf("%02X", ((u8 *)buf)[i]); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment