1. Android App Signature
Android App에 Signature 기능이 있는 것을 알아본게 된 이유가 System 권한을 가지고 실행하기 위해서 이를 알아보게되었다.
왜냐하면, 일반적으로 만든 App들은 untrusted_app domain으로 SELinux에서 제한이 있어 매번 제대로 실행이 되지 않는 것을 해결해볼까 하고 생각이였다.
물론 SELinux를 허용모드로 하면 이문제는 이 부분이 다 필요가 없지만, 개발환경이 아닌 실제에서는 다르기때문에 이를 다시 생각하게되었다.
물론 이 문제이외에도 permission에 관련된 문제가 있었으나, 그부분은 init.xxx.rc에서 강제로 했다.
이부분은 OpenSSL의 인증서 Certificate(X.509)부분을 보면 쉽게이해가 가며, 간단히 보면, private key 와 public key의 사용으로 동작되는 것을 알 수 있다.
암호화 기본개념 과 Cipher Suite
Android에서는 아래의 4종류의 Key가 있다고 하며 역할은 아래와 같다.
- platform: a key for packages that are part of the core platform.
- shared: a key for things that are shared in the home/contacts process.
- media: a key for packages that are part of the media/download system.
- testkey: the default key to sign with if not otherwise specified.
https://boundarydevices.com/android-security-part-1-application-signatures-permissions/ |
상위과 같이 동작원리는 간단하다.
Signing/Verfify 로 이를 쉽고 빠르게 검증하는 것이다.
AOSP Source 기준으로 살펴보면 각 Key 위치와 Certificate 위치확인
- Default build system signs package 들과 testkey 아래 위치에 존재
$ ls build/target/product/security/ Android.mk media.x509.pem networkstack.x509.pem platform.x509.pem shared.pk8 testkey.pk8 verity_key verity.x509.pem media.pk8 networkstack.pk8 platform.pk8 README shared.x509.pem testkey.x509.pem verity.pk8
- Vendor NXP(Freescale)용 signs package
$ ls device/fsl/common/security/
media.pk8 networkstack.pk8 platform.pk8 README shared.pk8 testkey.pk8 testkey_rsa4096.pem
media.x509.pem networkstack.x509.pem platform.x509.pem rpmb_key_test.bin shared.x509.pem testkey_public_rsa4096.bin testkey.x509.pem
$ grep -r PRODUCT_DEFAULT_DEV_CERTIFICATE. .
./device/fsl/imx6sl/ProductConfigCommon.mk:PRODUCT_DEFAULT_DEV_CERTIFICATE := \
./device/fsl/imx7d/ProductConfigCommon.mk:PRODUCT_DEFAULT_DEV_CERTIFICATE := \
./device/fsl/imx6sx/ProductConfigCommon.mk:PRODUCT_DEFAULT_DEV_CERTIFICATE := \
./device/fsl/imx6dq/ProductConfigCommon.mk:PRODUCT_DEFAULT_DEV_CERTIFICATE := \
./device/fsl/imx7ulp/ProductConfigCommon.mk:PRODUCT_DEFAULT_DEV_CERTIFICATE := \
./device/fsl/imx8m/ProductConfigCommon.mk:PRODUCT_DEFAULT_DEV_CERTIFICATE := \
./device/fsl/imx8q/ProductConfigCommon.mk:PRODUCT_DEFAULT_DEV_CERTIFICATE := \
$ cat ./device/fsl/imx8q/ProductConfigCommon.mk // OVERWRITE
...
PRODUCT_DEFAULT_DEV_CERTIFICATE := \
device/fsl/common/security/testkey
...
$ cat ./device/fsl/imx8q/BoardConfig.mk // AVB를 위한 RSA 비대칭키사용
.....
BOARD_AVB_ENABLE := true
BOARD_AVB_ALGORITHM := SHA256_RSA4096
# The testkey_rsa4096.pem is copied from external/avb/test/data/testkey_rsa4096.pem
BOARD_AVB_KEY_PATH := device/fsl/common/security/testkey_rsa4096.pem
.......
$ cat ./device/fsl/imx8q/mek_8q.mk
.....
# Copy rpmb test key and AVB test public key
ifeq ($(PRODUCT_IMX_TRUSTY),true)
PRODUCT_COPY_FILES += \
device/fsl/common/security/rpmb_key_test.bin:rpmb_key_test.bin \
device/fsl/common/security/testkey_public_rsa4096.bin:testkey_public_rsa4096.bin
endif
.....
PRODUCT_DEFAULT_DEV_CERTIFICATE 에 의해 overwrite가 가능하다고 하니, 상위와 같이 검색
platform/shared/media/testkey 생성부터 인증관련내용
1.1 ASOP Source에서 platform Key 추출
- ASOP Default Platform Key 추출
두개의 password는 android로 설정 했으며, key alias는 androiddebugkey로 설정
$ mkdir mytest1
$ cp build/target/product/security/platform.pk8 mytest1/
$ cp build/target/product/security/platform.x509.pem mytest1/
$ cd mytest1
//PKCS#08: Private-Key Information Syntax Standard 로 아래와 같이 변경 (DER) platform.pem로 생성
//PKCS#12: Personal Information Exchange Syntax Standard 로 platform.x509.pem을 platform.p12로 변경 Private KEY는 platform.pem이용하고 설정값
$ openssl pkcs8 -inform DER -nocrypt -in platform.pk8 -out platform.pem
$ openssl pkcs12 -export -in platform.x509.pem -inkey platform.pem -out platform.p12 -password pass:android -name androiddebugkey
$ keytool -importkeystore -deststorepass android -destkeystore platform.jks -srckeystore platform.p12 -srcstoretype PKCS12 -srcstorepass android
$ ls
platform.jks platform.p12 platform.pem platform.pk8 platform.x509.pem
PKCSx(Public Key Cryptography Standards)
- NXP용 Platform Key 추출
두개의 password는 android로 설정 했으며, key alias는 androiddebugkey로 설정
$ mkdir mytest2 $ cp device/fsl/common/security/platform.pk8 mytest2/ $ cp device/fsl/common/security/platform.x509.pem mytest2/ $ cd mytest2 $ openssl pkcs8 -inform DER -nocrypt -in platform.pk8 -out platform.pem $ openssl pkcs12 -export -in platform.x509.pem -inkey platform.pem -out platform.p12 -password pass:android -name androiddebugkey $ keytool -importkeystore -deststorepass android -destkeystore platform.jks -srckeystore platform.p12 -srcstoretype PKCS12 -srcstorepass android $ ls platform.jks platform.p12 platform.pem platform.pk8 platform.x509.pem
Platform Key 추출
Platform Key 관련링크들
2. App 에 System App 권한부여
상위에서도 설명했지만, 기본 App은 untruested_app으로 실행되기 때문에 SELinux와 Permission 문제가 발생해서 이부분을 system 권한으로 변경하도록 실행
- Androidmanifest.XML 에서 system 권한 부여
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.beep" android:sharedUserId="android.uid.system" >
- ASOP에서 NXP platform.jks 추출 후 Android Studio 에서 Sign 방법
Android Studio -> File -> Project Structure -> Signing Config
or
Android Studio -> Build -> Generate Signed Bundle/APK -> APK
상위처럼 하면, 구지 build.gradle를 직접 수정하지 하지 않해도 되지만, debug 와 release를 구분해서 넣어주자.
기본 SELinux Domain untrusted_app
[12387.628007] type=1400 audit(1611554077.764:163): avc: denied { read } for comm="om.example.beep" name="duty_cycle" dev="sysfs" ino=37724 scontext=u:r:untrusted_app:s0:c101,c256,c512,c768 tcontext=u:object_r:sysfs:s0 tclass=file permissive=1 app=com.example.beep
바뀔 SELInux Domain system_app
[14697.359731] type=1400 audit(1611556387.500:167): avc: denied { read } for comm="om.example.beep" name="duty_cycle" dev="sysfs" ino=37724 scontext=u:r:system_app:s0 tcontext=u:object_r:sysfs:s0 tclass=file permissive=1
현재 permission 과 권한도 system으로 변경했지만 SELinux에서 거부되는 것은 현재 sysfs 때문이라고 생각이 된다.
매번 Build Clean 후 다시 실행했으며, 만약 INSTALL_FAILED_SHARED_USER_INCOMPATIBLE 에러가 계속나면, 나의 경우, 상위 system 설정 후 Sign이 맞지않아 생겼다.
NXP용 platform key를 사용해야 문제가 없었음
- adb shell or serial 에서 package 설치확인
$ su # # pm list packages | grep <package> # pm uninstall <package>
2.1 signapk.jar를 이용한 Sign 방법
아직 해보지 못했으며, 관련부분만 현재 검색했음
- Android App Sign
apk 생성후 이를 ASOP에서 직접 signapk.jar를 이용하여 sign하는 방법
$ find . -name signapk.jar
./out/host/linux-x86/framework/signapk.jar
./out/soong/host/linux-x86/framework/signapk.jar
./out/soong/.intermediates/build/make/tools/signapk/signapk/linux_glibc_common/combined/signapk.jar
./out/soong/.intermediates/build/make/tools/signapk/signapk/linux_glibc_common/javac/signapk.jar
./prebuilts/sdk/tools/lib/signapk.jar
$ mkdir mytest
$ cp my_nosign.apk mytest/ // my app
$ cp build/target/product/security/platform.x509.pem mytest/
$ cp build/target/product/security/platform.pk8 mytest/
$ cp out/host/linux-x86/framework/signapk.jar mytest/
$ cd mytest
$ java -jar signapk.jar platform.x509.pem platform.pk8 my_nosign.apk my_sign.apk // signing apk
$ ls my_sign.apk
Android Studio System App Build 방법
AndroidManifest
Custom Framwork