mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-06-03 00:19:30 +02:00
137 lines
3.6 KiB
C++
137 lines
3.6 KiB
C++
#include <utils.hpp>
|
|
|
|
using namespace std;
|
|
|
|
// Top-level block container
|
|
struct signing_block {
|
|
uint64_t len;
|
|
|
|
struct id_value_pair {
|
|
uint64_t len;
|
|
struct /* v2_signature */ {
|
|
uint32_t id;
|
|
uint8_t value[0]; // size = (len - 4)
|
|
};
|
|
} id_value_pair_sequence[0];
|
|
|
|
uint64_t block_len; // *MUST* be same as len
|
|
char magic[16]; // "APK Sig Block 42"
|
|
};
|
|
|
|
struct len_prefixed {
|
|
uint32_t len;
|
|
};
|
|
|
|
// Generic length prefixed raw data
|
|
struct len_prefixed_value : public len_prefixed {
|
|
uint8_t value[0];
|
|
};
|
|
|
|
// V2 Signature Block
|
|
struct v2_signature {
|
|
uint32_t id; // 0x7109871a
|
|
uint32_t signer_sequence_len;
|
|
struct signer : public len_prefixed {
|
|
struct signed_data : public len_prefixed {
|
|
uint32_t digest_sequence_len;
|
|
struct : public len_prefixed {
|
|
uint32_t algorithm;
|
|
len_prefixed_value digest;
|
|
} digest_sequence[0];
|
|
|
|
uint32_t certificate_sequence_len;
|
|
len_prefixed_value certificate_sequence[0];
|
|
|
|
uint32_t attribute_sequence_len;
|
|
struct attribute : public len_prefixed {
|
|
uint32_t id;
|
|
uint8_t value[0]; // size = (len - 4)
|
|
} attribute_sequence[0];
|
|
} signed_data;
|
|
|
|
uint32_t signature_sequence_len;
|
|
struct : public len_prefixed {
|
|
uint32_t id;
|
|
len_prefixed_value signature;
|
|
} signature_sequence[0];
|
|
|
|
len_prefixed_value public_key;
|
|
} signer_sequence[0];
|
|
};
|
|
|
|
// The structures above are just for documentation purpose
|
|
// The real parsing logic is the following
|
|
|
|
string read_certificate(int fd) {
|
|
string certificate;
|
|
uint32_t size4;
|
|
uint64_t size8, size_of_block;
|
|
|
|
for (int i = 0;; i++) {
|
|
unsigned short n;
|
|
lseek(fd, -i - 2, SEEK_END);
|
|
read(fd, &n, 2);
|
|
if (n == i) {
|
|
lseek(fd, -22, SEEK_CUR);
|
|
read(fd, &size4, 4);
|
|
if (size4 == 0x6054b50u) { // central directory end magic
|
|
break;
|
|
}
|
|
}
|
|
if (i == 0xffff) {
|
|
return certificate;
|
|
}
|
|
}
|
|
|
|
lseek(fd, 12, SEEK_CUR);
|
|
|
|
read(fd, &size4, 0x4);
|
|
lseek(fd, (off_t) (size4 - 0x18), SEEK_SET);
|
|
|
|
read(fd, &size8, 0x8);
|
|
char magic[0x10] = {0};
|
|
read(fd, magic, sizeof(magic));
|
|
if (memcmp(magic, "APK Sig Block 42", sizeof(magic)) != 0) {
|
|
return certificate;
|
|
}
|
|
|
|
lseek(fd, (off_t) (size4 - (size8 + 0x8)), SEEK_SET);
|
|
read(fd, &size_of_block, 0x8);
|
|
if (size_of_block != size8) {
|
|
return certificate;
|
|
}
|
|
|
|
for (;;) {
|
|
uint32_t id;
|
|
uint32_t offset;
|
|
read(fd, &size8, 0x8); // sequence length
|
|
if (size8 == size_of_block) {
|
|
break;
|
|
}
|
|
read(fd, &id, 0x4); // id
|
|
offset = 4;
|
|
|
|
if (id == 0x7109871au) {
|
|
read(fd, &size4, 0x4); // signer-sequence length
|
|
read(fd, &size4, 0x4); // signer length
|
|
read(fd, &size4, 0x4); // signed data length
|
|
offset += 0x4 * 3;
|
|
|
|
read(fd, &size4, 0x4); // digests-sequence length
|
|
lseek(fd, (off_t) (size4), SEEK_CUR);// skip digests
|
|
offset += 0x4 + size4;
|
|
|
|
read(fd, &size4, 0x4); // certificates length
|
|
read(fd, &size4, 0x4); // certificate length
|
|
offset += 0x4 * 2;
|
|
|
|
certificate.resize(size4);
|
|
read(fd, certificate.data(), size4);
|
|
|
|
offset += size4;
|
|
}
|
|
lseek(fd, (off_t) (size8 - offset), SEEK_CUR);
|
|
}
|
|
return certificate;
|
|
}
|