#include #include #include #include #include #include #include #include #include #include #include namespace hex::crypt { u16 crc16(prv::Provider* &data, u64 offset, size_t size, u16 polynomial, u16 init) { const auto table = [polynomial] { std::array table; for (u16 i = 0; i < 256; i++) { u16 crc = 0; u16 c = i; for (u16 j = 0; j < 8; j++) { if (((crc ^ c) & 0x0001U) != 0) crc = (crc >> 1U) ^ polynomial; else crc >>= 1U; c >>= 1U; } table[i] = crc; } return table; }(); u16 crc = init; std::array buffer = { 0 }; for (u64 bufferOffset = 0; offset < size; offset += buffer.size()) { const u64 readSize = std::min(u64(buffer.size()), size - bufferOffset); data->read(offset + bufferOffset, buffer.data(), readSize); for (size_t i = 0; i < readSize; i++) { crc = (crc >> 8) ^ table[(crc ^ u16(buffer[i])) & 0x00FF]; } } return crc; } u32 crc32(prv::Provider* &data, u64 offset, size_t size, u32 polynomial, u32 init) { const auto table = [polynomial] { std::array table = {0}; for (uint32_t i = 0; i < 256; i++) { uint32_t c = i; for (size_t j = 0; j < 8; j++) { if (c & 1) c = polynomial ^ (c >> 1); else c >>= 1; } table[i] = c; } return table; }(); uint32_t c = init; std::array buffer = { 0 }; for (u64 bufferOffset = 0; offset < size; offset += buffer.size()) { const u64 readSize = std::min(u64(buffer.size()), size - bufferOffset); data->read(offset + bufferOffset, buffer.data(), readSize); for (size_t i = 0; i < readSize; i++) { c = table[(c ^ buffer[i]) & 0xFF] ^ (c >> 8); } } return ~c; } std::array md5(prv::Provider* &data, u64 offset, size_t size) { std::array result = { 0 }; mbedtls_md5_context ctx; mbedtls_md5_init(&ctx); mbedtls_md5_starts_ret(&ctx); std::array buffer = { 0 }; for (u64 bufferOffset = 0; bufferOffset < size; bufferOffset += buffer.size()) { const u64 readSize = std::min(u64(buffer.size()), size - bufferOffset); data->read(offset + bufferOffset, buffer.data(), readSize); mbedtls_md5_update_ret(&ctx, buffer.data(), readSize); } mbedtls_md5_finish_ret(&ctx, result.data()); mbedtls_md5_free(&ctx); return result; } std::array sha1(prv::Provider* &data, u64 offset, size_t size) { std::array result = { 0 }; mbedtls_sha1_context ctx; mbedtls_sha1_init(&ctx); mbedtls_sha1_starts_ret(&ctx); std::array buffer = { 0 }; for (u64 bufferOffset = 0; bufferOffset < size; bufferOffset += buffer.size()) { const u64 readSize = std::min(u64(buffer.size()), size - bufferOffset); data->read(offset + bufferOffset, buffer.data(), readSize); mbedtls_sha1_update_ret(&ctx, buffer.data(), readSize); } mbedtls_sha1_finish_ret(&ctx, result.data()); mbedtls_sha1_free(&ctx); return result; } std::array sha224(prv::Provider* &data, u64 offset, size_t size) { std::array result = { 0 }; mbedtls_sha256_context ctx; mbedtls_sha256_init(&ctx); mbedtls_sha256_starts_ret(&ctx, true); std::array buffer = { 0 }; for (u64 bufferOffset = 0; bufferOffset < size; bufferOffset += buffer.size()) { const u64 readSize = std::min(u64(buffer.size()), size - bufferOffset); data->read(offset + bufferOffset, buffer.data(), readSize); mbedtls_sha256_update_ret(&ctx, buffer.data(), readSize); } mbedtls_sha256_finish_ret(&ctx, result.data()); mbedtls_sha256_free(&ctx); return result; } std::array sha256(prv::Provider* &data, u64 offset, size_t size) { std::array result = { 0 }; mbedtls_sha256_context ctx; mbedtls_sha256_init(&ctx); mbedtls_sha256_starts_ret(&ctx, false); std::array buffer = { 0 }; for (u64 bufferOffset = 0; bufferOffset < size; bufferOffset += buffer.size()) { const u64 readSize = std::min(u64(buffer.size()), size - bufferOffset); data->read(offset + bufferOffset, buffer.data(), readSize); mbedtls_sha256_update_ret(&ctx, buffer.data(), readSize); } mbedtls_sha256_finish_ret(&ctx, result.data()); mbedtls_sha256_free(&ctx); return result; } std::array sha384(prv::Provider* &data, u64 offset, size_t size) { std::array result = { 0 }; mbedtls_sha512_context ctx; mbedtls_sha512_init(&ctx); mbedtls_sha512_starts_ret(&ctx, true); std::array buffer = { 0 }; for (u64 bufferOffset = 0; bufferOffset < size; bufferOffset += buffer.size()) { const u64 readSize = std::min(u64(buffer.size()), size - bufferOffset); data->read(offset + bufferOffset, buffer.data(), readSize); mbedtls_sha512_update_ret(&ctx, buffer.data(), readSize); } mbedtls_sha512_finish_ret(&ctx, result.data()); mbedtls_sha512_free(&ctx); return result; } std::array sha512(prv::Provider* &data, u64 offset, size_t size) { std::array result = { 0 }; mbedtls_sha512_context ctx; mbedtls_sha512_init(&ctx); mbedtls_sha512_starts_ret(&ctx, false); std::array buffer = { 0 }; for (u64 bufferOffset = 0; bufferOffset < size; bufferOffset += buffer.size()) { const u64 readSize = std::min(u64(buffer.size()), size - bufferOffset); data->read(offset + bufferOffset, buffer.data(), readSize); mbedtls_sha512_update_ret(&ctx, buffer.data(), readSize); } mbedtls_sha512_finish_ret(&ctx, result.data()); mbedtls_sha512_free(&ctx); return result; } std::vector decode64(const std::vector &input) { size_t outputSize = (3 * input.size()) / 4; std::vector output(outputSize + 1, 0x00); size_t written = 0; if (mbedtls_base64_decode(output.data(), output.size(), &written, reinterpret_cast(input.data()), input.size())) return { }; return output; } std::vector encode64(const std::vector &input) { size_t outputSize = 4 * ((input.size() + 2) / 3); std::vector output(outputSize + 1, 0x00); size_t written = 0; if (mbedtls_base64_encode(output.data(), output.size(), &written, reinterpret_cast(input.data()), input.size())) return { }; return output; } static std::vector aes(mbedtls_cipher_type_t type, mbedtls_operation_t operation, const std::vector &key, std::array nonce, std::array iv, const std::vector &input) { std::vector output; if (input.empty()) return { }; mbedtls_cipher_context_t ctx; auto cipherInfo = mbedtls_cipher_info_from_type(type); mbedtls_cipher_setup(&ctx, cipherInfo); mbedtls_cipher_setkey(&ctx, key.data(), key.size() * 8, operation); std::array nonceCounter = { 0 }; std::copy(nonce.begin(), nonce.end(), nonceCounter.begin()); std::copy(iv.begin(), iv.end(), nonceCounter.begin() + 8); size_t outputSize = input.size() + cipherInfo->block_size; output.resize(outputSize, 0x00); mbedtls_cipher_crypt(&ctx, nonceCounter.data(), nonceCounter.size(), input.data(), input.size(), output.data(), &outputSize); mbedtls_cipher_free(&ctx); output.resize(input.size()); return output; } std::vector aesDecrypt(AESMode mode, KeyLength keyLength, const std::vector &key, std::array nonce, std::array iv, const std::vector &input) { switch (keyLength) { case KeyLength::Key128Bits: if (key.size() != 128 / 8) return { }; break; case KeyLength::Key192Bits: if (key.size() != 192 / 8) return { }; break; case KeyLength::Key256Bits: if (key.size() != 256 / 8) return { }; break; default: return { }; } mbedtls_cipher_type_t type; switch (mode) { case AESMode::ECB: type = MBEDTLS_CIPHER_AES_128_ECB; break; case AESMode::CBC: type = MBEDTLS_CIPHER_AES_128_CBC; break; case AESMode::CFB128: type = MBEDTLS_CIPHER_AES_128_CFB128; break; case AESMode::CTR: type = MBEDTLS_CIPHER_AES_128_CTR; break; case AESMode::GCM: type = MBEDTLS_CIPHER_AES_128_GCM; break; case AESMode::CCM: type = MBEDTLS_CIPHER_AES_128_CCM; break; case AESMode::OFB: type = MBEDTLS_CIPHER_AES_128_OFB; break; case AESMode::XTS: type = MBEDTLS_CIPHER_AES_128_XTS; break; default: return { }; } type = mbedtls_cipher_type_t(type + u8(keyLength)); return aes(type, MBEDTLS_DECRYPT, key, nonce, iv, input); } }