Skip to content

Instantly share code, notes, and snippets.

@simontime
Last active December 15, 2018 07:20
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save simontime/b5e4516aedb4542516da9ec2fb5ddda6 to your computer and use it in GitHub Desktop.
Save simontime/b5e4516aedb4542516da9ec2fb5ddda6 to your computer and use it in GitHub Desktop.
Nintendo Switch screenshot filename encryptor/decryptor using x86 AES-NI intrinsics
#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