samsung-firmware-magic icon indicating copy to clipboard operation
samsung-firmware-magic copied to clipboard

Ported to C

Open Wiilf opened this issue 10 months ago • 2 comments

I have ported this to C. Now, we are utilizing the Windows Crypto API, however it fails to import key. Win32 console application. If anyone knows how to resolve this, by all means let me know. At this point, I really have no idea. Perhaps a difference between Python3's AES implementation, and the Crypto API. Here it is. Compiled with Pelles C v12 (C17 standard).

#define WIN32_LEAN_AND_MEAN

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <windows.h>
#include <wincrypt.h>

/* Define the shuffle map that Samsung uses */
const uint8_t shuffle[] = {
    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
    0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x30, 0x31, 0x32, 0x33,
    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D,
    0x3E, 0x3F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
    0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x70, 0x71,
    0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B,
    0x7C, 0x7D, 0x7E, 0x7F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95,
    0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
    0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9,
    0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xD0, 0xD1, 0xD2, 0xD3,
    0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD,
    0xDE, 0xDF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
    0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0xE0, 0xE1,
    0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB,
    0xEC, 0xED, 0xEE, 0xEF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5,
    0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
    0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9,
    0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0x80, 0x81, 0x82, 0x83,
    0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D,
    0x8E, 0x8F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
    0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x40, 0x41,
    0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B,
    0x4C, 0x4D, 0x4E, 0x4F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
    0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
    0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
};

/* Generate reverse map */
uint8_t lookup[256];

/* Generate reverse map */
uint8_t lookup[256];

/* Utility function to perform XOR operation */
void xor_buffers(const uint8_t *s1, const uint8_t *s2, uint8_t *result, size_t length) {
    for (size_t i = 0; i < length; i++) {
        result[i] = s1[i] ^ s2[i];
    }
}

/* Unshuffle function */
void unshuffle_buffer(const uint8_t *input, uint8_t *output, size_t length) {
    for (size_t i = 0; i < length; i++) {
        output[i] = lookup[input[i]];
    }
}

static HCRYPTKEY hKey;
static HCRYPTHASH hHash;

int main(int argc, char *argv[]) {
    if (argc != 3) {
        fprintf(stderr, "Usage: %s <input_file> <output_file>\n", argv[0]);
        return 1;
    }

    /* Initialize reverse lookup table */
    for (int i = 0; i < 256; i++) {
		lookup[(unsigned char)shuffle[i]] = (unsigned char)i;
    }

    /* Crypto constants */
    uint8_t iv0[] = { 0x8C, 0xE8, 0x2E, 0xEF, 0xBE, 0xA0, 0xDA, 0x3C, 0x44, 0x69, 0x9E, 0xD7 };
    uint8_t key[] = { 0x56, 0xE4, 0x7A, 0x38, 0xC5, 0x59, 0x89, 0x74, 0xBC, 0x46, 0x90, 0x3D, 0xBA, 0x29, 0x03, 0x49 };
    int ctr = 0;

    /* Initialize Windows Crypto API */
    HCRYPTPROV hCryptProv = 0;
    if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
        fprintf(stderr, "Error acquiring context.\n");
        return 1;
    }

    /* Import key */
    if (!CryptImportKey(hCryptProv, key, sizeof(key), 0, 0, &hKey)) {
        fprintf(stderr, "Error importing key.\n");
        CryptReleaseContext(hCryptProv, 0);
        return 1;
    }

    FILE *input_file = fopen(argv[1], "rb");
    if (!input_file) {
        perror("Error opening input file");
        CryptDestroyKey(hKey);
        CryptReleaseContext(hCryptProv, 0);
        return 1;
    }

    FILE *output_file = fopen(argv[2], "wb");
    if (!output_file) {
        perror("Error opening output file");
        fclose(input_file);
        CryptDestroyKey(hKey);
        CryptReleaseContext(hCryptProv, 0);
        return 1;
    }

    /* Main loop to process blocks */
    while (1) {
        uint8_t blk[16];
        size_t bytes_read = fread(blk, 1, sizeof(blk), input_file);

        if (bytes_read == 0) {
            break; // End of input file
        }

        /* Samsung arbitrarily resets the counter every 32 blocks */
        ctr = (ctr % 32) + 1;

        uint8_t iv[20];
        memcpy(iv, iv0, sizeof(iv0));
        iv[16] = (ctr >> 24) & 0xFF;
        iv[17] = (ctr >> 16) & 0xFF;
        iv[18] = (ctr >> 8) & 0xFF;
        iv[19] = ctr & 0xFF;

        /* Use AES encryption in ECB mode */
        uint8_t xblk[16];
        DWORD xblk_size = sizeof(xblk);
        if (!CryptEncrypt(hKey, 0, TRUE, 0, xblk, &xblk_size, sizeof(xblk))) {
            fprintf(stderr, "Error encrypting data.\n");
            fclose(input_file);
            fclose(output_file);
            CryptDestroyKey(hKey);
            CryptDestroyHash(hHash);
            CryptReleaseContext(hCryptProv, 0);
            return 1;
        }

        /* Decrypt and unshuffle to get the result */
        uint8_t res[16];
        xor_buffers(xblk, blk, res, sizeof(res));
        unshuffle_buffer(res, res, sizeof(res));

        fwrite(res, 1, sizeof(res), output_file);
    }

    /* Cleanup */
    fclose(input_file);
    fclose(output_file);
    CryptDestroyKey(hKey);
    CryptReleaseContext(hCryptProv, 0);

    return 0;
}

Wiilf avatar Aug 22 '23 07:08 Wiilf