Merge branch 'master' of github.com:stz2012/libarib25

This commit is contained in:
tsukumijima 2021-10-23 04:25:21 +09:00
commit f79b38b982
34 changed files with 2841 additions and 12 deletions

131
.appveyor.yml Normal file
View File

@ -0,0 +1,131 @@
version: "0.2.5 build #{build}"
shallow_clone: true
environment:
SOLUTION: arib_std_b25.sln
BUILDENV: MSBUILD
MSYS2_DIR: msys64
CYGWIN_MIRROR: http://cygwin.mirror.constant.com
CYGWIN_PACKAGES: mpfr,mpc,gcc-core,gcc-g++,make,cmake
matrix:
# Latest version of VisualStudio
- JOB_NAME: "Visual Studio 16 2019 (Win32)"
CMAKE_GENERATOR: "Visual Studio 16 2019"
CMAKE_GENERATOR_PLATFORM: Win32
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
- JOB_NAME: "Visual Studio 16 2019 (Win64)"
CMAKE_GENERATOR: "Visual Studio 16 2019"
CMAKE_GENERATOR_PLATFORM: x64
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
- JOB_NAME: "Visual Studio 16 2019 (ARM)"
CMAKE_GENERATOR: "Visual Studio 16 2019"
CMAKE_GENERATOR_PLATFORM: ARM
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
- JOB_NAME: "Visual Studio 16 2019 (ARM64)"
CMAKE_GENERATOR: "Visual Studio 16 2019"
CMAKE_GENERATOR_PLATFORM: ARM64
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
# Windows Server 2012R2 or Windows 8 or above
- JOB_NAME: "Visual Studio 15 2017 (Win32)"
CMAKE_GENERATOR: "Visual Studio 15 2017"
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
- JOB_NAME: "Visual Studio 15 2017 (Win64)"
CMAKE_GENERATOR: "Visual Studio 15 2017 Win64"
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
# Windows Server 2008R2 or Windows 7 or above
- JOB_NAME: "Visual Studio 14 2015 (Win32)"
CMAKE_GENERATOR: "Visual Studio 14 2015"
- JOB_NAME: "Visual Studio 14 2015 (Win64)"
CMAKE_GENERATOR: "Visual Studio 14 2015 Win64"
- JOB_NAME: "Visual Studio 12 2013 (Win32)"
CMAKE_GENERATOR: "Visual Studio 12 2013"
- JOB_NAME: "Visual Studio 12 2013 (Win64)"
CMAKE_GENERATOR: "Visual Studio 12 2013 Win64"
- JOB_NAME: "Visual Studio 11 2012 (Win32)"
CMAKE_GENERATOR: "Visual Studio 11 2012"
- JOB_NAME: "Visual Studio 11 2012 (Win64)"
CMAKE_GENERATOR: "Visual Studio 11 2012 Win64"
# WindowsXP or above (C99 is not yet supported)
- JOB_NAME: "Visual Studio 10 2010 (Win32)"
CMAKE_GENERATOR: "Visual Studio 10 2010"
- JOB_NAME: "Visual Studio 10 2010 (Win64)"
CMAKE_GENERATOR: "Visual Studio 10 2010 Win64"
- JOB_NAME: "Visual Studio 9 2008 (Win32)"
CMAKE_GENERATOR: "Visual Studio 9 2008"
# MSYS2
- JOB_NAME: "MSYS2 MinGW32 (i686)"
CMAKE_GENERATOR: "MSYS Makefiles"
BUILDENV: MSYS2
MSYS2_ARCH: i686
MSYSTEM: MINGW32
- JOB_NAME: "MSYS2 MinGW64 (x86_64)"
CMAKE_GENERATOR: "MSYS Makefiles"
BUILDENV: MSYS2
MSYS2_ARCH: x86_64
MSYSTEM: MINGW64
# Cygwin
- JOB_NAME: "Cygwin32 (x86)"
CMAKE_GENERATOR: "Unix Makefiles"
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
BUILDENV: CYGWIN
CYGWIN_DIR: cygwin
CYGWIN_ARCH: x86
- JOB_NAME: "Cygwin64 (x86_64)"
CMAKE_GENERATOR: "Unix Makefiles"
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
BUILDENV: CYGWIN
CYGWIN_DIR: cygwin64
CYGWIN_ARCH: x86_64
install:
- if "%BUILDENV%" == "MSYS2"
set MSYS2_ROOT=%HOMEDRIVE%\%MSYS2_DIR%
- if "%BUILDENV%" == "CYGWIN"
set CYGWIN_ROOT=%HOMEDRIVE%\%CYGWIN_DIR%
- if "%BUILDENV%" == "CYGWIN" (
appveyor
DownloadFile "https://cygwin.com/setup-%CYGWIN_ARCH%.exe"
-FileName "%CYGWIN_ROOT%/setup-%CYGWIN_ARCH%.exe" &&
"%CYGWIN_ROOT%/setup-%CYGWIN_ARCH%.exe"
-qnNdOW
--root "%CYGWIN_ROOT%"
--site "%CYGWIN_MIRROR%"
--local-package-dir "%CYGWIN_ROOT%/var/cache/setup"
--packages "%CYGWIN_PACKAGES%"
)
before_build:
- mkdir build
- if "%BUILDENV%" == "MSBUILD" (
cd build &&
cmake --version &&
cmake ..
)
- if "%BUILDENV%" == "MSYS2"
"%MSYS2_ROOT%/usr/bin/bash" --login -c 'cd "${APPVEYOR_BUILD_FOLDER}/build"; cmake --version; cmake ..'
- if "%BUILDENV%" == "CYGWIN"
"%CYGWIN_ROOT%/bin/bash" --login -c 'cd "${APPVEYOR_BUILD_FOLDER}/build"; cmake --version; cmake ..'
build_script:
- if "%BUILDENV%" == "MSBUILD"
msbuild "%SOLUTION%" /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
- if "%BUILDENV%" == "MSYS2"
"%MSYS2_ROOT%/usr/bin/bash" --login -c 'cd "${APPVEYOR_BUILD_FOLDER}/build"; make'
- if "%BUILDENV%" == "CYGWIN"
"%CYGWIN_ROOT%/bin/bash" --login -c 'cd "${APPVEYOR_BUILD_FOLDER}/build"; make'

11
.editorconfig Normal file
View File

@ -0,0 +1,11 @@
root = true
[*]
end_of_life = lf
charset = utf-8
indent_style = tab
indent_size = 2
[*.yml]
indent_style = space
indent_size = 2

1
.tarball-version Normal file
View File

@ -0,0 +1 @@
v0.2.5-20180204

99
.travis.yml Normal file
View File

@ -0,0 +1,99 @@
sudo: false
language: cpp
matrix:
include:
# Linux with GNU C Compiler
- os: linux
compiler: gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- george-edison55-precise-backports
packages:
- gcc
- cmake
- cmake-data
- libpcsclite-dev
# Linux with LLVM C Compiler
- os: linux
compiler: clang
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- george-edison55-precise-backports
packages:
- clang
- cmake
- cmake-data
- libpcsclite-dev
# ARM Raspbian (jessie)
- os: linux
sudo: required
compiler: gcc
addons:
apt:
packages:
- qemu-user-static
- debootstrap
env:
- TARGET_DIST=raspbian
- TARGET_REPO=jessie
- TARGET_ARCH=armhf
- TARGET_SITE=http://archive.raspbian.com/raspbian
- TARGET_DEPS=git,cmake,libpcsclite-dev
- QEMU_CPU=arm11mpcore
# MacOS X 10.10 (Yosemite)
- os: osx
osx_image: xcode6.4
compiler: clang
# MacOS X 10.11 (El Captain)
- os: osx
osx_image: xcode7.3
compiler: clang
# macOS 10.11 (Sierra)
- os: osx
osx_image: xcode8
compiler: clang
cache:
directories:
- ${HOME}/rootfs/${TARGET_DIST}/${TARGET_REPO}/${TARGET_ARCH}/var/cache/apt/archives
before_script:
- if [ ! -z "${TARGET_DIST}" ]; then
ROOTFS="${HOME}/rootfs/${TARGET_DIST}/${TARGET_REPO}/${TARGET_ARCH}";
if [ ! -f "/usr/share/debootstrap/scripts/${TARGET_REPO}" ]; then
sudo ln -s "/usr/share/debootstrap/scripts/sid" "/usr/share/debootstrap/scripts/${TARGET_REPO}";
fi;
sudo mkdir -p "${ROOTFS}";
sudo qemu-debootstrap
--no-check-gpg --variant=buildd
--include="${TARGET_DEPS}" --arch="${TARGET_ARCH}"
"${TARGET_REPO}" "${ROOTFS}" "${TARGET_SITE}";
sudo mount --bind /home "${ROOTFS}/home";
export SHELL="sudo chroot ${ROOTFS} /bin/bash";
else
export SHELL="/bin/bash";
fi
script:
- >
${SHELL} -e <<EOF
install -d "${TRAVIS_BUILD_DIR}/build"
cd "${TRAVIS_BUILD_DIR}/build"
cmake ..
make VERBOSE=1
./b25 2>&1 | grep --color=auto "ARIB STD-B25"
if [ "${TRAVIS_OS_NAME}" != "osx" ]; then
./libaribb25.so 2>&1 | grep --color=auto "ARIB STD-B25"
fi
exit
EOF

146
CMakeLists.txt Normal file
View File

@ -0,0 +1,146 @@
cmake_minimum_required(VERSION 2.8.5)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE INTERNAL "limit build types" FORCE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "default build type")
set(CMAKE_INSTALL_SO_NO_EXE False)
project(arib_std_b25 C)
enable_language(CXX)
include(GitRevision)
include(GenerateExportHeader)
include(GNUInstallDirs)
find_package(PCSC REQUIRED)
if (UNIX OR MSYS)
find_program(LDCONFIG_EXECUTABLE "ldconfig")
set(WITH_PCSC_PACKAGE "libpcsclite" CACHE STRING "pkg-config package name for PC/SC")
set(WITH_PCSC_LIBRARY "" CACHE STRING "library name for PC/SC")
endif()
if(WIN32)
option(USE_UNICODE "enable unicode support" ON)
endif()
option(USE_AVX2 "enable AVX2" OFF)
if(NOT WIN32)
option(USE_NEON "enable NEON" OFF)
endif()
set(ARIB25_LIB_NAME "arib25")
set(ARIB25_CMD_NAME "b25")
set(ARIB25_URL "https://github.com/stz2012/libarib25")
set(ARIB25_DESCRIPTION "Reference implementation of ARIB STD-B25")
set(ARIB25_COMPANY "㋲製作所")
set(ARIB25_COPYRIGHT "©2012 茂木 和洋")
set(ARIB25_PRODUCT "ARIB STD-B25")
set(ARIB25_MAJOR_VERSION "0")
set(ARIB25_MINOR_VERSION "2")
set(ARIB25_PATCH_VERSION "5")
set(ARIB25_VERSION_NUMBER ${ARIB25_MAJOR_VERSION}.${ARIB25_MINOR_VERSION}.${ARIB25_PATCH_VERSION})
set(ARIB25_VERSION_STRING stz-${ARIB25_VERSION_NUMBER})
if(CMAKE_C_COMPILER_ID MATCHES "(GNU|Clang)")
set(CMAKE_C_FLAGS "-Wall")
set(CMAKE_C_FLAGS_DEBUG "-O2 -g")
set(CMAKE_C_FLAGS_RELEASE "-O2")
set(CMAKE_CXX_FLAGS "-Wall")
set(CMAKE_CXX_FLAGS_DEBUG "-O3 -g")
set(CMAKE_CXX_FLAGS_RELEASE "-O3")
set(CMAKE_SHARED_LINKER_FLAGS "-fvisibility=hidden")
if(UNIX AND NOT CYGWIN)
include(ElfInterp)
set(CMAKE_C_FLAGS "-fPIC ${CMAKE_C_FLAGS}")
set(CMAKE_CXX_FLAGS "-fPIC ${CMAKE_CXX_FLAGS}")
if(NOT APPLE)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-eshow_version")
endif()
else(MINGW)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--enable-stdcall-fixup -static-libgcc")
endif()
if(MINGW AND USE_UNICODE)
set(CMAKE_C_FLAGS "-municode ${CMAKE_C_FLAGS}")
set(CMAKE_CXX_FLAGS "-municode ${CMAKE_CXX_FLAGS}")
endif()
if(USE_AVX2)
set(CMAKE_C_FLAGS "-mavx2 ${CMAKE_C_FLAGS}")
set(CMAKE_CXX_FLAGS "-mavx2 ${CMAKE_CXX_FLAGS}")
endif()
if(USE_NEON)
set(CMAKE_C_FLAGS "-mfpu=neon ${CMAKE_C_FLAGS}")
set(CMAKE_CXX_FLAGS "-mfpu=neon ${CMAKE_CXX_FLAGS}")
endif()
elseif(CMAKE_C_COMPILER_ID MATCHES "(MSVC)")
add_definitions("-D_CRT_SECURE_NO_WARNINGS")
set(CMAKE_STATIC_LIBRARY_PREFIX lib)
set(CMAKE_SHARED_LIBRARY_PREFIX lib)
set(CMAKE_SUPPRESS_REGENERATION TRUE)
if(USE_AVX2)
set(CMAKE_C_FLAGS "/arch:AVX2 ${CMAKE_C_FLAGS}")
set(CMAKE_CXX_FLAGS "/arch:AVX2 ${CMAKE_CXX_FLAGS}")
endif()
endif()
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
add_definitions("-DDEBUG")
endif()
if(USE_UNICODE)
add_definitions("-DUNICODE" "-D_UNICODE")
endif()
add_definitions("-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64")
include_directories(${CMAKE_CURRENT_BINARY_DIR})
if(PCSC_INCLUDE_DIRS)
include_directories(${PCSC_INCLUDE_DIRS})
endif()
link_directories(${PCSC_LIBRARY_DIRS})
add_library(arib25-objlib OBJECT src/arib_std_b25.c src/b_cas_card.c src/multi2.cc src/ts_section_parser.c src/version.c)
set_target_properties(arib25-objlib PROPERTIES COMPILE_DEFINITIONS ARIB25_DLL)
add_library(arib25-static STATIC $<TARGET_OBJECTS:arib25-objlib>)
set_target_properties(arib25-static PROPERTIES OUTPUT_NAME ${ARIB25_LIB_NAME})
target_link_libraries(arib25-static PRIVATE ${PCSC_LIBRARIES})
add_library(arib25-shared SHARED $<TARGET_OBJECTS:arib25-objlib> ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
set_target_properties(arib25-shared PROPERTIES MACOSX_RPATH ON)
set_target_properties(arib25-shared PROPERTIES DEFINE_SYMBOL ARIB25_DLL)
set_target_properties(arib25-shared PROPERTIES COMPILE_DEFINITIONS ARIB25_DLL)
set_target_properties(arib25-shared PROPERTIES OUTPUT_NAME ${ARIB25_LIB_NAME})
set_target_properties(arib25-shared PROPERTIES SOVERSION ${ARIB25_MAJOR_VERSION})
set_target_properties(arib25-shared PROPERTIES VERSION ${ARIB25_VERSION_NUMBER})
target_link_libraries(arib25-shared PRIVATE ${PCSC_LIBRARIES})
generate_export_header(arib25-shared BASE_NAME arib25_api EXPORT_FILE_NAME arib25_api.h)
add_executable(b25 src/td.c ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
set_target_properties(b25 PROPERTIES OUTPUT_NAME ${ARIB25_CMD_NAME})
target_link_libraries(b25 PRIVATE ${PCSC_LIBRARIES})
target_link_libraries(b25 PRIVATE arib25-shared)
configure_file(src/config.h.in config.h @ONLY)
configure_file(src/version.rc.in version.rc @ONLY)
if(UNIX AND NOT CYGWIN)
configure_file(src/libarib25.pc.in ${CMAKE_SHARED_LIBRARY_PREFIX}${ARIB25_LIB_NAME}.pc @ONLY)
install(TARGETS b25 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(TARGETS arib25-static arib25-shared ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(FILES src/arib_std_b25.h src/b_cas_card.h src/multi2.h src/ts_section_parser.h src/portable.h ${CMAKE_CURRENT_BINARY_DIR}/arib25_api.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/arib25)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}${ARIB25_LIB_NAME}.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
install(CODE "execute_process(COMMAND ${CMAKE_COMMAND} -DLDCONFIG_EXECUTABLE=${LDCONFIG_EXECUTABLE} -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/PostInstall.cmake)")
add_custom_target(uninstall ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Uninstall.cmake)
elseif(WIN32)
install(TARGETS b25 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(TARGETS arib25-static arib25-shared ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(FILES src/arib_std_b25.h src/b_cas_card.h src/multi2.h src/ts_section_parser.h src/portable.h ${CMAKE_CURRENT_BINARY_DIR}/arib25_api.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/arib25)
add_custom_target(uninstall ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Uninstall.cmake)
endif()

201
LICENSE Normal file
View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2012 stz2012, MARUMO Manufacturing, 2ch NoNames.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

8
NOTICE Normal file
View File

@ -0,0 +1,8 @@
stz2012 - libarib25
Copyright (c)2012 stz2012 <tslroom@hotmail.com>
This product include software from MARUMO Manufacturing libarib25 project.
* Copyright (c)2007-2012 MOGI, Kazuhiro <kazhiro@marumo.ne.jp>; All rights reserved.
MARUMO Manufacturing (https://www.marumo.ne.jp/)
Special Thanks: 2ch NoNames, eternalharvest, eru.

View File

@ -1687,7 +1687,7 @@ static int proc_pmt(ARIB_STD_B25_PRIVATE_DATA *prv, TS_PROGRAM *pgrm)
head += len;
/* save old streams */
tmp_old_strm = pgrm->old_strm;
memcpy(&tmp_old_strm, &(pgrm->old_strm), sizeof(TS_STREAM_LIST));
/* save current streams */
pgrm->old_strm = pgrm->streams;
@ -2092,6 +2092,22 @@ static int proc_ecm(DECRYPTOR_ELEM *dec, B_CAS_CARD *bcas, int32_t multi2_round)
dec->m2->set_scramble_key(dec->m2, res.scramble_key);
#if defined(DEBUG)
int i;
fprintf(stderr, "----\n");
fprintf(stderr, "odd: ");
for(i=0;i<8;i++){
fprintf(stderr, " %02x", res.scramble_key[i]);
}
fprintf(stderr, "\n");
fprintf(stderr, "even:");
for(i=8;i<16;i++){
fprintf(stderr, " %02x", res.scramble_key[i]);
}
fprintf(stderr, "\n");
fflush(stderr);
#endif
LAST:
if(sect.raw != NULL){
n = dec->ecm->ret(dec->ecm, &sect);
@ -2100,8 +2116,43 @@ LAST:
}
}
return r;
#if defined(DEBUG)
static void dump_pts(uint8_t *src, int32_t crypt)
{
int32_t pts_dts_flag;
int64_t pts,dts;
src += 4; // TS ヘッダ部
src += 4; // start_code_prefix + stream_id 部
src += 2; // packet_length 部
pts_dts_flag = (src[1] >> 6) & 3;
src += 3;
if(pts_dts_flag & 2){
// PTS
pts = (src[0] >> 1) & 0x07;
pts <<= 15;
pts += ((src[1] << 8) + src[2]) >> 1;
pts <<= 15;
pts += ((src[3] << 8) + src[4]) >> 1;
src += 5;
}
if(pts_dts_flag & 1){
// DTS
dts = (src[0] >> 1) & 0x07;
dts <<= 15;
dts += ((src[1] << 8) + src[2]) >> 1;
dts <<= 15;
dts += ((src[3] << 8) + src[4]) >> 1;
}
if(pts_dts_flag == 2){
fprintf(stderr, " key=%d, pts=%"PRId64"\n", crypt, pts/90);
fflush(stderr);
}
}
#endif
static int proc_arib_std_b25(ARIB_STD_B25_PRIVATE_DATA *prv)
{
@ -2207,9 +2258,14 @@ static int proc_arib_std_b25(ARIB_STD_B25_PRIVATE_DATA *prv)
}else{
prv->map[pid].normal_packet += 1;
}
if(!append_work_buffer(&(prv->dbuf), curr, unit)){
return ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY;
#if defined(DEBUG)
if( (hdr.payload_unit_start_indicator != 0) && (pid == 0x111) ){
dump_pts(curr, crypt);
}
#endif
if(!append_work_buffer(&(prv->dbuf), curr, 188)){
r = ARIB_STD_B25_ERROR_NO_ENOUGH_MEMORY;
goto LAST;
}
if(prv->map[pid].type == PID_MAP_TYPE_ECM){

View File

@ -1,6 +1,7 @@
#ifndef ARIB_STD_B25_H
#define ARIB_STD_B25_H
#include "arib25_api.h"
#include "portable.h"
#include "b_cas_card.h"

View File

@ -8,11 +8,15 @@
#include <winscard.h>
#if defined(_WIN32)
#include <windows.h>
#include <tchar.h>
# include <windows.h>
# include <tchar.h>
#else
#define TCHAR char
#define _tcslen strlen
# define TCHAR char
# define _tcslen strlen
# if !defined(__CYGWIN__)
# include <wintypes.h>
# endif
# define _tcslen strlen
#endif
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@ -171,7 +175,7 @@ static int init_b_cas_card(void *bcas)
}
prv->reader = (LPTSTR)(prv->pool);
prv->sbuf = (uint8_t *)(prv->reader + len);
prv->sbuf = prv->pool + len;
prv->rbuf = prv->sbuf + B_CAS_BUFFER_MAX;
prv->id.data = (int64_t *)(prv->rbuf + B_CAS_BUFFER_MAX);
prv->id_max = 16;
@ -508,7 +512,7 @@ static int change_id_max(B_CAS_CARD_PRIVATE_DATA *prv, int max)
old_pwctrl = (uint8_t *)(prv->pwc.data);
prv->reader = (LPTSTR)p;
prv->sbuf = p + reader_size;
prv->sbuf = prv->pool + reader_size;
prv->rbuf = prv->sbuf + B_CAS_BUFFER_MAX;
prv->id.data = (int64_t *)(prv->rbuf + B_CAS_BUFFER_MAX);
prv->id_max = max;
@ -549,7 +553,7 @@ static int change_pwc_max(B_CAS_CARD_PRIVATE_DATA *prv, int max)
old_cardid = (uint8_t *)(prv->id.data);
prv->reader = (LPTSTR)p;
prv->sbuf = p + reader_size;
prv->sbuf = prv->pool + reader_size;
prv->rbuf = prv->sbuf + B_CAS_BUFFER_MAX;
prv->id.data = (int64_t *)(prv->rbuf + B_CAS_BUFFER_MAX);
prv->pwc.data = (B_CAS_PWR_ON_CTRL *)(prv->id.data + prv->id_max);

View File

@ -1,6 +1,7 @@
#ifndef B_CAS_CARD_H
#define B_CAS_CARD_H
#include "arib25_api.h"
#include "portable.h"
typedef struct {

17
aribb25/config.h.in Normal file
View File

@ -0,0 +1,17 @@
#ifndef CONFIG_H
#define CONFIG_H
#define ARIB25_MAJOR_VERSION @ARIB25_MAJOR_VERSION@
#define ARIB25_MINOR_VERSION @ARIB25_MINOR_VERSION@
#define ARIB25_PATCH_VERSION @ARIB25_PATCH_VERSION@
#define ARIB25_VERSION_NUMBER "@ARIB25_VERSION_NUMBER@"
#define ARIB25_VERSION_STRING "@ARIB25_VERSION_STRING@"
#define BUILD_OS_NAME "@CMAKE_SYSTEM@"
#define BUILD_CC_NAME "@CMAKE_C_COMPILER_ID@"
#define BUILD_CC_VERSION "@CMAKE_C_COMPILER_VERSION@"
#define BUILD_GIT_REVISION "@GIT_REVISION@"
#define ELF_INTERP "@ELF_INTERP@"
#endif /* CONFIG_H */

11
aribb25/libarib25.pc.in Normal file
View File

@ -0,0 +1,11 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: @CMAKE_LIBRARY_PREFIX@@ARIB25_LIB_NAME@
Description: @ARIB25_DESCRIPTION@
URL: @ARIB25_URL@
Version: @ARIB25_VERSION_STRING@
Libs: -L${libdir} -l@ARIB25_LIB_NAME@
Cflags: -I${includedir}

271
aribb25/multi2.cc Normal file
View File

@ -0,0 +1,271 @@
#include <cstddef>
#include <new>
#include "multi2.h"
#include "multi2_error_code.h"
#include "portable.h"
#include "multi2_compat.h"
#include "multi2_cipher.h"
namespace multi2 {
struct multi2 : public MULTI2 {
uint32_t ref_count;
uint32_t round;
optional<system_key_type> system_key;
optional<iv_type> iv;
array<optional<data_key_type>, 2> data_key;
array<optional<work_key_type>, 2> work_key;
inline void set_system_key(uint8_t *p) {
system_key_type s;
for (size_t i = 0; i < s.size(); ++i) {
s[i] = load_be(p + i * 4);
}
system_key = s;
}
inline void set_iv(uint8_t *p) {
iv_type v;
v[0] = load_be(p);
v[1] = load_be(p + 4);
iv = v;
}
inline void set_work_keys(uint8_t *p) {
array<data_key_type, 2> k;
k[0][0] = load_be(p);
k[0][1] = load_be(p + 4);
k[1][0] = load_be(p + 8);
k[1][1] = load_be(p + 12);
for (int i = 0; i < 2; ++i) {
if (!data_key[i] || *data_key[i] != k[i]) {
data_key[i] = k[i];
work_key[i].reset();
}
}
}
inline void clear_work_keys() {
for (int i = 0; i < 2; ++i) {
data_key[i].reset();
work_key[i].reset();
}
}
inline int encrypt(int32_t type, uint8_t *b, size_t n) {
int i = (type == 0x02);
if (!iv) {
return MULTI2_ERROR_UNSET_CBC_INIT;
}
if (!work_key[i]) {
if (!system_key) {
return MULTI2_ERROR_UNSET_SYSTEM_KEY;
}
if (!data_key[i]) {
return MULTI2_ERROR_UNSET_SCRAMBLE_KEY;
}
work_key[i] = schedule(*data_key[i], *system_key);
}
encrypt_cbc_ofb(b, n, *iv, *work_key[i], round);
return 0;
}
inline int decrypt(int32_t type, uint8_t *b, size_t n) {
int i = (type == 0x02);
if (!iv) {
return MULTI2_ERROR_UNSET_CBC_INIT;
}
if (!work_key[i]) {
if (!system_key) {
return MULTI2_ERROR_UNSET_SYSTEM_KEY;
}
if (!data_key[i]) {
return MULTI2_ERROR_UNSET_SCRAMBLE_KEY;
}
work_key[i] = schedule(*data_key[i], *system_key);
}
decrypt_cbc_ofb(b, n, *iv, *work_key[i], round);
return 0;
}
};
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
function prottypes (interface method)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
static void release_multi2(void *m2);
static int add_ref_multi2(void *m2);
static int set_round_multi2(void *m2, int32_t val);
static int set_system_key_multi2(void *m2, uint8_t *val);
static int set_init_cbc_multi2(void *m2, uint8_t *val);
static int set_scramble_key_multi2(void *m2, uint8_t *val);
static int clear_scramble_key_multi2(void *m2);
static int encrypt_multi2(void *m2, int32_t type, uint8_t *buf, int32_t size);
static int decrypt_multi2(void *m2, int32_t type, uint8_t *buf, int32_t size);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
global function implementation
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
ARIB25_API_EXPORT MULTI2 *create_multi2()
{
multi2::multi2 *m2;
try {
m2 = new multi2::multi2();
} catch (std::bad_alloc &e) {
return NULL;
}
m2->ref_count = 1;
m2->round = 4;
MULTI2 *r = static_cast<MULTI2 *>(m2);
r->private_data = m2;
r->release = release_multi2;
r->add_ref = add_ref_multi2;
r->set_round = set_round_multi2;
r->set_system_key = set_system_key_multi2;
r->set_init_cbc = set_init_cbc_multi2;
r->set_scramble_key = set_scramble_key_multi2;
r->clear_scramble_key = clear_scramble_key_multi2;
r->encrypt = encrypt_multi2;
r->decrypt = decrypt_multi2;
return r;
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
function prottypes (private method)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
static multi2::multi2 *private_data(void *m2);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
interface method implementation
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
static void release_multi2(void *m2)
{
multi2::multi2 *prv = private_data(m2);
if (!prv) {
return;
}
--prv->ref_count;
if (!prv->ref_count) {
delete prv;
}
}
static int add_ref_multi2(void *m2)
{
multi2::multi2 *prv = private_data(m2);
if (!prv) {
return MULTI2_ERROR_INVALID_PARAMETER;
}
++prv->ref_count;
return 0;
}
static int set_round_multi2(void *m2, int32_t val)
{
multi2::multi2 *prv = private_data(m2);
if (!prv) {
return MULTI2_ERROR_INVALID_PARAMETER;
}
prv->round = val;
return 0;
}
static int set_system_key_multi2(void *m2, uint8_t *val)
{
multi2::multi2 *prv = private_data(m2);
if (!prv || !val) {
return MULTI2_ERROR_INVALID_PARAMETER;
}
prv->set_system_key(val);
return 0;
}
static int set_init_cbc_multi2(void *m2, uint8_t *val)
{
multi2::multi2 *prv = private_data(m2);
if (!prv || !val) {
return MULTI2_ERROR_INVALID_PARAMETER;
}
prv->set_iv(val);
return 0;
}
static int set_scramble_key_multi2(void *m2, uint8_t *val)
{
multi2::multi2 *prv = private_data(m2);
if (!prv || !val) {
return MULTI2_ERROR_INVALID_PARAMETER;
}
prv->set_work_keys(val);
return 0;
}
static int clear_scramble_key_multi2(void *m2)
{
multi2::multi2 *prv = private_data(m2);
if (!prv) {
return MULTI2_ERROR_INVALID_PARAMETER;
}
prv->clear_work_keys();
return 0;
}
static int encrypt_multi2(void *m2, int32_t type, uint8_t *buf, int32_t size)
{
multi2::multi2 *prv = private_data(m2);
if (!prv || !buf || size < 1) {
return MULTI2_ERROR_INVALID_PARAMETER;
}
return prv->encrypt(type, buf, size);
}
static int decrypt_multi2(void *m2, int32_t type, uint8_t *buf, int32_t size)
{
multi2::multi2 *prv = private_data(m2);
if (!prv || !buf || size < 1) {
return MULTI2_ERROR_INVALID_PARAMETER;
}
return prv->decrypt(type, buf, size);
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
private method implementation
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
static multi2::multi2 *private_data(void *m2)
{
if (!m2) {
return NULL;
}
MULTI2 *p = static_cast<MULTI2 *>(m2);
multi2::multi2 *r = static_cast<multi2::multi2 *>(p->private_data);
if (static_cast<MULTI2 *>(r) != p) {
return NULL;
}
return r;
}

View File

@ -1,6 +1,7 @@
#ifndef MULTI2_H
#define MULTI2_H
#include "arib25_api.h"
#include "portable.h"
#include "simd_instruction_type.h"

81
aribb25/multi2_block.h Normal file
View File

@ -0,0 +1,81 @@
#pragma once
#include <utility>
#include "portable.h"
namespace multi2 {
inline uint32_t load_be(const uint8_t *p) {
return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
}
inline void store_be(uint8_t *p, uint32_t v) {
p[0] = (v >> 24) & 0xff;
p[1] = (v >> 16) & 0xff;
p[2] = (v >> 8) & 0xff;
p[3] = v & 0xff;
}
template<typename T>
struct block {
T left;
T right;
inline block() { }
inline block(const T &l, const T &r) : left(l), right(r) { }
void load(const uint8_t *p);
void store(uint8_t *p) const;
block<T> operator^(const block<T> &other) const;
std::pair<block<T>, block<uint32_t> > cbc_post_decrypt(const block<T> &ciphertext, const block<uint32_t> &state) const;
};
template<typename T>
inline size_t block_size() {
return sizeof(T) * 2;
}
typedef block<uint32_t> cbc_state;;
template<>
inline void block<uint32_t>::load(const uint8_t *p) {
left = load_be(p);
right = load_be(p + 4);
}
template<>
inline void block<uint32_t>::store(uint8_t *p) const {
store_be(p, left);
store_be(p + 4, right);
}
template<>
inline block<uint32_t> block<uint32_t>::operator^(const block<uint32_t> &other) const {
return block<uint32_t>(left ^ other.left, right ^ other.right);
}
template<>
inline std::pair<block<uint32_t>, cbc_state> block<uint32_t>::cbc_post_decrypt(const block<uint32_t> &c, const cbc_state &state) const {
block<uint32_t> p = *this ^ state;
return std::make_pair(p, c);
}
template<size_t N, typename T>
inline T rot(const T &v) {
return (v << N) | (v >> (32 - N));
}
template<typename T>
inline T rot1_sub(const T &v) {
return v + (v >> 31);
}
template<typename T>
inline T rot1_add_dec(const T &v) {
return rot<1>(v) + v - T(1);
}
}

233
aribb25/multi2_cipher.h Normal file
View File

@ -0,0 +1,233 @@
#pragma once
#include <cstring>
#include "portable.h"
#include "multi2_block.h"
#include "multi2_ymm2.h"
#include "multi2_ymm.h"
#include "multi2_xmm.h"
#include "multi2_neon2.h"
#include "multi2_neon.h"
#if defined(__GNUC__) || defined(__clang__)
# define MULTI2_ALWAYS_INLINE __attribute__((always_inline))
# define MULTI2_LIKELY(x) __builtin_expect(!!(x), 1)
#else
# define MULTI2_ALWAYS_INLINE
# define MULTI2_LIKELY(x) (x)
#endif
namespace multi2 {
typedef array<uint32_t, 8> system_key_type;
typedef array<uint32_t, 2> iv_type;
typedef array<uint32_t, 2> data_key_type;
typedef array<uint32_t, 8> work_key_type;
template<typename T>
struct pi {
typedef block<T> block_type;
static inline block_type pi1(const block_type &p) {
return block_type(p.left, p.right ^ p.left);
}
static inline block_type pi2(const block_type &p, uint32_t k1) {
T x = p.right;
T y = x + T(k1);
T z = rot1_add_dec(y);
return block_type(p.left ^ rot<4>(z) ^ z, p.right);
}
static inline block_type pi3(const block_type &p, uint32_t k2, uint32_t k3) {
T x = p.left;
T y = x + T(k2);
T z = rot<2>(y) + y + T(1);
T a = rot<8>(z) ^ z;
T b = a + T(k3);
T c = rot1_sub(b);
return block_type(p.left, p.right ^ rot<16>(c) ^ (c | x));
}
static inline block_type pi4(const block_type &p, uint32_t k4) {
T x = p.right;
T y = x + T(k4);
return block_type(p.left ^ (rot<2>(y) + y + T(1)), p.right);
}
};
template<typename T>
struct cipher {
typedef block<T> block_type;
typedef pi<T> p;
static inline block_type encrypt(const block_type &b, const work_key_type &wk, int n) {
block_type t = b;
for (int i = 0; i < n; ++i) {
t = p::pi1(t);
t = p::pi2(t, wk[0]);
t = p::pi3(t, wk[1], wk[2]);
t = p::pi4(t, wk[3]);
t = p::pi1(t);
t = p::pi2(t, wk[4]);
t = p::pi3(t, wk[5], wk[6]);
t = p::pi4(t, wk[7]);
}
return t;
}
static inline block_type decrypt(const block_type &b, const work_key_type &wk, int n) {
block_type t = b;
for (int i = 0; i < n; ++i) {
t = p::pi4(t, wk[7]);
t = p::pi3(t, wk[5], wk[6]);
t = p::pi2(t, wk[4]);
t = p::pi1(t);
t = p::pi4(t, wk[3]);
t = p::pi3(t, wk[1], wk[2]);
t = p::pi2(t, wk[0]);
t = p::pi1(t);
}
return t;
}
};
inline work_key_type schedule(const data_key_type &dk, const system_key_type &sk) {
typedef pi<uint32_t> p;
block<uint32_t> a0 = p::pi1(block<uint32_t>(dk[0], dk[1]));
block<uint32_t> a1 = p::pi2(a0, sk[0]);
block<uint32_t> a2 = p::pi3(a1, sk[1], sk[2]);
block<uint32_t> a3 = p::pi4(a2, sk[3]);
block<uint32_t> a4 = p::pi1(a3);
block<uint32_t> a5 = p::pi2(a4, sk[4]);
block<uint32_t> a6 = p::pi3(a5, sk[5], sk[6]);
block<uint32_t> a7 = p::pi4(a6, sk[7]);
block<uint32_t> a8 = p::pi1(a7);
work_key_type w;
w[0] = a1.left;
w[1] = a2.right;
w[2] = a3.left;
w[3] = a4.right;
w[4] = a5.left;
w[5] = a6.right;
w[6] = a7.left;
w[7] = a8.right;
return w;
}
inline void encrypt_cbc_ofb(uint8_t *buf, size_t n, const iv_type &iv, const work_key_type &key, int round) {
cbc_state state(iv[0], iv[1]);
while (block_size<uint32_t>() <= n) {
block<uint32_t> p;
p.load(buf);
block<uint32_t> c = cipher<uint32_t>::encrypt(p ^ state, key, round);
c.store(buf);
state = c;
buf += block_size<uint32_t>();
n -= block_size<uint32_t>();
}
if (0 < n) {
array<uint8_t, 8> t;
memcpy(&t[0], buf, n);
memset(&t[n], 0, 8 - n);
block<uint32_t> p;
p.load(&t[0]);
block<uint32_t> c = p ^ cipher<uint32_t>::encrypt(state, key, round);
c.store(&t[0]);
memcpy(buf, &t[0], n);
}
}
template<typename T>
MULTI2_ALWAYS_INLINE
static inline void decrypt_block(uint8_t *&buf, size_t &n, cbc_state &state, const work_key_type &key, int round) {
block<T> c;
c.load(buf);
block<T> d = cipher<T>::decrypt(c, key, round);
std::pair<block<T>, cbc_state> ps = d.cbc_post_decrypt(c, state);
ps.first.store(buf);
state = ps.second;
buf += block_size<T>();
n -= block_size<T>();
}
inline void decrypt_cbc_ofb(uint8_t *buf, size_t n, const iv_type &iv, const work_key_type &key, int round) {
cbc_state state(iv[0], iv[1]);
#if defined(__AVX2__)
if (MULTI2_LIKELY(n == 184)) {
decrypt_block<x86::ymm2>(buf, n, state, key, round);
decrypt_block<x86::ymm>(buf, n, state, key, round);
return;
}
if (block_size<x86::ymm2>() <= n) {
decrypt_block<x86::ymm2>(buf, n, state, key, round);
}
if (block_size<x86::ymm>() <= n) {
decrypt_block<x86::ymm>(buf, n, state, key, round);
}
#if defined(__SSE2__)
if (block_size<x86::xmm>() <= n) {
decrypt_block<x86::xmm>(buf, n, state, key, round);
}
#endif
#elif defined(__SSE2__)
while (block_size<x86::xmm>() <= n) {
decrypt_block<x86::xmm>(buf, n, state, key, round);
}
#elif defined(__ARM_NEON__) || defined(__ARM_NEON)
if (MULTI2_LIKELY(n == 184)) {
decrypt_block<arm::neon2<7> >(buf, n, state, key, round);
decrypt_block<arm::neon2<8> >(buf, n, state, key, round);
decrypt_block<arm::neon2<8> >(buf, n, state, key, round);
return;
}
while (block_size<arm::neon2<8> >() <= n) {
decrypt_block<arm::neon2<8> >(buf, n, state, key, round);
}
if (block_size<arm::neon>() <= n) {
decrypt_block<arm::neon>(buf, n, state, key, round);
}
#endif
while (block_size<uint32_t>() <= n) {
decrypt_block<uint32_t>(buf, n, state, key, round);
}
if (0 < n) {
array<uint8_t, 8> t;
memcpy(&t[0], buf, n);
memset(&t[n], 0, 8 - n);
block<uint32_t> c;
c.load(&t[0]);
block<uint32_t> p = c ^ cipher<uint32_t>::encrypt(state, key, round);
p.store(&t[0]);
memcpy(buf, &t[0], n);
}
}
}
#undef MULTI2_ALWAYS_INLINE
#undef MULTI2_LIKELY

42
aribb25/multi2_compat.h Normal file
View File

@ -0,0 +1,42 @@
#pragma once
#include <algorithm>
namespace multi2 {
template<typename T, size_t N>
class array {
T v[N];
inline const T *begin() const { return &v[0]; }
inline const T *end() const { return &v[N]; }
public:
inline size_t size() { return N; }
inline bool operator!=(const array &other) const {
return !std::equal(begin(), end(), other.begin());
}
inline T &operator[](size_t n) { return v[n]; }
inline const T &operator[](size_t n) const { return v[n]; }
};
template<typename T>
class optional {
T v;
bool has;
public:
inline optional() : has(false) { }
inline optional &operator=(const T &other) {
v = other;
has = true;
return *this;
}
inline void reset() { has = false; }
inline operator bool() const { return has; }
inline T &operator*() { return v; }
};
}

113
aribb25/multi2_neon.h Normal file
View File

@ -0,0 +1,113 @@
#pragma once
#if defined(__ARM_NEON__) || defined(__ARM_NEON)
#if !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__) || (__BYTE_ORDER__) != (__ORDER_LITTLE_ENDIAN__)
#error "Currently, USE_NEON is only for little-endian."
#endif
#include <utility>
#include <arm_neon.h>
#include "portable.h"
#include "multi2_block.h"
namespace multi2 {
namespace arm {
class neon {
private:
uint32x4_t v;
public:
inline neon() { }
inline neon(uint32_t n) { v = vdupq_n_u32(n); }
inline neon(const uint32x4_t &r) { v = r; }
inline neon &operator=(const neon &other) {
v = other.v;
return *this;
}
inline neon operator+(const neon &other) const { return vaddq_u32(v, other.v); }
inline neon operator-(const neon &other) const { return vsubq_u32(v, other.v); }
inline neon operator^(const neon &other) const { return veorq_u32(v, other.v); }
inline neon operator|(const neon &other) const { return vorrq_u32(v, other.v); }
inline const uint32x4_t &value() const { return v; }
};
}
template<>
inline void block<arm::neon>::load(const uint8_t *p) {
const uint32_t *q = reinterpret_cast<const uint32_t *>(p);
uint32x4x2_t a = vld2q_u32(q);
left = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(a.val[0])));
right = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(a.val[1])));
}
template<>
inline void block<arm::neon>::store(uint8_t *p) const {
uint32x4_t a0 = left.value();
uint32x4_t a1 = right.value();
uint32x4_t b0 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(a0)));
uint32x4_t b1 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(a1)));
uint32_t *q = reinterpret_cast<uint32_t *>(p);
uint32x4x2_t d = { b0, b1 };
vst2q_u32(q, d);
}
template<>
inline std::pair<block<arm::neon>, cbc_state> block<arm::neon>::cbc_post_decrypt(const block<arm::neon> &c, const cbc_state &state) const {
uint32x4_t c0 = c.left.value(); // 3 2 1 0
uint32x4_t c1 = c.right.value();
uint32_t s0 = vgetq_lane_u32(c0, 3); // 3
uint32_t s1 = vgetq_lane_u32(c1, 3);
uint32x4_t b0 = vextq_u32(c0, c0, 3); // 2 1 0 3
uint32x4_t b1 = vextq_u32(c1, c1, 3);
uint32x4_t x0 = vsetq_lane_u32(state.left, b0, 0); // 2 1 0 s
uint32x4_t x1 = vsetq_lane_u32(state.right, b1, 0);
uint32x4_t d0 = left.value(); // 3 2 1 0
uint32x4_t d1 = right.value();
uint32x4_t p0 = veorq_u32(d0, x0);
uint32x4_t p1 = veorq_u32(d1, x1);
return std::make_pair(block<arm::neon>(p0, p1), cbc_state(s0, s1));
}
template<int N>
inline arm::neon rot(const arm::neon &v) {
uint32x4_t a = v.value();
if (N == 16) {
return vreinterpretq_u32_u16(vrev32q_u16(vreinterpretq_u16_u32(a)));
} else {
return vsliq_n_u32(vshrq_n_u32(a, 32 - N), a, N);
}
}
template<>
inline arm::neon rot1_sub<arm::neon>(const arm::neon &v) {
uint32x4_t a = v.value();
return vsraq_n_u32(a, a, 31);
}
template<>
inline arm::neon rot1_add_dec<arm::neon>(const arm::neon &v) {
uint32x4_t d = vcgeq_s32(vreinterpretq_s32_u32(v.value()), vdupq_n_s32(0));
return v + v + v + arm::neon(d);
}
}
#endif /* __ARM_NEON__ || __ARM_NEON */

201
aribb25/multi2_neon2.h Normal file
View File

@ -0,0 +1,201 @@
#pragma once
#if defined(__ARM_NEON__) || defined(__ARM_NEON)
#include <utility>
#include <arm_neon.h>
#include "portable.h"
#include "multi2_block.h"
namespace multi2 {
namespace arm {
template<size_t S>
class neon2 {
private:
uint32x4_t v0;
uint32x4_t v1;
public:
inline neon2() { }
inline neon2(uint32_t n) { v0 = v1 = vdupq_n_u32(n); }
inline neon2(const uint32x4_t &r0, const uint32x4_t &r1) {
v0 = r0;
v1 = r1;
}
inline neon2 &operator=(const neon2 &other) {
v0 = other.v0;
v1 = other.v1;
return *this;
}
inline neon2 operator+(const neon2 &other) const {
return neon2(vaddq_u32(v0, other.v0), vaddq_u32(v1, other.v1));
}
inline neon2 operator-(const neon2 &other) const {
return neon2(vsubq_u32(v0, other.v0), vsubq_u32(v1, other.v1));
}
inline neon2 operator^(const neon2 &other) const {
return neon2(veorq_u32(v0, other.v0), veorq_u32(v1, other.v1));
}
inline neon2 operator|(const neon2 &other) const {
return neon2(vorrq_u32(v0, other.v0), vorrq_u32(v1, other.v1));
}
inline const uint32x4_t &value0() const { return v0; }
inline const uint32x4_t &value1() const { return v1; }
static inline void load_block(block<neon2> &b, const uint8_t *p) {
size_t d = 8 - (8 - S) * 2;
const uint32_t *q = reinterpret_cast<const uint32_t *>(p);
uint32x4x2_t a0 = vld2q_u32(q);
uint32x4x2_t a1 = vld2q_u32(q + d);
uint32x4_t b0 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(a0.val[0])));
uint32x4_t b1 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(a0.val[1])));
uint32x4_t b2 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(a1.val[0])));
uint32x4_t b3 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(a1.val[1])));
b.left = neon2(b0, b2);
b.right = neon2(b1, b3);
}
static inline void store_block(uint8_t *p, const block<neon2> &b) {
uint32x4_t a0 = b.left.value0();
uint32x4_t a1 = b.right.value0();
uint32x4_t a2 = b.left.value1();
uint32x4_t a3 = b.right.value1();
uint32x4_t b0 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(a0)));
uint32x4_t b1 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(a1)));
uint32x4_t b2 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(a2)));
uint32x4_t b3 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(a3)));
size_t d = 8 - (8 - S) * 2;
uint32_t *q = reinterpret_cast<uint32_t *>(p);
uint32x4x2_t e0 = { b0, b1 };
uint32x4x2_t e1 = { b2, b3 };
vst2q_u32(q + d, e1);
vst2q_u32(q, e0);
}
static inline std::pair<block<neon2>, cbc_state> cbc_post_decrypt(const block<neon2> &d, const block<neon2> &c, const cbc_state &state) {
uint32x4_t c0 = c.left.value0(); // 3 2 1 0
uint32x4_t c1 = c.right.value0();
uint32x4_t c2 = c.left.value1(); // d c b a
uint32x4_t c3 = c.right.value1();
uint32_t s2 = vgetq_lane_u32(c2, 3); // d
uint32_t s3 = vgetq_lane_u32(c3, 3);
uint32x4_t b0 = vextq_u32(c0, c0, 3); // 2 1 0 3
uint32x4_t b1 = vextq_u32(c1, c1, 3);
uint32x4_t b2 = vextq_u32(c0, c2, 3); // c b a 3
uint32x4_t b3 = vextq_u32(c1, c3, 3);
uint32x4_t x0 = vsetq_lane_u32(state.left, b0, 0); // 2 1 0 s
uint32x4_t x1 = vsetq_lane_u32(state.right, b1, 0);
uint32x4_t x2 = b2; // c b a 3
uint32x4_t x3 = b3;
uint32x4_t d0 = d.left.value0(); // 3 2 1 0
uint32x4_t d1 = d.right.value0();
uint32x4_t d2 = d.left.value1(); // d c b a
uint32x4_t d3 = d.right.value1();
uint32x4_t p0 = veorq_u32(d0, x0); // 3 2 1 0
uint32x4_t p1 = veorq_u32(d1, x1);
uint32x4_t p2 = veorq_u32(d2, x2); // d c b a?
uint32x4_t p3 = veorq_u32(d3, x3);
return std::make_pair(block<neon2>(neon2(p0, p2), neon2(p1, p3)), cbc_state(s2, s3));
}
};
}
template<>
inline size_t block_size<arm::neon2<7> >() {
return 56;
}
template<>
inline size_t block_size<arm::neon2<8> >() {
return 64;
}
template<>
inline void block<arm::neon2<7> >::load(const uint8_t *p) {
arm::neon2<7>::load_block(*this, p);
}
template<>
inline void block<arm::neon2<8> >::load(const uint8_t *p) {
arm::neon2<8>::load_block(*this, p);
}
template<>
inline void block<arm::neon2<7> >::store(uint8_t *p) const {
arm::neon2<7>::store_block(p, *this);
}
template<>
inline void block<arm::neon2<8> >::store(uint8_t *p) const {
arm::neon2<8>::store_block(p, *this);
}
template<>
inline std::pair<block<arm::neon2<7> >, cbc_state> block<arm::neon2<7> >::cbc_post_decrypt(const block<arm::neon2<7> > &c, const cbc_state &state) const {
return arm::neon2<7>::cbc_post_decrypt(*this, c, state);
}
template<>
inline std::pair<block<arm::neon2<8> >, cbc_state> block<arm::neon2<8> >::cbc_post_decrypt(const block<arm::neon2<8> > &c, const cbc_state &state) const {
return arm::neon2<8>::cbc_post_decrypt(*this, c, state);
}
template<int N, size_t S>
inline arm::neon2<S> rot(const arm::neon2<S> &v) {
uint32x4_t a0 = v.value0();
uint32x4_t a1 = v.value1();
if (N == 16) {
uint32x4_t b0 = vreinterpretq_u32_u16(vrev32q_u16(vreinterpretq_u16_u32(a0)));
uint32x4_t b1 = vreinterpretq_u32_u16(vrev32q_u16(vreinterpretq_u16_u32(a1)));
return arm::neon2<S>(b0, b1);
} else {
uint32x4_t b0 = vshrq_n_u32(a0, 32 - N);
uint32x4_t b1 = vshrq_n_u32(a1, 32 - N);
uint32x4_t c0 = vsliq_n_u32(b0, a0, N);
uint32x4_t c1 = vsliq_n_u32(b1, a1, N);
return arm::neon2<S>(c0, c1);
}
}
template<size_t S>
inline arm::neon2<S> rot1_sub(const arm::neon2<S> &v) {
uint32x4_t a0 = v.value0();
uint32x4_t a1 = v.value1();
uint32x4_t b0 = vsraq_n_u32(a0, a0, 31);
uint32x4_t b1 = vsraq_n_u32(a1, a1, 31);
return arm::neon2<S>(b0, b1);
}
template<size_t S>
inline arm::neon2<S> rot1_add_dec(const arm::neon2<S> &v) {
uint32x4_t a0 = v.value0();
uint32x4_t a1 = v.value1();
uint32x4_t d0 = vcgeq_s32(vreinterpretq_s32_u32(a0), vdupq_n_s32(0));
uint32x4_t d1 = vcgeq_s32(vreinterpretq_s32_u32(a1), vdupq_n_s32(0));
return v + v + v + arm::neon2<S>(d0, d1);
}
}
#endif /* __ARM_NEON__ || __ARM_NEON */

208
aribb25/multi2_xmm.h Normal file
View File

@ -0,0 +1,208 @@
#pragma once
#if defined(__SSE2__)
#include <utility>
#if defined(_WIN32)
# include <intrin.h>
#else
# include <x86intrin.h>
#endif
#include "portable.h"
#include "multi2_block.h"
namespace multi2 {
namespace x86 {
class xmm {
private:
__m128i v;
public:
inline xmm() {
#if !defined(NO_MM_UNDEFINED)
v = _mm_undefined_si128();
#endif
}
inline xmm(uint32_t n) { v = _mm_set1_epi32(n); }
inline xmm(const __m128i &r) { v = r; }
inline xmm &operator=(const xmm &other) {
v = other.v;
return *this;
}
inline xmm operator+(const xmm &other) const { return _mm_add_epi32(v, other.v); }
inline xmm operator-(const xmm &other) const { return _mm_sub_epi32(v, other.v); }
inline xmm operator^(const xmm &other) const { return _mm_xor_si128(v, other.v); }
inline xmm operator|(const xmm &other) const { return _mm_or_si128(v, other.v); }
inline xmm operator<<(int n) const { return _mm_slli_epi32(v, n); }
inline xmm operator>>(int n) const { return _mm_srli_epi32(v, n); }
inline const __m128i &value() const { return v; }
};
}
#if defined(__SSSE3__)
template<>
inline void block<x86::xmm>::load(const uint8_t *p) {
const __m128i *q = reinterpret_cast<const __m128i *>(p);
__m128i a0 = _mm_loadu_si128(q); // 3 2 1 0 - DCBA
__m128i a1 = _mm_loadu_si128(q + 1); // 7 6 5 4 - DCBA
__m128i s = _mm_set_epi8(12, 13, 14, 15, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3);
__m128i b0 = _mm_shuffle_epi8(a0, s); // 3 1 2 0 - ABCD
__m128i b1 = _mm_shuffle_epi8(a1, s); // 7 5 6 4 - ABCD
left = _mm_unpacklo_epi32(b0, b1); // 6 2 4 0 - ABCD
right = _mm_unpackhi_epi32(b0, b1); // 7 3 5 1 - ABCD
}
template<>
inline void block<x86::xmm>::store(uint8_t *p) const {
__m128i a0 = left.value(); // 6 2 4 0 - ABCD
__m128i a1 = right.value(); // 7 3 5 1 - ABCD
__m128i s = _mm_set_epi8(12, 13, 14, 15, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3);
__m128i b0 = _mm_shuffle_epi8(a0, s); // 6 4 2 0 - DCBA
__m128i b1 = _mm_shuffle_epi8(a1, s); // 7 5 3 1 - DCBA
__m128i c0 = _mm_unpacklo_epi32(b0, b1); // 3 2 1 0 - DCBA
__m128i c1 = _mm_unpackhi_epi32(b0, b1); // 7 6 5 4 - DCBA
__m128i *q = reinterpret_cast<__m128i *>(p);
_mm_storeu_si128(q, c0);
_mm_storeu_si128(q + 1, c1);
}
template<>
inline x86::xmm rot<8, x86::xmm>(const x86::xmm &v) {
__m128i s = _mm_set_epi8(14, 13, 12, 15, 10, 9, 8, 11, 6, 5, 4, 7, 2, 1, 0, 3);
return _mm_shuffle_epi8(v.value(), s);
}
template<>
inline x86::xmm rot<16, x86::xmm>(const x86::xmm &v) {
__m128i s = _mm_set_epi8(13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2);
return _mm_shuffle_epi8(v.value(), s);
}
#else /* __SSSE3__ */
template<>
inline void block<x86::xmm>::load(const uint8_t *p) {
const __m128i *q = reinterpret_cast<const __m128i *>(p);
__m128i a0 = _mm_loadu_si128(q); // 3 2 1 0
__m128i a1 = _mm_loadu_si128(q + 1); // 7 6 5 4
__m128i b0 = _mm_unpacklo_epi32(a0, a1); // 5 1 4 0
__m128i b1 = _mm_unpackhi_epi32(a0, a1); // 7 3 6 2
__m128i c0 = _mm_unpacklo_epi32(b0, b1); // 6 4 2 0 - DCBA
__m128i c1 = _mm_unpackhi_epi32(b0, b1); // 7 5 3 1 - DCBA
__m128i d0 = _mm_shufflehi_epi16(_mm_shufflelo_epi16(c0, _MM_SHUFFLE(2, 3, 0, 1)), _MM_SHUFFLE(2, 3, 0, 1)); // BADC
__m128i d1 = _mm_shufflehi_epi16(_mm_shufflelo_epi16(c1, _MM_SHUFFLE(2, 3, 0, 1)), _MM_SHUFFLE(2, 3, 0, 1)); // BADC
left = _mm_or_si128(_mm_srli_epi16(d0, 8), _mm_slli_epi16(d0, 8)); // ABCD
right = _mm_or_si128(_mm_srli_epi16(d1, 8), _mm_slli_epi16(d1, 8)); // ABCD
}
template<>
inline void block<x86::xmm>::store(uint8_t *p) const {
__m128i a0 = left.value(); // ABCD
__m128i a1 = right.value(); // ABCD
__m128i b0 = _mm_or_si128(_mm_srli_epi16(a0, 8), _mm_slli_epi16(a0, 8)); // BADC
__m128i b1 = _mm_or_si128(_mm_srli_epi16(a1, 8), _mm_slli_epi16(a1, 8)); // BADC
__m128i c0 = _mm_shufflehi_epi16(_mm_shufflelo_epi16(b0, _MM_SHUFFLE(2, 3, 0, 1)), _MM_SHUFFLE(2, 3, 0, 1)); // 6 4 2 0 - DCBA
__m128i c1 = _mm_shufflehi_epi16(_mm_shufflelo_epi16(b1, _MM_SHUFFLE(2, 3, 0, 1)), _MM_SHUFFLE(2, 3, 0, 1)); // 7 5 3 1 - DCBA
__m128i d0 = _mm_unpacklo_epi32(c0, c1); // 3 2 1 0
__m128i d1 = _mm_unpackhi_epi32(c0, c1); // 7 6 5 4
__m128i *q = reinterpret_cast<__m128i *>(p);
_mm_storeu_si128(q, d0);
_mm_storeu_si128(q + 1, d1);
}
#endif /* __SSSE3__ */
#if defined(__SSE4_1__)
template<>
inline std::pair<block<x86::xmm>, cbc_state> block<x86::xmm>::cbc_post_decrypt(const block<x86::xmm> &c, const cbc_state &state) const {
__m128i c0 = c.left.value(); // 3 1 2 0
__m128i c1 = c.right.value();
uint32_t s0 = _mm_extract_epi32(c0, 3); // 3
uint32_t s1 = _mm_extract_epi32(c1, 3);
__m128i b0 = _mm_shuffle_epi32(c0, _MM_SHUFFLE(1, 0, 2, 3)); // 2 0 1 3
__m128i b1 = _mm_shuffle_epi32(c1, _MM_SHUFFLE(1, 0, 2, 3));
__m128i x0 = _mm_insert_epi32(b0, state.left, 0); // 2 0 1 s
__m128i x1 = _mm_insert_epi32(b1, state.right, 0);
__m128i d0 = left.value(); // 3 1 2 0
__m128i d1 = right.value();
__m128i p0 = _mm_xor_si128(d0, x0);
__m128i p1 = _mm_xor_si128(d1, x1);
return std::make_pair(block<x86::xmm>(p0, p1), cbc_state(s0, s1));
}
#else /* __SSE4_1__ */
template<>
inline std::pair<block<x86::xmm>, cbc_state> block<x86::xmm>::cbc_post_decrypt(const block<x86::xmm> &c, const cbc_state &state) const {
__m128i c0 = c.left.value(); // 3 1 2 0 / 3 2 1 0
__m128i c1 = c.right.value();
#if defined(__SSSE3__)
const int s = _MM_SHUFFLE(1, 0, 2, 3);
#else
const int s = _MM_SHUFFLE(2, 1, 0, 3);
#endif
__m128i b0 = _mm_shuffle_epi32(c0, s); // 2 0 1 3 / 2 1 0 3
__m128i b1 = _mm_shuffle_epi32(c1, s);
uint32_t s0 = _mm_cvtsi128_si32(b0); // 3
uint32_t s1 = _mm_cvtsi128_si32(b1);
__m128i i0 = _mm_cvtsi32_si128(state.left); // - - - s
__m128i i1 = _mm_cvtsi32_si128(state.right);
__m128i x0 = _mm_castps_si128(_mm_move_ss(_mm_castsi128_ps(b0), _mm_castsi128_ps(i0))); // 2 0 1 s / 2 1 0 s
__m128i x1 = _mm_castps_si128(_mm_move_ss(_mm_castsi128_ps(b1), _mm_castsi128_ps(i1)));
__m128i d0 = left.value(); // 3 1 2 0 / 3 2 1 0
__m128i d1 = right.value();
__m128i p0 = _mm_xor_si128(d0, x0);
__m128i p1 = _mm_xor_si128(d1, x1);
return std::make_pair(block<x86::xmm>(p0, p1), cbc_state(s0, s1));
}
#endif /* __SSE4_1__ */
template<>
inline x86::xmm rot1_add_dec<x86::xmm>(const x86::xmm &v) {
__m128i d = _mm_cmpgt_epi32(v.value(), _mm_set1_epi32(-1));
return v + v + v + x86::xmm(d);
}
}
#endif /* __SSE2__ */

140
aribb25/multi2_ymm.h Normal file
View File

@ -0,0 +1,140 @@
#pragma once
#if defined(__AVX2__)
#include <utility>
#if defined(_WIN32)
# include <intrin.h>
#else
# include <x86intrin.h>
#endif
#include "portable.h"
#include "multi2_block.h"
namespace multi2 {
namespace x86 {
class ymm {
private:
__m256i v;
public:
inline ymm() {
#if !defined(NO_MM_UNDEFINED)
v = _mm256_undefined_si256();
#endif
}
inline ymm(uint32_t n) { v = _mm256_set1_epi32(n); }
inline ymm(const __m256i &r) { v = r; }
inline ymm &operator=(const ymm &other) {
v = other.v;
return *this;
}
inline ymm operator+(const ymm &other) const { return _mm256_add_epi32(v, other.v); }
inline ymm operator-(const ymm &other) const { return _mm256_sub_epi32(v, other.v); }
inline ymm operator^(const ymm &other) const { return _mm256_xor_si256(v, other.v); }
inline ymm operator|(const ymm &other) const { return _mm256_or_si256(v, other.v); }
inline ymm operator<<(int n) const { return _mm256_slli_epi32(v, n); }
inline ymm operator>>(int n) const { return _mm256_srli_epi32(v, n); }
inline const __m256i &value() const { return v; }
};
}
template<>
inline void block<x86::ymm>::load(const uint8_t *p) {
const __m256i *q = reinterpret_cast<const __m256i *>(p);
__m256i a0 = _mm256_loadu_si256(q); // 7 6 5 4 3 2 1 0 - DCBA
__m256i a1 = _mm256_loadu_si256(q + 1); // f e d c b a 9 8 - DCBA
__m256i s = _mm256_set_epi8(
12, 13, 14, 15, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3,
12, 13, 14, 15, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3
);
__m256i b0 = _mm256_shuffle_epi8(a0, s); // 7 5 6 4 3 1 2 0 - ABCD
__m256i b1 = _mm256_shuffle_epi8(a1, s); // f d e c b 9 a 8 - ABCD
left = _mm256_unpacklo_epi32(b0, b1); // e 6 c 4 a 2 8 0 - ABCD
right = _mm256_unpackhi_epi32(b0, b1); // f 7 d 5 b 3 9 1 - ABCD
}
template<>
inline void block<x86::ymm>::store(uint8_t *p) const {
__m256i a0 = left.value(); // e 6 c 4 a 2 8 0 - ABCD
__m256i a1 = right.value(); // f 7 d 5 b 3 9 1 - ABCD
__m256i s = _mm256_set_epi8(
12, 13, 14, 15, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3,
12, 13, 14, 15, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3
);
__m256i b0 = _mm256_shuffle_epi8(a0, s); // e c 6 4 a 8 2 0 - DCBA
__m256i b1 = _mm256_shuffle_epi8(a1, s); // f d 7 5 b 9 3 1 - DCBA
__m256i c0 = _mm256_unpacklo_epi32(b0, b1); // 7 6 5 4 3 2 1 0 - DCBA
__m256i c1 = _mm256_unpackhi_epi32(b0, b1); // f e d c 7 6 5 4 - DCBA
__m256i *q = reinterpret_cast<__m256i *>(p);
_mm256_storeu_si256(q, c0);
_mm256_storeu_si256(q + 1, c1);
}
template<>
inline std::pair<block<x86::ymm>, cbc_state> block<x86::ymm>::cbc_post_decrypt(const block<x86::ymm> &c, const cbc_state &state) const {
__m256i c0 = c.left.value(); // 7 3 6 2 5 1 4 0
__m256i c1 = c.right.value();
uint32_t s0 = _mm256_extract_epi32(c0, 7); // 7
uint32_t s1 = _mm256_extract_epi32(c1, 7);
__m256i s = _mm256_set_epi32(5, 4, 3, 2, 1, 0, 6, 7);
__m256i a0 = _mm256_permutevar8x32_epi32(c0, s); // 6 2 5 1 4 0 3 7
__m256i a1 = _mm256_permutevar8x32_epi32(c1, s);
__m256i x0 = _mm256_insert_epi32(a0, state.left, 0); // 6 2 5 1 4 0 3 s
__m256i x1 = _mm256_insert_epi32(a1, state.right, 0);
__m256i d0 = left.value(); // 7 3 6 2 5 1 4 0
__m256i d1 = right.value();
__m256i p0 = _mm256_xor_si256(d0, x0);
__m256i p1 = _mm256_xor_si256(d1, x1);
return std::make_pair(block<x86::ymm>(p0, p1), cbc_state(s0, s1));
}
template<>
inline x86::ymm rot<8, x86::ymm>(const x86::ymm &v) {
__m256i s = _mm256_set_epi8(
14, 13, 12, 15, 10, 9, 8, 11, 6, 5, 4, 7, 2, 1, 0, 3,
14, 13, 12, 15, 10, 9, 8, 11, 6, 5, 4, 7, 2, 1, 0, 3
);
return _mm256_shuffle_epi8(v.value(), s);
}
template<>
inline x86::ymm rot<16, x86::ymm>(const x86::ymm &v) {
__m256i s = _mm256_set_epi8(
13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2,
13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2
);
return _mm256_shuffle_epi8(v.value(), s);
}
template<>
inline x86::ymm rot1_add_dec<x86::ymm>(const x86::ymm &v) {
__m256i d = _mm256_cmpgt_epi32(v.value(), _mm256_set1_epi32(-1));
return v + v + v + x86::ymm(d);
}
}
#endif /* __AVX2__ */

192
aribb25/multi2_ymm2.h Normal file
View File

@ -0,0 +1,192 @@
#pragma once
#if defined(__AVX2__)
#include <utility>
#if defined(_WIN32)
# include <intrin.h>
#else
# include <x86intrin.h>
#endif
#include "portable.h"
#include "multi2_block.h"
namespace multi2 {
namespace x86 {
class ymm2 {
private:
__m256i v0;
__m256i v1;
public:
inline ymm2() {
#if !defined(NO_MM_UNDEFINED)
v0 = v1 = _mm256_undefined_si256();
#endif
}
inline ymm2(uint32_t n) { v0 = v1 = _mm256_set1_epi32(n); }
inline ymm2(const __m256i &r0, const __m256i &r1) {
v0 = r0;
v1 = r1;
}
inline ymm2 &operator=(const ymm2 &other) {
v0 = other.v0;
v1 = other.v1;
return *this;
}
inline ymm2 operator+(const ymm2 &other) const {
return x86::ymm2(_mm256_add_epi32(v0, other.v0), _mm256_add_epi32(v1, other.v1));
}
inline ymm2 operator-(const ymm2 &other) const {
return x86::ymm2(_mm256_sub_epi32(v0, other.v0), _mm256_sub_epi32(v1, other.v1));
}
inline ymm2 operator^(const ymm2 &other) const {
return x86::ymm2(_mm256_xor_si256(v0, other.v0), _mm256_xor_si256(v1, other.v1));
}
inline ymm2 operator|(const ymm2 &other) const {
return x86::ymm2(_mm256_or_si256(v0, other.v0), _mm256_or_si256(v1, other.v1));
}
inline ymm2 operator<<(int n) const {
return x86::ymm2(_mm256_slli_epi32(v0, n), _mm256_slli_epi32(v1, n));
}
inline ymm2 operator>>(int n) const {
return x86::ymm2(_mm256_srli_epi32(v0, n), _mm256_srli_epi32(v1, n));
}
inline const __m256i &value0() const { return v0; }
inline const __m256i &value1() const { return v1; }
};
}
template<>
inline size_t block_size<x86::ymm2>() {
return 120;
}
template<>
inline void block<x86::ymm2>::load(const uint8_t *p) {
const __m256i *q0 = reinterpret_cast<const __m256i *>(p);
const __m256i *q1 = reinterpret_cast<const __m256i *>(p + 56);
__m256i a0 = _mm256_loadu_si256(q0); // 07 06 05 04 03 02 01 00 - DCBA
__m256i a1 = _mm256_loadu_si256(q0 + 1); // 0f 0e 0d 0c 0b 0a 09 08 - DCBA
__m256i a2 = _mm256_loadu_si256(q1); // 15 14 13 12 11 10 0f 0e - DCBA
__m256i a3 = _mm256_loadu_si256(q1 + 1); // 1d 1c 1b 1a 19 18 17 16 - DCBA
__m256i s = _mm256_set_epi8(
12, 13, 14, 15, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3,
12, 13, 14, 15, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3
);
__m256i b0 = _mm256_shuffle_epi8(a0, s); // 07 05 06 04 03 01 02 00 - ABCD
__m256i b1 = _mm256_shuffle_epi8(a1, s); // 0f 0d 0e 0c 0b 09 0a 08 - ABCD
__m256i b2 = _mm256_shuffle_epi8(a2, s); // 15 13 14 12 11 0f 10 0e - ABCD
__m256i b3 = _mm256_shuffle_epi8(a3, s); // 1d 1b 1c 1a 19 17 18 16 - ABCD
__m256i c0 = _mm256_unpacklo_epi32(b0, b1); // 0e 06 0c 04 0a 02 08 00 - ABCD
__m256i c1 = _mm256_unpackhi_epi32(b0, b1); // 0f 07 0d 05 0b 03 09 01 - ABCD
__m256i c2 = _mm256_unpacklo_epi32(b2, b3); // 1c 14 1a 12 18 10 16 0e - ABCD
__m256i c3 = _mm256_unpackhi_epi32(b2, b3); // 1d 15 1b 13 19 11 17 0f - ABCD
left = x86::ymm2(c0, c2); // 0e 06 0c 04 0a 02 08 00 - 1c 14 1a 12 18 10 16 0e
right = x86::ymm2(c1, c3); // 0f 07 0d 05 0b 03 09 01 - 1d 15 1b 13 19 11 17 0f
}
template<>
inline void block<x86::ymm2>::store(uint8_t *p) const {
__m256i a0 = left.value0(); // 0e 06 0c 04 0a 02 08 00 - ABCD
__m256i a1 = right.value0(); // 0f 07 0d 05 0b 03 09 01 - ABCD
__m256i a2 = left.value1(); // 1c 14 1a 12 18 10 16 -- - ABCD
__m256i a3 = right.value1(); // 1d 15 1b 13 19 11 17 -- - ABCD
__m256i s = _mm256_set_epi8(
12, 13, 14, 15, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3,
12, 13, 14, 15, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3
);
__m256i b0 = _mm256_shuffle_epi8(a0, s); // 0e 0c 06 04 0a 08 02 00 - DCBA
__m256i b1 = _mm256_shuffle_epi8(a1, s); // 0f 0d 07 05 0b 09 03 01 - DCBA
__m256i b2 = _mm256_shuffle_epi8(a2, s); // 1c 1a 14 12 18 16 10 -- - DCBA
__m256i b3 = _mm256_shuffle_epi8(a3, s); // 1d 1b 15 13 19 17 11 -- - DCBA
__m256i c0 = _mm256_unpacklo_epi32(b0, b1); // 07 06 05 04 03 02 01 00 - DCBA
__m256i c1 = _mm256_unpackhi_epi32(b0, b1); // 0f 0e 0d 0c 07 06 05 04 - DCBA
__m256i c2 = _mm256_unpacklo_epi32(b2, b3); // 15 14 13 12 11 10 -- -- - DCBA
__m256i c3 = _mm256_unpackhi_epi32(b2, b3); // 1d 1c 1b 1a 19 18 17 16 - DCBA
__m256i *q0 = reinterpret_cast<__m256i *>(p);
__m256i *q1 = reinterpret_cast<__m256i *>(p + 56);
_mm256_storeu_si256(q0, c0);
_mm256_storeu_si256(q1, c2);
_mm256_storeu_si256(q0 + 1, c1);
_mm256_storeu_si256(q1 + 1, c3);
}
template<>
inline std::pair<block<x86::ymm2>, cbc_state> block<x86::ymm2>::cbc_post_decrypt(const block<x86::ymm2> &c, const cbc_state &state) const {
__m256i c0 = c.left.value0(); // 7 3 6 2 5 1 4 0
__m256i c1 = c.right.value0();
__m256i c2 = c.left.value1(); // e a d 9 c 8 b 7
__m256i c3 = c.right.value1();
uint32_t s2 = _mm256_extract_epi32(c2, 7); // e
uint32_t s3 = _mm256_extract_epi32(c3, 7);
__m256i s = _mm256_set_epi32(5, 4, 3, 2, 1, 0, 6, 7);
__m256i a0 = _mm256_permutevar8x32_epi32(c0, s); // 6 2 5 1 4 0 3 7
__m256i a1 = _mm256_permutevar8x32_epi32(c1, s);
__m256i a2 = _mm256_permutevar8x32_epi32(c2, s); // d 9 c 8 b 7 a e
__m256i a3 = _mm256_permutevar8x32_epi32(c3, s);
__m256i x0 = _mm256_insert_epi32(a0, state.left, 0); // 6 2 5 1 4 0 3 s
__m256i x1 = _mm256_insert_epi32(a1, state.right, 0);
__m256i x2 = a2; // d 9 c 8 b 7 a e
__m256i x3 = a3;
__m256i d0 = left.value0(); // 7 3 6 2 5 1 4 0
__m256i d1 = right.value0();
__m256i d2 = left.value1(); // e a d 9 c 8 b 7
__m256i d3 = right.value1();
__m256i p0 = _mm256_xor_si256(d0, x0);
__m256i p1 = _mm256_xor_si256(d1, x1);
__m256i p2 = _mm256_xor_si256(d2, x2);
__m256i p3 = _mm256_xor_si256(d3, x3);
return std::make_pair(block<x86::ymm2>(x86::ymm2(p0, p2), x86::ymm2(p1, p3)), cbc_state(s2, s3));
}
template<>
inline x86::ymm2 rot<8, x86::ymm2>(const x86::ymm2 &v) {
__m256i s = _mm256_set_epi8(
14, 13, 12, 15, 10, 9, 8, 11, 6, 5, 4, 7, 2, 1, 0, 3,
14, 13, 12, 15, 10, 9, 8, 11, 6, 5, 4, 7, 2, 1, 0, 3
);
return x86::ymm2(_mm256_shuffle_epi8(v.value0(), s), _mm256_shuffle_epi8(v.value1(), s));
}
template<>
inline x86::ymm2 rot<16, x86::ymm2>(const x86::ymm2 &v) {
__m256i s = _mm256_set_epi8(
13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2,
13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2
);
return x86::ymm2(_mm256_shuffle_epi8(v.value0(), s), _mm256_shuffle_epi8(v.value1(), s));
}
template<>
inline x86::ymm2 rot1_add_dec<x86::ymm2>(const x86::ymm2 &v) {
__m256i d0 = _mm256_cmpgt_epi32(v.value0(), _mm256_set1_epi32(-1));
__m256i d1 = _mm256_cmpgt_epi32(v.value1(), _mm256_set1_epi32(-1));
return v + v + v + x86::ymm2(d0, d1);
}
}
#endif /* __AVX2__ */

View File

@ -1,6 +1,7 @@
#ifndef TS_SECTION_PARSER_H
#define TS_SECTION_PARSER_H
#include "arib25_api.h"
#include "ts_common_types.h"
typedef struct {

17
aribb25/version.c Normal file
View File

@ -0,0 +1,17 @@
#include <stdio.h>
#include <config.h>
#if defined(__GNUC__) || defined(__clang__)
# if !defined(__APPLE__)
const char elf_interp[] __attribute__((section(".interp"))) = ELF_INTERP;
# endif
#include <unistd.h>
void show_version(void)
{
fprintf(stderr, "libaribb25.so - ARIB STD-B25 shared library version %s (%s)\n", ARIB25_VERSION_STRING, BUILD_GIT_REVISION);
fprintf(stderr, " built with %s %s on %s\n", BUILD_CC_NAME, BUILD_CC_VERSION, BUILD_OS_NAME);
_exit(0);
}
#endif

48
aribb25/version.rc.in Normal file
View File

@ -0,0 +1,48 @@
#include <windows.h>
#include <config.h>
#pragma code_page(65001)
VS_VERSION_INFO VERSIONINFO
FILEVERSION @ARIB25_MAJOR_VERSION@,@ARIB25_MINOR_VERSION@,@ARIB25_PATCH_VERSION@,0
PRODUCTVERSION @ARIB25_MAJOR_VERSION@,@ARIB25_MINOR_VERSION@,@ARIB25_PATCH_VERSION@,0
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
#ifdef DEBUG
FILEFLAGS VS_FF_DEBUG | VS_FF_PRERELEASE
#else
FILEFLAGS 0
#endif
FILEOS VOS_NT_WINDOWS32
#ifdef ARIB25_DLL
FILETYPE VFT_DLL
#else
FILETYPE VFT_APP
#endif
FILESUBTYPE VFT2_UNKNOWN
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "080904b0"
BEGIN
VALUE "CompanyName", "@ARIB25_COMPANY@"
VALUE "FileDescription", "@ARIB25_PRODUCT@ built with @CMAKE_C_COMPILER_ID@ @CMAKE_C_COMPILER_VERSION@ on @CMAKE_SYSTEM@"
VALUE "FileVersion", "@ARIB25_VERSION_STRING@"
VALUE "InternalName", "@PROJECT_NAME@"
VALUE "LegalCopyright", "@ARIB25_COPYRIGHT@"
#if defined(ARIB25_DLL)
VALUE "OriginalFilename", "@CMAKE_SHARED_LIBRARY_PREFIX@@ARIB25_LIB_NAME@@CMAKE_SHARED_LIBRARY_SUFFIX@"
#else
VALUE "OriginalFilename", "@ARIB25_CMD_NAME@@CMAKE_EXECUTABLE_SUFFIX@"
#endif
#if defined(UNICODE)
VALUE "ProductName", "@ARIB25_PRODUCT@ UNICODE"
#else
VALUE "ProductName", "@ARIB25_PRODUCT@"
#endif
VALUE "ProductVersion", "@ARIB25_VERSION_STRING@ (" BUILD_GIT_REVISION ")"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x809, 1200
END
END

19
cmake/ElfInterp.cmake Normal file
View File

@ -0,0 +1,19 @@
find_program(OBJCOPY_EXECUTABLE "objcopy")
if(OBJCOPY_EXECUTABLE)
set(ELF_INTERP_BIN ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/elf_interp)
set(ELF_INTERP_SRC ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/elf_interp.c)
set(ELF_INTERP_DAT ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/elf_interp.dat)
file(WRITE ${ELF_INTERP_SRC} "int main(int argc, char **argv) { return 0; }")
execute_process(COMMAND ${CMAKE_C_COMPILER} ${CMAKE_C_FLAGS} -o ${ELF_INTERP_BIN} ${ELF_INTERP_SRC})
execute_process(COMMAND ${OBJCOPY_EXECUTABLE} -O binary --only-section=.interp ${ELF_INTERP_BIN} ${ELF_INTERP_DAT})
if(EXISTS ${ELF_INTERP_DAT})
file(READ ${ELF_INTERP_DAT} ELF_INTERP)
string(STRIP ${ELF_INTERP} ELF_INTERP)
endif()
endif()
message(STATUS "ELF Interpreter: ${ELF_INTERP}")

31
cmake/FindPCSC.cmake Normal file
View File

@ -0,0 +1,31 @@
find_package(PkgConfig)
if(PKG_CONFIG_FOUND AND WITH_PCSC_PACKAGE AND NOT CMAKE_CROSSCOMPILING)
if(WITH_PCSC_PACKAGE STREQUAL "libpcsclite")
pkg_check_modules(PCSC ${WITH_PCSC_PACKAGE})
else()
pkg_check_modules(PCSC REQUIRED ${WITH_PCSC_PACKAGE})
endif()
endif()
if(NOT PCSC_FOUND)
find_path(PCSC_INCLUDE_DIRS NAMES WinSCard.h winscard.h PATH_SUFFIXES PCSC)
if(WITH_PCSC_LIBRARY)
find_library(PCSC_LIBRARIES NAMES ${WITH_PCSC_LIBRARY})
else()
find_library(PCSC_LIBRARIES NAMES pcsclite PCSC WinSCard winscard)
endif()
if(PCSC_LIBRARIES)
set(PCSC_FOUND True)
endif()
endif()
if(NOT PCSC_FOUND AND NOT WITH_PCSC_LIBRARY AND WIN32)
set(PCSC_LIBRARIES winscard)
set(PCSC_FOUND True)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(PCSC DEFAULT_MSG PCSC_LIBRARIES)
mark_as_advanced(PCSC_INCLUDE_DIRS PCSC_LIBRARIES)

26
cmake/GitRevision.cmake Normal file
View File

@ -0,0 +1,26 @@
find_package(Git)
if(GIT_FOUND AND IS_DIRECTORY ${CMAKE_SOURCE_DIR}/.git)
execute_process(
COMMAND ${GIT_EXECUTABLE} describe --always --tags
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_REVISION
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND ${GIT_EXECUTABLE} diff --shortstat --exit-code --quiet
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
RESULT_VARIABLE GIT_IS_DIRTY
)
if(GIT_IS_DIRTY)
set(GIT_REVISION "${GIT_REVISION} dirty")
endif()
else()
if (EXISTS ${CMAKE_SOURCE_DIR}/.tarball-version)
file(STRINGS ${CMAKE_SOURCE_DIR}/.tarball-version GIT_REVISION LIMIT_COUNT 1)
else()
set(GIT_REVISION "Unknown Source")
endif()
set(GIT_IS_DIRTY False)
endif()

7
cmake/PostInstall.cmake Normal file
View File

@ -0,0 +1,7 @@
if(LDCONFIG_EXECUTABLE)
message(STATUS "Running: ldconfig")
execute_process(COMMAND ${LDCONFIG_EXECUTABLE} RESULT_VARIABLE ldconfig_result)
if (NOT ldconfig_result EQUAL 0)
message(WARNING "ldconfig failed")
endif()
endif()

24
cmake/Uninstall.cmake Normal file
View File

@ -0,0 +1,24 @@
set(MANIFEST "${CMAKE_CURRENT_BINARY_DIR}/install_manifest.txt")
if(NOT EXISTS ${MANIFEST})
message(FATAL_ERROR "Cannot find install manifest: '${MANIFEST}'")
endif()
file(STRINGS ${MANIFEST} files)
foreach(file ${files})
if(EXISTS ${file} OR IS_SYMLINK ${file})
message(STATUS "Removing file: '${file}'")
exec_program(
${CMAKE_COMMAND} ARGS "-E remove ${file}"
OUTPUT_VARIABLE stdout
RETURN_VALUE result
)
if(NOT "${result}" STREQUAL 0)
message(FATAL_ERROR "Failed to remove file: '${file}'.")
endif()
else()
message(STATUS "File '${file}' does not exist.")
endif()
endforeach(file)

46
src/portable.h Normal file
View File

@ -0,0 +1,46 @@
#ifndef PORTABLE_H
#define PORTABLE_H
#if (defined(_WIN32) && defined(_MSC_VER) && _MSC_VER < 1800)
typedef unsigned char uint8_t;
typedef signed char int8_t;
typedef unsigned short uint16_t;
typedef signed short int16_t;
typedef unsigned int uint32_t;
typedef signed int int32_t;
typedef unsigned __int64 uint64_t;
typedef signed __int64 int64_t;
#else
#include <stdint.h>
#include <inttypes.h>
#endif
#if !defined(_WIN32)
#define _open open
#define _close close
#define _read read
#define _write write
#define _lseeki64 lseek
#define _telli64(fd) (lseek(fd,0,SEEK_CUR))
#define _O_BINARY (0)
#define _O_RDONLY (O_RDONLY)
#define _O_WRONLY (O_WRONLY)
#define _O_SEQUENTIAL (0)
#define _O_CREAT (O_CREAT)
#define _O_TRUNC (O_TRUNC)
#define _S_IREAD (S_IRUSR|S_IRGRP|S_IROTH)
#define _S_IWRITE (S_IWUSR|S_IWGRP|S_IWOTH)
#endif
#if defined(__GNUC__) && (__GNUC__ < 5 && !(__GNUC__ == 4 && 9 <= __GNUC_MINOR__))
#define NO_MM_UNDEFINED
#endif
#if defined(__clang__) && (__clang_major__ < 4 && !(__clang_major__ == 3 && 8 <= __clang_minor__))
#define NO_MM_UNDEFINED
#endif
#endif /* PORTABLE_H */

441
src/td.c Normal file
View File

@ -0,0 +1,441 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <config.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#if defined(_WIN32)
#include <io.h>
#include <windows.h>
#include <crtdbg.h>
#include <tchar.h>
#else
#define __STDC_FORMAT_MACROS
#define TCHAR char
#define _T(X) X
#define _ftprintf fprintf
#define _ttoi atoi
#define _tmain main
#define _topen _open
#include <inttypes.h>
#include <unistd.h>
#include <sys/time.h>
#endif
#include "arib_std_b25.h"
#include "b_cas_card.h"
typedef struct {
int32_t round;
int32_t strip;
int32_t emm;
int32_t verbose;
int32_t power_ctrl;
} OPTION;
static void show_usage();
static int parse_arg(OPTION *dst, int argc, TCHAR **argv);
static void test_arib_std_b25(const TCHAR *src, const TCHAR *dst, OPTION *opt);
static void show_bcas_power_on_control_info(B_CAS_CARD *bcas);
int _tmain(int argc, TCHAR **argv)
{
int n;
OPTION opt;
#if defined(_WIN32)
_CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT );
_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT );
_CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT );
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_DELAY_FREE_MEM_DF|_CRTDBG_CHECK_ALWAYS_DF|_CRTDBG_LEAK_CHECK_DF);
#endif
n = parse_arg(&opt, argc, argv);
if(n+2 > argc){
show_usage();
exit(EXIT_FAILURE);
}
for(;n<=(argc-2);n+=2){
test_arib_std_b25(argv[n+0], argv[n+1], &opt);
}
#if defined(_WIN32)
_CrtDumpMemoryLeaks();
#endif
return EXIT_SUCCESS;
}
static void show_usage()
{
_ftprintf(stderr, _T("b25 - ARIB STD-B25 test program version %s (%s)\n"), _T(ARIB25_VERSION_STRING), _T(BUILD_GIT_REVISION));
_ftprintf(stderr, _T(" built with %s %s on %s\n"), _T(BUILD_CC_NAME), _T(BUILD_CC_VERSION), _T(BUILD_OS_NAME));
_ftprintf(stderr, _T("usage: b25 [options] src.m2t dst.m2t [more pair ..]\n"));
_ftprintf(stderr, _T("options:\n"));
_ftprintf(stderr, _T(" -r round (integer, default=4)\n"));
_ftprintf(stderr, _T(" -s strip\n"));
_ftprintf(stderr, _T(" 0: keep null(padding) stream (default)\n"));
_ftprintf(stderr, _T(" 1: strip null stream\n"));
_ftprintf(stderr, _T(" -m EMM\n"));
_ftprintf(stderr, _T(" 0: ignore EMM (default)\n"));
_ftprintf(stderr, _T(" 1: send EMM to B-CAS card\n"));
_ftprintf(stderr, _T(" -p power_on_control_info\n"));
_ftprintf(stderr, _T(" 0: do nothing additionally\n"));
_ftprintf(stderr, _T(" 1: show B-CAS EMM receiving request (default)\n"));
_ftprintf(stderr, _T(" -v verbose\n"));
_ftprintf(stderr, _T(" 0: silent\n"));
_ftprintf(stderr, _T(" 1: show processing status (default)\n"));
_ftprintf(stderr, _T("\n"));
}
static int parse_arg(OPTION *dst, int argc, TCHAR **argv)
{
int i;
dst->round = 4;
dst->strip = 0;
dst->emm = 0;
dst->power_ctrl = 1;
dst->verbose = 1;
for(i=1;i<argc;i++){
if(argv[i][0] != '-'){
break;
}
switch(argv[i][1]){
case 'm':
if(argv[i][2]){
dst->emm = _ttoi(argv[i]+2);
}else{
dst->emm = _ttoi(argv[i+1]);
i += 1;
}
break;
case 'p':
if(argv[i][2]){
dst->power_ctrl = _ttoi(argv[i]+2);
}else{
dst->power_ctrl = _ttoi(argv[i+1]);
i += 1;
}
break;
case 'r':
if(argv[i][2]){
dst->round = _ttoi(argv[i]+2);
}else{
dst->round = _ttoi(argv[i+1]);
i += 1;
}
break;
case 's':
if(argv[i][2]){
dst->strip = _ttoi(argv[i]+2);
}else{
dst->strip = _ttoi(argv[i+1]);
i += 1;
}
break;
case 'v':
if(argv[i][2]){
dst->verbose = _ttoi(argv[i]+2);
}else{
dst->verbose = _ttoi(argv[i+1]);
i += 1;
}
break;
default:
_ftprintf(stderr, _T("error - unknown option '-%c'\n"), argv[i][1]);
return argc;
}
}
return i;
}
static void test_arib_std_b25(const TCHAR *src, const TCHAR *dst, OPTION *opt)
{
int code,i,n,m;
int sfd,dfd;
int64_t total;
int64_t offset;
#if defined(_WIN32)
unsigned long tick,tock;
#else
struct timeval tick,tock;
double millisec;
#endif
double mbps;
ARIB_STD_B25 *b25;
B_CAS_CARD *bcas;
ARIB_STD_B25_PROGRAM_INFO pgrm;
uint8_t data[64*1024];
ARIB_STD_B25_BUFFER sbuf;
ARIB_STD_B25_BUFFER dbuf;
sfd = -1;
dfd = -1;
b25 = NULL;
bcas = NULL;
sfd = _topen(src, _O_BINARY|_O_RDONLY|_O_SEQUENTIAL);
if(sfd < 0){
_ftprintf(stderr, _T("error - failed on _open(%s) [src]\n"), src);
goto LAST;
}
_lseeki64(sfd, 0, SEEK_END);
total = _telli64(sfd);
_lseeki64(sfd, 0, SEEK_SET);
b25 = create_arib_std_b25();
if(b25 == NULL){
_ftprintf(stderr, _T("error - failed on create_arib_std_b25()\n"));
goto LAST;
}
code = b25->set_multi2_round(b25, opt->round);
if(code < 0){
_ftprintf(stderr, _T("error - failed on ARIB_STD_B25::set_multi2_round() : code=%d\n"), code);
goto LAST;
}
code = b25->set_strip(b25, opt->strip);
if(code < 0){
_ftprintf(stderr, _T("error - failed on ARIB_STD_B25::set_strip() : code=%d\n"), code);
goto LAST;
}
code = b25->set_emm_proc(b25, opt->emm);
if(code < 0){
_ftprintf(stderr, _T("error - failed on ARIB_STD_B25::set_emm_proc() : code=%d\n"), code);
goto LAST;
}
bcas = create_b_cas_card();
if(bcas == NULL){
_ftprintf(stderr, _T("error - failed on create_b_cas_card()\n"));
goto LAST;
}
code = bcas->init(bcas);
if(code < 0){
_ftprintf(stderr, _T("error - failed on B_CAS_CARD::init() : code=%d\n"), code);
goto LAST;
}
code = b25->set_b_cas_card(b25, bcas);
if(code < 0){
_ftprintf(stderr, _T("error - failed on ARIB_STD_B25::set_b_cas_card() : code=%d\n"), code);
goto LAST;
}
dfd = _topen(dst, _O_BINARY|_O_WRONLY|_O_SEQUENTIAL|_O_CREAT|_O_TRUNC, _S_IREAD|_S_IWRITE);
if(dfd < 0){
_ftprintf(stderr, _T("error - failed on _open(%s) [dst]\n"), dst);
goto LAST;
}
offset = 0;
#if defined(_WIN32)
tock = GetTickCount();
#else
gettimeofday(&tock, NULL);
#endif
while( (n = _read(sfd, data, sizeof(data))) > 0 ){
sbuf.data = data;
sbuf.size = n;
code = b25->put(b25, &sbuf);
if(code < 0){
_ftprintf(stderr, _T("error - failed on ARIB_STD_B25::put() : code=%d\n"), code);
goto LAST;
}
code = b25->get(b25, &dbuf);
if(code < 0){
_ftprintf(stderr, _T("error - failed on ARIB_STD_B25::get() : code=%d\n"), code);
goto LAST;
}
if(dbuf.size > 0){
n = _write(dfd, dbuf.data, dbuf.size);
if(n != dbuf.size){
_ftprintf(stderr, _T("error failed on _write(%d)\n"), dbuf.size);
goto LAST;
}
}
offset += sbuf.size;
if(opt->verbose != 0){
m = (int)((uint64_t)10000*offset/total);
mbps = 0.0;
#if defined(_WIN32)
tick = GetTickCount();
if (tick-tock > 100) {
mbps = offset;
mbps /= 1024;
mbps /= (tick-tock);
}
#else
gettimeofday(&tick, NULL);
millisec = (tick.tv_sec - tock.tv_sec) * 1000;
millisec += (tick.tv_usec - tock.tv_usec) / 1000;
if(millisec > 100.0) {
mbps = offset;
mbps /= 1024;
mbps /= millisec;
}
#endif
_ftprintf(stderr, _T("\rprocessing: %2d.%02d%% [%6.2f MB/sec]"), m/100, m%100, mbps);
}
}
code = b25->flush(b25);
if(code < 0){
_ftprintf(stderr, _T("error - failed on ARIB_STD_B25::flush() : code=%d\n"), code);
goto LAST;
}
code = b25->get(b25, &dbuf);
if(code < 0){
_ftprintf(stderr, _T("error - failed on ARIB_STD_B25::get() : code=%d\n"), code);
goto LAST;
}
if(dbuf.size > 0){
n = _write(dfd, dbuf.data, dbuf.size);
if(n != dbuf.size){
_ftprintf(stderr, _T("error - failed on _write(%d)\n"), dbuf.size);
goto LAST;
}
}
if(opt->verbose != 0){
mbps = 0.0;
#if defined(_WIN32)
tick = GetTickCount();
if (tick-tock > 100) {
mbps = offset;
mbps /= 1024;
mbps /= (tick-tock);
}
#else
gettimeofday(&tick, NULL);
millisec = (tick.tv_sec - tock.tv_sec) * 1000;
millisec += (tick.tv_usec - tock.tv_usec) / 1000;
if(millisec > 100.0) {
mbps = offset;
mbps /= 1024;
mbps /= millisec;
}
#endif
_ftprintf(stderr, _T("\rprocessing: finish [%6.2f MB/sec]\n"), mbps);
fflush(stderr);
fflush(stdout);
}
n = b25->get_program_count(b25);
if(n < 0){
_ftprintf(stderr, _T("error - failed on ARIB_STD_B25::get_program_count() : code=%d\n"), code);
goto LAST;
}
for(i=0;i<n;i++){
code = b25->get_program_info(b25, &pgrm, i);
if(code < 0){
_ftprintf(stderr, _T("error - failed on ARIB_STD_B25::get_program_info(%d) : code=%d\n"), i, code);
goto LAST;
}
if(pgrm.ecm_unpurchased_count > 0){
_ftprintf(stderr, _T("warning - unpurchased ECM is detected\n"));
_ftprintf(stderr, _T(" channel: %d\n"), pgrm.program_number);
_ftprintf(stderr, _T(" unpurchased ECM count: %d\n"), pgrm.ecm_unpurchased_count);
_ftprintf(stderr, _T(" last ECM error code: %04x\n"), pgrm.last_ecm_error_code);
#if defined(_WIN32)
_ftprintf(stderr, _T(" undecrypted TS packet: %I64d\n"), pgrm.undecrypted_packet_count);
_ftprintf(stderr, _T(" total TS packet: %I64d\n"), pgrm.total_packet_count);
#else
_ftprintf(stderr, _T(" undecrypted TS packet: %"PRId64"\n"), pgrm.undecrypted_packet_count);
_ftprintf(stderr, _T(" total TS packet: %"PRId64"\n"), pgrm.total_packet_count);
#endif
}
}
if(opt->power_ctrl != 0){
show_bcas_power_on_control_info(bcas);
}
LAST:
if(sfd >= 0){
_close(sfd);
sfd = -1;
}
if(dfd >= 0){
_close(dfd);
dfd = -1;
}
if(b25 != NULL){
b25->release(b25);
b25 = NULL;
}
if(bcas != NULL){
bcas->release(bcas);
bcas = NULL;
}
}
static void show_bcas_power_on_control_info(B_CAS_CARD *bcas)
{
int code;
int i,w;
B_CAS_PWR_ON_CTRL_INFO pwc;
code = bcas->get_pwr_on_ctrl(bcas, &pwc);
if(code < 0){
_ftprintf(stderr, _T("error - failed on B_CAS_CARD::get_pwr_on_ctrl() : code=%d\n"), code);
return;
}
if(pwc.count == 0){
_ftprintf(stdout, _T("no EMM receiving request\n"));
return;
}
_ftprintf(stdout, _T("total %d EMM receiving request\n"), pwc.count);
for(i=0;i<pwc.count;i++){
_ftprintf(stdout, _T("+ [%d] : tune "), i);
switch(pwc.data[i].network_id){
case 4:
w = pwc.data[i].transport_id;
_ftprintf(stdout, _T("BS-%d/TS-%d "), ((w >> 4) & 0x1f), (w & 7));
break;
case 6:
case 7:
w = pwc.data[i].transport_id;
_ftprintf(stdout, _T("ND-%d/TS-%d "), ((w >> 4) & 0x1f), (w & 7));
break;
default:
_ftprintf(stdout, _T("unknown(b:0x%02x,n:0x%04x,t:0x%04x) "), pwc.data[i].broadcaster_group_id, pwc.data[i].network_id, pwc.data[i].transport_id);
break;
}
_ftprintf(stdout, _T("between %04d %02d/%02d "), pwc.data[i].s_yy, pwc.data[i].s_mm, pwc.data[i].s_dd);
_ftprintf(stdout, _T("to %04d %02d/%02d "), pwc.data[i].l_yy, pwc.data[i].l_mm, pwc.data[i].l_dd);
_ftprintf(stdout, _T("least %d hours\n"), pwc.data[i].hold_time);
}
}