Merge branch 'tizen' into cynara 84/223084/1
authorDariusz Michaluk <d.michaluk@samsung.com>
Wed, 22 Jan 2020 15:47:01 +0000 (16:47 +0100)
committerDariusz Michaluk <d.michaluk@samsung.com>
Wed, 22 Jan 2020 15:47:01 +0000 (16:47 +0100)
Change-Id: I5a9367d2418e17f76ed4ffe0f2a802d8466249f1

85 files changed:
CMakeLists.txt
README
packaging/security-tests.spec
src/CMakeLists.txt
src/ckm/CMakeLists.txt
src/ckm/keys/pkcs12.tgz [deleted file]
src/ckm/keys/pkcs12/HOWTO.txt [new file with mode: 0644]
src/ckm/keys/pkcs12/ca-int.crt [new file with mode: 0644]
src/ckm/keys/pkcs12/ca-int.csr [new file with mode: 0644]
src/ckm/keys/pkcs12/ca-int.key [new file with mode: 0644]
src/ckm/keys/pkcs12/ca.crt [new file with mode: 0644]
src/ckm/keys/pkcs12/ca.key [new file with mode: 0644]
src/ckm/keys/pkcs12/chain.pem [new file with mode: 0644]
src/ckm/keys/pkcs12/server.crt [new file with mode: 0644]
src/ckm/keys/pkcs12/server.csr [new file with mode: 0644]
src/ckm/keys/pkcs12/server.key [new file with mode: 0644]
src/ckm/privileged/CMakeLists.txt
src/ckm/privileged/aes_128_cbc_encrypt.sh
src/ckm/privileged/capi-access_control.cpp
src/ckm/privileged/initial-values.cpp
src/ckm/resource/XML_1_okay.xml
src/ckm/resource/XML_2_okay.xml
src/ckm/resource/XML_3_wrong.xml
src/ckm/resource/device_key.xml [deleted file]
src/ckm/resource/pkcs.p12
src/ckm/test-certs.cpp
src/ckm/unprivileged/CMakeLists.txt
src/ckm/unprivileged/capi-testcases.cpp
src/ckm/unprivileged/encryption-decryption.cpp
src/ckm/unprivileged/main.cpp
src/ckm/unprivileged/sign-verify.cpp [new file with mode: 0644]
src/common/app_install_helper.cpp
src/common/app_install_helper.h
src/common/label_generator.cpp
src/common/label_generator.h
src/common/scoped_installer.h
src/common/scoped_process_label.cpp
src/common/service_manager.cpp
src/common/sm_api.cpp
src/common/sm_api.h
src/common/sm_request.cpp
src/common/sm_request.h
src/common/synchronization_pipe.cpp
src/common/synchronization_pipe.h
src/common/tests_common.h
src/cynara-tests/common/cynara_test_client_async_client.cpp
src/framework/include/dpl/test/test_case.h
src/framework/include/dpl/test/test_group.h [new file with mode: 0644]
src/framework/include/dpl/test/test_runner.h
src/framework/src/assert.cpp
src/framework/src/test_results_collector_console.cpp
src/framework/src/test_runner.cpp
src/nether-tests/CMakeLists.txt [new file with mode: 0644]
src/nether-tests/nether_tests.cpp [new file with mode: 0644]
src/nether-tests/setup-nether-tests-dns.sh [new file with mode: 0644]
src/nether-tests/setup-nether-tests-nns.sh [new file with mode: 0644]
src/nether-tests/teardown-nether-tests-dns.sh [new file with mode: 0644]
src/nether-tests/teardown-nether-tests-nns.sh [new file with mode: 0644]
src/ode/CMakeLists.txt [new file with mode: 0644]
src/ode/ode-tests-common.cpp [new file with mode: 0644]
src/ode/ode-tests-common.h [new file with mode: 0644]
src/ode/ode-tests-external-encryption.cpp [new file with mode: 0644]
src/ode/ode-tests-internal-encryption.cpp [new file with mode: 0644]
src/ode/ode-tests-keys.cpp [new file with mode: 0644]
src/ode/ode-tests-luks.cpp [new file with mode: 0644]
src/ode/ode-tests-secure-erase.cpp [new file with mode: 0644]
src/ode/ode-tests.cpp [new file with mode: 0644]
src/security-manager-tests/CMakeLists.txt
src/security-manager-tests/common/sm_commons.cpp
src/security-manager-tests/common/sm_commons.h
src/security-manager-tests/common/template_parser.cpp [new file with mode: 0644]
src/security-manager-tests/common/template_parser.h [new file with mode: 0644]
src/security-manager-tests/test_cases.cpp
src/security-manager-tests/test_cases_prepare_app.cpp
src/security-manager-tests/test_cases_public_sharing.cpp
src/security-manager-tests/test_cases_register_paths.cpp
src/security-tests-all.sh
src/security-tests.sh
src/yaca/test-vectors/sign_param_comb.txt [new file with mode: 0644]
src/yaca/yaca-test-digest.cpp
src/yaca/yaca-test-encrypt.cpp
src/yaca/yaca-test-rsa.cpp
src/yaca/yaca-test-sign.cpp
src/yaca/yaca-test-vector.cpp
src/yaca/yaca-test-vector.h

index 01ce9fb..26b21d0 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (c) 2012-2015 Samsung Electronics Co., Ltd All Rights Reserved
+# Copyright (c) 2012-2020 Samsung Electronics Co., Ltd. All rights reserved
 #
 #    Licensed under the Apache License, Version 2.0 (the "License");
 #    you may not use this file except in compliance with the License.
@@ -15,6 +15,7 @@
 # @file        CMakeLists.txt
 # @author      Bartlomiej Grzelewski (b.grzelewski@samsung.com)
 # @author      Pawel Polawski (p.polawski@partner.samsung.com)
+# @author      Piotr Sawicki (p.sawicki2@partner.samsung.com)
 # @brief
 #
 
@@ -34,7 +35,7 @@ INCLUDE(FindPkgConfig)
 ############################# compiler flags ##################################
 
 SET(CMAKE_C_FLAGS              "-g")
-SET(CMAKE_CXX_FLAGS            "-g -std=c++0x")
+SET(CMAKE_CXX_FLAGS            "-g -std=c++14")
 SET(CMAKE_C_FLAGS_PROFILING    "-O0 -pg")
 SET(CMAKE_CXX_FLAGS_PROFILING  "-O0 -pg")
 SET(CMAKE_C_FLAGS_DEBUG        "-O0 -ggdb")
@@ -64,6 +65,8 @@ IF(BUILD_ALL_TESTS)
     SET(BUILD_CYNARA ON)
     SET(BUILD_WEB ON)
     SET(BUILD_YACA ON)
+    SET(BUILD_NETHER ON)
+    SET(BUILD_ODE ON)
 ENDIF(BUILD_ALL_TESTS)
 
 # If supported for the target machine, emit position-independent code,suitable
@@ -83,6 +86,7 @@ ADD_DEFINITIONS("-Wextra")                      # Generate even more extra warni
 ADD_DEFINITIONS("-Wno-variadic-macros")         # Inhibit variadic macros warnings (needed for ORM)
 ADD_DEFINITIONS("-Wno-deprecated")               # No warnings about deprecated features
 ADD_DEFINITIONS("-Wno-deprecated-declarations")               # No warnings about deprecated features
+ADD_DEFINITIONS("-Wno-implicit-fallthrough")    # No warnings about switc() statements, often done on purpose
 ADD_DEFINITIONS("-DCYNARA_DB_DIR=\"${CYNARA_DB_DIR}\"")
 ADD_DEFINITIONS("-DAPP_USER=\"${APP_USER}\"")
 
diff --git a/README b/README
index c94a739..ea2b291 100644 (file)
--- a/README
+++ b/README
@@ -15,6 +15,8 @@ security-manager
   security-manager-tests
 cynara
   cynara-test
+ode
+  ode-tests
 
 There are also inner-tests for testing complex security-tests framework
 mechanisms with binary:
index 9809e03..76d554c 100644 (file)
@@ -16,6 +16,7 @@ BuildRequires: pkgconfig(key-manager)
 BuildRequires: key-manager-initial-values
 BuildRequires: util-linux
 BuildRequires: pkgconfig(yaca)
+BuildRequires: pkgconfig(ode)
 BuildRequires: pkgconfig(dlog)
 BuildRequires: pkgconfig(glib-2.0)
 BuildRequires: pkgconfig(dbus-1)
@@ -23,7 +24,7 @@ BuildRequires: pkgconfig(libpcrecpp)
 BuildRequires: pkgconfig(libxml-2.0)
 BuildRequires: pkgconfig(sqlite3)
 BuildRequires: pkgconfig(libwebappenc)
-BuildRequires: pkgconfig(openssl)
+BuildRequires: pkgconfig(openssl1.1)
 BuildRequires: cynara-devel
 BuildRequires: libcynara-creds-dbus-devel
 BuildRequires: libcynara-creds-gdbus-devel
@@ -34,9 +35,12 @@ BuildRequires: pkgconfig(vconf)
 BuildRequires: pkgconfig(libgum) >= 1.0.5
 BuildRequires: pkgconfig(security-privilege-manager)
 BuildRequires: pkgconfig(libsystemd)
+BuildRequires: openssl1.1
 Requires: perf
 Requires: gdb
 Requires: diffutils
+Requires: iproute2
+Requires: toybox-symlinks-ping
 
 %global ckm_test_dir %{?TZ_SYS_SHARE:%TZ_SYS_SHARE/ckm-test/}%{!?TZ_SYS_SHARE:/usr/share/ckm-test/}
 %global ckm_rw_data_dir %{?TZ_SYS_DATA:%TZ_SYS_DATA/ckm/}%{!?TZ_SYS_DATA:/opt/data/ckm/}
@@ -52,6 +56,9 @@ Security tests repository - for tests that can't be kept together with code.
 export LDFLAGS+="-Wl,--rpath=%{_prefix}/lib"
 
 cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} \
+%if "%{_with_emulator}" == "1"
+        -DEMULATOR="ON"                   \
+%endif
 %if %{tz_backend_enabled} == ON
         -DTZ_BACKEND="ON"                 \
 %endif
@@ -92,6 +99,10 @@ echo "security-tests postinst done ..."
 /usr/bin/security-tests.sh
 /usr/bin/security-tests-all.sh
 /usr/bin/test-performance-check.sh
+/usr/bin/setup-nether-tests-nns.sh
+/usr/bin/teardown-nether-tests-nns.sh
+/usr/bin/setup-nether-tests-dns.sh
+/usr/bin/teardown-nether-tests-dns.sh
 
 /etc/dbus-1/system.d/security-tests.conf
 
@@ -110,6 +121,8 @@ echo "security-tests postinst done ..."
 %caps(cap_mac_admin=ep) /usr/bin/ckm-privileged-tests
 %caps(cap_mac_admin=ep) /usr/bin/ckm-integration-tests
 /usr/bin/yaca-test
+/usr/bin/nether-tests
+/usr/bin/ode-tests
 %{ckm_test_dir}/*
 /etc/security-tests
 /usr/lib/security-tests/cynara-tests/plugins/single-policy/*
index 471c28e..aadbe67 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (c) 2011-2015 Samsung Electronics Co., Ltd All Rights Reserved
+# Copyright (c) 2011-2017 Samsung Electronics Co., Ltd All Rights Reserved
 #
 #    Licensed under the Apache License, Version 2.0 (the "License");
 #    you may not use this file except in compliance with the License.
@@ -110,3 +110,11 @@ ENDIF(BUILD_WEB)
 IF(BUILD_YACA)
     ADD_SUBDIRECTORY(yaca)
 ENDIF(BUILD_YACA)
+
+IF(BUILD_NETHER)
+    ADD_SUBDIRECTORY(nether-tests)
+ENDIF(BUILD_NETHER)
+
+IF(BUILD_ODE)
+    ADD_SUBDIRECTORY(ode)
+ENDIF(BUILD_ODE)
index fea09d3..97f1239 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (c) 2013-2018 Samsung Electronics Co., Ltd All Rights Reserved
+# Copyright (c) 2013-2019 Samsung Electronics Co., Ltd All Rights Reserved
 #
 #   Licensed under the Apache License, Version 2.0 (the "License");
 #   you may not use this file except in compliance with the License.
@@ -29,10 +29,19 @@ ENDIF (DEFINED SECURITY_MDFPP_STATE_ENABLED)
 
 ADD_DEFINITIONS("-DCKM_TEST_DIR=\"${CKM_TEST_DIR}\"")
 ADD_DEFINITIONS("-DCKM_RW_DATA_DIR=\"${CKM_RW_DATA_DIR}\"")
+OPTION("TZ_BACKEND" OFF)
+IF(TZ_BACKEND)
+    ADD_DEFINITIONS("-DTZ_BACKEND")
+ENDIF(TZ_BACKEND)
+
+OPTION("TZ_BACKEND" OFF)
+IF(TZ_BACKEND)
+    ADD_DEFINITIONS("-DTZ_BACKEND")
+ENDIF(TZ_BACKEND)
 
 PKG_CHECK_MODULES(CKM_TEST_COMMON_DEP
     REQUIRED
-    openssl
+    openssl1.1
     key-manager
     libtzplatform-config
 )
diff --git a/src/ckm/keys/pkcs12.tgz b/src/ckm/keys/pkcs12.tgz
deleted file mode 100644 (file)
index 0dfe5e2..0000000
Binary files a/src/ckm/keys/pkcs12.tgz and /dev/null differ
diff --git a/src/ckm/keys/pkcs12/HOWTO.txt b/src/ckm/keys/pkcs12/HOWTO.txt
new file mode 100644 (file)
index 0000000..b1af637
--- /dev/null
@@ -0,0 +1,131 @@
+This guideline explains how src/resource/pkcs.p12 is generated.
+
+
+The certificate chain looks as follows (arrow denotes the signing):
+
+SERVER <-- CA_INT <-- CA
+
+That is the CA is a root CA, CA_INT is an intermediate/1st level CA,
+and SERVER is a final/2nd level CA.
+
+
+Files:
+- ca.key, CA's private key used to sign CA_INT certificate
+- ca.crt, CA's certificate used to verify a certificate chain (it's
+  the last certificate in the chain)
+- ca-int.key, CA_INT's private key used to sign SERVER certificate
+- ca-int.csr, CA_INT's certificate signing request (to be signed with
+  ca.key)
+- ca-int.crt, CA_INT's certificate signed by CA
+- server.key, SERVER's private key used to sign client certificates
+- server.csr, SERVER's certificate signing request (to be signed with
+  ca-int.key)
+- server.crt, SERVER's certificate signed by CA_INT
+- chain.pem, chain of CA, CA_INT and SERVER certificates in PEM format
+  (can be used for validation)
+
+
+Keys should be left untouched. In case they are lost they can be
+regenerated with:
+
+ openssl genrsa -out ca.key 1024 (or any other lenght)
+
+
+Certificate signing requests
+
+ Each certificate must have a different Common Name (CN). The command
+ for CSR generation will prompt you for it (and for other fields).
+
+
+Openssl ca setup
+
+ Openssl 1.1.1 requires root and intermediate CA certficates (that is
+ all 3 of above) to have a 'CA' set to 'true' in basicConstraints
+ extension. It applies to trusted certificates as well. The 'openssl
+ ca' tool allows that with proper configuration. Modifications in
+ /etc/ssl/openssl.cnf in [ CA_default ] section:
+ - set 'x509_extensions' to 'v3_ca' to add the v3 CA extension,
+ - set 'policy' to 'policy_anything' to get rid of strict CSR field
+ matching rules.
+
+ Before 'openssl ca' can be used you have to provide a proper
+ directory structure for it. By default it needs a following hierarchy
+ in ./demoCA (paths can be modified in /etc/ssl/openssl.cnf):
+ - demoCA/
+   - private/
+     - cakey.pem - The private key used to sign the certificate. For
+       ca-int.csr it will be ca.key.
+   - cacert.pem - The certificate of the signing CA. For ca-int.csr it
+     will be ca.crt.
+   - index.txt - Empty file (touch index.txt)
+   - serial - A file with serial number (echo 1000 > serial)
+
+
+Certificate generation
+
+- CA:
+
+ Generate a self signed certificate (root ca):
+
+  openssl req -key ca.key -new -x509 -days 3650 -sha256 -out ca.crt
+
+- CA_INT:
+
+ Generate a signing request:
+
+  openssl req -new -key ca.key -out ca-int.csr
+
+ Sign the certificate using CA:
+
+  openssl ca -days 3650 -notext -md sha256 -in ca-int.csr -out \
+  ca-int.crt
+
+- SERVER:
+
+ Generate a signing request:
+
+  openssl req -new -key ca-int.key -out server.csr
+
+ Sign the certificate using CA_INT:
+
+  openssl ca -days 3650 -notext -md sha256 -in server.csr -out \
+  server.crt
+
+
+Export server private key, certificate and the rest of the chain to
+pkcs12:
+
+ cat ca.crt ca-int.crt > chain.pem
+
+ openssl pkcs12 -export -out pkcs.p12 -inkey server.key -in server.crt \
+ -certfile chain.pem
+
+
+Useful commands
+
+- Display certificate info
+
+ openssl x509 -in ca.crt -text -noout
+
+- Display csr info
+
+ openssl req -in ca-int.csr -text -noout
+
+- Display pkcs12 contents in PEM format
+
+ openssl pkcs12 -in pkcs.p12 -info
+
+- Display certificate purpose
+
+ openssl x509 -in ca.crt -purpose
+
+- Sign a client's certificate with server one:
+
+ openssl req -new -key server.key -out client.csr
+ openssl x509 -req -in client.csr -CA server.crt -CAkey server.key \
+ -CAcreateserial -out client.crt -days 3650
+
+- Verify a certficate against a local chain
+
+ openssl verify -CAfile chain.pem client.crt
+
diff --git a/src/ckm/keys/pkcs12/ca-int.crt b/src/ckm/keys/pkcs12/ca-int.crt
new file mode 100644 (file)
index 0000000..dea0763
--- /dev/null
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICtzCCAiCgAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAlBM
+MQ8wDQYDVQQIDAZQb2xhbmQxDzANBgNVBAcMBldhcnNhdzEQMA4GA1UECgwHU2Ft
+c3VuZzEMMAoGA1UECwwDS1NGMRMwEQYDVQQDDAptLmthcnBpdWsyMSUwIwYJKoZI
+hvcNAQkBFhZtLmthcnBpdWsyQHNhbXN1bmcuY29tMB4XDTE5MDYxMzExNTQ0OFoX
+DTI5MDYxMDExNTQ0OFowYTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3Rh
+dGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEaMBgGA1UEAwwR
+Y2EtaW50QHRlc3RtZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOEp
+AxNNreF+HPTPznNdeUpcwXfJf5sDjfC9p648jDbiwu8fyEpWQyg1XnhoGc3ZST7o
+u3c3oJq89rw5L8c4vxG6QHXE3NHzZOFpvu+tpyIcfoToBRUiKEmpt60SmixA9VVX
+C9pUGRyUnjDI4Wuv2ZNw04lYgIGE9jdSMA+dSKYfAgMBAAGjUzBRMB0GA1UdDgQW
+BBSvHyNEVaNf2+iZ79oCpVmniojtLzAfBgNVHSMEGDAWgBSIkmgdQrVdA6+R4OHY
+kc1mlXOu7jAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GBAEo7oCMW
+gApPBjArw/AyPWw4vxLH6U7/kxJFThVu5b1/6bwEpE8hHK9FRuCZKw1ydegyuuO8
+7JgshhHGBlDECa3INdshCk2xi02SDjWZhxJU8r0eIrji2PxqBI3fEpF2067K2DUS
+vA1tUP253JYcln+xHxbZDUtzaoXM7LmN9tWx
+-----END CERTIFICATE-----
diff --git a/src/ckm/keys/pkcs12/ca-int.csr b/src/ckm/keys/pkcs12/ca-int.csr
new file mode 100644 (file)
index 0000000..ecd6d3e
--- /dev/null
@@ -0,0 +1,11 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIIBoTCCAQoCAQAwYTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx
+ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEaMBgGA1UEAwwRY2Et
+aW50QHRlc3RtZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOEpAxNN
+reF+HPTPznNdeUpcwXfJf5sDjfC9p648jDbiwu8fyEpWQyg1XnhoGc3ZST7ou3c3
+oJq89rw5L8c4vxG6QHXE3NHzZOFpvu+tpyIcfoToBRUiKEmpt60SmixA9VVXC9pU
+GRyUnjDI4Wuv2ZNw04lYgIGE9jdSMA+dSKYfAgMBAAGgADANBgkqhkiG9w0BAQsF
+AAOBgQC8b7cVVV4z5Bp/XxowzlfhMGL17EE2vgMwpCNNQ+fOpPrrEwmhyg0I4R5+
+iXrnxELVI/cqBUpS84ZHBlNgQAS8F9Wx6AU0yEUBcNqJiMjUreA56VZAfGb+/Sv+
+t6ZQrYtof38aaHfMxhYlCsZzuKGNWvQsLAgxvlBQgHEW9xsqHQ==
+-----END CERTIFICATE REQUEST-----
diff --git a/src/ckm/keys/pkcs12/ca-int.key b/src/ckm/keys/pkcs12/ca-int.key
new file mode 100644 (file)
index 0000000..0b3b26e
--- /dev/null
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXwIBAAKBgQDhKQMTTa3hfhz0z85zXXlKXMF3yX+bA43wvaeuPIw24sLvH8hK
+VkMoNV54aBnN2Uk+6Lt3N6CavPa8OS/HOL8RukB1xNzR82Thab7vraciHH6E6AUV
+IihJqbetEposQPVVVwvaVBkclJ4wyOFrr9mTcNOJWICBhPY3UjAPnUimHwIDAQAB
+AoGBAMvEP+JCVHBTn4T2Y5IIL/JaS0RK+M6iwtvx50RJy2MIiP27N5n+wzwqQFqb
+a27di+oA2Vck4pXnGSxyXIjhFBgWdLmryJM44DSVlWanb5n2A1GW291MGA8bGR/H
+TCbsuaEm3Z2ggFighQAp2Zuao2lKuMDOgOzpu+0k7lqtfsqxAkEA8ZHC7ocrlRtM
+EzafCi1htuwl9t02Do1q+wn8u5kbKPJ7q4ZNm/sUECfHBE7SbwxNxIEWKuZ5U8V4
+A42VPnO9gwJBAO6cT4IdILqxfxNPd97DY+rT64O/mPIJGC3cmDonf4kc+RuaqbT+
+D9WKp1cwmoeaJDrWbWFWi3cjBrrLd6JxzjUCQQC7s8Heq6Mesd4z065SLx8NDoMV
+RZ+aQSJOO91oOzhSYc/cYHfvanGVeAL5AvIaHVpUBOWfogPGJtrxD9NWeoJXAkEA
+n4CLwZ15AHOgT6dCqP2R8Crjd3l/YuPjbtzUQaOfpGdiuiokIaHnscZy4FzUH6tR
+ZqdqDLROnEAkwn86pLNQtQJBAOAsXPLUpVuJEtPZB1CNLdFkRqkqgFNPnGSIUnTp
++f5H8AHCb1tX/QllL3s6phZ9qds0qrwNxQzgiVATXZyRov4=
+-----END RSA PRIVATE KEY-----
diff --git a/src/ckm/keys/pkcs12/ca.crt b/src/ckm/keys/pkcs12/ca.crt
new file mode 100644 (file)
index 0000000..301187d
--- /dev/null
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC5jCCAk+gAwIBAgIJAOMDgLjsxef2MA0GCSqGSIb3DQEBCwUAMIGLMQswCQYD
+VQQGEwJQTDEPMA0GA1UECAwGUG9sYW5kMQ8wDQYDVQQHDAZXYXJzYXcxEDAOBgNV
+BAoMB1NhbXN1bmcxDDAKBgNVBAsMA0tTRjETMBEGA1UEAwwKbS5rYXJwaXVrMjEl
+MCMGCSqGSIb3DQEJARYWbS5rYXJwaXVrMkBzYW1zdW5nLmNvbTAeFw0xNDExMTMx
+MTExNDFaFw0yNDExMTAxMTExNDFaMIGLMQswCQYDVQQGEwJQTDEPMA0GA1UECAwG
+UG9sYW5kMQ8wDQYDVQQHDAZXYXJzYXcxEDAOBgNVBAoMB1NhbXN1bmcxDDAKBgNV
+BAsMA0tTRjETMBEGA1UEAwwKbS5rYXJwaXVrMjElMCMGCSqGSIb3DQEJARYWbS5r
+YXJwaXVrMkBzYW1zdW5nLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
+9VvZ3lG1y9a56vUr8s6a44VgSl8mCkIqxt1ds8lJ1GhNuEqtiL+yEq8DDfxulnI6
+xpnmQxFsKy+M14dNNjfAQ9cGiT0aJ8cLVZIRct3phmrUpse3iHpcuR/jwTSJkbwY
+druBloGujhF3FDXX2gVHMZ/j+uePP86Q4cjS80CpORcCAwEAAaNQME4wHQYDVR0O
+BBYEFIiSaB1CtV0Dr5Hg4diRzWaVc67uMB8GA1UdIwQYMBaAFIiSaB1CtV0Dr5Hg
+4diRzWaVc67uMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADgYEAXTvQ6fhZ
+SZhfd1DsNx+85ikyvPnSAffOWghJjJA2BMaHdKvoSJTHgBn29BmQSz0kSUM4GOM3
+ikD3aSEaqGJWXVUXxAx8vTe8qFfqr9RE0WsBmPPuWa2fwUaq2ttW5Je4UBs/9jiA
+2UqgKbtqxvacHpGFoM86QxgV+52AA+Bwfzw=
+-----END CERTIFICATE-----
diff --git a/src/ckm/keys/pkcs12/ca.key b/src/ckm/keys/pkcs12/ca.key
new file mode 100644 (file)
index 0000000..234a51a
--- /dev/null
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXQIBAAKBgQD1W9neUbXL1rnq9SvyzprjhWBKXyYKQirG3V2zyUnUaE24Sq2I
+v7ISrwMN/G6WcjrGmeZDEWwrL4zXh002N8BD1waJPRonxwtVkhFy3emGatSmx7eI
+ely5H+PBNImRvBh2u4GWga6OEXcUNdfaBUcxn+P6548/zpDhyNLzQKk5FwIDAQAB
+AoGAR+4WkBuqTUj1FlGsAbHaLKt0UDlWwJknS0eoacWwFEpDxqx19WolfV67aYVA
+snBolMKXg7/+0yZMhv8Ofr+XaHkPQplVVn9BwT0rmtEovJXwx+poRP9Bm3emglj/
+iYd8EkaXDlIXCtewtQW9JEIctWppntHj3TvA/h7FCXPN6SkCQQD/N7sn5S1gBkVh
+dyXQKoyKsZDb7hMIS1q6cKwYCMf2UrsD1/lnr7xXkvORdL213MfueO8g0WkuKfRY
+bDD6WGX1AkEA9hxiOlsgvermqLJkOlJffbSaM8n/6wtnM0HV+Vd9NfSBOmxFDXPO
+vrvdgiDPENhbqTJSQVDsfzHilTpK7lEvWwJBAJLxHoOg0tg3pBiyxgWtic+M3q+R
+ykl7QViY6KzJ2X98MIrM/Z7yMollZXE4+sVLwZ0O6fdGOr3GkBWc7TImVUUCQQC7
+pf6bQfof9Ce0fnf/I+ldHkPost7nJsWkBlGQkM2OQwP5OK4ZyK/dK76DxmI7FMwm
+oJCo7nuzq6R4ZX7WYJ47AkBavxBDo/e9/0Vk5yrloGKW3f8RQXBJLcCkVUGyyJ3D
+3gu/nafW4hzjSJniTjC1fOj0eb0OSg1JAvqHTYAnUsI7
+-----END RSA PRIVATE KEY-----
diff --git a/src/ckm/keys/pkcs12/chain.pem b/src/ckm/keys/pkcs12/chain.pem
new file mode 100644 (file)
index 0000000..b4b75e6
--- /dev/null
@@ -0,0 +1,51 @@
+-----BEGIN CERTIFICATE-----
+MIIC5jCCAk+gAwIBAgIJAOMDgLjsxef2MA0GCSqGSIb3DQEBCwUAMIGLMQswCQYD
+VQQGEwJQTDEPMA0GA1UECAwGUG9sYW5kMQ8wDQYDVQQHDAZXYXJzYXcxEDAOBgNV
+BAoMB1NhbXN1bmcxDDAKBgNVBAsMA0tTRjETMBEGA1UEAwwKbS5rYXJwaXVrMjEl
+MCMGCSqGSIb3DQEJARYWbS5rYXJwaXVrMkBzYW1zdW5nLmNvbTAeFw0xNDExMTMx
+MTExNDFaFw0yNDExMTAxMTExNDFaMIGLMQswCQYDVQQGEwJQTDEPMA0GA1UECAwG
+UG9sYW5kMQ8wDQYDVQQHDAZXYXJzYXcxEDAOBgNVBAoMB1NhbXN1bmcxDDAKBgNV
+BAsMA0tTRjETMBEGA1UEAwwKbS5rYXJwaXVrMjElMCMGCSqGSIb3DQEJARYWbS5r
+YXJwaXVrMkBzYW1zdW5nLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
+9VvZ3lG1y9a56vUr8s6a44VgSl8mCkIqxt1ds8lJ1GhNuEqtiL+yEq8DDfxulnI6
+xpnmQxFsKy+M14dNNjfAQ9cGiT0aJ8cLVZIRct3phmrUpse3iHpcuR/jwTSJkbwY
+druBloGujhF3FDXX2gVHMZ/j+uePP86Q4cjS80CpORcCAwEAAaNQME4wHQYDVR0O
+BBYEFIiSaB1CtV0Dr5Hg4diRzWaVc67uMB8GA1UdIwQYMBaAFIiSaB1CtV0Dr5Hg
+4diRzWaVc67uMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADgYEAXTvQ6fhZ
+SZhfd1DsNx+85ikyvPnSAffOWghJjJA2BMaHdKvoSJTHgBn29BmQSz0kSUM4GOM3
+ikD3aSEaqGJWXVUXxAx8vTe8qFfqr9RE0WsBmPPuWa2fwUaq2ttW5Je4UBs/9jiA
+2UqgKbtqxvacHpGFoM86QxgV+52AA+Bwfzw=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICtzCCAiCgAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwgYsxCzAJBgNVBAYTAlBM
+MQ8wDQYDVQQIDAZQb2xhbmQxDzANBgNVBAcMBldhcnNhdzEQMA4GA1UECgwHU2Ft
+c3VuZzEMMAoGA1UECwwDS1NGMRMwEQYDVQQDDAptLmthcnBpdWsyMSUwIwYJKoZI
+hvcNAQkBFhZtLmthcnBpdWsyQHNhbXN1bmcuY29tMB4XDTE5MDYxMzExNTQ0OFoX
+DTI5MDYxMDExNTQ0OFowYTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3Rh
+dGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEaMBgGA1UEAwwR
+Y2EtaW50QHRlc3RtZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOEp
+AxNNreF+HPTPznNdeUpcwXfJf5sDjfC9p648jDbiwu8fyEpWQyg1XnhoGc3ZST7o
+u3c3oJq89rw5L8c4vxG6QHXE3NHzZOFpvu+tpyIcfoToBRUiKEmpt60SmixA9VVX
+C9pUGRyUnjDI4Wuv2ZNw04lYgIGE9jdSMA+dSKYfAgMBAAGjUzBRMB0GA1UdDgQW
+BBSvHyNEVaNf2+iZ79oCpVmniojtLzAfBgNVHSMEGDAWgBSIkmgdQrVdA6+R4OHY
+kc1mlXOu7jAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GBAEo7oCMW
+gApPBjArw/AyPWw4vxLH6U7/kxJFThVu5b1/6bwEpE8hHK9FRuCZKw1ydegyuuO8
+7JgshhHGBlDECa3INdshCk2xi02SDjWZhxJU8r0eIrji2PxqBI3fEpF2067K2DUS
+vA1tUP253JYcln+xHxbZDUtzaoXM7LmN9tWx
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICjDCCAfWgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwYTELMAkGA1UEBhMCQVUx
+EzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMg
+UHR5IEx0ZDEaMBgGA1UEAwwRY2EtaW50QHRlc3RtZS5jb20wHhcNMTkwNjEzMTIw
+NzU5WhcNMjkwNjEwMTIwNzU5WjBhMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29t
+ZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRowGAYD
+VQQDDBFzZXJ2ZXJAdGVzdG1lLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEAw4Jj7q00Gt8G55TPvZwhEL4Q74mEb0gvUy+ZQDAQpgUpfd79FAV1rKjvn5gC
+DZuUCWvPYReTe0OMbb30iVDyHss6MEzhBjOFNxZybZbDULKDWxZTckC6GWZpmOJY
+xuv2Kl/iRgYEvfyfLr2g1pL7PpLZDkcoHzc+BouQxEU+3nkCAwEAAaNTMFEwHQYD
+VR0OBBYEFE8OYEtgOx9klZOaDcNJF6nkfeE6MB8GA1UdIwQYMBaAFK8fI0RVo1/b
+6Jnv2gKlWaeKiO0vMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADgYEA
+pkpwMYqyEFl1fPGHbub4ieDxm9U+KSkMOoB3pB5atqvP4LJj7sGQL6qnRYiL5er3
+cyBaIQdKt/NqWR4LKrLGPsfIbtDesRAP8HfG5ZfxiRr4Z4PhdMzO4XVSihuoGUoh
+DfQkQRjWw60PKpc9uQypCcHY5yWu/b+lPL5ydXKyU5o=
+-----END CERTIFICATE-----
diff --git a/src/ckm/keys/pkcs12/server.crt b/src/ckm/keys/pkcs12/server.crt
new file mode 100644 (file)
index 0000000..40b6b69
--- /dev/null
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE-----
+MIICjDCCAfWgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwYTELMAkGA1UEBhMCQVUx
+EzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMg
+UHR5IEx0ZDEaMBgGA1UEAwwRY2EtaW50QHRlc3RtZS5jb20wHhcNMTkwNjEzMTIw
+NzU5WhcNMjkwNjEwMTIwNzU5WjBhMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29t
+ZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRowGAYD
+VQQDDBFzZXJ2ZXJAdGVzdG1lLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEAw4Jj7q00Gt8G55TPvZwhEL4Q74mEb0gvUy+ZQDAQpgUpfd79FAV1rKjvn5gC
+DZuUCWvPYReTe0OMbb30iVDyHss6MEzhBjOFNxZybZbDULKDWxZTckC6GWZpmOJY
+xuv2Kl/iRgYEvfyfLr2g1pL7PpLZDkcoHzc+BouQxEU+3nkCAwEAAaNTMFEwHQYD
+VR0OBBYEFE8OYEtgOx9klZOaDcNJF6nkfeE6MB8GA1UdIwQYMBaAFK8fI0RVo1/b
+6Jnv2gKlWaeKiO0vMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADgYEA
+pkpwMYqyEFl1fPGHbub4ieDxm9U+KSkMOoB3pB5atqvP4LJj7sGQL6qnRYiL5er3
+cyBaIQdKt/NqWR4LKrLGPsfIbtDesRAP8HfG5ZfxiRr4Z4PhdMzO4XVSihuoGUoh
+DfQkQRjWw60PKpc9uQypCcHY5yWu/b+lPL5ydXKyU5o=
+-----END CERTIFICATE-----
diff --git a/src/ckm/keys/pkcs12/server.csr b/src/ckm/keys/pkcs12/server.csr
new file mode 100644 (file)
index 0000000..11fc7f9
--- /dev/null
@@ -0,0 +1,11 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIIBoTCCAQoCAQAwYTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx
+ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEaMBgGA1UEAwwRc2Vy
+dmVyQHRlc3RtZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMOCY+6t
+NBrfBueUz72cIRC+EO+JhG9IL1MvmUAwEKYFKX3e/RQFdayo75+YAg2blAlrz2EX
+k3tDjG299IlQ8h7LOjBM4QYzhTcWcm2Ww1Cyg1sWU3JAuhlmaZjiWMbr9ipf4kYG
+BL38ny69oNaS+z6S2Q5HKB83PgaLkMRFPt55AgMBAAGgADANBgkqhkiG9w0BAQsF
+AAOBgQCY3jWaE33hy1JVni9bLCUYwOz6VJVV8d1WWpSf7CpIgrXUQFPOIfO71jlf
+Vn99iYCUIodq+9M9dyeNoU1mkAp2LpG3Y3DjePpIyM3zLLEM/CmQ9ZbuS/zKl5fO
+KoItsRl0uFJEEEHw7lWxdRuIvzix5SFxTApiMPktjtCs/9eAew==
+-----END CERTIFICATE REQUEST-----
diff --git a/src/ckm/keys/pkcs12/server.key b/src/ckm/keys/pkcs12/server.key
new file mode 100644 (file)
index 0000000..a1197d7
--- /dev/null
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICWwIBAAKBgQDDgmPurTQa3wbnlM+9nCEQvhDviYRvSC9TL5lAMBCmBSl93v0U
+BXWsqO+fmAINm5QJa89hF5N7Q4xtvfSJUPIeyzowTOEGM4U3FnJtlsNQsoNbFlNy
+QLoZZmmY4ljG6/YqX+JGBgS9/J8uvaDWkvs+ktkORygfNz4Gi5DERT7eeQIDAQAB
+AoGAARIqx/js6yTDnesjxC8hwzy3TQic0Bs+Hx+IoGBjBvXKR2U8T6rD/UEjpuUn
+RbnPcsnDZg3CAg/ZqhQ7TbFC0kPo+S6+wKsZGDWUUvnpMkdcZUqXel8GFhdnmeIh
+22vYthP4TCbolxwXlwvuhu0PLZWhRO/Z+g37T3QENexqGv0CQQDmqJ9PDoUj5eUR
+wWEqEPraoU6ARBUUX5EhmTT9g9/BXnhwumIOksDHcBqNUwNOlKCUlWfBOelO93Ys
+PRW3QyejAkEA2P0tW/8iU4j+0a6DV+TUYFDTjD29y8KPw0Aj59591xD5eIPK3IgU
+91vnmtvU/QR26PnMOx4OAPk9a7BtN62zMwJAIFV0950edtjMUr/cAgydTbadDYf9
+uHxpGN+kOQGahT3b/llyU36o/YwufK8tYH+fPxTulXyrwwEXlL3/ZFBKpwJAeLGS
+Wlp2WGqZ+j2MdwYkDxLGKHprKHwnBN6XWjCKZGbfrGX6H2Jd7xyinaNrO/UQwxO2
+wqc7+NSpkk3G4jJuuwJAODYlk2Q+djE4jkjDc4xiqsQGBQlI2dlgzjRjIF4HWiLx
+bIrI0uCCbGItx++hlvmDx7G8anBmIFfBWIaKdX0aWw==
+-----END RSA PRIVATE KEY-----
index cbe717b..705562c 100644 (file)
@@ -26,6 +26,9 @@ SET(EIV_KEY_TO_BE_IMPORTED "KeyOne16BytesLen")
 SET(EIV_PLAIN_MESSAGE "ShortTestMessage")
 SET(EIV_MESSAGE_ENCRYPTION_IV "abcdefghijklmnop")
 
+SET(EIV_TEST_ASYM_XML_FILENAME "encrypted_initial_values_asym.xml")
+SET(EIV_TEST_ASYM_XML ${CMAKE_CURRENT_SOURCE_DIR}/${EIV_TEST_ASYM_XML_FILENAME})
+
 # encrypt ShortTestMessage using the imported key and 'abcdefghijklmnop' IV
 EXECUTE_PROCESS(
     COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/aes_128_cbc_encrypt.sh ${EIV_KEY_TO_BE_IMPORTED} ${EIV_MESSAGE_ENCRYPTION_IV}
@@ -38,18 +41,39 @@ IF(NOT ${EIV_ENCRYPTION_RESULT} STREQUAL "0")
     MESSAGE(FATAL_ERROR "Encryption failed: ${EIV_ENCRYPTION_STDERR}")
 ENDIF(NOT ${EIV_ENCRYPTION_RESULT} STREQUAL "0")
 
+SET(EIV_FILES ${EIV_TEST_XML} ${EIV_TEST_ASYM_XML})
+
 # prepare initial values xml target
-ADD_CUSTOM_COMMAND(OUTPUT ${EIV_TEST_XML}
-    COMMAND echo -n ${EIV_KEY_TO_BE_IMPORTED} > /tmp/key
+ADD_CUSTOM_COMMAND(OUTPUT ${EIV_FILES}
     COMMAND echo -n THIS/STRING/MUST/BE/REPLACED/IN/REAL/DEVICE= | base64 --decode > /tmp/encryption_key
-    COMMAND ${CMAKE_INSTALL_FULL_BINDIR}/ckm_initial_values -d /tmp/key -k /tmp/encryption_key -n TEI_0 -t Key -s AES -b hardware -x ${EIV_TEST_XML}
+
+    COMMAND echo -n ${EIV_KEY_TO_BE_IMPORTED} > /tmp/key
+    COMMAND ${CMAKE_INSTALL_FULL_BINDIR}/ckm_initial_values -d /tmp/key -k /tmp/encryption_key -n TEI_0 -t Key -s AES -b hardware > ${EIV_TEST_XML}
+
+    COMMAND openssl genpkey -algorithm RSA -outform DER > /tmp/prvkey
+    COMMAND openssl rsa -in /tmp/prvkey -inform DER -pubout -outform DER > /tmp/pubkey
+    COMMAND ${CMAKE_INSTALL_FULL_BINDIR}/ckm_initial_values -d /tmp/prvkey -k /tmp/encryption_key -n TEI_RSA_PRV -t Key -s RSA_PRV > ${EIV_TEST_ASYM_XML}
+    COMMAND ${CMAKE_INSTALL_FULL_BINDIR}/ckm_initial_values -d /tmp/pubkey -k /tmp/encryption_key -n TEI_RSA_PUB -t Key -s RSA_PUB -x ${EIV_TEST_ASYM_XML}
+
+    COMMAND openssl genpkey -algorithm RSA -outform PEM > /tmp/prvkey.pem
+    COMMAND openssl pkcs8 -topk8 -inform PEM -in /tmp/prvkey.pem -outform DER -nocrypt -out /tmp/prvkey
+    COMMAND openssl rsa -in /tmp/prvkey -inform DER -pubout -outform DER > /tmp/pubkey
+    COMMAND ${CMAKE_INSTALL_FULL_BINDIR}/ckm_initial_values -d /tmp/prvkey -k /tmp/encryption_key -n TEI_RSA_PKCS8_PRV -t Key -s RSA_PRV -x ${EIV_TEST_ASYM_XML}
+    COMMAND ${CMAKE_INSTALL_FULL_BINDIR}/ckm_initial_values -d /tmp/pubkey -k /tmp/encryption_key -n TEI_RSA_PKCS8_PUB -t Key -s RSA_PUB -x ${EIV_TEST_ASYM_XML}
+
+    COMMAND openssl genpkey -genparam -algorithm DSA -pkeyopt dsa_paramgen_bits:1024 -pkeyopt dsa_paramgen_q_bits:160 > /tmp/params.pem
+    COMMAND openssl genpkey -paramfile /tmp/params.pem -outform DER > /tmp/prvkey
+    COMMAND openssl dsa -in /tmp/prvkey -inform DER -pubout -outform DER > /tmp/pubkey
+    COMMAND ${CMAKE_INSTALL_FULL_BINDIR}/ckm_initial_values -d /tmp/prvkey -k /tmp/encryption_key -n TEI_DSA_PRV -t Key -s DSA_PRV -x ${EIV_TEST_ASYM_XML}
+    COMMAND ${CMAKE_INSTALL_FULL_BINDIR}/ckm_initial_values -d /tmp/pubkey -k /tmp/encryption_key -n TEI_DSA_PUB -t Key -s DSA_PUB -x ${EIV_TEST_ASYM_XML}
+
     COMMENT "Generating encrypted initial values test xml"
     VERBATIM
 )
 
-ADD_CUSTOM_TARGET(TARGET_EIV_TEST_XML DEPENDS ${EIV_TEST_XML})
+ADD_CUSTOM_TARGET(TARGET_EIV_TEST_XML DEPENDS ${EIV_FILES})
 
-INSTALL(FILES ${EIV_TEST_XML} DESTINATION ${CKM_TEST_DIR})
+INSTALL(FILES ${EIV_FILES} DESTINATION ${CKM_TEST_DIR})
 
 # ckm-tests
 PKG_CHECK_MODULES(CKM_DEP
@@ -58,11 +82,6 @@ PKG_CHECK_MODULES(CKM_DEP
     dbus-1
 )
 
-OPTION("TZ_BACKEND" OFF)
-IF(TZ_BACKEND)
-    ADD_DEFINITIONS("-DTZ_BACKEND")
-ENDIF(TZ_BACKEND)
-
 SET(CKM_SOURCES
     access_provider2.cpp
     async-api.cpp
@@ -95,6 +114,7 @@ TARGET_COMPILE_DEFINITIONS(${TARGET_CKM_PRIVILEGED_TESTS}
     PRIVATE EIV_ENCRYPTED_MESSAGE_HEX="${EIV_ENCRYPTED_MESSAGE_HEX}"
     PRIVATE EIV_MESSAGE_ENCRYPTION_IV="${EIV_MESSAGE_ENCRYPTION_IV}"
     PRIVATE EIV_TEST_XML_FILENAME="${EIV_TEST_XML_FILENAME}"
+    PRIVATE EIV_TEST_ASYM_XML_FILENAME="${EIV_TEST_ASYM_XML_FILENAME}"
 )
 
 INSTALL(TARGETS ${TARGET_CKM_PRIVILEGED_TESTS} DESTINATION bin)
index 69a74ee..baad9a8 100755 (executable)
@@ -1,4 +1,5 @@
-#!/bin/bash -e
+#!/bin/bash
+set -euo pipefail
 
 if [ "$#" -ne 2 ]
 then
index f0328ed..db28b1c 100644 (file)
@@ -37,6 +37,16 @@ const char* TEST_ALIAS2 = "test-alias2";
 const char* TEST_ALIAS3 = "test-alias3";
 
 const char* TEST_DATA = "dsflsdkghkslhglrtghierhgilrehgidsafasdffsgfdgdgfdgfdgfdgfdggf";
+const char* RSA_PUB_KEY_PEM =
+    "-----BEGIN PUBLIC KEY-----\n"
+    "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2b1bXDa+S8/MGWnMkru4\n"
+    "T4tUddtZNi0NVjQn9RFH1NMa220GsRhRO56F77FlSVFKfSfVZKIiWg6C+DVCkcLf\n"
+    "zXJ/Z0pvwOQYBAqVMFjV6efQGN0JzJ1Unu7pPRiZl7RKGEI+cyzzrcDyrLLrQ2W7\n"
+    "0ZySkNEOv6Frx9JgC5NExuYY4lk2fQQa38JXiZkfyzif2em0px7mXbyf5LjccsKq\n"
+    "v1e+XLtMsL0ZefRcqsP++NzQAI8fKX7WBT+qK0HJDLiHrKOTWYzx6CwJ66LD/vvf\n"
+    "j55xtsKDLVDbsotvf8/m6VLMab+vqKk11TP4tq6yo0mwyTADvgl1zowQEO9I1W6o\n"
+    "zQIDAQAB\n"
+    "-----END PUBLIC KEY-----";
 
 void allow_access_deprecated(const char* alias, const char* accessor, ckmc_access_right_e accessRights)
 {
@@ -889,3 +899,156 @@ RUNNER_TEST(T3145_control_deprecated_remove_allowed, RemoveDataEnv<APP_1>)
         check_remove_allowed(aliasWithLabel(APP_LABEL_1, TEST_ALIAS).c_str());
     }
 }
+
+RUNNER_TEST(utc_ckmc_get_key_alias_info_list_p)
+{
+    ckmc_alias_info_list_s* ppalias_list = NULL;
+
+    int ret = ckmc_get_key_alias_info_list(&ppalias_list);
+    ckmc_alias_info_list_all_free(ppalias_list);
+    RUNNER_ASSERT_MSG(ret == CKMC_ERROR_DB_ALIAS_UNKNOWN, "Expected CKMC_ERROR_DB_ALIAS_UNKNOWN, returned: " << CKMCErrorToString(ret));
+}
+
+RUNNER_TEST(utc_ckmc_get_key_alias_info_list_n)
+{
+    int ret = ckmc_get_key_alias_info_list(NULL);
+    RUNNER_ASSERT_MSG(ret == CKMC_ERROR_INVALID_PARAMETER, "Expected invalid parameter error, returned: " << CKMCErrorToString(ret));
+}
+
+RUNNER_TEST(utc_ckmc_get_cert_alias_info_list_p)
+{
+    ckmc_alias_info_list_s* ppalias_list = NULL;
+
+    int ret = ckmc_get_cert_alias_info_list(&ppalias_list);
+    ckmc_alias_info_list_all_free(ppalias_list);
+    RUNNER_ASSERT_MSG(ret == CKMC_ERROR_DB_ALIAS_UNKNOWN, "Expected CKMC_ERROR_DB_ALIAS_UNKNOWN, returned: " <<  CKMCErrorToString(ret));
+}
+
+RUNNER_TEST(utc_ckmc_get_cert_alias_info_list_n)
+{
+    int ret = ckmc_get_cert_alias_info_list(NULL);
+    RUNNER_ASSERT_MSG(ret == CKMC_ERROR_INVALID_PARAMETER, "Expected invalid parameter error, returned: " << CKMCErrorToString(ret));
+}
+
+
+RUNNER_TEST(utc_ckmc_get_data_alias_info_list_p1)
+{
+    ckmc_alias_info_list_s* ppalias_list = NULL;
+
+    int ret = ckmc_get_data_alias_info_list(&ppalias_list);
+    ckmc_alias_info_list_all_free(ppalias_list);
+    RUNNER_ASSERT_MSG(ret == CKMC_ERROR_DB_ALIAS_UNKNOWN, "Expected CKMC_ERROR_DB_ALIAS_UNKNOWN, returned: " <<  CKMCErrorToString(ret));
+}
+
+
+RUNNER_TEST(utc_ckmc_get_data_alias_info_list_p2, RemoveDataEnv<APP_1>)
+{
+    ScopedAccessProvider ap(APP_LABEL_1, APP_1, GROUP_1);
+    save_data(TEST_ALIAS, TEST_DATA);
+
+    ckmc_alias_info_list_s* ppalias_list = NULL;
+
+    int ret = ckmc_get_data_alias_info_list(&ppalias_list);
+    RUNNER_ASSERT_MSG(ret == CKMC_ERROR_NONE, "Expected no error, returned: " <<  CKMCErrorToString(ret));
+
+    char* alias = NULL;
+    ret = ckmc_alias_info_get_alias(ppalias_list->info, &alias);
+    RUNNER_ASSERT_MSG(ret == CKMC_ERROR_NONE, "Failed to get alias, returned: " << CKMCErrorToString(ret));
+    RUNNER_ASSERT_MSG(ppalias_list->next == NULL, "More elements returned");
+    std::string aliasOrig =  std::string(APP_LABEL_1) + " " + std::string(TEST_ALIAS);
+    RUNNER_ASSERT_MSG(strcmp(alias, aliasOrig.c_str()) == 0, "Invalid aliast returned : " << alias);
+
+    ckmc_alias_info_list_all_free(ppalias_list);
+
+}
+
+
+RUNNER_TEST(utc_ckmc_get_data_alias_info_list_n)
+{
+    int ret = ckmc_get_data_alias_info_list(NULL);
+    RUNNER_ASSERT_MSG(ret == CKMC_ERROR_INVALID_PARAMETER, "Expected invalid parameter error, returned: " << CKMCErrorToString(ret));
+}
+
+RUNNER_TEST(utc_ckmc_alias_info_get_alias_p)
+{
+    ckmc_alias_info_list_s *ppalias_list, *tmp;
+    ckmc_key_s test_key;
+    ckmc_policy_s test_policy;
+    int ret;
+    char* current_alias;
+    const char* alias = "utc_ckmc_alias_info_get_alias_p_test_alias";
+    bool foundAlias = false;
+
+    test_key.raw_key =  (unsigned char *)RSA_PUB_KEY_PEM;
+    test_key.key_size = strlen(RSA_PUB_KEY_PEM);
+    test_key.key_type = CKMC_KEY_RSA_PUBLIC;
+    test_key.password = NULL;
+
+    test_policy.password = NULL;
+    test_policy.extractable = true;
+
+    ret = ckmc_save_key(alias, test_key, test_policy);
+    RUNNER_ASSERT_MSG(ret == CKMC_ERROR_NONE, "Expected no error, got " << CKMCErrorToString(ret));
+
+    ret = ckmc_get_key_alias_info_list(&ppalias_list);
+    RUNNER_ASSERT_MSG(ret == CKMC_ERROR_NONE, "Expected no error, got " << CKMCErrorToString(ret));
+
+    tmp = ppalias_list;
+
+    while (tmp) {
+        ret = ckmc_alias_info_get_alias(tmp->info, &current_alias);
+        RUNNER_ASSERT_MSG(ret == CKMC_ERROR_NONE, "Expected no error, got " << CKMCErrorToString(ret));
+        if (strstr(current_alias, alias)) {
+            foundAlias = true;
+            break;
+        }
+        tmp = tmp->next;
+    }
+    ckmc_alias_info_list_all_free(ppalias_list);
+    ckmc_remove_key(alias);
+    RUNNER_ASSERT_MSG(foundAlias == true, "Expected to find alias, but alias not found");
+}
+
+RUNNER_TEST(utc_ckmc_alias_info_is_password_protected_p)
+{
+    ckmc_alias_info_list_s *ppalias_list, *tmp;
+    ckmc_key_s test_key;
+    ckmc_policy_s test_policy;
+    int ret;
+    char* current_alias;
+    const char* alias = "utc_ckmc_alias_info_get_alias_p_test_alias";
+    bool foundAlias = false;
+
+    test_key.raw_key =  (unsigned char *)RSA_PUB_KEY_PEM;
+    test_key.key_size = strlen(RSA_PUB_KEY_PEM);
+    test_key.key_type = CKMC_KEY_RSA_PUBLIC;
+    test_key.password = NULL;
+
+    test_policy.password = NULL;
+    test_policy.extractable = true;
+
+    ret = ckmc_save_key(alias, test_key, test_policy);
+    RUNNER_ASSERT_MSG(ret == CKMC_ERROR_NONE, "Expected no error, got " << CKMCErrorToString(ret));
+
+    ret = ckmc_get_key_alias_info_list(&ppalias_list);
+    RUNNER_ASSERT_MSG(ret == CKMC_ERROR_NONE, "Expected no error, got " << CKMCErrorToString(ret));
+
+    tmp = ppalias_list;
+
+    while (tmp) {
+        ret = ckmc_alias_info_get_alias(tmp->info, &current_alias);
+        RUNNER_ASSERT_MSG(ret == CKMC_ERROR_NONE, "Expected no error, got " << CKMCErrorToString(ret));
+        if (strstr(current_alias, alias)) {
+            foundAlias = true;
+            bool is_password_protected;
+            ret = ckmc_alias_info_is_password_protected(tmp->info, &is_password_protected);
+            RUNNER_ASSERT_MSG(ret == CKMC_ERROR_NONE, "Expected no error, got " << CKMCErrorToString(ret));
+            RUNNER_ASSERT(is_password_protected == false);
+            break;
+        }
+        tmp = tmp->next;
+    }
+    ckmc_alias_info_list_all_free(ppalias_list);
+    ckmc_remove_key(alias);
+    RUNNER_ASSERT(foundAlias == true);
+}
index 94f635a..e8988de 100644 (file)
@@ -37,8 +37,6 @@ const uid_t USER_APP            = 5070;
 const uid_t GROUP_APP           = 5070;
 const char* APP_PASS            = "user-pass";
 
-const char *XML_DEVICE_KEY              = "device_key.xml";
-
 const char *XML_1_okay                  = "XML_1_okay.xml";
 std::string XML_1_EXPECTED_KEY_1_RSA    = aliasWithLabel(ckmc_owner_id_system, "test-key1");
 std::string XML_1_EXPECTED_KEY_1_PASSWD = "123";
@@ -48,11 +46,6 @@ std::string XML_1_EXPECTED_KEY_3_AES    = aliasWithLabel(ckmc_owner_id_system, "
 std::string XML_1_EXPECTED_CERT_1       = aliasWithLabel(ckmc_owner_id_system, "test-cert1");
 std::string XML_1_EXPECTED_DATA_1       = aliasWithLabel(ckmc_owner_id_system, "test-data1");
 const char *XML_1_EXPECTED_DATA_1_DATA  = "My secret data";
-// encrypted
-std::string XML_1_EXPECTED_KEY_3_RSA_PRV    = aliasWithLabel(ckmc_owner_id_system, "test-encryption-prv");
-std::string XML_1_EXPECTED_KEY_3_RSA_PUB    = aliasWithLabel(ckmc_owner_id_system, "test-encryption-pub");
-std::string XML_1_EXPECTED_ASCII_DATA       = aliasWithLabel(ckmc_owner_id_system, "test-ascii-data-encryption");
-std::string XML_1_EXPECTED_BIG_DATA         = aliasWithLabel(ckmc_owner_id_system, "test-binary-data-encryption");
 
 const char *XML_2_okay                  = "XML_2_okay.xml";
 std::string XML_2_EXPECTED_KEY_1_RSA    = aliasWithLabel(ckmc_owner_id_system, "test2-key1");
@@ -70,45 +63,36 @@ std::string XML_3_EXPECTED_KEY_2_RSA    = aliasWithLabel(ckmc_owner_id_system, "
 std::string XML_3_EXPECTED_CERT_1       = aliasWithLabel(ckmc_owner_id_system, "test3-cert1");
 std::string XML_3_EXPECTED_DATA_1       = aliasWithLabel(ckmc_owner_id_system, "test3-data1");
 
-std::string format_src_path(const char *file)
+auto format_dest_path(const char *file)
 {
-    return std::string(CKM_TEST_DIR) + std::string(file);
+    return std::string(CKM_RW_DATA_DIR "/initial_values/") + file;
 }
 
-std::string format_dest_key_path(const char *file)
-{
-    return std::string(CKM_RW_DATA_DIR) + std::string(file);
-}
-
-std::string format_dest_path(const char *file)
-{
-    return std::string(CKM_RW_DATA_DIR) + std::string( "/initial_values/") + std::string(file);
+void test_not_exists(const char *file) {
+    const auto name = format_dest_path(file);
+    const bool file_exists = access(name.c_str(), F_OK) != -1;
+    RUNNER_ASSERT_MSG(!file_exists, "File " << name << " exists");
 }
 
-void copy_file(const std::string &from, const std::string &to)
+void copy_file(const char *file)
 {
-    std::ifstream infile(from, std::ios_base::binary);
-    RUNNER_ASSERT_MSG(infile, "Input file " << from << " does not exist.");
-    std::ofstream outfile(to, std::ios_base::binary);
-    RUNNER_ASSERT_MSG(outfile, "Output file " << to << " does not exist. Reinstall key-manager.");
+    const auto src = std::string(CKM_TEST_DIR) + file;
+    const auto dest = format_dest_path(file);
+    std::ifstream infile(src, std::ios_base::binary);
+    RUNNER_ASSERT_MSG(infile, "Input file " << src << " does not exist.");
+    std::ofstream outfile(dest, std::ios_base::binary);
+    RUNNER_ASSERT_MSG(outfile, "Output file " << dest << " does not exist. Reinstall key-manager.");
     outfile << infile.rdbuf();
 }
 
-void restart_key_manager()
+void restart_key_manager(const std::initializer_list<const char *> files_to_copy = {})
 {
     stop_service(MANAGER);
+    for (const auto f : files_to_copy)
+        copy_file(f);
     start_service(MANAGER);
 }
 
-void test_exists(const std::string& name, bool expected) {
-    bool file_exists = (access( name.c_str(), F_OK ) != -1);
-    RUNNER_ASSERT_MSG(file_exists == expected,
-                      "File " << name << " status: " << file_exists <<
-                      " while expected: " << expected);
-}
-
-}
-
 int hexToBin(char h) {
     if (h >= '0' && h <= '9')
         return h - '0';
@@ -129,9 +113,11 @@ CKM::RawBuffer hexToBin(std::string &hex) {
     return output;
 }
 
+} // namespace
+
 RUNNER_TEST_GROUP_INIT(T60_INITIAL_VALUES);
 
-RUNNER_TEST_TZ_BACKEND(T6001_init)
+RUNNER_TEST(T6001_init)
 {
     // [prepare]
     // remove database 0
@@ -140,23 +126,13 @@ RUNNER_TEST_TZ_BACKEND(T6001_init)
     // restart the key-manager
     // check XML file doesn't exist
 
-    copy_file(format_src_path(XML_DEVICE_KEY), format_dest_key_path(XML_DEVICE_KEY));
-    copy_file(format_src_path(XML_1_okay), format_dest_path(XML_1_okay));
-    copy_file(format_src_path(XML_2_okay), format_dest_path(XML_2_okay));
-    copy_file(format_src_path(XML_3_wrong), format_dest_path(XML_3_wrong));
-
-    test_exists(format_dest_path(XML_1_okay), true);
-    test_exists(format_dest_path(XML_2_okay), true);
-    test_exists(format_dest_path(XML_3_wrong), true);
-
-    restart_key_manager();
-
-    test_exists(format_dest_path(XML_1_okay), false);
-    test_exists(format_dest_path(XML_2_okay), false);
-    test_exists(format_dest_path(XML_3_wrong), false);
+    const auto files = {XML_1_okay, XML_2_okay, XML_3_wrong};
+    restart_key_manager(files);
+    for (const auto f : files)
+        test_not_exists(f);
 }
 
-RUNNER_TEST_TZ_BACKEND(T6010_PARSE_XML_FILE_AT_STARTUP)
+RUNNER_TEST(T6010_PARSE_XML_FILE_AT_STARTUP)
 {
     // [test1]
     // check items existence as system service
@@ -201,7 +177,7 @@ RUNNER_TEST_TZ_BACKEND(T6010_PARSE_XML_FILE_AT_STARTUP)
     }
 }
 
-RUNNER_TEST_TZ_BACKEND(T6020_PARSE_TWO_XML_FILES_AT_STARTUP)
+RUNNER_TEST(T6020_PARSE_TWO_XML_FILES_AT_STARTUP)
 {
     // [test]
     // check items existence as system service
@@ -217,7 +193,7 @@ RUNNER_TEST_TZ_BACKEND(T6020_PARSE_TWO_XML_FILES_AT_STARTUP)
     check_read_allowed(XML_2_EXPECTED_DATA_1.c_str(), XML_2_EXPECTED_DATA_1_DATA);
 }
 
-RUNNER_TEST_TZ_BACKEND(T6030_PARSE_FAIL_XML_AT_STARTUP)
+RUNNER_TEST(T6030_PARSE_FAIL_XML_AT_STARTUP)
 {
     // [test]
     // check items existence as system service - nothing should be available
@@ -227,7 +203,7 @@ RUNNER_TEST_TZ_BACKEND(T6030_PARSE_FAIL_XML_AT_STARTUP)
     check_read_not_visible(XML_3_EXPECTED_DATA_1.c_str());
 }
 
-RUNNER_TEST_TZ_BACKEND(T6040_CHECK_KEYS_VALID)
+RUNNER_TEST(T6040_CHECK_KEYS_VALID)
 {
     // [test]
     // check if key can create & verify signature
@@ -271,95 +247,7 @@ RUNNER_TEST_TZ_BACKEND(T6040_CHECK_KEYS_VALID)
     ckmc_buffer_free(signature);
 }
 
-RUNNER_TEST_TZ_BACKEND(T6050_ENCRYPTED_KEY)
-{
-    // [prepare]
-    // to encrypt using RSA OAEP:  openssl rsautl -encrypt -oaep -pubin -inkey pub.key -in input.txt -out cipher.out
-    // to decrypt RSA OAEP cipher: openssl rsautl -decrypt -oaep -in cipher.out -out plaintext -inkey priv.key
-    // [test0]
-    // check if encrypted private key is present
-    // check if public key is present
-    // [test1]
-    // extract the private, encrypted key
-    // extract the public key
-    // create signature using the public key
-    // verify signature using the decrypted private key
-
-    // [test0]
-    check_key_allowed(XML_1_EXPECTED_KEY_3_RSA_PRV.c_str(), CKMC_KEY_RSA_PRIVATE);
-    check_key_allowed(XML_1_EXPECTED_KEY_3_RSA_PUB.c_str(), CKMC_KEY_RSA_PUBLIC);
-
-
-    ckmc_raw_buffer_s msg_buff = prepare_message_buffer("Raz ugryzla misia pszczola..");
-    ckmc_hash_algo_e hash_algo = CKMC_HASH_SHA256;
-    ckmc_rsa_padding_algo_e pad_algo = CKMC_PKCS1_PADDING;
-    ckmc_raw_buffer_s *signature = NULL;
-    int temp;
-    RUNNER_ASSERT_MSG(
-            CKMC_ERROR_NONE == (temp = ckmc_create_signature(
-                    XML_1_EXPECTED_KEY_3_RSA_PRV.c_str(),
-                    NULL,
-                    msg_buff,
-                    hash_algo,
-                    pad_algo,
-                    &signature)),
-            CKMCReadableError(temp));
-
-    // invalid password
-    RUNNER_ASSERT_MSG(
-            CKMC_ERROR_NONE == (temp = ckmc_verify_signature(
-                        XML_1_EXPECTED_KEY_3_RSA_PUB.c_str(),
-                        NULL,
-                        msg_buff,
-                        *signature,
-                        hash_algo,
-                        pad_algo)),
-                CKMCReadableError(temp));
-
-    ckmc_buffer_free(signature);
-}
-
-RUNNER_TEST_TZ_BACKEND(T6060_ENCRYPTED_ASCII_DATA)
-{
-    // [prepare]
-    // to encrypt using RSA OAEP:  openssl rsautl -encrypt -oaep -pubin -inkey pub.key -in input.txt -out cipher.out
-    // to decrypt RSA OAEP cipher: openssl rsautl -decrypt -oaep -in cipher.out -out plaintext -inkey priv.key
-    // [test0]
-    // extract data
-    // check if data matches the expected size and content
-
-    // [test0]
-    ckmc_raw_buffer_s *testData1;
-    int temp;
-    RUNNER_ASSERT_MSG(
-            CKMC_ERROR_NONE == (temp = ckmc_get_data(XML_1_EXPECTED_ASCII_DATA.c_str(), NULL, &testData1)),
-            CKMCReadableError(temp));
-    size_t expected_len = 15;
-    RUNNER_ASSERT_MSG(expected_len /* src/ckm/keys/EIV/ascii_data */ == testData1->size, "invalid data size");
-    RUNNER_ASSERT_MSG(memcmp(reinterpret_cast<char*>(testData1->data), "My secret data\n", expected_len) == 0, "invalid data contents");
-    ckmc_buffer_free(testData1);
-}
-
-RUNNER_TEST_TZ_BACKEND(T6070_ENCRYPTED_BIG_DATA)
-{
-    // [prepare]
-    // to encrypt using RSA OAEP:  openssl rsautl -encrypt -oaep -pubin -inkey pub.key -in input.txt -out cipher.out
-    // to decrypt RSA OAEP cipher: openssl rsautl -decrypt -oaep -in cipher.out -out plaintext -inkey priv.key
-    // [test0]
-    // extract data
-    // check if data matches the expected size
-
-    // [test0]
-    ckmc_raw_buffer_s *testData1;
-    int temp;
-    RUNNER_ASSERT_MSG(
-            CKMC_ERROR_NONE == (temp = ckmc_get_data(XML_1_EXPECTED_BIG_DATA.c_str(), NULL, &testData1)),
-            CKMCReadableError(temp));
-    RUNNER_ASSERT_MSG(5918 /* src/ckm/keys/EIV/code.png */ == testData1->size, "invalid data size");
-    ckmc_buffer_free(testData1);
-}
-
-RUNNER_TEST_TZ_BACKEND(T6999_deinit)
+RUNNER_TEST(T6999_deinit)
 {
     remove_user_data(0);
 }
@@ -370,8 +258,7 @@ RUNNER_TEST_TZ_BACKEND(T7000_Encrypted_initial_values, RemoveDataEnv<0>)
     std::string messageHex = EIV_ENCRYPTED_MESSAGE_HEX;
     std::string iv         = EIV_MESSAGE_ENCRYPTION_IV;
 
-    copy_file(format_src_path(EIV_TEST_XML_FILENAME), format_dest_path(EIV_TEST_XML_FILENAME));
-    restart_key_manager();
+    restart_key_manager({EIV_TEST_XML_FILENAME});
 
     CKM::CryptoAlgorithm algo;
     CKM::RawBuffer messageBin = hexToBin(messageHex);
@@ -386,3 +273,49 @@ RUNNER_TEST_TZ_BACKEND(T7000_Encrypted_initial_values, RemoveDataEnv<0>)
     RUNNER_ASSERT_MSG(std::string(decrypted.begin(), decrypted.end()) == EIV_PLAIN_MESSAGE, "Data does not match");
 }
 
+RUNNER_TEST_TZ_BACKEND(T7010_Encrypted_initial_values_asymmetric, RemoveDataEnv<0>)
+{
+    restart_key_manager({EIV_TEST_ASYM_XML_FILENAME});
+    constexpr char testDataStr[] = "test-data";
+    const CKM::RawBuffer testData(testDataStr, testDataStr+sizeof(testDataStr)-1);
+    CKM::RawBuffer encrypted, decrypted, signature;
+    CKM::CryptoAlgorithm algoRsa;
+    algoRsa.setParam(CKM::ParamName::ALGO_TYPE, CKM::AlgoType::RSA_OAEP);
+
+    auto mgr = CKM::Manager::create();
+    int temp;
+
+    #define MGR(OP, ...) do { RUNNER_ASSERT_MSG(CKM_API_SUCCESS == (temp = mgr->OP(__VA_ARGS__)), "Failed to " #OP " " << CKM::APICodeToString(temp)); } while (0)
+
+    const auto rsaCrypt = [&](auto pub, auto prv) {
+        MGR(encrypt, algoRsa, pub, CKM::Password(), testData, encrypted);
+        RUNNER_ASSERT_MSG(testData != encrypted, "Data not encrypted");
+        MGR(decrypt, algoRsa, prv, CKM::Password(), encrypted, decrypted);
+        RUNNER_ASSERT_MSG(testData == decrypted, "Data does not match");
+    };
+
+    rsaCrypt("/System TEI_RSA_PUB", "/System TEI_RSA_PRV");
+    rsaCrypt("/System TEI_RSA_PKCS8_PUB", "/System TEI_RSA_PKCS8_PRV");
+
+    const auto sign = [&](auto prv, auto pub, auto hash, auto pad) {
+        MGR(createSignature, prv, CKM::Password(), testData, hash, pad, signature);
+        MGR(verifySignature, pub, CKM::Password(), testData, signature, hash, pad);
+    };
+
+    constexpr auto rsaHashAlgo = CKM::HashAlgorithm::SHA512;
+    constexpr auto rsaPaddingAlgo = CKM::RSAPaddingAlgorithm::X931;
+    sign("/System TEI_RSA_PRV", "/System TEI_RSA_PUB", rsaHashAlgo, rsaPaddingAlgo);
+    sign("/System TEI_RSA_PKCS8_PRV", "/System TEI_RSA_PKCS8_PUB", rsaHashAlgo, rsaPaddingAlgo);
+    sign("/System TEI_DSA_PRV", "/System TEI_DSA_PUB", CKM::HashAlgorithm::SHA1, CKM::RSAPaddingAlgorithm::NONE);
+
+    #undef MGR
+}
+
+/* TODO
+ * - RW/RO location support (files removal, flag handling)
+ * - item overwrite
+ * - backend attribute support
+ * - independent tests
+ * - different formats (also encrypted)
+ * - complex tests using ckm-initial-values tool
+ */
index 92fe3fd..e40a026 100644 (file)
@@ -1,18 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<InitialValues version="1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="initial_values.xsd">
-  <!-- if EncryptionKey present, the content is an AES key encrypted using device key.
-       The format is Base64(encrypt(AES_key_binary))
-       i.e.:
-           * RSA-OAEP encrypt AES key: openssl rsautl -encrypt -oaep -pubin -inkey device.pub -in encryption_AES_key -out encryption_AES_key.encrypted
-           * encode base64: openssl enc -base64 -in encryption_AES_key.encrypted -->
-  <EncryptionKey>
-      QL/5RW1VfS1uya04CWkVy1eykdhnRaTFiQ6Lcv0XFYhqgUKp6+PxxT1xjaz8TCVp
-      UcKorZayMPCuStRAylViZfxHFhXKR3awH+FcnGMZrhV6kORy39YCba0NGc5eAk3s
-      CBPYdRRiV7ejJSOI8n3zFjituVhHLcLuZB6xHvQQpQFFYV0BuF3BXfx6roP4+Olj
-      bZ1fYDrj8QIzqi3RV/ORGbl1BqHVRoMN/5XB+8oVKVn/EMRZPao4hnkV3pTI01Ss
-      Wid4fIHzBpi8rkkxr80/ym2BkeA/piaPNGOQtKjVfBOn/SuR2LQJreG6QbI6MYXC
-      ZVOanzc0euaenw1q9b+yEQ==
-  </EncryptionKey>
+<InitialValues version="2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="initial_values.xsd">
   <Key name="test-key1" type="RSA_PUB" password="123">
     <PEM>
       -----BEGIN PUBLIC KEY-----
     <Permission accessor="test_label"/>
     <Permission accessor="test_label_2"/>
   </Key>
-  <!-- key below is encrypted using AES-CBC algorithm.
-     The key used is decrypted <EncryptionKey> provided above.
-     Encryption:
-       * encrypt AES CBC: openssl aes-256-cbc -K `xxd -p -c 64 encryption_AES_key` -iv `xxd -p -c 64 encryption_AES_IV` -e -in data -out data.enc
-  -->
-  <Key name="test-encryption-prv" type="RSA_PRV" exportable="true">
-    <EncryptedDER IV="X1RoaXNJc0lWRm9yQUVTXw==">
-      BflJyNgOcGyJSqTegG+y7MJXI1crgsGY3PjFfMpbmMbwJkVexvxoEPdf2yE5Z7da
-      6Vp4Qo2WOCUv/hllNTfm/dH7kOJOjcs/vaV1eRIfzEx3hvgKOyP82Hhkm1POynsF
-      0GyMm/VwtJFwFHA5DaJzwLln2/AoD//vC731Qhucw0Zvi2hi74d6igPog9EugIj/
-      tStvpgiNE6/Hb2ZRMDswgZ8o+tKCn+QHktR/YoZ19HfX7nDVRkMQxsiA8P4zO9Do
-      +iuiu/mGPVavlZA3df47TLG0kz+sz72jzPeEbfmvQo3gHWSuJ87TUwIcIoXDvaxY
-      xE8/On5OTqJy8HZ+jGvEThKI/96LQsFqKlEeGGenvzVJ+BVAF9x65uOkRll9yE6v
-      FIQcqbgipuBkdC6XLLaWTMgs5iiWvMn/lpNYrfZr52/TKqr09mNdei6yGvy+YuG8
-      vu/xN7/3An/zE4FOIJadgI5eADj+Dz7exml3tKTuuDpR9fhxiXd7HmZhCCf11C3r
-      54S6X9bZb7335L/5UfLxs4jMMfGhYD+1UF1Qb5zVW9IVMZ+owGeC6QQPUiX6HAxy
-      Rx7kLzd78uSbLNqeuiUeGiprxnuwMY2BgSqLq4WNCDWxY4hGTdkC7yg6DgY+L9Lz
-      wqVuJ6STmK9Hj9bL9YUe0KrzmVUfmsaq5PL+gfcv+S5lp2YlKw1cIVP9utw1ZuOo
-      j25EozWU8J+tuEa3l60Mmmh/sKzH9SH7C9EscwTYWOYjYYPwfCM9UIlNE9lnbl9s
-      bzkqJvaaXpB/HVY/b4wrldr1rK73+y9LOOzfNpV4L+R4spZXXjZ2HIW/iKQj/c14
-    </EncryptedDER>
-  </Key>
-  <Key name="test-encryption-pub" type="RSA_PUB" exportable="true">
-    <PEM>
-      -----BEGIN PUBLIC KEY-----
-      MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMP6sKttnQ58BAi27b8X+8KVQt
-      JgpJhhCF0RtWaTVqAhVDG3y4x6IuAvXDtPSjLe/2E01fYGVxNComPJOmUOfUD06B
-      CWPYH2+7jOfQIOy/TMlt+W7xfou9rqnPRoKRaodoLqH5WK0ahkntWCAjstoKZoG+
-      3Op0tEjy0jpmzeyNiQIDAQAB
-      -----END PUBLIC KEY-----
-    </PEM>
-  </Key>
-  <Cert name="test-encryption-certificate" exportable="true">
-    <!-- Note IV differs between items -->
-    <EncryptedDER IV="SVZkaWZmZXJzRnJJdGVtcw==">
-      pPjY7wULPaBIwPKkgwKyKSZPa6NVJN3312q829KaXcNdQSoNJmsyyPDMqLr1W3Nw
-      /5DSfstMCh/MiUq4Dc1VCaHbVkRFVZMvitg7nfjDVkI9HGLpSGWzz1dc6kxn/rPv
-      l1Ox3sVog96Ebss+Givm4cKKYSQihCLTxcQcP6v4RGvTMhXIZmlz8n4Tr3MgyRB7
-      XTWdoowosEUWrzPMSD39y18gRJVZ/ZKv68o5mntatSE8FS1L6dgb2TdKEFdydVd2
-      /ob9GVwRkMxpBsQeUvPRYXnZS2f1L18IRPrKLKLKsDB+FysyXMAHMaxGWWil29/d
-      osOwMt34i6Bv21132lGt08t2LebmDJViZRVjzz9edIChBzsoG/E/3hX6v32ruJGU
-      2kq5l0bOmpQFs9M0TTNNWnaZKvpFPA8b3ywaDRWeKAPHsNQpnrx0WygCmvbjUChf
-      TP1E5BVm6YjWxptvFvEINcotCj2+0fvG3zIcq01O/MpSFWbGdu9MLZtFl1rTRt8e
-      ER8+nOKZNi9JUOfsYJyrZmtwm56LXTPjgNYY+a8yp2EXFtHjO62QKYr8zAi98PxL
-      oiELHLF2xwFufvBAssSOPwRmDSIhljPbUy4UKUxFCeMJzdxgK0DMZw4FtcyBXGgG
-      ABP57OQ60HomoZZDwAQ/4B8unuOCp7uERsQH5Z4Ns+PiIM4Tk8j9Qg4YVN43FJtJ
-      tCsfagBPuQM+Cm5law0Y01asMr0wq/VlILMKX0KXpwgnVmQClRfcYBLHQmDTyCos
-      kYSWrSYDesvXJnB1j/hn1puCQHfyrmPH5fQTzanD5whyed7DeXBl+F5+f73uj9pC
-      DrtqG+YEOeJNj0PCAMq9B4Qe6xi06P6D/sG17Phl9wH5DSzfxxlst1xeaPBko9Bo
-      LM6Sh6echKIh0HddStmaBICXNeVKz958tD0piVYMVipZm5/+cpDxdGSuemUxWXJO
-      XAuYydZkuLksYjLyXDO5vEaqcVMtu54tjfdFS7vO87a9IF+mI7HHHdnNaDRHaAFi
-      4rXdaGQr8zohq91NE3JYgSMbk1DlGfL1m9GN6IEUjqMQlAkGWal1Et9uwO98PpOk
-      a+r+N4lsYPKJbX2ywUvDHg==
-    </EncryptedDER>
-  </Cert>
-  <Data name="test-ascii-data-encryption" exportable="true">
-    <!-- this below decrypts to ASCII: "My secret data" -->
-    <EncryptedASCII IV="X19hbm90aGVyX0lWXzJfXw==">zuBDjp8ptFthrU69Ua5cfg==</EncryptedASCII>
-  </Data>
-  <Data name="test-binary-data-encryption" exportable="true">
-    <!-- this below decrypts to small PNG image -->
-    <EncryptedBinary IV="UE5HSVZQTkdJVlBOR0lWUA==">
-      weK/LmGIPHeNA2YipqJa4K1+KPkE/Jl5EtfJjzP5x5ZGhf/OOTYe+fj4p2Wx47AC
-      Nd/heOAi3MkFrwu5x+swFMIeQMCMzQpRbXeCvTEuTXWnmRMoyMbHlPd7Nnk9xooF
-      oYfbKhVd5DOcHN3pwc+5DQkrRy/XaD1faj3YR3JEYSfOLq4F6hLlj4U7rYJyyFuf
-      kSBOTAQOXs0q83cc2L7RaK7OzFJPKYJjDkVYIakpIHXUcvNrb2DrJ13se4pcX6Zk
-      KARviziVu4x9r7hTRErU8SNEWrO6E63oDfyetWvtymT17MEhRsRKS39zhrVLHzGy
-      iWx2Igh6eH6t4UNkMIHZvJW4j8hxdmbRwhQstXrVq7Uyne0B1Fl2w7Lpn48jYEq8
-      gaNlTZDzd8Pjz2ByrRq3/jln/xWnFwEY9oV/H53j6ctoJ2KUMiVYKej8anan8Fju
-      yO86HVEIYx++LblhqzuaqBhveVfB/feMYWpP8hi4AeWKcAGdM3L9QOYxbQ9OAOuC
-      Totu55NULkrzb5b+Rr+exTFpdEyic7sSEpBRV0vi6t/Lz72ebBq1oY3kn0dzZ6Ps
-      ia6ccITSdHW1MmW7cOkiA4XtyfvXtZtEJgmVnAnRrj4Qh0Oa9gxNOZrY/tlyyJod
-      v8JLYeBi3HRSlm2TME5hCHpBShVCRpkjLMQQ/nTPHvRNqr/BlPoXZg2FbJwreEzW
-      NZ2BaiKylRds5gnmmSnqnYUl4QtVSGsJPn8Hx0bNWwUeImjrXO9Nm01P8e5Iy+Ti
-      udxXTwpxZGyK2pbTs6EVxFY+fRF3SB4xcpup5fB6NHVPjiSrWABN848OReny3iS0
-      FXwimWaVzmA5Ppnfqx1HGopmhH++oZyKt8W/f8GbhOffON0Gg3bsewhysW5Rz+Rx
-      IAGqzV5RR1lOb+UKPBI2OPXqYUWZ9ipicSw1LC39olImBZbDmmxLDEjX5r+rg77h
-      ss0hG/6847KQybmemJ7zUVE2oxmic2fONpgjn3OLecOZpUY/5n/1cvN8utLBJ2nx
-      asan7zBT+nW5RjAny8pOyyV1Ux2qga/CyV46LajHJiFPokAAl6JnDYRmahtA5BM0
-      +jBvvnvSDGSM5qTh0EBLIN50WmN2TeEy/u2ZjuHFwJ41gtB6pARdJ1OT59+g5TcA
-      Ffc8twDzdbPbmWq8CGXVQHCvfS+2N2ECjwgnfVL1UZF69d5t9b5ysK17pU+ITPyI
-      Bxxde23I6U7sh2owrZgRAOVoA804flRg6g6rDJyVfu00oDkuui+Z/3RAsu6EiqiK
-      XISmLg236iumsxXcdAtOYyXn0nPZolsZnxzY2/bI0Df7rNSQ7RF5SSqhkFg1+OYT
-      gM4wMYYU0ts9jqr3ckJRWMRMdJxRsVVqSBo4fz8M5/dXMsOvGbLfnbwrqZSPCXrg
-      g+MX3QQdemmOgiEAGE+hxFBQMyQ6nIrDP061F4TVVhu4kGkZGxs/2W+CcQJT0aF8
-      DC0EwfEBVP8yq4ytCU7Js72KkA4YsK2udUsQF/90cuzPSgT8FPDEOzszKsLGuct4
-      T7Fj2Du1bVeVq4gPfdLgOdVRrZLab6vS5GFbli8UO0oAbM/Srxfh2Ghn4zS7Ol3q
-      MnwX36r3+KFNJYkBxCDMNEnj/QrSWpOlKo8LfAyGdvP/29CpmzPIGTUc1u8xZpJ0
-      CmFOaxjaAFJH3BjW625QbcicOnN02p0Pv00andcDNEO4k3b3MgW6yjkDBKqQ61dz
-      traH19g0fFa0pjXycMqy2uwq7PhLW0QqYt4Q7cfvWRMnAOwJqhHOGGyzEixB1U5c
-      q4d8izdqb0JacE6px+WJ44a530L1nhy2O5jpaKVQmNYIKTBM+HYVuHNWTWmnauKP
-      ag4q8G+9EI/SRp9wKoGy81W5GwonV3D6/4N9hnQfqqRKUrbrhWc9NcUciWKh4b1n
-      Om499jdDw+7qXipi3ggPCFq0H3b9CPkKMFh4Y/YDy1SvXEDSlwJ4bXXakOpVzW9t
-      gDxk/fvZ8AHrFAYzW1wiDFZ8H5ZnhgBMyfztLOYBbjr5YSGej++Sq0DYoOkrK4X3
-      7+2nMrrhqmlukI7ufoP+8nsJjHdQK8yoQYGmwEEw9QHLyupqPVIQrO/VDgSN+6mW
-      YsulTKW9wPhk6dvsSMOscLUdDiOTeK0jGH7Qa6QQwk/u/agHSPWh7qLpEICjKBxx
-      pOMbZ3mGqTXIj+7tG0yO1/y2UXE6JTIXiMEvMmdCEiRcz1RJ6xx/aBwC2//tfiys
-      nNMswTCXePtv5P9Zn+ibIiOhpm0napHopQcqmevn/DSkxSuDfwevae3bgEcJ1gN9
-      pkTnOm22CQzoGJY/b0wgNvxXdWhAAfeRhzpdh3V1C4dZEF8VXHDDt5gdjb0s1fNI
-      2LiSruLVdAWmRNX5mrkUFfBOzWwsN3D34pG2Vaj6GuH8mAoko68oy6fUdjCjZooY
-      hn+u5bGm1T8Mf/YYloTWg4hlOWIEfOiLP7nCdCgRdsg+y0Gi5MY04fS29SlfffUp
-      VUdLzQAij+a/wbBLJZMLzJiYeHv+pFY6m1SbMoUsDbAo4PTRaLHmMOFKa6s/hlka
-      lfN408DHSNs63Gd6s3W+Owe5hMccfKyRvWdNRVrXBe39I101Sci7GwWAvHhhS9EP
-      2HxxNyiwF1OCovnRHcm1b8Fcd42gbAveRVuFdI96dbFIeP0Z4I2gj+nk/yzlsG32
-      LYYzE9D4WR2zjrTyVnylsJN76lyvjvkYjMt7fPt7lFYz7QLdZX8riGxqeFmim6Sk
-      UQ4RXxw/ObCw4omILxvgigW+eAhgng63Yb9mRDOrqk/cL5XECiahSs3VWTjV9sy2
-      rNSPViWZW/LFOjuC3cT5rWEbc64cl0eKJTivEangOXxirRGW1ltTlzQo5kA933l/
-      sRMr2tBSrX/+LqfPWNA8UZWSdMBcc0oDvDGrpTUtLcor5kshYN7PPdaR9TAf8ikY
-      631mOef0HkQFsBUCFp9sr6QJD0/cfLlK5iLlyt+qFo2IgX2boddFwMtpYCt1+Uy1
-      H2u6FuItIfpRu9lZ7MZf24HGibGx5/fzTXjqGMObPOaoLxI4eh1GGhIfVqmT9ntv
-      e2xHoNH+tLxOHPRNHEkKRtJoB1HH20+mT6JzEdPNPmsdTcN4R0xjw0ZHTha2iBkt
-      ocGow+1nYgkoieq1QweEbbCbF71XtUpyMxMSd+BAPIJJReRGvt3mD9RZ54HqlczW
-      MA0LYe1rUX0Mh2Ic0x1rXZuo33PXcsKsUpfb+EIPhBjpx2vCNMiFPcM+F0NVh/PP
-      zgbdjlnHr6DXn3rut6Y9fTau6UY8BmeOjG4LcNzcvcHHr9/8jXyW9wWAYYVRUI3J
-      89/GR+YxW4WGuRBIV+wMkzBJmP7QDwAedSNBSAKa+08GKfJJRL2zIVgjffeBO+Un
-      TMTT7Q/a3bm+yekGsM6bchWTpY2ywdYQr936D55THonqCGlvPKyVHQaEa4U2eFDb
-      aIH84kP4olPCcC+TmWHBeBwMGvbW160hRCr3kSGY7hHcD0aXkdZPh1bYyWsIz/yS
-      eyUYCR+4Abu9lT1rTwHiSeo4YjNHOwQcfzBN9BwFUs6G1R81oC3qCwTYuJS2Eo09
-      +sii/oH/o/7VjvewMmUzDHVJ4iMa8yRXtfOObrM9MfsQ0p9GnP7UTG3VwleIenFZ
-      43DhvDl+kolw9phRuyCuCy7fSI8e7ejcQ3gSYWcIcgIIA5y/KdoCJDNdTjj3xDdo
-      p+hzg0OTjK57Fw286IVdzO5e5zznX0SPqXnZYncHHl2OmGZ+DT8ftkvD4BUJ74aO
-      fLsVwAZYJT1tSG2ymzu9yJR5p+hPTScpPi8HUDCnL4xL304Lmj3UfDauNJQcM/gT
-      mAJ/bfEtRqldMtN1EuH1TexvSkwkPrTUkryq2TYcw7vS72tNi+g6aZ7NdrQ8l4KZ
-      ZmrfwFnKNiVWus+zrffSDooEFZ3mj/vsFvV6fhw/Ni4QD1XAb0fJawUHvt0WHqZA
-      YnszBOzdmd8coJI17XbcwcP7DEoKIhLbPl1n0KNjL6j4EEoClwxZC+hAhi8kKMB3
-      aWj4zpeIExYST8NgtCz44SoBTv5U0iCR19mhdcTnafGyRK82dGiBNguk8//siUiC
-      jt3Aa7chapoiQNwZGDCmSrZOxOoxMYlBuPRVQqeokPinsw5rkLh8+arz1XRDyuTK
-      vQ+jttyIVA9OFI5+e/hN0ryn4GPbiCG5wV5SKweRUCcX9m8TK5u6A3rhMvlcls3T
-      INn9/XjCX6HhVGgZ47LSmcZ5ojtWzOKpad0v8qjD3z2BWzUlbalgYsdWrsRPSeDA
-      wiGpKbqb9u0S1e6hMmGyNa8UbzhYtJ/AQ0qh003YR7j+nlfJXffNkt2B4DkDdsG3
-      Alfhalwn5YUdcgm/6E+gnIg7JR4gXZhBL1R5SV1mzUgzyDEq5w2LBOx+TU33a3qf
-      ld0dJDJl0cG22n+GzQmm/6nPMnWX1ymK49h0tO9fLBLZsL8T1muo/PshhjhIv5VR
-      9ET5UN5I+9d0nHWAv2DjNwetyD3WGZDHnuq0mpti58xzkOr4jfYqy9qKwFk/coAu
-      Briwv8OJ2U5XEOuU/9fEL+NdYWkHga++oObyxJUU5Qgfs6OWUXERyPwzgXHkbDqm
-      q6+GP1AxBAP32zD0XyGUht1nl+L5qpnbOpISJjMMrl7wuKezWbFAE8VzQNbbp62O
-      eI1GEX2c2resPXZ/tS5LtoZ2TrT8TKYRZ0k1qLuQhOTXXNYQhP8i4PGOAL6BMZsZ
-      USAEHcAZnlByBS8i49IlvJMewPfHmm7ceLu8aYlm3yOAr1QBNRMkxoJBXjAAnCCx
-      qCGIQtINrVIJNQDSogMPXa4JQzCRSsT0Hz8ejQeQ9xmaK4VjM64VRj11RWsHFexk
-      p+GdAGVteipz1xEQHBvnUdOVm/5ULHK+8w+5LgEwN0jGXlsQ6KhUX5BLQMWob0jL
-      1np3Hml3MDxsPJPJjT4OKxNdWyyyP6PIDZj7DFqEa6+9Eg5Io7TSNk4e+LylfpPS
-      orsF2xaUzCaKOXjyXwPrW57UH8HtjnaeWh03qqdZCozCDdQ0pNpPk2vJYStZR/rY
-      BpQHZ6kZyLFdqLs+wMoPphF7q4bhjYk6MXwdHp5Q9q+MWPuM916g6vKaHUX+q6pL
-      YM8s13NkuUX1hEHaOC8I2dEsgcVPk++kDAR7JL5tn5hfJ06K8u5IHwuLUMtLKPt5
-      ZA3LfrnXxqlZD164blhAvb1qPlRTh79+Tj+3zfwaUPma3PmTY12fvJiOn1aD4aYm
-      HgA0yrl2cApzB3C6M1S2QllsoJ/KrWVeSg16XuC+vjSnsRWgIj3PSvSwh9YVZT0h
-      TQlD/PoxrMOlPtQnpHzryQ8YKrTBc4SAuO23wKGkfUBkaBDFrUeprO2p0K9Eeus9
-      jLkIgwTBwmF9bWMi214VdAI3I2BrJkGnx8Rb11C6rEu/5ZeI7g2dACSO27OhckNQ
-      ex490kQvqs1OJ6Fb/CyO8BsLBIyOhkEtglJsVibbcZrHnvoRYeRaWZj9TNdN6I3B
-      Dj0SwxDK9XAwGgWb+E4iwFUUg6yGrbBhUDWv5K7/ncgXz8iESXFKRowuD/J7rriU
-      V/s+yZ8URntBrZ35unuKu4xRieOEkn/JZg+HP0Grs5q3OQumEvZVjHqeJt40WaZ5
-      RJ3NiiHGwWVa6Db/1q0cfETbTn5Qcy2k8ZE+OnRzAmI14nr6lt4eJRnMJ63k4nGc
-      Xj0WpVm7vhVWAQ9gfiYCcbYrR31dUeOBxsRtF+Lvg3TNEx8/x4LeGfxC9c5Ho1Sc
-      Z7fz+/ZycHFx+08W5Mb6PlKhI44uY8bed2Xz5gQhZ1hyXk6Y41uxabUryeCvrLrh
-      PJX25FkOcLhZnWDcyCQ1Rt4JltnZcZzHq12Ipgovos3lPOarySOzSHjs1TjB6Bv1
-      zfBrCAGiY3rrG/W5gXs5eb97dWn5P8CD2uuZCBbTo0GVHdSHV9+JFHQO/0udmnEV
-      e9KRka43HU7AC+3aLeCq1KMoW/anl4DwPXdBCV6hj75TZ0EaA7Q51ETYFCLtyXzt
-      eiU9PE+bEymV6nk927wg7v38GLmdLTJ0F/G4MV0T4UxAdUrsAW33MGXC9/8YyOAz
-      zGh36fBdxTpM6hb1FHJl/tdboIAcTBJRobgmvhaDDVhsJiMJMwRhSFqcE7Q04c3c
-      6rLNGZQ3/u5/Atj5ApZ60ZMH0N5LYcTm98HOROGiFbrYSiSqUyeoIPvME5FwijLw
-      eCxbwjP3WvUSw8XTeIoAf5QwzdI6GRX+6ontCvw6m3l1TohH/ACA+MK+qV1cTgMV
-      HdjywH4SKs3KfwCcTF4gxkHdYlNYDW63Z0lhAtDBXMxUNM/u215Wo+zX0gaSUqeu
-      by47hfhTHP5mW6ITRFvKcS/qUqo3iELljwSXhdw7PwM0whLnSEMGsYh27YVxEzBT
-      n9vcM5tqGykKs1wwmpXpEa6Zliu9swprpQCL5TcOVFKVMjSmDH2OwmaDwcFeTM50
-      mg7BpiA5xLyQFphs8BPbyzkxNlbSI20S67Gx6yScrjsDxcEcVqmcyVVPwn/SqzVL
-      PyklAUbvRcRzkhvibBngIaFUfXXdCOrdQc8Ym/5kKeQ+QLiXxfIYmYKa2uyvMeTe
-      xoag7cmuUnICIYBrmHnVDNxXtC9mNiooUaX2S1lH2ct4s/NwRJm2c5O/igKO/byg
-      wQjiGqDZHyLlPSRxXbxG+tTf3qx8thYbJAO0r+AXYRj+sjJ+MtRozgY0nUeFEJb0
-      ZeYQGlvtoXlGo876JWJ/e7JMatHxGGQ58vJApMTphe/PPh3WTJTE02Bs3Ylft2bp
-      EK5ODopXJ0UmQTn6T1hUwBRu9RO5rICr34XnFav06WekBT5/QTqHEvZ4k4//hvGr
-      d7PQS/EVLApiYWySLg56svmjn4RwfPSPHOwGagU311QOx7woYJD/vb4NBxXb99Qb
-      7z42exUoZgqX+uKwHCuTzH/OVxhqrSoMX2yj09V6ZDUVHU11GOtDzVv07OU+u2vi
-      F0wPdrbedpmIr5BMCdCmqlIPYeBiaMVa/2+q3ud4o6/TeWmQpDZJCQ3xtxrNORQ7
-      HTlY0MDp7G+sdPWJCN5OJ0Ac7uKW72ZC/5yHBJY7Lmrhi3V3vA+DH7A4GgPAphQM
-      yWlBP7sQqVWcA1XlgTycRzkfffXEUoS6qef+IgU/3i/kXmeNnf2kSvmtbiO4GRhC
-      Nhk2s71NUtYXNFJPav5/ZPXI3qOuySow5GYp3njGYmDhO45IzFCcQu40FqiOeyoV
-      lRYTS/BrybkMCu2S3VmIY9/2e7gguYigmyZRvvqOUED9JRqOfC14n5+wtxzSj/nw
-      xFFukVHQRNF6jcZLUNs0SoeFS/obPCE+QiDYBKVrTeT54LuwNLpTrgTnTkDE5VIm
-      LpX9ERh0Yh8HAO7eLHIPAiU/G1Etlc43GcDLN7bbGPQbCvKRzWKSUrLwKmryvTPi
-      eC36fh/yZEWtT2zEtddwbncRgXT20opzMJxB3qF5ZMQ1qLIsQbGYeUsRl9lxsT7A
-      CE6vCP235+urdA9IaBRPN1VpWDpV7YDbF/ZIkRDJevSnSSrBTed4WcXcSe7JNGFb
-      U3eFPi2vsekvb59CHqHPD8QvvqF3N/3Xp1uQZV+eBOCtRpMOZduBJ6QdZlGBaGrB
-      +RKJEl9ziqGkiqiQzw8MR2kSrRVKIs5cISbl/dOEqfkbp2A1Siy4kWt+2Zk5V+Sw
-      IPJDrjYIZKSzV6XhhN+fhMNOYJjByxEXXLvHRTydIUQpS5JPe3T1sMJCN8o41uKx
-      4g+oPomYfJzKSbdpP84fVC4WQCMj+CiMGz/dWV27LgKPF0X9wel5s5gke4UDYQKe
-      FDf/4n3+neMgKohFUIcnqGnBTtThXqvK637m37WfQTIqNWkRH4pU/Acl/djkd+TD
-      yYRBt5UqwGovABM08jYkuA==
-    </EncryptedBinary>
-  </Data>
 </InitialValues>
index 0c3a76d..ff84dbc 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<InitialValues version="1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="initial_values.xsd ">
+<InitialValues version="2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="initial_values.xsd ">
   <Key name="test2-key1" type="RSA_PUB" password="123">
     <PEM>
       -----BEGIN PUBLIC KEY-----
index 2fcb32a..c37883a 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<InitialValues version="1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="initial_values.xsd ">
+<InitialValues version="2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="initial_values.xsd ">
   <Key name="test3-key1" type="RSA_PUB" password="123">
     <Permission accessor="test_label"/>
     <PEM>
diff --git a/src/ckm/resource/device_key.xml b/src/ckm/resource/device_key.xml
deleted file mode 100644 (file)
index 30c162a..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<DeviceKey version="1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="sw_key.xsd ">
-  <RSAPrivateKey>
-    <DERBase64>
-      MIIEowIBAAKCAQEA4Vx4MBKFGalaRh+BzSYnW8am8ajbnyD6AaweHcH+oAAQX7Ll
-      1/XrorzOkyQV3+eo4czRCklq6BXMI4Ppa+Hy+/X/pMBa4MHrjzH01gzzV0jyqEOr
-      S6/MGPsoWUgGl6FRhEnSX62JQoUpsURMbNLgjBkbrmKEMHMk6jT5NUtKhpBXo0/g
-      OgW48PuADuSjRmKWQssfR/KMsv3SRy9iGFOG1tFxGbeQkmBBxXVIr7u/z9WDG32R
-      DiG8Mda8dNXJGaBcltUY9HvMogmgCPMrBspFy7ek0x0Lll3t1P7FMgF1V21PFhcl
-      yX0L0XbBthpYojjglCYT5MnFfhKnI9zbMLlcSQIDAQABAoIBAGnH57pY1xUGgxMr
-      MthCsnLHuhDwu7Xj2rXyPmilaIldvlHNPUmzaxmGGkjCxWnF6WWjp/N2JrItmRaK
-      koRLGKzf+VEx4PZiz9j1EAFxLr+nxA7rRHpQWDLZoUTXJBEEbaj0pcS3RhhtPPay
-      IlVqXnAkUPP31iiPw6ITn24+mwqx0I6AenMsh9vJHKl5y9Yu/aslYbwcxkSXinlO
-      HHcWopZlJKUQnqlwJ6Xk4e4hjwZn7OQN2jQWKT5oQHO9tEUARqF8waY9yVfUSpjM
-      mw+gvywAoP1cT7M3q7MsKRNlZsrrC5zYWJ0ev4TIEa+zooqQymZoYeCd8s/77gsv
-      l7nz/CECgYEA846Xp3wWci8auSUv4SrqcjFZHz3YTqnPZzEf/U4nfFhhwzDHgOHD
-      u/M4gmEIcvxukhGO66/fqNnDJKQeu5XzgOKKO8/YCkjdIvULKNIOijmucx6oKn+K
-      4AIIzTYaI9Ft8+nOpfQV78+xnLGxiUamp8iRJgXei0RcISrEuw7+LQUCgYEA7N/m
-      Xgb1wkkrFp2fefTD6/5hGWizx3yO+jd+LXBRrPJQOvcf3Wh8jrEpWkeuUF8JYBZP
-      IOqc+TmbETuRUiokoYCihJKT0VkCqKz8qjUq7IwYf5Cx0gfEVUk3iyt3yTlJe9RJ
-      hOXV61PPtaebzg7MYmDfAkSU0ScqXV6Gd5Dl9XUCgYBprXE4Bqtml/Gsa+o+dPSM
-      38SfvaHhX+TSDYqnygVv+plQrBWkYlEfeAUI7TlRSx5e2qd8tC8DgJkfiOac1g91
-      2NXJ5gEDVWI+DLzu1VXhu+1pnd+xsO19DOTsxZDKAdEHiGdVsnbiOugB6UfzHGir
-      XGc+bEWHf/3JllkOIQ9AUQKBgCnL6C43NC4wEvZOodE3K0r8+80r+Gz+wYvNNup1
-      ozPNHfMJoAnFYhUblZxkgZGU82aNCTFZtJEVZRNJW38QCJ6mwAZ8hrCt8BYrT/oI
-      n6ZVog0ATyAsVqxl2vMnnF9ZSGodL0vP8ksv4rq+9HMLkWzagv83crrlGkiXYUq/
-      upPxAoGBAMrq/dAyhHKaM84C68JDZNuzPt/flAEgIf/iCYwHDKlWu0W2PmN9ZFbG
-      RkeC5ljD1V2QodLF6BZ+LWbK7aY9OGQR37tdm5whxZo+CqmQZ5Bybnlkfvo3cEPI
-      tW38eiYAnPQ3zy8WJ6if3Q+y+vaiM15C/MMVKyXAGcyop1qFVYAT
-    </DERBase64>
-  </RSAPrivateKey>
-</DeviceKey>
index 4548d51..3dff3d6 100644 (file)
Binary files a/src/ckm/resource/pkcs.p12 and b/src/ckm/resource/pkcs.p12 differ
index ff137b1..5642a86 100644 (file)
@@ -40,15 +40,15 @@ enum RawCertificateID {
     TEST_LEAF,           // TEST_LEAF, signed by TEST_IM_CA, expires 2035
 
     // third party
-    DIGICERT_ROOT_CA,    // DIGICERT_ROOT_CA, (root CA), expires 10 Nov 2031
-    DIGICERT_IM_CA,      // DIGICERT_IM_CA, signed by DIGICERT_ROOT_CA,
-                         //   expires 22 Oct 2028
-    FACEBOOK_COM,        // FACEBOOK_COM, *.facebook.com - signed by DIGICERT_IM_CA,
-                         //   expires 22 Mar 2019
+    BALTIMORE_CYBER_TRUST_ROOT,    // Baltimore CyberTrust Root, (root CA), expires May 13, 2025
+    MS_IT_TLS_CA_5,      // Microsoft IT TLS CA 5, signed by Baltimore CyberTrust Root,
+                         // expires May 20, 2024
+    MICROSOFT_COM,       // www.microsoft.com - signed by Microsoft IT TLS CA 5,
+                         // expires October 22, 2021
 
     // ocsp available chain on third party
-    MICROSOFT_IM_CA,     // MICROSOFT_IM_CA, signed by Baltimore CyberTrust Root, expires 20 May 2024
-    BING_COM,            // BING, signed by MICROSOFT_IM_CA, expires 10 Jul 2019
+    MS_IT_TLS_CA_2,      // Microsoft IT TLS CA 2, signed by Baltimore CyberTrust Root, expires 20 May 2024
+    BING_COM,            // BING, signed by Microsoft IT TLS CA 2, expires 30 Apr 2021
 
     // footer - last element in the set
     NO_CERT
@@ -85,11 +85,11 @@ RawCertificateID toRawCertificateID(certificateID id)
     case certificateID::TEST_IM_CA:          return RawCertificateID::TEST_IM_CA;
     case certificateID::TEST_LEAF:           return RawCertificateID::TEST_LEAF;
 
-    case certificateID::THIRD_PARTY_ROOT_CA: return RawCertificateID::DIGICERT_ROOT_CA;
-    case certificateID::THIRD_PARTY_IM_CA:   return RawCertificateID::DIGICERT_IM_CA;
-    case certificateID::THIRD_PARTY_LEAF:    return RawCertificateID::FACEBOOK_COM;
+    case certificateID::THIRD_PARTY_ROOT_CA: return RawCertificateID::BALTIMORE_CYBER_TRUST_ROOT;
+    case certificateID::THIRD_PARTY_IM_CA:   return RawCertificateID::MS_IT_TLS_CA_5;
+    case certificateID::THIRD_PARTY_LEAF:    return RawCertificateID::MICROSOFT_COM;
 
-    case certificateID::OCSP_AVAILABLE_IM:   return RawCertificateID::MICROSOFT_IM_CA;
+    case certificateID::OCSP_AVAILABLE_IM:   return RawCertificateID::MS_IT_TLS_CA_2;
     case certificateID::OCSP_AVAILABLE_LEAF: return RawCertificateID::BING_COM;
 
     case certificateID::NO_CERT:             return RawCertificateID::NO_CERT;
@@ -186,85 +186,164 @@ CertMap initializeTestCerts()
         cm[RawCertificateID::TEST_LEAF].certPtr = createCert(raw_base64);
     }
 
-    // BING.COM, signed by MICROSOFT_IM_CA, expires 10 Jul 2019
+    // BING, signed by Microsoft IT TLS CA 2, expires 30 Apr 2021
     {
         std::string raw_base64(
             "-----BEGIN CERTIFICATE-----\n"
-            "MIIMAjCCCeqgAwIBAgITLQAAMpnXBx230XCKQgAAAAAymTANBgkqhkiG9w0BAQsF\n"
+            "MIIN+jCCC+KgAwIBAgITIAAGDxuOsc5CY0aDQgAAAAYPGzANBgkqhkiG9w0BAQsF\n"
             "ADCBizELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcT\n"
             "B1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEVMBMGA1UE\n"
-            "CxMMTWljcm9zb2Z0IElUMR4wHAYDVQQDExVNaWNyb3NvZnQgSVQgVExTIENBIDUw\n"
-            "HhcNMTcwNzIwMTc0NzA4WhcNMTkwNzEwMTc0NzA4WjAXMRUwEwYDVQQDEwx3d3cu\n"
-            "YmluZy5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6jsg+/7Dl\n"
-            "IrdgFOcaDlK3RQ9sIgkJsgpj+ZxAbIe3ziyimIxjVlHX87pqgXcNhaYNbCFD0iPm\n"
-            "+aUfbv4GDTLR+AIr8eSegqxZ+CBToYM67NhpVYra1KAvY4XgqxorO4FB9IWYJRqh\n"
-            "I3SZeZ3lLK5t9XuUMicG8l52nJfpPdXXvBca2wUCq8FHEObG81vJzESA0htLLPTj\n"
-            "dUWBQnXPiW5bqzlGHzzv8ISV6jtDLNNa5JRlhSlXho+6pCedhNF7MP4yTaantPvA\n"
-            "ELLRWX13VhjgoCcRCCu0s8rxW5DuVWl2Pb2iw35MFnNWlcoVwq0AjAfGA+xEba/W\n"
-            "Lid6qfkQctYjAgMBAAGjggfQMIIHzDAdBgNVHQ4EFgQUCYflhSl4MCAls91+3Gzt\n"
-            "pSmoA3AwCwYDVR0PBAQDAgSwMB8GA1UdIwQYMBaAFAj+JZ906ocEwry7jqg4XzPG\n"
-            "0WxlMIGsBgNVHR8EgaQwgaEwgZ6ggZuggZiGS2h0dHA6Ly9tc2NybC5taWNyb3Nv\n"
-            "ZnQuY29tL3BraS9tc2NvcnAvY3JsL01pY3Jvc29mdCUyMElUJTIwVExTJTIwQ0El\n"
-            "MjA1LmNybIZJaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraS9tc2NvcnAvY3Js\n"
-            "L01pY3Jvc29mdCUyMElUJTIwVExTJTIwQ0ElMjA1LmNybDCBhQYIKwYBBQUHAQEE\n"
-            "eTB3MFEGCCsGAQUFBzAChkVodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL21z\n"
-            "Y29ycC9NaWNyb3NvZnQlMjBJVCUyMFRMUyUyMENBJTIwNS5jcnQwIgYIKwYBBQUH\n"
-            "MAGGFmh0dHA6Ly9vY3NwLm1zb2NzcC5jb20wPgYJKwYBBAGCNxUHBDEwLwYnKwYB\n"
-            "BAGCNxUIh9qGdYPu2QGCyYUbgbWeYYX062CBXYTS30KC55N6AgFkAgEQMB0GA1Ud\n"
-            "JQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATBNBgNVHSAERjBEMEIGCSsGAQQBgjcq\n"
-            "ATA1MDMGCCsGAQUFBwIBFidodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL21z\n"
-            "Y29ycC9jcHMwJwYJKwYBBAGCNxUKBBowGDAKBggrBgEFBQcDAjAKBggrBgEFBQcD\n"
-            "ATCCBW0GA1UdEQSCBWQwggVgggx3d3cuYmluZy5jb22CEGRpY3QuYmluZy5jb20u\n"
-            "Y26CEyoucGxhdGZvcm0uYmluZy5jb22CCiouYmluZy5jb22CCGJpbmcuY29tghZp\n"
-            "ZW9ubGluZS5taWNyb3NvZnQuY29tghMqLndpbmRvd3NzZWFyY2guY29tghljbi5p\n"
-            "ZW9ubGluZS5taWNyb3NvZnQuY29tghEqLm9yaWdpbi5iaW5nLmNvbYINKi5tbS5i\n"
-            "aW5nLm5ldIIOKi5hcGkuYmluZy5jb22CGGVjbi5kZXYudmlydHVhbGVhcnRoLm5l\n"
-            "dIINKi5jbi5iaW5nLm5ldIINKi5jbi5iaW5nLmNvbYIQc3NsLWFwaS5iaW5nLmNv\n"
-            "bYIQc3NsLWFwaS5iaW5nLm5ldIIOKi5hcGkuYmluZy5uZXSCDiouYmluZ2FwaXMu\n"
-            "Y29tgg9iaW5nc2FuZGJveC5jb22CFmZlZWRiYWNrLm1pY3Jvc29mdC5jb22CG2lu\n"
-            "c2VydG1lZGlhLmJpbmcub2ZmaWNlLm5ldIIOci5iYXQuYmluZy5jb22CECouci5i\n"
-            "YXQuYmluZy5jb22CEiouZGljdC5iaW5nLmNvbS5jboIPKi5kaWN0LmJpbmcuY29t\n"
-            "gg4qLnNzbC5iaW5nLmNvbYIQKi5hcHBleC5iaW5nLmNvbYIWKi5wbGF0Zm9ybS5j\n"
-            "bi5iaW5nLmNvbYINd3AubS5iaW5nLmNvbYIMKi5tLmJpbmcuY29tgg9nbG9iYWwu\n"
-            "YmluZy5jb22CEXdpbmRvd3NzZWFyY2guY29tgg5zZWFyY2gubXNuLmNvbYIRKi5i\n"
-            "aW5nc2FuZGJveC5jb22CGSouYXBpLnRpbGVzLmRpdHUubGl2ZS5jb22CDyouZGl0\n"
-            "dS5saXZlLmNvbYIYKi50MC50aWxlcy5kaXR1LmxpdmUuY29tghgqLnQxLnRpbGVz\n"
-            "LmRpdHUubGl2ZS5jb22CGCoudDIudGlsZXMuZGl0dS5saXZlLmNvbYIYKi50My50\n"
-            "aWxlcy5kaXR1LmxpdmUuY29tghUqLnRpbGVzLmRpdHUubGl2ZS5jb22CCzNkLmxp\n"
-            "dmUuY29tghNhcGkuc2VhcmNoLmxpdmUuY29tghRiZXRhLnNlYXJjaC5saXZlLmNv\n"
-            "bYIVY253ZWIuc2VhcmNoLmxpdmUuY29tggxkZXYubGl2ZS5jb22CDWRpdHUubGl2\n"
-            "ZS5jb22CEWZhcmVjYXN0LmxpdmUuY29tgg5pbWFnZS5saXZlLmNvbYIPaW1hZ2Vz\n"
-            "LmxpdmUuY29tghFsb2NhbC5saXZlLmNvbS5hdYIUbG9jYWxzZWFyY2gubGl2ZS5j\n"
-            "b22CFGxzNGQuc2VhcmNoLmxpdmUuY29tgg1tYWlsLmxpdmUuY29tghFtYXBpbmRp\n"
-            "YS5saXZlLmNvbYIObG9jYWwubGl2ZS5jb22CDW1hcHMubGl2ZS5jb22CEG1hcHMu\n"
-            "bGl2ZS5jb20uYXWCD21pbmRpYS5saXZlLmNvbYINbmV3cy5saXZlLmNvbYIcb3Jp\n"
-            "Z2luLmNud2ViLnNlYXJjaC5saXZlLmNvbYIWcHJldmlldy5sb2NhbC5saXZlLmNv\n"
-            "bYIPc2VhcmNoLmxpdmUuY29tghJ0ZXN0Lm1hcHMubGl2ZS5jb22CDnZpZGVvLmxp\n"
-            "dmUuY29tgg92aWRlb3MubGl2ZS5jb22CFXZpcnR1YWxlYXJ0aC5saXZlLmNvbYIM\n"
-            "d2FwLmxpdmUuY29tghJ3ZWJtYXN0ZXIubGl2ZS5jb22CE3dlYm1hc3RlcnMubGl2\n"
-            "ZS5jb22CFXd3dy5sb2NhbC5saXZlLmNvbS5hdYIUd3d3Lm1hcHMubGl2ZS5jb20u\n"
-            "YXUwDQYJKoZIhvcNAQELBQADggIBADTpW/UWeupk40OP6k4yxihKStswxwqPAfMR\n"
-            "mx4XyqmTAawAKRNM+6EZth1BQdPdOplwRTvs69kkmUHJH+ZjYXBezEACWkzEiNUQ\n"
-            "nzkRWajdSQIz08Ubj/mBD6U8xLYD+NXgiB0xNWabd8aiPsqPaj6I3qkNw4JvtgtH\n"
-            "ZQG1zlwC5/Lu6yV3DM3sKpQMyBmOnX6nVUiS0MTOzLgZOQzRk07nO7EXWGcKTmDB\n"
-            "jE8cqv5IA/jQ6gtaxCI5pDxfXK4ct7oQyoChfxOXcEDKMmMndFmg9ch5c4an/FRM\n"
-            "2cgzDfjR01A71LNUpLUdOjNV0T+ZEStqEpdyDFfjrHGDtzLyqEz3iyvvQFyjmlGh\n"
-            "6OtZXwjCPpnVSrKCmfJKio0kUxyq+6t5tZAQbPVgFKiMrVnU+sgvmNVip1toijyz\n"
-            "8vMVCkwJ2G++7xjJukoELMxZ50W4/SAMZLy1Asx02NBwYCu9+CTQPVnmPe7rmxhl\n"
-            "QRBOfDNa1+5jwRHY64YudEzKhWR1uqS3ABd/fk+TL86yuNYGAgxnOm1FtOGieRgV\n"
-            "iV3+NzC+bDbuUOtmbD/GvDGmRwJRcCTHL7jBmkHePh2ABY93NE/IbkaDP6l1Kw98\n"
-            "AfqkzSUxhqHXuThe7KIoX9/0zv4AA1WZFis1QvAG7dpl9eio6vCdC/73HvBAlqRL\n"
-            "+7Mb1uu0\n"
+            "CxMMTWljcm9zb2Z0IElUMR4wHAYDVQQDExVNaWNyb3NvZnQgSVQgVExTIENBIDIw\n"
+            "HhcNMTkwNDMwMjA0ODAwWhcNMjEwNDMwMjA0ODAwWjAXMRUwEwYDVQQDEwx3d3cu\n"
+            "YmluZy5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDhIlPb0iP7\n"
+            "xRmUScK43QI7Ci/lvfMumWhRFAHcFzjIDHs74sq0B+ze8HW5PR6LWRe/d3yR5dC8\n"
+            "7gQs0qXGitzsP9vWJcpwKV273tlnWiEfgZx5tvNCFdHOqoYoHL3a8zed/JkGTEeX\n"
+            "ukGEX0TeBgCjcVTj5qRxJhjlWxs3AcB/q4f4vi3QG80TbSU2UO0lkvhvfs73C1jq\n"
+            "i7Zspia/YsMqcQ6X+APAZ+4guKjQr5q32tzj2FGtJO6ZmZuNV9Wwb32891UhwZ3D\n"
+            "2PrIcnCNlIQ1/Fah6im7Vc67qO2x/++r7gO7PtR8byCFnFuNUVQxhSIkCkj6FvPx\n"
+            "cYefok0wJ0VRAgMBAAGjggnIMIIJxDCCAfQGCisGAQQB1nkCBAIEggHkBIIB4AHe\n"
+            "AHUA7ku9t3XOYLrhQmkfq+GeZqMPfl+wctiDAMR7iXqo/csAAAFqcApGzAAABAMA\n"
+            "RjBEAiAiASIs5j19VcTLbxcOGHQlIl62d3iy1FY8dnNq+6lebQIgchbSq2Qh78zs\n"
+            "mmucyslucBycij/FYUe3F1lNpJiB9KsAdgBVgdTCFpA2AUrqC5tXPFPwwOQ4eHAl\n"
+            "CBcvo6odBxPTDAAAAWpwCkgDAAAEAwBHMEUCIQDx6RqcvDdfIY9qdAuaRFBVvSHN\n"
+            "ttpAzie3KP9AAiGvBwIgSMvjse/hJusDoRFnSTtX96ierTaqzQH4oDLLnW/Gwc0A\n"
+            "dQBc3EOS/uarRUSxXprUVuYQN/vV+kfcoXOUsl7m9scOygAAAWpwCkbmAAAEAwBG\n"
+            "MEQCICbYF6Lv93BFrwLguzmas/5gQ87fzRHkTaMxDSD7PlhRAiA/DXOeTcHaiUPQ\n"
+            "WsKbJ/7x9EWKvVisqtQMnYk6cBxbBwB2AESUZS6w7s6vxEAH2Kj+KMDa5oK+2Msx\n"
+            "tT/TM5a1toGoAAABanAKRtoAAAQDAEcwRQIgardRfR7bxwSGF212a603dXYz6O5z\n"
+            "YHpPks8/RR/AMzQCIQD4VYDD+2zVDHEjz8elkKEzhgzTdOMtc1yYhCU+eHAGkjAn\n"
+            "BgkrBgEEAYI3FQoEGjAYMAoGCCsGAQUFBwMCMAoGCCsGAQUFBwMBMD4GCSsGAQQB\n"
+            "gjcVBwQxMC8GJysGAQQBgjcVCIfahnWD7tkBgsmFG4G1nmGF9OtggV2E0t9CgueT\n"
+            "egIBZAIBHTCBhQYIKwYBBQUHAQEEeTB3MFEGCCsGAQUFBzAChkVodHRwOi8vd3d3\n"
+            "Lm1pY3Jvc29mdC5jb20vcGtpL21zY29ycC9NaWNyb3NvZnQlMjBJVCUyMFRMUyUy\n"
+            "MENBJTIwMi5jcnQwIgYIKwYBBQUHMAGGFmh0dHA6Ly9vY3NwLm1zb2NzcC5jb20w\n"
+            "HQYDVR0OBBYEFDcHtZt8HkKSRO8ETiTkCLixB9PaMAsGA1UdDwQEAwIEsDCCBW0G\n"
+            "A1UdEQSCBWQwggVgggx3d3cuYmluZy5jb22CEGRpY3QuYmluZy5jb20uY26CEyou\n"
+            "cGxhdGZvcm0uYmluZy5jb22CCiouYmluZy5jb22CCGJpbmcuY29tghZpZW9ubGlu\n"
+            "ZS5taWNyb3NvZnQuY29tghMqLndpbmRvd3NzZWFyY2guY29tghljbi5pZW9ubGlu\n"
+            "ZS5taWNyb3NvZnQuY29tghEqLm9yaWdpbi5iaW5nLmNvbYINKi5tbS5iaW5nLm5l\n"
+            "dIIOKi5hcGkuYmluZy5jb22CGGVjbi5kZXYudmlydHVhbGVhcnRoLm5ldIINKi5j\n"
+            "bi5iaW5nLm5ldIINKi5jbi5iaW5nLmNvbYIQc3NsLWFwaS5iaW5nLmNvbYIQc3Ns\n"
+            "LWFwaS5iaW5nLm5ldIIOKi5hcGkuYmluZy5uZXSCDiouYmluZ2FwaXMuY29tgg9i\n"
+            "aW5nc2FuZGJveC5jb22CFmZlZWRiYWNrLm1pY3Jvc29mdC5jb22CG2luc2VydG1l\n"
+            "ZGlhLmJpbmcub2ZmaWNlLm5ldIIOci5iYXQuYmluZy5jb22CECouci5iYXQuYmlu\n"
+            "Zy5jb22CEiouZGljdC5iaW5nLmNvbS5jboIPKi5kaWN0LmJpbmcuY29tgg4qLnNz\n"
+            "bC5iaW5nLmNvbYIQKi5hcHBleC5iaW5nLmNvbYIWKi5wbGF0Zm9ybS5jbi5iaW5n\n"
+            "LmNvbYINd3AubS5iaW5nLmNvbYIMKi5tLmJpbmcuY29tgg9nbG9iYWwuYmluZy5j\n"
+            "b22CEXdpbmRvd3NzZWFyY2guY29tgg5zZWFyY2gubXNuLmNvbYIRKi5iaW5nc2Fu\n"
+            "ZGJveC5jb22CGSouYXBpLnRpbGVzLmRpdHUubGl2ZS5jb22CDyouZGl0dS5saXZl\n"
+            "LmNvbYIYKi50MC50aWxlcy5kaXR1LmxpdmUuY29tghgqLnQxLnRpbGVzLmRpdHUu\n"
+            "bGl2ZS5jb22CGCoudDIudGlsZXMuZGl0dS5saXZlLmNvbYIYKi50My50aWxlcy5k\n"
+            "aXR1LmxpdmUuY29tghUqLnRpbGVzLmRpdHUubGl2ZS5jb22CCzNkLmxpdmUuY29t\n"
+            "ghNhcGkuc2VhcmNoLmxpdmUuY29tghRiZXRhLnNlYXJjaC5saXZlLmNvbYIVY253\n"
+            "ZWIuc2VhcmNoLmxpdmUuY29tggxkZXYubGl2ZS5jb22CDWRpdHUubGl2ZS5jb22C\n"
+            "EWZhcmVjYXN0LmxpdmUuY29tgg5pbWFnZS5saXZlLmNvbYIPaW1hZ2VzLmxpdmUu\n"
+            "Y29tghFsb2NhbC5saXZlLmNvbS5hdYIUbG9jYWxzZWFyY2gubGl2ZS5jb22CFGxz\n"
+            "NGQuc2VhcmNoLmxpdmUuY29tgg1tYWlsLmxpdmUuY29tghFtYXBpbmRpYS5saXZl\n"
+            "LmNvbYIObG9jYWwubGl2ZS5jb22CDW1hcHMubGl2ZS5jb22CEG1hcHMubGl2ZS5j\n"
+            "b20uYXWCD21pbmRpYS5saXZlLmNvbYINbmV3cy5saXZlLmNvbYIcb3JpZ2luLmNu\n"
+            "d2ViLnNlYXJjaC5saXZlLmNvbYIWcHJldmlldy5sb2NhbC5saXZlLmNvbYIPc2Vh\n"
+            "cmNoLmxpdmUuY29tghJ0ZXN0Lm1hcHMubGl2ZS5jb22CDnZpZGVvLmxpdmUuY29t\n"
+            "gg92aWRlb3MubGl2ZS5jb22CFXZpcnR1YWxlYXJ0aC5saXZlLmNvbYIMd2FwLmxp\n"
+            "dmUuY29tghJ3ZWJtYXN0ZXIubGl2ZS5jb22CE3dlYm1hc3RlcnMubGl2ZS5jb22C\n"
+            "FXd3dy5sb2NhbC5saXZlLmNvbS5hdYIUd3d3Lm1hcHMubGl2ZS5jb20uYXUwgawG\n"
+            "A1UdHwSBpDCBoTCBnqCBm6CBmIZLaHR0cDovL21zY3JsLm1pY3Jvc29mdC5jb20v\n"
+            "cGtpL21zY29ycC9jcmwvTWljcm9zb2Z0JTIwSVQlMjBUTFMlMjBDQSUyMDIuY3Js\n"
+            "hklodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL21zY29ycC9jcmwvTWljcm9z\n"
+            "b2Z0JTIwSVQlMjBUTFMlMjBDQSUyMDIuY3JsME0GA1UdIARGMEQwQgYJKwYBBAGC\n"
+            "NyoBMDUwMwYIKwYBBQUHAgEWJ2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kv\n"
+            "bXNjb3JwL2NwczAfBgNVHSMEGDAWgBSRnjtEbD1XnEJ3KjTXT9HMSpcs2jAdBgNV\n"
+            "HSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggIBAA1g\n"
+            "NJF5ks5Qrg0/qeOXQbcO3SCs+HKTKxVL8QdaTL3s5gsmWQzcYNS671DmN4lEob2g\n"
+            "WWZKyKAzQbjDOcf9ndxX4+i+PaCw5K3uONbMOwnuOCwRvDy8YEoCb3OzKFX4sjzh\n"
+            "1HVL/ljKHUPT+9ap/SpYserNxixibqF2LZYx+9hwr1bcx9GWrg3CoFUFgSZqRQ14\n"
+            "eiK94iM5kzJLKynKPhez+UOwS5VRev1mxh5nD9hBPzXHHqI9mNWu/lyr7KPUMigi\n"
+            "QfKKZuqV6W3i1H3BoJi1uDkL3SJo1F39XN3AyGSAZWS9RNn5JzEQQGiJRjrz/PE1\n"
+            "vTg1BlbsPdKa4gGZGdGBWcj2eXZc+GbLpTy3qWlmJrEn2KGLeomyndlftRPFrBUH\n"
+            "/5Mio5OeSawjlacBV25fKaoZ1BPc3i+HGKd5ctddCy6kJsgdMD221zGvf/0uW25Z\n"
+            "ImzDeH7KkOcGbzyWJwBzDgra0RP+qRgK3aYPSWI81OLlnHJ2VOix/UU63NCK2fO/\n"
+            "URzE8KxoHrgRGXCE52viHv6ksL7QXWelbERU7GEpcZU1suPhDohn4CrfrCYCjpa5\n"
+            "Ys6ci7Rren82SsXJBfNrgm2U4lxWfzWj+2Ay6yATbdoOPntue8cbbMoTzoNMHQXD\n"
+            "2DpjtFPs8/RVOFQb0IFVluCrTAnHmI8tTtsmzg6z\n"
             "-----END CERTIFICATE-----\n");
         cm[RawCertificateID::BING_COM].raw_base64 = raw_base64;
         cm[RawCertificateID::BING_COM].certPtr = createCert(raw_base64);
 
     }
 
-    // MICROSOFT_IM_CA, expires 20 May 2024
+    // Microsoft IT TLS CA 2, signed by Baltimore CyberTrust Root, expires 20 May 2024
     {
         std::string raw_base64(
             "-----BEGIN CERTIFICATE-----\n"
+            "MIIFtDCCBJygAwIBAgIQDywQyVsGwJN/uNRJ+D6FaTANBgkqhkiG9w0BAQsFADBa\n"
+            "MQswCQYDVQQGEwJJRTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJl\n"
+            "clRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTE2\n"
+            "MDUyMDEyNTE1N1oXDTI0MDUyMDEyNTE1N1owgYsxCzAJBgNVBAYTAlVTMRMwEQYD\n"
+            "VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy\n"
+            "b3NvZnQgQ29ycG9yYXRpb24xFTATBgNVBAsTDE1pY3Jvc29mdCBJVDEeMBwGA1UE\n"
+            "AxMVTWljcm9zb2Z0IElUIFRMUyBDQSAyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A\n"
+            "MIICCgKCAgEAnqoVwRuhY1/mURjFFrsR3AtNm5EKukBJK9zWBgvFd1ksNEJFC06o\n"
+            "yRbwKPMflpW/HtOfzIeBliGk57MwZq18bgASr70sPUWuoD917HUgBfxBYoF8zA7Z\n"
+            "Ie5zAHODFboJL7Fg/apgbQs/GiZZNCi0QkQUWzw0nTUmVSNQ0mz6pCu95Dv1WMsL\n"
+            "GyPGfdN9zD3Q/QEDyJ695QgjRIxYA1DUE+54ti2k6r0ycKFQYkyWwZ25HD1h2kYt\n"
+            "3ovW85vF6y7tjTqUEcLbgKUCB81/955hdLLsbFd6f9o2PkU8xuOc3U+bUedvv6Sb\n"
+            "tvGjBEZeFyH8/CaQhzlsKMH0+OPOFv/bMqcLarPw1V1sOV1bl4W9vi2278niblzI\n"
+            "bEHt7nN888p4KNIwqCcXaGhbtS4tjn3NKI6v1d2XRyxIvCJDjgoZ09zF39Pyoe92\n"
+            "sSRikZh7xns4tQEQ8BCs4o5NBSx8UxEsgyzNSskWGEWqsIjt+7+A1skDDZv6k2o8\n"
+            "VCHNbTLFKS7d72wMI4ErpzVsBIicxaG2ezuMBBuqThxIiJ+G9zfoP9lxim/9rvJA\n"
+            "xbh3nujA1VJfkOYTJIojEAYCxR3QjEoGdapJmBle97AfqEBnwoJsu2wav8h9v+po\n"
+            "DL4h6dRzRUxY1DHypcFlXGoHu/REQgFLq2IN30/AhQLN90Pj9TT2RQECAwEAAaOC\n"
+            "AUIwggE+MB0GA1UdDgQWBBSRnjtEbD1XnEJ3KjTXT9HMSpcs2jAfBgNVHSMEGDAW\n"
+            "gBTlnVkwgkdYzKz6CFQ2hns6tQRN8DASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1Ud\n"
+            "DwEB/wQEAwIBhjAnBgNVHSUEIDAeBggrBgEFBQcDAQYIKwYBBQUHAwIGCCsGAQUF\n"
+            "BwMJMDQGCCsGAQUFBwEBBCgwJjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGln\n"
+            "aWNlcnQuY29tMDoGA1UdHwQzMDEwL6AtoCuGKWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0\n"
+            "LmNvbS9PbW5pcm9vdDIwMjUuY3JsMD0GA1UdIAQ2MDQwMgYEVR0gADAqMCgGCCsG\n"
+            "AQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMA0GCSqGSIb3DQEB\n"
+            "CwUAA4IBAQBsf+pqb89rW8E0rP/cDuB9ixMX4C9OWQ7EA7n0BSllR64ZmuhU9mTV\n"
+            "2L0G4HEiGXvOmt15i99wJ0ho2/dvMxm1ZeufkAfMuEc5fQ9RE5ENgNR2UCuFB2Bt\n"
+            "bVmaKUAWxscN4GpXS4AJv+/HS0VXs5Su19J0DA8Bg+lo8ekCl4dq2G1m1WsCvFBI\n"
+            "oLIjd4neCLlGoxT2jA43lj2JpQ/SMkLkLy9DXj/JHdsqJDR5ogcij4VIX8V+bVD0\n"
+            "NCw7kQa6Ulq9Zo0jDEq1at4zSeH4mV2PMM3LwIXBA2xo5sda1cnUWJo3Pq4uMgcL\n"
+            "e0t+fCut38NMkTl8F0arflspaqUVVUov\n"
+            "-----END CERTIFICATE-----\n");
+        cm[RawCertificateID::MS_IT_TLS_CA_2].raw_base64 = raw_base64;
+        cm[RawCertificateID::MS_IT_TLS_CA_2].certPtr = createCert(raw_base64);
+
+    }
+
+    // Baltimore CyberTrust Root, (root CA), expires May 13, 2025
+    {
+        std::string raw_base64 = std::string(
+            "-----BEGIN CERTIFICATE-----\n"
+            "MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ\n"
+            "RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD\n"
+            "VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX\n"
+            "DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y\n"
+            "ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy\n"
+            "VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr\n"
+            "mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr\n"
+            "IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK\n"
+            "mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu\n"
+            "XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy\n"
+            "dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye\n"
+            "jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1\n"
+            "BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3\n"
+            "DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92\n"
+            "9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx\n"
+            "jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0\n"
+            "Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz\n"
+            "ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS\n"
+            "R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp\n"
+            "-----END CERTIFICATE-----\n");
+        cm[RawCertificateID::BALTIMORE_CYBER_TRUST_ROOT].raw_base64 = raw_base64;
+        cm[RawCertificateID::BALTIMORE_CYBER_TRUST_ROOT].certPtr = createCert(raw_base64);
+    }
+
+    // Microsoft IT TLS CA 5, signed by Baltimore CyberTrust Root, expires May 20, 2024
+    {
+        std::string raw_base64 = std::string(
+            "-----BEGIN CERTIFICATE-----\n"
             "MIIFtDCCBJygAwIBAgIQCIjNUl8ZJERNFKWCkd65UjANBgkqhkiG9w0BAQsFADBa\n"
             "MQswCQYDVQQGEwJJRTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJl\n"
             "clRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTE2\n"
@@ -297,119 +376,66 @@ CertMap initializeTestCerts()
             "TlHk/R4RFsyeANmXGpfjZceGNRtTdr4y0SxBSUujPpMMW3dXBzA8NYuM0WmiJ/pV\n"
             "6KudEB7RF9+6bInTyVvXC5SIqdi0ldeO\n"
             "-----END CERTIFICATE-----\n");
-        cm[RawCertificateID::MICROSOFT_IM_CA].raw_base64 = raw_base64;
-        cm[RawCertificateID::MICROSOFT_IM_CA].certPtr = createCert(raw_base64);
-
-    }
-
-    // DIGICERT_ROOT_CA, (root CA), expires 10 Nov 2031
-    {
-        std::string raw_base64 = std::string(
-            "-----BEGIN CERTIFICATE-----\n"
-            "MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs\n"
-            "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n"
-            "d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j\n"
-            "ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL\n"
-            "MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3\n"
-            "LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug\n"
-            "RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm\n"
-            "+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW\n"
-            "PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM\n"
-            "xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB\n"
-            "Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3\n"
-            "hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg\n"
-            "EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF\n"
-            "MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA\n"
-            "FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec\n"
-            "nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z\n"
-            "eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF\n"
-            "hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2\n"
-            "Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe\n"
-            "vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep\n"
-            "+OkuE6N36B9K\n"
-            "-----END CERTIFICATE-----\n");
-        cm[RawCertificateID::DIGICERT_ROOT_CA].raw_base64 = raw_base64;
-        cm[RawCertificateID::DIGICERT_ROOT_CA].certPtr = createCert(raw_base64);
-    }
-
-    // DIGICERT_IM_CA, signed by DIGICERT_ROOT_CA, expires 22 Oct 2028
-    {
-        std::string raw_base64 = std::string(
-            "-----BEGIN CERTIFICATE-----\n"
-            "MIIEsTCCA5mgAwIBAgIQBOHnpNxc8vNtwCtCuF0VnzANBgkqhkiG9w0BAQsFADBs\n"
-            "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n"
-            "d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j\n"
-            "ZSBFViBSb290IENBMB4XDTEzMTAyMjEyMDAwMFoXDTI4MTAyMjEyMDAwMFowcDEL\n"
-            "MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3\n"
-            "LmRpZ2ljZXJ0LmNvbTEvMC0GA1UEAxMmRGlnaUNlcnQgU0hBMiBIaWdoIEFzc3Vy\n"
-            "YW5jZSBTZXJ2ZXIgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC2\n"
-            "4C/CJAbIbQRf1+8KZAayfSImZRauQkCbztyfn3YHPsMwVYcZuU+UDlqUH1VWtMIC\n"
-            "Kq/QmO4LQNfE0DtyyBSe75CxEamu0si4QzrZCwvV1ZX1QK/IHe1NnF9Xt4ZQaJn1\n"
-            "itrSxwUfqJfJ3KSxgoQtxq2lnMcZgqaFD15EWCo3j/018QsIJzJa9buLnqS9UdAn\n"
-            "4t07QjOjBSjEuyjMmqwrIw14xnvmXnG3Sj4I+4G3FhahnSMSTeXXkgisdaScus0X\n"
-            "sh5ENWV/UyU50RwKmmMbGZJ0aAo3wsJSSMs5WqK24V3B3aAguCGikyZvFEohQcft\n"
-            "bZvySC/zA/WiaJJTL17jAgMBAAGjggFJMIIBRTASBgNVHRMBAf8ECDAGAQH/AgEA\n"
-            "MA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw\n"
-            "NAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2Vy\n"
-            "dC5jb20wSwYDVR0fBEQwQjBAoD6gPIY6aHR0cDovL2NybDQuZGlnaWNlcnQuY29t\n"
-            "L0RpZ2lDZXJ0SGlnaEFzc3VyYW5jZUVWUm9vdENBLmNybDA9BgNVHSAENjA0MDIG\n"
-            "BFUdIAAwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQ\n"
-            "UzAdBgNVHQ4EFgQUUWj/kK8CB3U8zNllZGKiErhZcjswHwYDVR0jBBgwFoAUsT7D\n"
-            "aQP4v0cB1JgmGggC72NkK8MwDQYJKoZIhvcNAQELBQADggEBABiKlYkD5m3fXPwd\n"
-            "aOpKj4PWUS+Na0QWnqxj9dJubISZi6qBcYRb7TROsLd5kinMLYBq8I4g4Xmk/gNH\n"
-            "E+r1hspZcX30BJZr01lYPf7TMSVcGDiEo+afgv2MW5gxTs14nhr9hctJqvIni5ly\n"
-            "/D6q1UEL2tU2ob8cbkdJf17ZSHwD2f2LSaCYJkJA69aSEaRkCldUxPUd1gJea6zu\n"
-            "xICaEnL6VpPX/78whQYwvwt/Tv9XBZ0k7YXDK/umdaisLRbvfXknsuvCnQsH6qqF\n"
-            "0wGjIChBWUMo0oHjqvbsezt3tkBigAVBRQHvFwY+3sAzm2fTYS5yh+Rp/BIAV0Ae\n"
-            "cPUeybQ=\n"
-            "-----END CERTIFICATE-----\n");
-        cm[RawCertificateID::DIGICERT_IM_CA].raw_base64 = raw_base64;
-        cm[RawCertificateID::DIGICERT_IM_CA].certPtr = createCert(raw_base64);
+        cm[RawCertificateID::MS_IT_TLS_CA_5].raw_base64 = raw_base64;
+        cm[RawCertificateID::MS_IT_TLS_CA_5].certPtr = createCert(raw_base64);
     }
 
-    // FACEBOOK_COM, *.facebook.com - signed by DIGICERT_IM_CA, expires 22 Mar 2019
+    // www.microsoft.com - signed by Microsoft IT TLS CA 5, expires October 22, 2021
     {
         std::string raw_base64 = std::string(
             "-----BEGIN CERTIFICATE-----\n"
-            "MIIGsjCCBZqgAwIBAgIQCzw7YBoY9Z7itrsFYF7ywDANBgkqhkiG9w0BAQsFADBw\n"
-            "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n"
-            "d3cuZGlnaWNlcnQuY29tMS8wLQYDVQQDEyZEaWdpQ2VydCBTSEEyIEhpZ2ggQXNz\n"
-            "dXJhbmNlIFNlcnZlciBDQTAeFw0xNzEyMTUwMDAwMDBaFw0xOTAzMjIxMjAwMDBa\n"
-            "MGkxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRMwEQYDVQQHEwpN\n"
-            "ZW5sbyBQYXJrMRcwFQYDVQQKEw5GYWNlYm9vaywgSW5jLjEXMBUGA1UEAwwOKi5m\n"
-            "YWNlYm9vay5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASIA87IjqqM6JBX\n"
-            "puN20BXCVsDjoP9wnF2rSV60qC130oLTrgfOQ3Uk1dv1R6LFCx4gs2pJUu6iDKBS\n"
-            "/b+BXOUbo4IEGDCCBBQwHwYDVR0jBBgwFoAUUWj/kK8CB3U8zNllZGKiErhZcjsw\n"
-            "HQYDVR0OBBYEFMD9dPV9y8Yn8QPTYqJF14QcFSEIMIHHBgNVHREEgb8wgbyCDiou\n"
-            "ZmFjZWJvb2suY29tgg4qLnh4LmZiY2RuLm5ldIILKi5mYnNieC5jb22CDioueHou\n"
-            "ZmJjZG4ubmV0gg4qLmZhY2Vib29rLm5ldIIOKi54eS5mYmNkbi5uZXSCDyoubWVz\n"
-            "c2VuZ2VyLmNvbYIGZmIuY29tggsqLmZiY2RuLm5ldIIIKi5mYi5jb22CECoubS5m\n"
-            "YWNlYm9vay5jb22CDW1lc3Nlbmdlci5jb22CDGZhY2Vib29rLmNvbTAOBgNVHQ8B\n"
-            "Af8EBAMCB4AwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMHUGA1UdHwRu\n"
-            "MGwwNKAyoDCGLmh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9zaGEyLWhhLXNlcnZl\n"
-            "ci1nNi5jcmwwNKAyoDCGLmh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9zaGEyLWhh\n"
-            "LXNlcnZlci1nNi5jcmwwTAYDVR0gBEUwQzA3BglghkgBhv1sAQEwKjAoBggrBgEF\n"
-            "BQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAIBgZngQwBAgIwgYMG\n"
-            "CCsGAQUFBwEBBHcwdTAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQu\n"
-            "Y29tME0GCCsGAQUFBzAChkFodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGln\n"
-            "aUNlcnRTSEEySGlnaEFzc3VyYW5jZVNlcnZlckNBLmNydDAMBgNVHRMBAf8EAjAA\n"
-            "MIIBfgYKKwYBBAHWeQIEAgSCAW4EggFqAWgAdgCkuQmQtBhYFIe7E6LMZ3AKPDWY\n"
-            "BPkb37jjd80OyA3cEAAAAWBXnEHoAAAEAwBHMEUCIBC3Rn4i2bhLyR344u3vl7be\n"
-            "vxoi+WPJBhGT+j1gJmg5AiEAwQ3rzH1mmMSYNYKtVNDZMo+l6e8Z35t+X9NDR7Du\n"
-            "gWAAdwCHdb/nWXz4jEOZX73zbv9WjUdWNv9KtWDBtOr/XqCDDwAAAWBXnEL7AAAE\n"
-            "AwBIMEYCIQCRjvvPARW3J1ENmo2Nz1cxisa1BcbDuqvSrfuXkz8btAIhAPmllqgF\n"
-            "8JjlVHUChiFzghsKVBeTxRagi55tgsAciaoZAHUAu9nfvB+KcbWTlCOXqpJ7RzhX\n"
-            "lQqrUugakJZkNo4e0YUAAAFgV5xCUgAABAMARjBEAiBY6qdNgMoQAqVTl3zRrTmy\n"
-            "+X/1f/esBUczsb3MWdZ1ZgIgXdxZNTrDBgyTzxgbVRObkqU3tZZdaiwsw4WI0xI0\n"
-            "BtQwDQYJKoZIhvcNAQELBQADggEBAGu0uxZD+IRXXlFWLPvknRkXA7J08NyVKG70\n"
-            "M2vDi2xF2YB8qlZgoxW8YiiV86IpwtOhYLZinSO0iCBDQmTf627LTPfuDcF6qOuO\n"
-            "WFTvj1IbplPvGWIu5tNBiFWNQxFAIL2Rf+5vmIe+YezUHTLGGqwRtFa2ImS17IMk\n"
-            "YjZ90LYXXO5qb1RKkFJtAvEBTbJsv8kr+J6Rx+YNJy17LnBX+MbWiyBbvUQoM3sY\n"
-            "MmcWmcaQmECz9ZHWYjZeufSHbHKG6KDYLU8x6DyhgtxK2rsoIMlNnJkNHaLjw+b8\n"
-            "7VCYa+EMWppvVuNyXOk9Jkbx7Q3SEoodT77kkHUX0bF2OkZy6cc=\n"
+            "MIIJHzCCBwegAwIBAgITLQAMNxVixB2TlAh/aAAAAAw3FTANBgkqhkiG9w0BAQsF\n"
+            "ADCBizELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcT\n"
+            "B1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEVMBMGA1UE\n"
+            "CxMMTWljcm9zb2Z0IElUMR4wHAYDVQQDExVNaWNyb3NvZnQgSVQgVExTIENBIDUw\n"
+            "HhcNMTkxMDIxMjIwNDA0WhcNMjExMDIxMjIwNDA0WjCBiDELMAkGA1UEBhMCVVMx\n"
+            "CzAJBgNVBAgTAldBMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3Nv\n"
+            "ZnQgQ29ycG9yYXRpb24xHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEa\n"
+            "MBgGA1UEAxMRd3d3Lm1pY3Jvc29mdC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IB\n"
+            "DwAwggEKAoIBAQDTEK1CzUwdArEOb/vDOqds7/vQ1yGQtAYaZYNBch27Kw3/XKnf\n"
+            "td3NVj7tYe7MhI1U+bknxhSx7m4ti7Pzt6mxQiTZ/KegYhxosd3sOEikXgJVzECv\n"
+            "h0Mvd6adrvi00cUeQz0dlkUkuxMAjiFs+FX7Ogf4xt8ub4hKZPGB85vDnQQ0OHVh\n"
+            "L9IuUbYHhmh8EoDEdR+og+lj7u5OKt3YEWntgbnfV1d66U59kfp5Dg4T/zFjqz/l\n"
+            "U3KGBWgj0YoxH8KGfuq2YfFQsm7Q4MDJnR2PNUbwwrK5JldcRn27o5SVZxaB55bs\n"
+            "dyHWL0GbG5JoIIWg8pGJXKYGfARDEVjWijBPAgMBAAGjggR7MIIEdzCCAXwGCisG\n"
+            "AQQB1nkCBAIEggFsBIIBaAFmAHYA9lyUL9F3MCIUVBgIMJRWjuNNExkzv98MLyAL\n"
+            "zE7xZOMAAAFt8GJxcQAABAMARzBFAiEAldKDzhaLTJ1PpTpE7TmrRp+nDwoEZbW5\n"
+            "JOfrPKoR6PsCIBOqc6bzu7MnferBbxkUKwS67LpFTJgxYk6RV98m5fK2AHUAVYHU\n"
+            "whaQNgFK6gubVzxT8MDkOHhwJQgXL6OqHQcT0wwAAAFt8GJyzQAABAMARjBEAiBa\n"
+            "JqHGYrk+yh3ccuelsJxqLbhE3DJuSBZxe+xEpiabhQIgRdcckht/x8uG6tSrRKg5\n"
+            "0GdwnWlFKMBDT50rQjIPflMAdQB9PvL4j/+IVWgkwsDKnlKJeSvFDngJfy5ql2iZ\n"
+            "fiLw1wAAAW3wYnG7AAAEAwBGMEQCIGToqXolvHTes1f0QwV9RSvEE5HVwX6jn70+\n"
+            "KaExl0+BAiBosObeHSU867FO1Aw5dw+R01ZZ1fudHxDwuXgLvqFmQzAnBgkrBgEE\n"
+            "AYI3FQoEGjAYMAoGCCsGAQUFBwMCMAoGCCsGAQUFBwMBMD4GCSsGAQQBgjcVBwQx\n"
+            "MC8GJysGAQQBgjcVCIfahnWD7tkBgsmFG4G1nmGF9OtggV2E0t9CgueTegIBZAIB\n"
+            "HTCBhQYIKwYBBQUHAQEEeTB3MFEGCCsGAQUFBzAChkVodHRwOi8vd3d3Lm1pY3Jv\n"
+            "c29mdC5jb20vcGtpL21zY29ycC9NaWNyb3NvZnQlMjBJVCUyMFRMUyUyMENBJTIw\n"
+            "NS5jcnQwIgYIKwYBBQUHMAGGFmh0dHA6Ly9vY3NwLm1zb2NzcC5jb20wHQYDVR0O\n"
+            "BBYEFParvwUeQbdw6ZH4GpVu9gwrCfuVMAsGA1UdDwQEAwIEsDCBmQYDVR0RBIGR\n"
+            "MIGOghN3d3dxYS5taWNyb3NvZnQuY29tghF3d3cubWljcm9zb2Z0LmNvbYIYc3Rh\n"
+            "dGljdmlldy5taWNyb3NvZnQuY29tghFpLnMtbWljcm9zb2Z0LmNvbYINbWljcm9z\n"
+            "b2Z0LmNvbYIRYy5zLW1pY3Jvc29mdC5jb22CFXByaXZhY3kubWljcm9zb2Z0LmNv\n"
+            "bTCBrAYDVR0fBIGkMIGhMIGeoIGboIGYhktodHRwOi8vbXNjcmwubWljcm9zb2Z0\n"
+            "LmNvbS9wa2kvbXNjb3JwL2NybC9NaWNyb3NvZnQlMjBJVCUyMFRMUyUyMENBJTIw\n"
+            "NS5jcmyGSWh0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvbXNjb3JwL2NybC9N\n"
+            "aWNyb3NvZnQlMjBJVCUyMFRMUyUyMENBJTIwNS5jcmwwTQYDVR0gBEYwRDBCBgkr\n"
+            "BgEEAYI3KgEwNTAzBggrBgEFBQcCARYnaHR0cDovL3d3dy5taWNyb3NvZnQuY29t\n"
+            "L3BraS9tc2NvcnAvY3BzMB8GA1UdIwQYMBaAFAj+JZ906ocEwry7jqg4XzPG0Wxl\n"
+            "MB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATANBgkqhkiG9w0BAQsFAAOC\n"
+            "AgEAdWMaW3NOP5Yr47Sow1UZNLMmDlxNjz+8DcHiflQfKsImOvs/UflUrMGXG7rH\n"
+            "57NbJZ9nYpSTHWxSJfKsGPc3pgc5R1sxZxDb6lBuXEN9NvhJMmPwBkyKJAAnjYN6\n"
+            "yCNZP4X6dBOONW8uopknF+CRHDZdSiMaFiE4fVCe0LrO90b4ROPsRV8zHn57i1B1\n"
+            "69n1cqsLXrMHvK0Xnu7rwrvvd5BbOaqm7DrgwJYUk0UciNEfcyN2dNRcCxofWQdV\n"
+            "GQqvagqtjyDCm/EJ6DJ2kWllGHjauc8IkMaUeCedTYphChEckXoRBZikZtyL0oZj\n"
+            "67iKht6mm4fST+x0Zuu5wdzUoCTQsNTHV0GSbcVIRcgmaNiwP+0+lrRocUrj2h/7\n"
+            "2IQN8Pe/+CrDeVJNlKA9gWNl+t1F/r3CKWnkENyNUCTggiCSojdY9Rkj1rTieP6M\n"
+            "SBUZBWf3MB5XIuaLOTO0/whM831krxNG/k0mdCpDtdKvCKIcARrkKM9A3TxtVpOd\n"
+            "8f9kifcGaPqTQYr8fxhrNB864qsCG17o8ZckBKW8FY5H/jSQAZb1qbwsTbBMXJIr\n"
+            "0lAPwH7LIAHJJyslG0X3Mp0ARumGWqVwiHOCaLXO1iSQX0wW4yo+lGxWONvOIoad\n"
+            "2Ned/fxM675fEVC+r+DI6BKbt9ChfIXiXeULqOZC3yp2Fo8=\n"
             "-----END CERTIFICATE-----\n");
-        cm[RawCertificateID::FACEBOOK_COM].raw_base64 = raw_base64;
-        cm[RawCertificateID::FACEBOOK_COM].certPtr = createCert(raw_base64);
+        cm[RawCertificateID::MICROSOFT_COM].raw_base64 = raw_base64;
+        cm[RawCertificateID::MICROSOFT_COM].certPtr = createCert(raw_base64);
     }
 
     return cm;
index 6efdfbe..14a8973 100644 (file)
@@ -23,6 +23,7 @@ SET(CKM_SOURCES
     capi-testcases.cpp
     encryption-decryption-env.cpp
     encryption-decryption.cpp
+    sign-verify.cpp
     main.cpp
 )
 
index 757826f..0e0cfca 100644 (file)
@@ -779,7 +779,8 @@ RUNNER_TEST(T3044_remove_bin_data_C_API)
 
 RUNNER_TEST(T3045_save_big_data_C_API, RemoveDataEnv<USER_APP>)
 {
-       const size_t BIG_SIZE = 5000000;
+       // We don't know which backend will be used
+       const size_t BIG_SIZE = 100000;
 
        std::vector<char> big_data(BIG_SIZE);
        std::ifstream is("/dev/urandom", std::ifstream::binary);
index 76f1c92..c183c81 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *  Copyright (c) 2000 - 2019 Samsung Electronics Co., Ltd All Rights Reserved
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
 
 #include <string>
 #include <vector>
-#include <map>
-#include <sstream>
+#include <unordered_map>
 
 #include <dpl/test/test_runner.h>
 #include <ckm-common.h>
 #include <ckmc/ckmc-manager.h>
+#include <ckmc/ckmc-control.h>
 #include <ckm/ckm-type.h>
 #include <ckm/ckm-manager.h>
 #include <encryption-decryption-env.h>
@@ -57,24 +57,6 @@ EncryptionError apiEncrypt(ckmc_param_list_h params,
     return g_api->encrypt(params, key_alias, password, decrypted, ppencrypted);
 }
 
-// Policy backend to use in subsequent operations (global for each test case)
-PolicyBackend g_backend = PolicyBackend::DEFAULT;
-
-class testBackend {
-public:
-    testBackend(PolicyBackend backend){
-        m_backend = g_backend;
-        g_backend = backend;
-    }
-
-    virtual ~testBackend(){
-        //restore in destructor
-        g_backend = m_backend;
-    }
-private:
-    PolicyBackend m_backend;
-};
-
 inline CKM::Password _tostring(const char *str)
 {
     return (str == nullptr) ? Password() : Password(str);
@@ -127,167 +109,184 @@ struct KeyAliasPair
     Alias pub;
 };
 
-class EncEnv : public RemoveDataEnv<UID> {
-public:
-    EncEnv() : m_dbu(NULL) {}
-    ~EncEnv() { delete m_dbu; }
-
-    void init(const std::string& str) {
-        RemoveDataEnv<UID>::init(str);
-        m_dbu = new ScopedDBUnlock(UID, "db-pass"); // unlock user's database
+struct SyncEnv {
+    void init(const std::string&) {
+        g_api = &g_syncApi;
     }
 
     void finish() {
-        delete m_dbu;
-        m_dbu = NULL;
-        RemoveDataEnv<UID>::finish();
-        g_api = NULL;
-    }
-
-    ScopedDBUnlock* m_dbu;
-};
-
-struct SyncEnv : public EncEnv {
-    void init(const std::string& str) {
-        EncEnv::init(str);
-        g_api = &g_syncApi;
+        g_api = nullptr;
     }
 
     static std::string suffix() { return "_sync"; }
 };
 
-struct AsyncEnv : public EncEnv {
-    void init(const std::string& str) {
-        EncEnv::init(str);
+struct AsyncEnv {
+    void init(const std::string&) {
         g_api = &g_asyncApi;
     }
 
+    void finish() {
+        g_api = nullptr;
+    }
+
     static std::string suffix() { return "_async"; }
 };
 
-struct AlgoBase {
-    ckmc_algo_type_e m_type;
-    size_t m_keyLen;
-
-    AlgoBase(ckmc_algo_type_e type, size_t keyLen) : m_type(type), m_keyLen(keyLen) {}
-
-    virtual KeyAliasPair keyGen(const char* pass = nullptr, const char* suffix = nullptr) = 0;
+struct Algo {
+    ckmc_algo_type_e type;
+    size_t keyLen;
 };
 
-typedef std::shared_ptr<AlgoBase> AlgoBasePtr;
+std::unordered_map<size_t, std::vector<Alias>> g_symKeys;
+std::unordered_map<size_t, std::vector<KeyAliasPair>> g_asymKeys;
 
-template <typename T>
-AlgoBasePtr createAlgo(ckmc_algo_type_e type, size_t keyLen) {
-    return AlgoBasePtr(new T(type, keyLen));
-}
+enum KeyIdx {
+    PRIMARY = 0,
+    PASSWORD_PROTECTED = 1,
 
-struct AlgoAes : public AlgoBase {
-    AlgoAes(ckmc_algo_type_e type, size_t keyLen) : AlgoBase(type, keyLen) {}
-    KeyAliasPair keyGen(const char* pass = nullptr, const char* suffix = nullptr);
+    KEY_IDX_MAX
 };
 
-KeyAliasPair AlgoAes::keyGen(const char* pass, const char* suffix)
-{
-    KeyAliasPair aliases;
-    std::ostringstream oss;
-    std::string ownerId = getOwnerIdFromSelf();
-    CharPtr passPtr(nullptr, free);
-    if (pass)
-        passPtr.reset(strdup(pass));
+RawBufferPtr PLAIN_DATA;
+RawBufferPtr BIG_DATA;
+ckmc_raw_buffer_s* DEFAULT_IV;
+ckmc_raw_buffer_s* IV11;
+ckmc_raw_buffer_s* IV12;
+ckmc_raw_buffer_s* IV15;
+ckmc_raw_buffer_s* IV17;
+ckmc_raw_buffer_s* IV128;
+ckmc_raw_buffer_s* AAD32;
+ckmc_raw_buffer_s* AAD64;
 
-    oss << "aes_" << static_cast<int>(m_type) << "_" << m_keyLen << "_key_alias";
-    if (suffix)
-        oss << suffix;
-    aliases.prv = aliasWithLabel(ownerId.c_str(),oss.str().c_str());
-    aliases.pub = aliasWithLabel(ownerId.c_str(), oss.str().c_str());
+KeyAliasPair getKey(const Algo& algo, KeyIdx idx)
+{
+    if (algo.type == CKMC_ALGO_RSA_OAEP)
+        return g_asymKeys[algo.keyLen][idx];
 
-    ckmc_policy_s policy;
-    policy.extractable = false;
-    policy.password = passPtr.get();
+    KeyAliasPair pair;
+    pair.prv = g_symKeys[algo.keyLen][idx];
+    pair.pub = pair.prv;
+    return pair;
+}
 
-    auto mgr = CKM::Manager::create();
-    RUNNER_ASSERT_MSG(CKM_API_SUCCESS == mgr->createKeyAES(m_keyLen, Alias(aliases.prv.c_str()),
-                        _toCkmPolicy(policy, g_backend)),
-                        "AES key creation failed");
+class EncGroupFixture: public DPL::Test::TestGroup
+{
+public:
+    void Init() override
+    {
+        remove_user_data(UID);
+        int ret = ckmc_unlock_user_key(UID, "db-pass");
+        if (ret != CKMC_ERROR_NONE)
+            RUNNER_ERROR_MSG("DB unlock failed: " << CKMCErrorToString(ret));
+
+        // Policy backend to use in subsequent operations (global for each test case)
+#ifdef TZ_BACKEND
+        m_backend = PolicyBackend::FORCE_HARDWARE;
+#else
+        m_backend = PolicyBackend::FORCE_SOFTWARE;
+#endif
+
+        // generate keys
+        m_manager = Manager::create();
+        generateSymmetricKeys(128);
+        generateSymmetricKeys(192);
+        generateSymmetricKeys(256);
+        generateRsaKeys(1024);
+        generateRsaKeys(2048);
+        generateRsaKeys(4096);
+
+        PLAIN_DATA = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
+#ifdef TZ_BACKEND
+        BIG_DATA = create_raw_buffer(createRandomBufferCAPI(1000));
+#else
+        BIG_DATA = create_raw_buffer(createRandomBufferCAPI(5000000));
+#endif
+        DEFAULT_IV = createRandomBufferCAPI(DEFAULT_IV_LEN);
+        IV11 = createRandomBufferCAPI(11);
+        IV12 = createRandomBufferCAPI(12);
+        IV15 = createRandomBufferCAPI(15);
+        IV17 = createRandomBufferCAPI(17);
+        IV128 = createRandomBufferCAPI(128);
+        AAD32 = createRandomBufferCAPI(32);
+        AAD64 = createRandomBufferCAPI(64);
+    }
 
-    return aliases;
-}
+    void generateSymmetricKeys(size_t bitLen)
+    {
+        for (int i = 0; i < KEY_IDX_MAX; i++)
+        {
+            Policy p(Password(), false, m_backend);
+            if (i == PASSWORD_PROTECTED)
+                p.password.assign(PASSWORD);
+
+            std::string alias = std::string("skey_") + std::to_string(bitLen) + std::string("_") + std::to_string(i);
+            int ret = m_manager->createKeyAES(bitLen, alias, p);
+            if (ret != CKM_API_SUCCESS)
+                RUNNER_ERROR_MSG("AES key creation failed");
+
+            g_symKeys[bitLen].push_back(alias);
+        }
+    }
 
-struct AlgoRsa : public AlgoBase {
-    AlgoRsa(ckmc_algo_type_e type, size_t keyLen) : AlgoBase(type, keyLen) {}
-    KeyAliasPair keyGen(const char* pass = nullptr, const char* suffix = nullptr);
-};
+    void generateRsaKeys(size_t bitLen)
+    {
+        for (int i = 0; i < KEY_IDX_MAX; i++)
+        {
+            Policy prvPolicy(Password(), false, m_backend);
+            Policy pubPolicy(Password(), true, m_backend);
+            if (i == PASSWORD_PROTECTED) {
+                prvPolicy.password.assign(PASSWORD);
+                pubPolicy.password.assign(PASSWORD);
+            }
+
+            KeyAliasPair alias;
+            alias.prv = std::string("akey_") + std::to_string(bitLen) + std::string("_") + std::to_string(i);
+            alias.pub = std::string("pub") + alias.prv;
+            int ret = m_manager->createKeyPairRSA(bitLen, alias.prv, alias.pub, prvPolicy, pubPolicy);
+            if (ret != CKM_API_SUCCESS)
+                RUNNER_ERROR_MSG("RSA key creation failed");
+
+            g_asymKeys[bitLen].push_back(alias);
+        }
+    }
 
-KeyAliasPair AlgoRsa::keyGen(const char* pass, const char* suffix)
-{
-    std::ostringstream oss_prv, oss_pub;
-    oss_prv << "rsa_oaep_prv_alias_" << m_keyLen;
-    oss_pub << "rsa_oaep_pub_alias_" << m_keyLen;
-    if (suffix) {
-        oss_prv << suffix;
-        oss_pub << suffix;
+    void Finish() override
+    {
+        for (const auto &entry : g_asymKeys) {
+            for (const auto &keyPair : entry.second) {
+                m_manager->removeAlias(keyPair.prv);
+                m_manager->removeAlias(keyPair.pub);
+            }
+        }
+
+        for (const auto &entry : g_symKeys) {
+            for (const auto &key : entry.second) {
+                m_manager->removeAlias(key);
+            }
+        }
+
+        BIG_DATA.reset();
+        PLAIN_DATA.reset();
+        ckmc_buffer_free(AAD64);
+        ckmc_buffer_free(AAD32);
+        ckmc_buffer_free(IV128);
+        ckmc_buffer_free(IV17);
+        ckmc_buffer_free(IV15);
+        ckmc_buffer_free(IV12);
+        ckmc_buffer_free(IV11);
+        ckmc_buffer_free(DEFAULT_IV);
+
+        int ret = ckmc_lock_user_key(UID);
+        if (ret != CKMC_ERROR_NONE)
+            RUNNER_ERROR_MSG("DB lock failed: " << CKMCErrorToString(ret));
+        remove_user_data(UID);
     }
-    KeyAliasPair aliases = {
-            aliasWithLabel(getOwnerIdFromSelf().c_str(), oss_prv.str().c_str()),
-            aliasWithLabel(getOwnerIdFromSelf().c_str(), oss_pub.str().c_str())
-    };
-    CharPtr passPtr(nullptr, free);
-    if (pass)
-        passPtr.reset(strdup(pass));
-
-    ckmc_policy_s policyPrv;
-    policyPrv.password = passPtr.get();
-    policyPrv.extractable = 0;
-
-    ckmc_policy_s policyPub;
-    policyPub.password = passPtr.get();
-    policyPub.extractable = 0;
-
-    auto mgr = CKM::Manager::create();
-
-    RUNNER_ASSERT_MSG(CKM_API_SUCCESS == mgr->createKeyPairRSA(static_cast<int>(m_keyLen),
-                                                CKM::Alias(aliases.prv.c_str()),
-                                                CKM::Alias(aliases.pub.c_str()),
-                                                _toCkmPolicy(policyPrv, g_backend),
-                                                _toCkmPolicy(policyPub, g_backend)), "RSA key pair generation failed" );
-    return aliases;
-}
-
-enum Algorithm {
-    AES_CBC_128,
-    AES_CBC_192,
-    AES_CBC_256,
-    AES_GCM_128,
-    AES_GCM_192,
-    AES_GCM_256,
-    AES_CTR_128,
-    AES_CTR_192,
-    AES_CTR_256,
-    AES_CFB_128,
-    AES_CFB_192,
-    AES_CFB_256,
-    RSA_OAEP_1024,
-    RSA_OAEP_2048,
-    RSA_OAEP_4096,
+private:
+    ManagerShPtr m_manager;
+    PolicyBackend m_backend;
 };
 
-std::map<Algorithm, AlgoBasePtr> g_algorithms = {
-        { AES_CBC_128, createAlgo<AlgoAes>(CKMC_ALGO_AES_CBC, 128) },
-        { AES_CBC_192, createAlgo<AlgoAes>(CKMC_ALGO_AES_CBC, 192) },
-        { AES_CBC_256, createAlgo<AlgoAes>(CKMC_ALGO_AES_CBC, 256) },
-        { AES_GCM_128, createAlgo<AlgoAes>(CKMC_ALGO_AES_GCM, 128) },
-        { AES_GCM_192, createAlgo<AlgoAes>(CKMC_ALGO_AES_GCM, 192) },
-        { AES_GCM_256, createAlgo<AlgoAes>(CKMC_ALGO_AES_GCM, 256) },
-        { AES_CTR_128, createAlgo<AlgoAes>(CKMC_ALGO_AES_CTR, 128) },
-        { AES_CTR_192, createAlgo<AlgoAes>(CKMC_ALGO_AES_CTR, 192) },
-        { AES_CTR_256, createAlgo<AlgoAes>(CKMC_ALGO_AES_CTR, 256) },
-        { AES_CFB_128, createAlgo<AlgoAes>(CKMC_ALGO_AES_CFB, 128) },
-        { AES_CFB_192, createAlgo<AlgoAes>(CKMC_ALGO_AES_CFB, 192) },
-        { AES_CFB_256, createAlgo<AlgoAes>(CKMC_ALGO_AES_CFB, 256) },
-        { RSA_OAEP_1024, createAlgo<AlgoRsa>(CKMC_ALGO_RSA_OAEP, 1024) },
-        { RSA_OAEP_2048, createAlgo<AlgoRsa>(CKMC_ALGO_RSA_OAEP, 2048) },
-        { RSA_OAEP_4096, createAlgo<AlgoRsa>(CKMC_ALGO_RSA_OAEP, 4096) },
-};
 
 void setParam(ParamListPtr& params, ckmc_param_name_e name, ckmc_raw_buffer_s* buffer)
 {
@@ -311,18 +310,18 @@ struct EncryptionResult
     Alias pubKey;
 };
 
-EncryptionResult encrypt(const AlgoBasePtr& algo,
+EncryptionResult encrypt(const Algo& algo,
                          const RawBufferPtr& plain,
                          const char* pass = nullptr)
 {
     EncryptionResult ret;
     ckmc_raw_buffer_s* encrypted = nullptr;
-    KeyAliasPair aliases = algo->keyGen(pass);
+    KeyAliasPair aliases = getKey(algo, pass == nullptr ? PRIMARY : PASSWORD_PROTECTED);
 
     ckmc_param_list_h handle = NULL;
-    assert_positive(ckmc_generate_new_params, algo->m_type, &handle);
+    assert_positive(ckmc_generate_new_params, algo.type, &handle);
     ret.params = ParamListPtr(handle, ckmc_param_list_free);
-    setParam(ret.params, CKMC_PARAM_ED_IV, createRandomBufferCAPI(DEFAULT_IV_LEN));
+    setParam(ret.params, CKMC_PARAM_ED_IV, DEFAULT_IV);
 
     assert_crypto_positive(apiEncrypt,
                            ret.params.get(),
@@ -338,48 +337,55 @@ EncryptionResult encrypt(const AlgoBasePtr& algo,
 }
 
 void testAllAlgorithms(
-        const std::function<void(const AlgoBasePtr& algo)>& test)
-{
-    for(const auto& it : g_algorithms)
-        test(it.second);
-}
-
-void testNoIvEnc(Algorithm type)
+        const std::function<void(const Algo& algo)>& test)
+{
+    test( { CKMC_ALGO_AES_CBC, 128 });
+    test( { CKMC_ALGO_AES_CBC, 192 });
+    test( { CKMC_ALGO_AES_CBC, 256 });
+    test( { CKMC_ALGO_AES_GCM, 128 });
+    test( { CKMC_ALGO_AES_GCM, 192 });
+    test( { CKMC_ALGO_AES_GCM, 256 });
+    test( { CKMC_ALGO_AES_CTR, 128 });
+    test( { CKMC_ALGO_AES_CTR, 192 });
+    test( { CKMC_ALGO_AES_CTR, 256 });
+    test( { CKMC_ALGO_AES_CFB, 128 });
+    test( { CKMC_ALGO_AES_CFB, 192 });
+    test( { CKMC_ALGO_AES_CFB, 256 });
+    test( { CKMC_ALGO_RSA_OAEP, 1024 });
+    test( { CKMC_ALGO_RSA_OAEP, 2048 });
+    test( { CKMC_ALGO_RSA_OAEP, 4096 });
+}
+
+void testNoIvEnc(const Algo& algo)
 {
-    const AlgoBasePtr& algo = g_algorithms.at(type);
-
     // prepare buffers
-    RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
     ckmc_raw_buffer_s* encrypted = nullptr;
 
     // add key
-    KeyAliasPair aliases = algo->keyGen();
+    KeyAliasPair aliases = getKey(algo, PRIMARY);
 
     // param list with algo type only
     ParamListPtr params = createParamListPtr();
-    setParam(params, CKMC_PARAM_ALGO_TYPE, algo->m_type);
+    setParam(params, CKMC_PARAM_ALGO_TYPE, algo.type);
     assert_crypto_invalid_param(apiEncrypt,
                                 params.get(),
                                 aliases.pub.c_str(),
                                 nullptr,
-                                *plain.get(),
+                                *PLAIN_DATA.get(),
                                 &encrypted);
 }
 
-void testNoIvDec(Algorithm type)
+void testNoIvDec(const Algo& algo)
 {
-    const AlgoBasePtr& algo = g_algorithms.at(type);
-
     // prepare buffers
-    RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
     ckmc_raw_buffer_s* decrypted = nullptr;
 
     // encrypt;
-    auto ret = encrypt(algo, plain);
+    auto ret = encrypt(algo, PLAIN_DATA);
 
     // param list with algo type only
     ParamListPtr params = createParamListPtr();
-    setParam(params, CKMC_PARAM_ALGO_TYPE, algo->m_type);
+    setParam(params, CKMC_PARAM_ALGO_TYPE, algo.type);
     assert_crypto_invalid_param(apiDecrypt,
                                 params.get(),
                                 ret.prvKey.c_str(),
@@ -388,20 +394,17 @@ void testNoIvDec(Algorithm type)
                                 &decrypted);
 }
 
-void testInvalidIvEnc(Algorithm type)
+void testInvalidIvEnc(const Algo& algo)
 {
-    const AlgoBasePtr& algo = g_algorithms.at(type);
-
     // prepare buffers
-    RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
     ckmc_raw_buffer_s* encryptedTmp = nullptr;
 
     // add key
-    KeyAliasPair aliases = algo->keyGen();
+    KeyAliasPair aliases = getKey(algo, PRIMARY);
 
     // setup params
     ckmc_param_list_h handle = NULL;
-    assert_positive(ckmc_generate_new_params, algo->m_type, &handle);
+    assert_positive(ckmc_generate_new_params, algo.type, &handle);
     ParamListPtr params = ParamListPtr(handle, ckmc_param_list_free);
 
     // invalid encryption
@@ -410,28 +413,25 @@ void testInvalidIvEnc(Algorithm type)
                                     params.get(),
                                     aliases.pub.c_str(),
                                     nullptr,
-                                    *plain.get(),
+                                    *PLAIN_DATA.get(),
                                     &encryptedTmp);
         ckmc_buffer_free(encryptedTmp);
         encryptedTmp = nullptr;
     };
     // invalid iv size
-    setParam(params, CKMC_PARAM_ED_IV, createRandomBufferCAPI(DEFAULT_IV_LEN-1));
+    setParam(params, CKMC_PARAM_ED_IV, IV15);
     test();
-    setParam(params, CKMC_PARAM_ED_IV, createRandomBufferCAPI(DEFAULT_IV_LEN+1));
+    setParam(params, CKMC_PARAM_ED_IV, IV17);
     test();
 };
 
-void testInvalidIvDec(Algorithm type)
+void testInvalidIvDec(const Algo& algo)
 {
-    const AlgoBasePtr& algo = g_algorithms.at(type);
-
     // prepare buffers
-    RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
     ckmc_raw_buffer_s* decrypted = nullptr;
 
     // valid encryption
-    auto ret = encrypt(algo, plain);
+    auto ret = encrypt(algo, PLAIN_DATA);
 
     // decryption
     auto test2 = [&](){
@@ -446,40 +446,37 @@ void testInvalidIvDec(Algorithm type)
     };
 
     // invalid iv size
-    setParam(ret.params, CKMC_PARAM_ED_IV, createRandomBufferCAPI(DEFAULT_IV_LEN-1));
+    setParam(ret.params, CKMC_PARAM_ED_IV, IV15);
     test2();
-    setParam(ret.params, CKMC_PARAM_ED_IV, createRandomBufferCAPI(DEFAULT_IV_LEN+1));
+    setParam(ret.params, CKMC_PARAM_ED_IV, IV17);
     test2();
 };
 
-void encryptionWithCustomData(Algorithm type, ckmc_param_name_e name)
+void encryptionWithCustomData(const Algo& algo, ckmc_param_name_e name)
 {
-    const AlgoBasePtr& algo = g_algorithms.at(type);
-
     // prepare buffers
-    RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
     ckmc_raw_buffer_s* encrypted = nullptr;
     ckmc_raw_buffer_s* decrypted = nullptr;
 
     // add key
-    KeyAliasPair aliases = algo->keyGen();
+    KeyAliasPair aliases = getKey(algo, PRIMARY);
 
     // setup params
     ckmc_param_list_h handle = NULL;
-    assert_positive(ckmc_generate_new_params, algo->m_type, &handle);
+    assert_positive(ckmc_generate_new_params, algo.type, &handle);
     ParamListPtr params = ParamListPtr(handle, ckmc_param_list_free);
 
-    setParam(params, CKMC_PARAM_ED_IV, createRandomBufferCAPI(DEFAULT_IV_LEN));
+    setParam(params, CKMC_PARAM_ED_IV, DEFAULT_IV);
 
     // set AAD
-    setParam(params, name, createRandomBufferCAPI(64));
+    setParam(params, name, AAD64);
 
     // encrypt
     assert_crypto_positive(apiEncrypt,
                            params.get(),
                            aliases.pub.c_str(),
                            nullptr,
-                           *plain.get(),
+                           *PLAIN_DATA.get(),
                            &encrypted);
     RawBufferPtr tmpEnc = create_raw_buffer(encrypted);
 
@@ -493,12 +490,12 @@ void encryptionWithCustomData(Algorithm type, ckmc_param_name_e name)
     RawBufferPtr tmpDec = create_raw_buffer(decrypted);
 
     // check
-    assert_buffers_equal(*plain.get(), *tmpDec.get());
+    assert_buffers_equal(*PLAIN_DATA.get(), *tmpDec.get());
     tmpDec.reset();
     decrypted = nullptr;
 
     // set wrong AAD
-    setParam(params, name, createRandomBufferCAPI(32));
+    setParam(params, name, AAD32);
 
     // decrypt
     assert_crypto_result(EncryptionError::INVALID_PARAM,
@@ -510,12 +507,11 @@ void encryptionWithCustomData(Algorithm type, ckmc_param_name_e name)
                          &decrypted);
 }
 
-void testGcmIvSize(size_t size,
+void testGcmIvSize(ckmc_raw_buffer_s* iv,
                    const KeyAliasPair& aliases,
                    EncryptionError error = EncryptionError::SUCCESS)
 {
     // prepare buffers
-    RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
     RawBufferPtr encrypted;
     RawBufferPtr decrypted;
     ckmc_raw_buffer_s* encryptedTmp = nullptr;
@@ -525,8 +521,8 @@ void testGcmIvSize(size_t size,
     ckmc_param_list_h handle = NULL;
     assert_positive(ckmc_generate_new_params, CKMC_ALGO_AES_GCM, &handle);
     ParamListPtr params = ParamListPtr(handle, ckmc_param_list_free);
-    setParam(params, CKMC_PARAM_ED_IV, createRandomBufferCAPI(DEFAULT_IV_LEN));
-    setParam(params, CKMC_PARAM_ED_IV, createRandomBufferCAPI(size));
+    setParam(params, CKMC_PARAM_ED_IV, DEFAULT_IV);
+    setParam(params, CKMC_PARAM_ED_IV, iv);
 
     // encryption
     assert_crypto_result(error,
@@ -534,7 +530,7 @@ void testGcmIvSize(size_t size,
                          params.get(),
                          aliases.pub.c_str(),
                          nullptr,
-                         *plain.get(),
+                         *PLAIN_DATA.get(),
                          &encryptedTmp);
 
     if(error != EncryptionError::SUCCESS)
@@ -550,19 +546,16 @@ void testGcmIvSize(size_t size,
                            &decryptedTmp);
     decrypted = create_raw_buffer(decryptedTmp);
 
-    assert_buffers_equal(*plain.get(), *decrypted.get());
+    assert_buffers_equal(*PLAIN_DATA.get(), *decrypted.get());
 }
 
-void testIntegrity(Algorithm type)
+void testIntegrity(const Algo& algo)
 {
-    const AlgoBasePtr& algo = g_algorithms.at(type);
-
     // prepare buffers
-    RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
     ckmc_raw_buffer_s* decrypted = nullptr;
 
     // encrypt
-    auto ret = encrypt(algo, plain);
+    auto ret = encrypt(algo, PLAIN_DATA);
 
     // break the encrypted data
     ret.encrypted->data[BUF_LEN/2]++;
@@ -576,25 +569,22 @@ void testIntegrity(Algorithm type)
                            &decrypted);
 
     RawBufferPtr tmp = create_raw_buffer(decrypted);
-    assert_buffers_equal(*plain.get(), *decrypted, false);
+    assert_buffers_equal(*PLAIN_DATA.get(), *decrypted, false);
 }
 
-void testCtrEncryptionInvalidLength(Algorithm type)
+void testCtrEncryptionInvalidLength(const Algo& algo)
 {
-    const AlgoBasePtr& algo = g_algorithms.at(type);
-
     // prepare buffers
-    RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
     ckmc_raw_buffer_s* encryptedTmp = nullptr;
 
     // add AES CTR key
-    KeyAliasPair aliases = algo->keyGen();
+    KeyAliasPair aliases = getKey(algo, PRIMARY);
 
     // setup params
     ckmc_param_list_h handle = NULL;
-    assert_positive(ckmc_generate_new_params, algo->m_type, &handle);
+    assert_positive(ckmc_generate_new_params, algo.type, &handle);
     ParamListPtr params = ParamListPtr(handle, ckmc_param_list_free);
-    setParam(params, CKMC_PARAM_ED_IV, createRandomBufferCAPI(DEFAULT_IV_LEN));
+    setParam(params, CKMC_PARAM_ED_IV, DEFAULT_IV);
 
     // encryption
     auto test = [&](){
@@ -602,7 +592,7 @@ void testCtrEncryptionInvalidLength(Algorithm type)
                                     params.get(),
                                     aliases.pub.c_str(),
                                     nullptr,
-                                    *plain.get(),
+                                    *PLAIN_DATA.get(),
                                     &encryptedTmp);
         ckmc_buffer_free(encryptedTmp);
         encryptedTmp = nullptr;
@@ -616,22 +606,19 @@ void testCtrEncryptionInvalidLength(Algorithm type)
     test();
 }
 
-void testCtrEncryptionValidLength(Algorithm type)
+void testCtrEncryptionValidLength(const Algo& algo)
 {
-    const AlgoBasePtr& algo = g_algorithms.at(type);
-
     // prepare buffers
-    RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
     ckmc_raw_buffer_s* encryptedTmp = nullptr;
 
     // add AES CTR key
-    KeyAliasPair aliases = algo->keyGen();
+    KeyAliasPair aliases = getKey(algo, PRIMARY);
 
     // setup params
     ckmc_param_list_h handle = NULL;
-    assert_positive(ckmc_generate_new_params, algo->m_type, &handle);
+    assert_positive(ckmc_generate_new_params, algo.type, &handle);
     ParamListPtr params = ParamListPtr(handle, ckmc_param_list_free);
-    setParam(params, CKMC_PARAM_ED_IV, createRandomBufferCAPI(DEFAULT_IV_LEN));
+    setParam(params, CKMC_PARAM_ED_IV, DEFAULT_IV);
 
     // encryption
     auto test = [&](){
@@ -639,7 +626,7 @@ void testCtrEncryptionValidLength(Algorithm type)
                                params.get(),
                                aliases.pub.c_str(),
                                nullptr,
-                               *plain.get(),
+                               *PLAIN_DATA.get(),
                                &encryptedTmp);
         ckmc_buffer_free(encryptedTmp);
         encryptedTmp = nullptr;
@@ -655,16 +642,13 @@ void testCtrEncryptionValidLength(Algorithm type)
     test();
 }
 
-void testCtrDecryptionInvalidLength(Algorithm type)
+void testCtrDecryptionInvalidLength(const Algo& algo)
 {
-    const AlgoBasePtr& algo = g_algorithms.at(type);
-
     // prepare buffers
-    RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
     ckmc_raw_buffer_s* decrypted = nullptr;
 
     // add AES CTR key & encrypt
-    auto ret = encrypt(algo, plain);
+    auto ret = encrypt(algo, PLAIN_DATA);
 
     // decryption
     auto test = [&](){
@@ -686,16 +670,13 @@ void testCtrDecryptionInvalidLength(Algorithm type)
     test();
 }
 
-void testCtrDecryptionValidLength(Algorithm type)
+void testCtrDecryptionValidLength(const Algo& algo)
 {
-    const AlgoBasePtr& algo = g_algorithms.at(type);
-
     // prepare buffers
-    RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
     ckmc_raw_buffer_s* decrypted = nullptr;
 
     // add AES CTR key & encrypt
-    auto ret = encrypt(algo, plain);
+    auto ret = encrypt(algo, PLAIN_DATA);
 
     // decryption
     auto test = [&](){
@@ -707,7 +688,7 @@ void testCtrDecryptionValidLength(Algorithm type)
                                &decrypted);
         ckmc_buffer_free(decrypted);
         RawBufferPtr tmp = create_raw_buffer(decrypted);
-        assert_buffers_equal(*plain.get(), *decrypted);
+        assert_buffers_equal(*PLAIN_DATA.get(), *decrypted);
     };
     // invalid counter size
     setParam(ret.params, CKMC_PARAM_ED_CTR_LEN, 1);
@@ -720,22 +701,19 @@ void testCtrDecryptionValidLength(Algorithm type)
     test();
 }
 
-void testGcmEncryptionTagLen(Algorithm type)
+void testGcmEncryptionTagLen(const Algo& algo)
 {
-    const AlgoBasePtr& algo = g_algorithms.at(type);
-
     // prepare buffers
-    RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
     ckmc_raw_buffer_s* encryptedTmp = nullptr;
 
     // add AES GCM key
-    KeyAliasPair aliases = algo->keyGen();
+    KeyAliasPair aliases = getKey(algo, PRIMARY);
 
     // setup params
     ckmc_param_list_h handle = NULL;
-    assert_positive(ckmc_generate_new_params, algo->m_type, &handle);
+    assert_positive(ckmc_generate_new_params, algo.type, &handle);
     ParamListPtr params = ParamListPtr(handle, ckmc_param_list_free);
-    setParam(params, CKMC_PARAM_ED_IV, createRandomBufferCAPI(DEFAULT_IV_LEN));
+    setParam(params, CKMC_PARAM_ED_IV, DEFAULT_IV);
 
     std::vector<TagTest> testData = {
             // illegal tag lengths
@@ -749,9 +727,16 @@ void testGcmEncryptionTagLen(Algorithm type)
             { 116,  EncryptionError::INVALID_PARAM },
             { 124,  EncryptionError::INVALID_PARAM },
             { 256,  EncryptionError::INVALID_PARAM },
+#ifdef TZ_BACKEND
+            { 32,   EncryptionError::INVALID_PARAM },
+            { 64,   EncryptionError::INVALID_PARAM },
+            // legal tag lengths
+#else
             // legal tag lengths
             { 32,   EncryptionError::SUCCESS },
             { 64,   EncryptionError::SUCCESS },
+#endif
+
             { 96,   EncryptionError::SUCCESS },
             { 104,  EncryptionError::SUCCESS },
             { 112,  EncryptionError::SUCCESS },
@@ -768,23 +753,20 @@ void testGcmEncryptionTagLen(Algorithm type)
                              params.get(),
                              aliases.pub.c_str(),
                              nullptr,
-                             *plain.get(),
+                             *PLAIN_DATA.get(),
                              &encryptedTmp);
         ckmc_buffer_free(encryptedTmp);
         encryptedTmp = nullptr;
     }
 }
 
-void testGcmDecryptionTagLen(Algorithm type)
+void testGcmDecryptionTagLen(const Algo& algo)
 {
-    const AlgoBasePtr& algo = g_algorithms.at(type);
-
     // prepare buffers
-    RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
     ckmc_raw_buffer_s* decrypted = nullptr;
 
     // add AES GCM key & encrypt
-    auto ret = encrypt(algo, plain);
+    auto ret = encrypt(algo, PLAIN_DATA);
 
     std::vector<TagTest> testData = {
             // illegal tag lengths
@@ -825,16 +807,13 @@ void testGcmDecryptionTagLen(Algorithm type)
     }
 }
 
-void testGcmWrongTag(Algorithm type)
+void testGcmWrongTag(const Algo& algo)
 {
-    const AlgoBasePtr& algo = g_algorithms.at(type);
-
     // prepare buffers
-    RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
     ckmc_raw_buffer_s* decrypted = nullptr;
 
     // encrypt with AES GCM
-    auto ret = encrypt(algo, plain);
+    auto ret = encrypt(algo, PLAIN_DATA);
 
     // modify tag (last 16B of encrypted message)
     ret.encrypted->data[ret.encrypted->size-1]++;
@@ -849,29 +828,24 @@ void testGcmWrongTag(Algorithm type)
                          &decrypted);
 }
 
-void testGcmDifferentIvSizes(Algorithm type)
+void testGcmDifferentIvSizes(const Algo& algo)
 {
-    const AlgoBasePtr& algo = g_algorithms.at(type);
-
     // add AES GCM key
-    KeyAliasPair aliases = algo->keyGen();
+    KeyAliasPair aliases = getKey(algo, PRIMARY);
 
-    testGcmIvSize(11,  aliases, EncryptionError::SERVER_ERROR); // 12B is the smallest
-    testGcmIvSize(12,  aliases);
-    testGcmIvSize(17,  aliases);
-    testGcmIvSize(128, aliases);
+    testGcmIvSize(IV11,  aliases, EncryptionError::SERVER_ERROR); // 12B is the smallest
+    testGcmIvSize(IV12,  aliases);
+    testGcmIvSize(IV17,  aliases);
+    testGcmIvSize(IV128, aliases);
 }
 
-void testEncryptDecryptBigData(Algorithm type)
+void testEncryptDecryptBigData(const Algo& algo)
 {
-    const AlgoBasePtr& algo = g_algorithms.at(type);
-
     // prepare buffers
-    RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(5000000));
     ckmc_raw_buffer_s* decrypted = nullptr;
 
     // encrypt
-    auto ret = encrypt(algo, plain);
+    auto ret = encrypt(algo, BIG_DATA);
 
     assert_positive(apiDecrypt,
                     ret.params.get(),
@@ -881,53 +855,44 @@ void testEncryptDecryptBigData(Algorithm type)
                     &decrypted);
     RawBufferPtr tmp = create_raw_buffer(decrypted);
 
-    assert_buffers_equal(*plain.get(), *decrypted);
+    assert_buffers_equal(*BIG_DATA.get(), *decrypted);
 }
 
-void testEncryptDecryptDifferentKeys(Algorithm type, bool success)
+void testEncryptDecryptDifferentKeys(const Algo& algo, bool success)
 {
-    const AlgoBasePtr& algo = g_algorithms.at(type);
     // prepare buffers
-    RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
     ckmc_raw_buffer_s* decrypted = nullptr;
 
     // encrypt
-    auto ret = encrypt(algo, plain);
+    auto ret = encrypt(algo, PLAIN_DATA);
 
-    // add different key
-    KeyAliasPair differentKeys = algo->keyGen(nullptr, "_wrong");
+    // get different keys
+    KeyAliasPair differentKeys = getKey(algo, PASSWORD_PROTECTED);
 
     if (success) {
         // some algorithms don't verify key validity
         assert_crypto_positive(apiDecrypt,
                                ret.params.get(),
                                differentKeys.prv.c_str(),
-                               nullptr,
+                               PASSWORD,
                                *ret.encrypted.get(),
                                &decrypted);
         RawBufferPtr tmp = create_raw_buffer(decrypted);
 
-        assert_buffers_equal(*plain.get(), *decrypted, false);
+        assert_buffers_equal(*PLAIN_DATA.get(), *decrypted, false);
     } else {
-               assert_crypto_result(EncryptionError::INVALID_PARAM,
+        assert_crypto_result(EncryptionError::INVALID_PARAM,
                              apiDecrypt,
                              ret.params.get(),
                              differentKeys.prv.c_str(),
-                             nullptr,
+                             PASSWORD,
                              *ret.encrypted.get(),
                              &decrypted);
-       }
-
-    // Cleanup before testing next algorithm. Ignore results because not all keys are present
-    ckmc_remove_alias(ret.prvKey.c_str());
-    ckmc_remove_alias(ret.pubKey.c_str());
-    ckmc_remove_alias(differentKeys.prv.c_str());
-    ckmc_remove_alias(differentKeys.pub.c_str());
+    }
 }
 
-void testRsaLongestData(Algorithm type, size_t dataSize)
+void testRsaLongestData(const Algo& algo, size_t dataSize)
 {
-    const AlgoBasePtr& algo = g_algorithms.at(type);
     // prepare buffers
     RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(dataSize));
     ckmc_raw_buffer_s* decrypted = nullptr;
@@ -946,19 +911,18 @@ void testRsaLongestData(Algorithm type, size_t dataSize)
     assert_buffers_equal(*plain.get(), *decrypted);
 }
 
-void testRsaDataTooLong(Algorithm type, size_t dataSize)
+void testRsaDataTooLong(const Algo& algo, size_t dataSize)
 {
-    const AlgoBasePtr& algo = g_algorithms.at(type);
     // prepare buffers
     RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(dataSize));
 
     // encrypt
     EncryptionResult ret;
     ckmc_raw_buffer_s* encrypted = nullptr;
-    KeyAliasPair aliases = algo->keyGen();
+    KeyAliasPair aliases = getKey(algo, PRIMARY);
 
     ckmc_param_list_h handle = NULL;
-    assert_positive(ckmc_generate_new_params, algo->m_type, &handle);
+    assert_positive(ckmc_generate_new_params, algo.type, &handle);
     ret.params = ParamListPtr(handle, ckmc_param_list_free);
     assert_crypto_result(EncryptionError::INVALID_PARAM,
                          apiEncrypt,
@@ -971,8 +935,7 @@ void testRsaDataTooLong(Algorithm type, size_t dataSize)
 
 } // namespace anonymous
 
-
-RUNNER_TEST_GROUP_INIT(CKM_ENCRYPTION_DECRYPTION);
+RUNNER_TEST_GROUP_INIT_ENV(CKM_ENCRYPTION_DECRYPTION, EncGroupFixture);
 
 /////////////////////////////////////////
 // Generic encryption decryption tests
@@ -980,20 +943,19 @@ RUNNER_TEST_GROUP_INIT(CKM_ENCRYPTION_DECRYPTION);
 
 RUNNER_TEST_MULTIPLE(TED_0010_encrypt_invalid_param_list, SyncEnv, AsyncEnv)
 {
-    testAllAlgorithms([](const AlgoBasePtr& algo){
+    testAllAlgorithms([](const Algo& algo){
         // prepare buffers
-        RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
         ckmc_raw_buffer_s* encrypted = nullptr;
 
         // add key
-        KeyAliasPair aliases = algo->keyGen();
+        KeyAliasPair aliases = getKey(algo, PRIMARY);
 
         // null param list
         assert_crypto_invalid_param(apiEncrypt,
                                     nullptr,
                                     aliases.pub.c_str(),
                                     nullptr,
-                                    *plain.get(),
+                                    *PLAIN_DATA.get(),
                                     &encrypted);
 
         // empty param list
@@ -1002,49 +964,48 @@ RUNNER_TEST_MULTIPLE(TED_0010_encrypt_invalid_param_list, SyncEnv, AsyncEnv)
                                     params.get(),
                                     aliases.pub.c_str(),
                                     nullptr,
-                                    *plain.get(),
+                                    *PLAIN_DATA.get(),
                                     &encrypted);
     });
 }
 
 RUNNER_TEST_MULTIPLE(TED_0020_encrypt_missing_key, SyncEnv, AsyncEnv)
 {
-    testAllAlgorithms([](const AlgoBasePtr& algo){
+    testAllAlgorithms([](const Algo& algo){
         // prepare buffers
-        RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
         ckmc_raw_buffer_s* encrypted = nullptr;
 
         // setup params
         ckmc_param_list_h handle = NULL;
-        assert_positive(ckmc_generate_new_params, algo->m_type, &handle);
+        assert_positive(ckmc_generate_new_params, algo.type, &handle);
         ParamListPtr params = ParamListPtr(handle, ckmc_param_list_free);
-        setParam(params, CKMC_PARAM_ED_IV, createRandomBufferCAPI(DEFAULT_IV_LEN));
+        setParam(params, CKMC_PARAM_ED_IV, DEFAULT_IV);
 
         assert_crypto_result(EncryptionError::ALIAS_UNKNOWN,
                              apiEncrypt,
                              params.get(),
                              "non-existing-key-alias",
                              nullptr,
-                             *plain.get(),
+                             *PLAIN_DATA.get(),
                              &encrypted);
     });
 }
 
 RUNNER_TEST_MULTIPLE(TED_0030_encrypt_no_plain_text, SyncEnv, AsyncEnv)
 {
-    testAllAlgorithms([](const AlgoBasePtr& algo){
+    testAllAlgorithms([](const Algo& algo){
         // prepare buffers
         ckmc_raw_buffer_s plain = { nullptr, 0 };
         ckmc_raw_buffer_s* encrypted = nullptr;
 
         // add key
-        KeyAliasPair aliases = algo->keyGen();
+        KeyAliasPair aliases = getKey(algo, PRIMARY);
 
         // setup params
         ckmc_param_list_h handle = NULL;
-        assert_positive(ckmc_generate_new_params, algo->m_type, &handle);
+        assert_positive(ckmc_generate_new_params, algo.type, &handle);
         ParamListPtr params = ParamListPtr(handle, ckmc_param_list_free);
-        setParam(params, CKMC_PARAM_ED_IV, createRandomBufferCAPI(DEFAULT_IV_LEN));
+        setParam(params, CKMC_PARAM_ED_IV, DEFAULT_IV);
 
         assert_crypto_invalid_param(apiEncrypt,
                                     params.get(),
@@ -1057,38 +1018,36 @@ RUNNER_TEST_MULTIPLE(TED_0030_encrypt_no_plain_text, SyncEnv, AsyncEnv)
 
 RUNNER_TEST_MULTIPLE(TED_0040_encrypt_no_output_buffer, SyncEnv, AsyncEnv)
 {
-    testAllAlgorithms([](const AlgoBasePtr& algo){
+    testAllAlgorithms([](const Algo& algo){
         // prepare buffers
-        RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
         ckmc_raw_buffer_s** encrypted = nullptr;
 
         // add key
-        KeyAliasPair aliases = algo->keyGen();
+        KeyAliasPair aliases = getKey(algo, PRIMARY);
 
         // setup params
         ckmc_param_list_h handle = NULL;
-        assert_positive(ckmc_generate_new_params, algo->m_type, &handle);
+        assert_positive(ckmc_generate_new_params, algo.type, &handle);
         ParamListPtr params = ParamListPtr(handle, ckmc_param_list_free);
-        setParam(params, CKMC_PARAM_ED_IV, createRandomBufferCAPI(DEFAULT_IV_LEN));
+        setParam(params, CKMC_PARAM_ED_IV, DEFAULT_IV);
 
         assert_crypto_invalid_param(apiEncrypt,
                                     params.get(),
                                     aliases.pub.c_str(),
                                     nullptr,
-                                    *plain.get(),
+                                    *PLAIN_DATA.get(),
                                     encrypted);
     });
 }
 
 RUNNER_TEST_MULTIPLE(TED_0110_decrypt_invalid_param_list, SyncEnv, AsyncEnv)
 {
-    testAllAlgorithms([](const AlgoBasePtr& algo){
+    testAllAlgorithms([](const Algo& algo){
         // prepare buffers
-        RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
         ckmc_raw_buffer_s* decrypted = nullptr;
 
         // encrypt;
-        auto ret = encrypt(algo, plain);
+        auto ret = encrypt(algo, PLAIN_DATA);
 
         // null param list
         assert_crypto_invalid_param(apiDecrypt,
@@ -1111,22 +1070,18 @@ RUNNER_TEST_MULTIPLE(TED_0110_decrypt_invalid_param_list, SyncEnv, AsyncEnv)
 
 RUNNER_TEST_MULTIPLE(TED_0120_decrypt_missing_key, SyncEnv, AsyncEnv)
 {
-    testAllAlgorithms([](const AlgoBasePtr& algo){
+    testAllAlgorithms([](const Algo& algo){
         // prepare buffers
-        RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
         ckmc_raw_buffer_s* decrypted = nullptr;
 
         // encrypt
-        auto ret = encrypt(algo, plain);
-
-        // remove key
-        assert_positive(ckmc_remove_alias, ret.prvKey.c_str());
+        auto ret = encrypt(algo, PLAIN_DATA);
 
         // try to decrypt
         assert_crypto_result(EncryptionError::ALIAS_UNKNOWN,
                              apiDecrypt,
                              ret.params.get(),
-                             ret.prvKey.c_str(),
+                             "non-existent-key",
                              nullptr,
                              *ret.encrypted.get(),
                              &decrypted);
@@ -1135,19 +1090,19 @@ RUNNER_TEST_MULTIPLE(TED_0120_decrypt_missing_key, SyncEnv, AsyncEnv)
 
 RUNNER_TEST_MULTIPLE(TED_0130_decrypt_no_encrypted_text, SyncEnv, AsyncEnv)
 {
-    testAllAlgorithms([](const AlgoBasePtr& algo){
+    testAllAlgorithms([](const Algo& algo){
         // prepare buffers
         ckmc_raw_buffer_s encrypted = { nullptr, 0 };
         ckmc_raw_buffer_s* decrypted = nullptr;
 
         // add key
-        KeyAliasPair aliases = algo->keyGen();
+        KeyAliasPair aliases = getKey(algo, PRIMARY);
 
         // setup params
         ckmc_param_list_h handle = NULL;
-        assert_positive(ckmc_generate_new_params, algo->m_type, &handle);
+        assert_positive(ckmc_generate_new_params, algo.type, &handle);
         ParamListPtr params = ParamListPtr(handle, ckmc_param_list_free);
-        setParam(params, CKMC_PARAM_ED_IV, createRandomBufferCAPI(DEFAULT_IV_LEN));
+        setParam(params, CKMC_PARAM_ED_IV, DEFAULT_IV);
 
         assert_crypto_invalid_param(apiDecrypt,
                                     params.get(),
@@ -1160,13 +1115,12 @@ RUNNER_TEST_MULTIPLE(TED_0130_decrypt_no_encrypted_text, SyncEnv, AsyncEnv)
 
 RUNNER_TEST_MULTIPLE(TED_0140_decrypt_no_output_buffer, SyncEnv, AsyncEnv)
 {
-    testAllAlgorithms([](const AlgoBasePtr& algo){
+    testAllAlgorithms([](const Algo& algo){
         // prepare buffers
-        RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
         ckmc_raw_buffer_s** decrypted = nullptr;
 
         // encrypt
-        auto ret = encrypt(algo, plain);
+        auto ret = encrypt(algo, PLAIN_DATA);
 
         assert_crypto_invalid_param(apiDecrypt,
                                     ret.params.get(),
@@ -1179,33 +1133,28 @@ RUNNER_TEST_MULTIPLE(TED_0140_decrypt_no_output_buffer, SyncEnv, AsyncEnv)
 
 RUNNER_TEST_MULTIPLE(TED_0200_encrypt_decrypt_different_keys, SyncEnv, AsyncEnv)
 {
-    testBackend b(PolicyBackend::FORCE_SOFTWARE);
-    testEncryptDecryptDifferentKeys(AES_CBC_128, false);
-    testEncryptDecryptDifferentKeys(AES_CBC_192, false);
-    testEncryptDecryptDifferentKeys(AES_CBC_256, false);
-    testEncryptDecryptDifferentKeys(AES_GCM_128, false);
-    testEncryptDecryptDifferentKeys(AES_GCM_192, false);
-    testEncryptDecryptDifferentKeys(AES_GCM_256, false);
-    testEncryptDecryptDifferentKeys(AES_CTR_128, true);
-    testEncryptDecryptDifferentKeys(AES_CTR_192, true);
-    testEncryptDecryptDifferentKeys(AES_CTR_256, true);
-    testEncryptDecryptDifferentKeys(AES_CFB_128, true);
-    testEncryptDecryptDifferentKeys(AES_CFB_192, true);
-    testEncryptDecryptDifferentKeys(AES_CFB_256, true);
-    testEncryptDecryptDifferentKeys(RSA_OAEP_1024, false);
-    testEncryptDecryptDifferentKeys(RSA_OAEP_2048, false);
-    testEncryptDecryptDifferentKeys(RSA_OAEP_4096, false);
+    testEncryptDecryptDifferentKeys({CKMC_ALGO_AES_GCM, 128}, false);
+    testEncryptDecryptDifferentKeys({CKMC_ALGO_AES_GCM, 192}, false);
+    testEncryptDecryptDifferentKeys({CKMC_ALGO_AES_GCM, 256}, false);
+    testEncryptDecryptDifferentKeys({CKMC_ALGO_AES_CTR, 128}, true);
+    testEncryptDecryptDifferentKeys({CKMC_ALGO_AES_CTR, 192}, true);
+    testEncryptDecryptDifferentKeys({CKMC_ALGO_AES_CTR, 256}, true);
+    testEncryptDecryptDifferentKeys({CKMC_ALGO_AES_CFB, 128}, true);
+    testEncryptDecryptDifferentKeys({CKMC_ALGO_AES_CFB, 192}, true);
+    testEncryptDecryptDifferentKeys({CKMC_ALGO_AES_CFB, 256}, true);
+    testEncryptDecryptDifferentKeys({CKMC_ALGO_RSA_OAEP, 1024}, false);
+    testEncryptDecryptDifferentKeys({CKMC_ALGO_RSA_OAEP, 2048}, false);
+    testEncryptDecryptDifferentKeys({CKMC_ALGO_RSA_OAEP, 4096}, false);
 }
 
 RUNNER_TEST_MULTIPLE(TED_0300_encrypt_decrypt, SyncEnv, AsyncEnv)
 {
-    testAllAlgorithms([](const AlgoBasePtr& algo){
+    testAllAlgorithms([](const Algo& algo){
         // prepare buffers
-        RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
         ckmc_raw_buffer_s* decrypted = nullptr;
 
         // encrypt
-        auto ret = encrypt(algo, plain);
+        auto ret = encrypt(algo, PLAIN_DATA);
 
         assert_crypto_positive(apiDecrypt,
                                ret.params.get(),
@@ -1215,19 +1164,18 @@ RUNNER_TEST_MULTIPLE(TED_0300_encrypt_decrypt, SyncEnv, AsyncEnv)
                                &decrypted);
         RawBufferPtr tmp = create_raw_buffer(decrypted);
 
-        assert_buffers_equal(*plain.get(), *decrypted);
+        assert_buffers_equal(*PLAIN_DATA.get(), *decrypted);
     });
 }
 
 RUNNER_TEST_MULTIPLE(TED_0310_encrypt_decrypt_password, SyncEnv, AsyncEnv)
 {
-    testAllAlgorithms([](const AlgoBasePtr& algo){
+    testAllAlgorithms([](const Algo& algo){
         // prepare buffers
-        RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
         ckmc_raw_buffer_s* decrypted = nullptr;
 
         // encrypt
-        auto ret = encrypt(algo, plain, PASSWORD);
+        auto ret = encrypt(algo, PLAIN_DATA, PASSWORD);
 
         // wrong password
         assert_crypto_result(EncryptionError::AUTH_FAILED,
@@ -1247,81 +1195,69 @@ RUNNER_TEST_MULTIPLE(TED_0310_encrypt_decrypt_password, SyncEnv, AsyncEnv)
                                &decrypted);
         RawBufferPtr tmp = create_raw_buffer(decrypted); // guarantees deletion
 
-        assert_buffers_equal(*plain.get(), *decrypted);
+        assert_buffers_equal(*PLAIN_DATA.get(), *decrypted);
     });
 }
 
 // long test split into smaller ones
-RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_aes_cbc_128, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_CBC_128, SyncEnv, AsyncEnv)
 {
-    testBackend b(PolicyBackend::FORCE_SOFTWARE);
-    testEncryptDecryptBigData(AES_CBC_128);
+    testEncryptDecryptBigData({CKMC_ALGO_AES_CBC, 128});
 }
 
-RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_aes_cbc_192, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_CBC_192, SyncEnv, AsyncEnv)
 {
-    testBackend b(PolicyBackend::FORCE_SOFTWARE);
-    testEncryptDecryptBigData(AES_CBC_192);
+    testEncryptDecryptBigData({CKMC_ALGO_AES_CBC, 192});
 }
 
-RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_aes_cbc_256, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_CBC_256, SyncEnv, AsyncEnv)
 {
-    testBackend b(PolicyBackend::FORCE_SOFTWARE);
-    testEncryptDecryptBigData(AES_CBC_256);
+    testEncryptDecryptBigData({CKMC_ALGO_AES_CBC, 256});
 }
 
-RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_aes_gcm_128, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_GCM_128, SyncEnv, AsyncEnv)
 {
-    testBackend b(PolicyBackend::FORCE_SOFTWARE);
-    testEncryptDecryptBigData(AES_GCM_128);
+    testEncryptDecryptBigData({CKMC_ALGO_AES_GCM, 128});
 }
 
-RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_aes_gcm_192, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_GCM_192, SyncEnv, AsyncEnv)
 {
-    testBackend b(PolicyBackend::FORCE_SOFTWARE);
-    testEncryptDecryptBigData(AES_GCM_192);
+    testEncryptDecryptBigData({CKMC_ALGO_AES_GCM, 192});
 }
 
-RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_aes_gcm_256, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_GCM_256, SyncEnv, AsyncEnv)
 {
-    testBackend b(PolicyBackend::FORCE_SOFTWARE);
-    testEncryptDecryptBigData(AES_GCM_256);
+    testEncryptDecryptBigData({CKMC_ALGO_AES_GCM, 256});
 }
 
-RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_aes_ctr_128, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_CTR_128, SyncEnv, AsyncEnv)
 {
-    testBackend b(PolicyBackend::FORCE_SOFTWARE);
-    testEncryptDecryptBigData(AES_CTR_128);
+    testEncryptDecryptBigData({CKMC_ALGO_AES_CTR, 128});
 }
 
-RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_aes_ctr_192, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_CTR_192, SyncEnv, AsyncEnv)
 {
-    testBackend b(PolicyBackend::FORCE_SOFTWARE);
-    testEncryptDecryptBigData(AES_CTR_192);
+    testEncryptDecryptBigData({CKMC_ALGO_AES_CTR, 192});
 }
 
-RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_aes_ctr_256, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_CTR_256, SyncEnv, AsyncEnv)
 {
-    testBackend b(PolicyBackend::FORCE_SOFTWARE);
-    testEncryptDecryptBigData(AES_CTR_256);
+    testEncryptDecryptBigData({CKMC_ALGO_AES_CTR, 256});
 }
 
-RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_aes_cfb_128, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_CFB_128, SyncEnv, AsyncEnv)
 {
-    testBackend b(PolicyBackend::FORCE_SOFTWARE);
-    testEncryptDecryptBigData(AES_CFB_128);
+    testEncryptDecryptBigData({CKMC_ALGO_AES_CFB, 128});
 }
 
-RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_aes_cfb_192, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_CFB_192, SyncEnv, AsyncEnv)
 {
-    testBackend b(PolicyBackend::FORCE_SOFTWARE);
-    testEncryptDecryptBigData(AES_CFB_192);
+    testEncryptDecryptBigData({CKMC_ALGO_AES_CFB, 192});
 }
 
-RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_aes_cfb_256, SyncEnv, AsyncEnv)
+RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_AES_CFB_256, SyncEnv, AsyncEnv)
 {
-    testBackend b(PolicyBackend::FORCE_SOFTWARE);
-    testEncryptDecryptBigData(AES_CFB_256);
+    testEncryptDecryptBigData({CKMC_ALGO_AES_CFB, 256});
 }
 
 /////////////////////////////////////////
@@ -1330,183 +1266,179 @@ RUNNER_TEST_MULTIPLE(TED_0400_encrypt_decrypt_big_data_aes_cfb_256, SyncEnv, Asy
 
 RUNNER_TEST_MULTIPLE(TED_1005_no_iv_enc, SyncEnv, AsyncEnv)
 {
-    testNoIvEnc(AES_CTR_128);
-    testNoIvEnc(AES_CTR_192);
-    testNoIvEnc(AES_CTR_256);
-    testNoIvEnc(AES_CBC_128);
-    testNoIvEnc(AES_CBC_192);
-    testNoIvEnc(AES_CBC_256);
-    testNoIvEnc(AES_CFB_128);
-    testNoIvEnc(AES_CFB_192);
-    testNoIvEnc(AES_CFB_256);
-    testNoIvEnc(AES_GCM_128);
-    testNoIvEnc(AES_GCM_192);
-    testNoIvEnc(AES_GCM_256);
+    testNoIvEnc({CKMC_ALGO_AES_CTR, 128});
+    testNoIvEnc({CKMC_ALGO_AES_CTR, 192});
+    testNoIvEnc({CKMC_ALGO_AES_CTR, 256});
+    testNoIvEnc({CKMC_ALGO_AES_CBC, 128});
+    testNoIvEnc({CKMC_ALGO_AES_CBC, 192});
+    testNoIvEnc({CKMC_ALGO_AES_CBC, 256});
+    testNoIvEnc({CKMC_ALGO_AES_CFB, 128});
+    testNoIvEnc({CKMC_ALGO_AES_CFB, 192});
+    testNoIvEnc({CKMC_ALGO_AES_CFB, 256});
+    testNoIvEnc({CKMC_ALGO_AES_GCM, 128});
+    testNoIvEnc({CKMC_ALGO_AES_GCM, 192});
+    testNoIvEnc({CKMC_ALGO_AES_GCM, 256});
 }
 
 RUNNER_TEST_MULTIPLE(TED_1010_invalid_iv_enc, SyncEnv, AsyncEnv)
 {
-    testInvalidIvEnc(AES_CTR_128);
-    testInvalidIvEnc(AES_CTR_192);
-    testInvalidIvEnc(AES_CTR_256);
-    testInvalidIvEnc(AES_CBC_128);
-    testInvalidIvEnc(AES_CBC_192);
-    testInvalidIvEnc(AES_CBC_256);
-    testInvalidIvEnc(AES_CFB_128);
-    testInvalidIvEnc(AES_CFB_192);
-    testInvalidIvEnc(AES_CFB_256);
+    testInvalidIvEnc({CKMC_ALGO_AES_CTR, 128});
+    testInvalidIvEnc({CKMC_ALGO_AES_CTR, 192});
+    testInvalidIvEnc({CKMC_ALGO_AES_CTR, 256});
+    testInvalidIvEnc({CKMC_ALGO_AES_CBC, 128});
+    testInvalidIvEnc({CKMC_ALGO_AES_CBC, 192});
+    testInvalidIvEnc({CKMC_ALGO_AES_CBC, 256});
+    testInvalidIvEnc({CKMC_ALGO_AES_CFB, 128});
+    testInvalidIvEnc({CKMC_ALGO_AES_CFB, 192});
+    testInvalidIvEnc({CKMC_ALGO_AES_CFB, 256});
 }
 
 RUNNER_TEST_MULTIPLE(TED_1015_no_iv_dec, SyncEnv, AsyncEnv)
 {
-    testNoIvDec(AES_CTR_128);
-    testNoIvDec(AES_CTR_192);
-    testNoIvDec(AES_CTR_256);
-    testNoIvDec(AES_CBC_128);
-    testNoIvDec(AES_CBC_192);
-    testNoIvDec(AES_CBC_256);
-    testNoIvDec(AES_CFB_128);
-    testNoIvDec(AES_CFB_192);
-    testNoIvDec(AES_CFB_256);
-    testNoIvDec(AES_GCM_128);
-    testNoIvDec(AES_GCM_192);
-    testNoIvDec(AES_GCM_256);
+    testNoIvDec({CKMC_ALGO_AES_CTR, 128});
+    testNoIvDec({CKMC_ALGO_AES_CTR, 192});
+    testNoIvDec({CKMC_ALGO_AES_CTR, 256});
+    testNoIvDec({CKMC_ALGO_AES_CBC, 128});
+    testNoIvDec({CKMC_ALGO_AES_CBC, 192});
+    testNoIvDec({CKMC_ALGO_AES_CBC, 256});
+    testNoIvDec({CKMC_ALGO_AES_CFB, 128});
+    testNoIvDec({CKMC_ALGO_AES_CFB, 192});
+    testNoIvDec({CKMC_ALGO_AES_CFB, 256});
+    testNoIvDec({CKMC_ALGO_AES_GCM, 128});
+    testNoIvDec({CKMC_ALGO_AES_GCM, 192});
+    testNoIvDec({CKMC_ALGO_AES_GCM, 256});
 }
 
 RUNNER_TEST_MULTIPLE(TED_1020_invalid_iv_dec, SyncEnv, AsyncEnv)
 {
-    testInvalidIvDec(AES_CTR_128);
-    testInvalidIvDec(AES_CTR_192);
-    testInvalidIvDec(AES_CTR_256);
-    testInvalidIvDec(AES_CBC_128);
-    testInvalidIvDec(AES_CBC_192);
-    testInvalidIvDec(AES_CBC_256);
-    testInvalidIvDec(AES_CFB_128);
-    testInvalidIvDec(AES_CFB_192);
-    testInvalidIvDec(AES_CFB_256);
+    testInvalidIvDec({CKMC_ALGO_AES_CTR, 128});
+    testInvalidIvDec({CKMC_ALGO_AES_CTR, 192});
+    testInvalidIvDec({CKMC_ALGO_AES_CTR, 256});
+    testInvalidIvDec({CKMC_ALGO_AES_CBC, 128});
+    testInvalidIvDec({CKMC_ALGO_AES_CBC, 192});
+    testInvalidIvDec({CKMC_ALGO_AES_CBC, 256});
+    testInvalidIvDec({CKMC_ALGO_AES_CFB, 128});
+    testInvalidIvDec({CKMC_ALGO_AES_CFB, 192});
+    testInvalidIvDec({CKMC_ALGO_AES_CFB, 256});
 }
 
 RUNNER_TEST_MULTIPLE(TED_1050_data_integrity, SyncEnv, AsyncEnv)
 {
-    testIntegrity(AES_CTR_128);
-    testIntegrity(AES_CTR_192);
-    testIntegrity(AES_CTR_256);
-    testIntegrity(AES_CBC_128);
-    testIntegrity(AES_CBC_192);
-    testIntegrity(AES_CBC_256);
-    testIntegrity(AES_CFB_128);
-    testIntegrity(AES_CFB_192);
-    testIntegrity(AES_CFB_256);
+    testIntegrity({CKMC_ALGO_AES_CTR, 128});
+    testIntegrity({CKMC_ALGO_AES_CTR, 192});
+    testIntegrity({CKMC_ALGO_AES_CTR, 256});
+    testIntegrity({CKMC_ALGO_AES_CBC, 128});
+    testIntegrity({CKMC_ALGO_AES_CBC, 192});
+    testIntegrity({CKMC_ALGO_AES_CBC, 256});
+    testIntegrity({CKMC_ALGO_AES_CFB, 128});
+    testIntegrity({CKMC_ALGO_AES_CFB, 192});
+    testIntegrity({CKMC_ALGO_AES_CFB, 256});
 }
 
 RUNNER_TEST_MULTIPLE(TED_1100_ctr_encryption_invalid_length, SyncEnv, AsyncEnv)
 {
-    testCtrEncryptionInvalidLength(AES_CTR_128);
-    testCtrEncryptionInvalidLength(AES_CTR_192);
-    testCtrEncryptionInvalidLength(AES_CTR_256);
+    testCtrEncryptionInvalidLength({CKMC_ALGO_AES_CTR, 128});
+    testCtrEncryptionInvalidLength({CKMC_ALGO_AES_CTR, 192});
+    testCtrEncryptionInvalidLength({CKMC_ALGO_AES_CTR, 256});
 }
 
 RUNNER_TEST_MULTIPLE(TED_1105_ctr_encryption_valid_length, SyncEnv, AsyncEnv)
 {
     RUNNER_IGNORED_MSG("Openssl supports only 128-bit AES CTR length");
-    testCtrEncryptionValidLength(AES_CTR_128);
-    testCtrEncryptionValidLength(AES_CTR_192);
-    testCtrEncryptionValidLength(AES_CTR_256);
+    testCtrEncryptionValidLength({CKMC_ALGO_AES_CTR, 128});
+    testCtrEncryptionValidLength({CKMC_ALGO_AES_CTR, 192});
+    testCtrEncryptionValidLength({CKMC_ALGO_AES_CTR, 256});
 }
 
 RUNNER_TEST_MULTIPLE(TED_1110_ctr_decryption_invalid_length, SyncEnv, AsyncEnv)
 {
-    testCtrDecryptionInvalidLength(AES_CTR_128);
-    testCtrDecryptionInvalidLength(AES_CTR_192);
-    testCtrDecryptionInvalidLength(AES_CTR_256);
+    testCtrDecryptionInvalidLength({CKMC_ALGO_AES_CTR, 128});
+    testCtrDecryptionInvalidLength({CKMC_ALGO_AES_CTR, 192});
+    testCtrDecryptionInvalidLength({CKMC_ALGO_AES_CTR, 256});
 }
 
 RUNNER_TEST_MULTIPLE(TED_1115_ctr_decryption_valid_length, SyncEnv, AsyncEnv)
 {
     RUNNER_IGNORED_MSG("Openssl supports only 128-bit AES CTR length");
-    testCtrDecryptionValidLength(AES_CTR_128);
-    testCtrDecryptionValidLength(AES_CTR_192);
-    testCtrDecryptionValidLength(AES_CTR_256);
+    testCtrDecryptionValidLength({CKMC_ALGO_AES_CTR, 128});
+    testCtrDecryptionValidLength({CKMC_ALGO_AES_CTR, 192});
+    testCtrDecryptionValidLength({CKMC_ALGO_AES_CTR, 256});
 }
 
 RUNNER_TEST_MULTIPLE(TED_1200_gcm_encryption_tag_len, SyncEnv, AsyncEnv)
 {
-    testBackend b(PolicyBackend::FORCE_SOFTWARE);
-    testGcmEncryptionTagLen(AES_GCM_128);
-    testGcmEncryptionTagLen(AES_GCM_192);
-    testGcmEncryptionTagLen(AES_GCM_256);
+    testGcmEncryptionTagLen({CKMC_ALGO_AES_GCM, 128});
+    testGcmEncryptionTagLen({CKMC_ALGO_AES_GCM, 192});
+    testGcmEncryptionTagLen({CKMC_ALGO_AES_GCM, 256});
 }
 
 RUNNER_TEST_MULTIPLE(TED_1210_gcm_decryption_tag_len, SyncEnv, AsyncEnv)
 {
-    testBackend b(PolicyBackend::FORCE_SOFTWARE);
-    testGcmDecryptionTagLen(AES_GCM_128);
-    testGcmDecryptionTagLen(AES_GCM_192);
-    testGcmDecryptionTagLen(AES_GCM_256);
+    testGcmDecryptionTagLen({CKMC_ALGO_AES_GCM, 128});
+    testGcmDecryptionTagLen({CKMC_ALGO_AES_GCM, 192});
+    testGcmDecryptionTagLen({CKMC_ALGO_AES_GCM, 256});
 }
 
 RUNNER_TEST_MULTIPLE(TED_1230_gcm_wrong_tag, SyncEnv, AsyncEnv)
 {
-    testBackend b(PolicyBackend::FORCE_SOFTWARE);
-    testGcmWrongTag(AES_GCM_128);
-    testGcmWrongTag(AES_GCM_192);
-    testGcmWrongTag(AES_GCM_256);
+    testGcmWrongTag({CKMC_ALGO_AES_GCM, 128});
+    testGcmWrongTag({CKMC_ALGO_AES_GCM, 192});
+    testGcmWrongTag({CKMC_ALGO_AES_GCM, 256});
 }
 
 RUNNER_TEST_MULTIPLE(TED_1240_gcm_different_iv_sizes, SyncEnv, AsyncEnv)
 {
-    testGcmDifferentIvSizes(AES_GCM_128);
-    testGcmDifferentIvSizes(AES_GCM_192);
-    testGcmDifferentIvSizes(AES_GCM_256);
+    testGcmDifferentIvSizes({CKMC_ALGO_AES_GCM, 128});
+    testGcmDifferentIvSizes({CKMC_ALGO_AES_GCM, 192});
+    testGcmDifferentIvSizes({CKMC_ALGO_AES_GCM, 256});
 }
 
 RUNNER_TEST_MULTIPLE(TED_1250_gcm_aad, SyncEnv, AsyncEnv)
 {
-    testBackend b(PolicyBackend::FORCE_SOFTWARE);
-    encryptionWithCustomData(AES_GCM_128, CKMC_PARAM_ED_AAD);
-    encryptionWithCustomData(AES_GCM_192, CKMC_PARAM_ED_AAD);
-    encryptionWithCustomData(AES_GCM_256, CKMC_PARAM_ED_AAD);
+    encryptionWithCustomData({CKMC_ALGO_AES_GCM, 128}, CKMC_PARAM_ED_AAD);
+    encryptionWithCustomData({CKMC_ALGO_AES_GCM, 192}, CKMC_PARAM_ED_AAD);
+    encryptionWithCustomData({CKMC_ALGO_AES_GCM, 256}, CKMC_PARAM_ED_AAD);
 }
 
 RUNNER_TEST_MULTIPLE(TED_1300_rsa_label, SyncEnv, AsyncEnv)
 {
     RUNNER_IGNORED_MSG("RSA-OAEP labels are not supported in openssl");
-    encryptionWithCustomData(RSA_OAEP_1024, CKMC_PARAM_ED_LABEL);
-    encryptionWithCustomData(RSA_OAEP_2048, CKMC_PARAM_ED_LABEL);
-    encryptionWithCustomData(RSA_OAEP_4096, CKMC_PARAM_ED_LABEL);
+    encryptionWithCustomData({CKMC_ALGO_RSA_OAEP, 1024}, CKMC_PARAM_ED_LABEL);
+    encryptionWithCustomData({CKMC_ALGO_RSA_OAEP, 2048}, CKMC_PARAM_ED_LABEL);
+    encryptionWithCustomData({CKMC_ALGO_RSA_OAEP, 4096}, CKMC_PARAM_ED_LABEL);
 }
 
 RUNNER_TEST_MULTIPLE(TED_1330_rsa_longest_data, SyncEnv, AsyncEnv)
 {
-    testRsaLongestData(RSA_OAEP_1024, 86);
-    testRsaLongestData(RSA_OAEP_2048, 214);
-    testRsaLongestData(RSA_OAEP_4096, 470);
+    testRsaLongestData({CKMC_ALGO_RSA_OAEP, 1024}, 86);
+    testRsaLongestData({CKMC_ALGO_RSA_OAEP, 2048}, 214);
+    testRsaLongestData({CKMC_ALGO_RSA_OAEP, 4096}, 470);
 }
 
 RUNNER_TEST_MULTIPLE(TED_1350_rsa_data_too_long, SyncEnv, AsyncEnv)
 {
-    testRsaDataTooLong(RSA_OAEP_1024, 87);
-    testRsaDataTooLong(RSA_OAEP_2048, 215);
-    testRsaDataTooLong(RSA_OAEP_4096, 471);
+    testRsaDataTooLong({CKMC_ALGO_RSA_OAEP, 1024}, 87);
+    testRsaDataTooLong({CKMC_ALGO_RSA_OAEP, 2048}, 215);
+    testRsaDataTooLong({CKMC_ALGO_RSA_OAEP, 4096}, 471);
 }
 
 /////////////////////////////////////////
 // Asynchronous only tests
 /////////////////////////////////////////
-RUNNER_TEST(TED_2000_enc_no_observer_async, EncEnv)
+RUNNER_TEST(TED_2000_enc_no_observer_async, AsyncEnv)
 {
-    testAllAlgorithms([](const AlgoBasePtr& algo){
+    testAllAlgorithms([](const Algo& algo){
         // prepare buffers
         RawBuffer plain = createRandomBuffer(BUF_LEN);
 
         // keys
-        KeyAliasPair aliases = algo->keyGen(nullptr);
+        KeyAliasPair aliases = getKey(algo, PRIMARY);
 
         // params
         ckmc_param_list_h handle = NULL;
-        assert_positive(ckmc_generate_new_params, algo->m_type, &handle);
+        assert_positive(ckmc_generate_new_params, algo.type, &handle);
         ParamListPtr params = ParamListPtr(handle, ckmc_param_list_free);
-        setParam(params, CKMC_PARAM_ED_IV, createRandomBufferCAPI(DEFAULT_IV_LEN));
+        setParam(params, CKMC_PARAM_ED_IV, DEFAULT_IV);
 
         // encrypt
         test_no_observer(&ManagerAsync::encrypt,
@@ -1519,12 +1451,9 @@ RUNNER_TEST(TED_2000_enc_no_observer_async, EncEnv)
 
 RUNNER_TEST(TED_2010_dec_no_observer_async, AsyncEnv)
 {
-    testAllAlgorithms([](const AlgoBasePtr& algo){
-        // prepare buffers
-        RawBufferPtr plain = create_raw_buffer(createRandomBufferCAPI(BUF_LEN));
-
+    testAllAlgorithms([](const Algo& algo){
         // encrypt
-        auto ret = encrypt(algo, plain);
+        auto ret = encrypt(algo, PLAIN_DATA);
         RawBuffer encrypted(ret.encrypted->data, ret.encrypted->data + ret.encrypted->size);
 
         // decrypt
index 6f0966f..f4a2eec 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2016 - 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *  Copyright (c) 2016-2020 Samsung Electronics Co., Ltd. All rights reserved
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -280,6 +280,42 @@ RUNNER_TEST(T1014_save_with_label)
         "Key value has been changed by service");
 }
 
+RUNNER_TEST(T1020_save_big_data)
+{
+#ifdef TZ_BACKEND
+    const size_t BIG_SIZE = 100000;
+    CKM::PolicyBackend backend = CKM::PolicyBackend::FORCE_HARDWARE;
+#else
+    const size_t BIG_SIZE = 5000000;
+    CKM::PolicyBackend backend = CKM::PolicyBackend::FORCE_SOFTWARE;
+#endif
+
+    int temp;
+    std::vector<char> big_data(BIG_SIZE);
+    std::ifstream is("/dev/urandom", std::ifstream::binary);
+    if(is)
+        is.read(big_data.data(), BIG_SIZE);
+
+    RUNNER_ASSERT_MSG(is,
+            "Only " << is.gcount() << "/" << BIG_SIZE << " bytes read from /dev/urandom");
+
+    CKM::RawBuffer buffer(big_data.begin(), big_data.end());
+    CKM::Policy policy(CKM::Password(), true, backend);
+    CKM::RawBuffer returned;
+
+    auto manager = CKM::Manager::create();
+
+    RUNNER_ASSERT_MSG(
+        CKM_API_SUCCESS == (temp = manager->saveData("big_data", buffer, policy)),
+        "Error=" << CKM::APICodeToString(temp));
+
+    RUNNER_ASSERT_MSG(
+        CKM_API_SUCCESS == (temp = manager->getData("big_data", CKM::Password(), returned)),
+        "Error=" << CKM::APICodeToString(temp));
+
+    RUNNER_ASSERT_MSG(buffer == returned, "Returned data doesn't match the original");
+}
+
 RUNNER_TEST(T1015_deinit)
 {
     remove_user_data(USER_APP);
@@ -1267,7 +1303,7 @@ RUNNER_TEST(T13129_get_chain)
     auto manager = CKM::Manager::create();
 
     RUNNER_ASSERT_MSG(NULL != cert.get(), "Certificate should not be empty");
-    RUNNER_ASSERT_MSG(false != cert1.get(), "Certificate should not be empty");
+    RUNNER_ASSERT_MSG(NULL != cert1.get(), "Certificate should not be empty");
 
     tmp = manager->getCertificateChain(cert,
                                        EMPTY_CERT_VECTOR,
@@ -2290,68 +2326,13 @@ RUNNER_TEST(T14184_ECDSA_create_signatue_nohash)
 
     std::string message = "message test";
 
-    CKM::Alias aliasPub = "ecpub_nohash1";
     CKM::Alias aliasPrv = "ecprv_nohash1";
     CKM::HashAlgorithm hash = CKM::HashAlgorithm::NONE;
     CKM::RSAPaddingAlgorithm padd = CKM::RSAPaddingAlgorithm::PKCS1;
     CKM::RawBuffer signature;
 
     RUNNER_ASSERT_MSG(
-        CKM_API_SUCCESS == (temp = manager->createSignature(
-                                        aliasPrv,
-                                        CKM::Password(),
-                                        CKM::RawBuffer(message.begin(), message.end()),
-                                        hash,
-                                        padd,
-                                        signature)),
-        "Error=" << CKM::APICodeToString(temp));
-
-    RUNNER_ASSERT_MSG(
-        CKM_API_SUCCESS == (temp = manager->verifySignature(
-                                        aliasPub,
-                                        CKM::Password(),
-                                        CKM::RawBuffer(message.begin(), message.end()),
-                                        signature,
-                                        hash,
-                                        padd)),
-        "Error=" << CKM::APICodeToString(temp));
-
-    RUNNER_ASSERT_MSG(signature.size() > 6, "Signature is too small");
-
-    memcpy((void*)signature.data(), "BROKEN", 6);
-
-    RUNNER_ASSERT_MSG(
-        CKM_API_ERROR_VERIFICATION_FAILED == (temp = manager->verifySignature(
-                                        aliasPub,
-                                        CKM::Password(),
-                                        CKM::RawBuffer(message.begin(), message.end()),
-                                        signature,
-                                        hash,
-                                        padd)),
-        "Error=" << CKM::APICodeToString(temp));
-}
-
-RUNNER_TEST(T14185_ECDSA_create_signatue_nohash_bigmsg)
-{
-    int temp;
-    auto manager = CKM::Manager::create();
-
-    int msgSize = 1024*1024;
-    char big_msg[msgSize];
-    for(int i =0; i<msgSize-1; i++) {
-        big_msg[i] = 'a';
-    }
-    big_msg[msgSize-1]=0x00;
-    std::string message(big_msg);
-
-    CKM::Alias aliasPub = "ecpub_nohash1";
-    CKM::Alias aliasPrv = "ecprv_nohash1";
-    CKM::HashAlgorithm hash = CKM::HashAlgorithm::NONE;
-    CKM::RSAPaddingAlgorithm padd = CKM::RSAPaddingAlgorithm::NONE;
-    CKM::RawBuffer signature;
-
-    RUNNER_ASSERT_MSG(
-            CKM_API_SUCCESS == (temp = manager->createSignature(
+        CKM_API_ERROR_INPUT_PARAM == (temp = manager->createSignature(
                                         aliasPrv,
                                         CKM::Password(),
                                         CKM::RawBuffer(message.begin(), message.end()),
@@ -2361,7 +2342,6 @@ RUNNER_TEST(T14185_ECDSA_create_signatue_nohash_bigmsg)
         "Error=" << CKM::APICodeToString(temp));
 }
 
-
 RUNNER_TEST(T14189_deinit)
 {
     remove_user_data(USER_APP);
@@ -2634,21 +2614,23 @@ RUNNER_TEST(T1808_create_signature_on_raw_key_and_verify_on_PKCS)
     int temp;
     auto manager = CKM::Manager::create();
 
-    std::string prv = "-----BEGIN RSA PRIVATE KEY-----\n"
-        "MIICXQIBAAKBgQD1W9neUbXL1rnq9SvyzprjhWBKXyYKQirG3V2zyUnUaE24Sq2I\n"
-        "v7ISrwMN/G6WcjrGmeZDEWwrL4zXh002N8BD1waJPRonxwtVkhFy3emGatSmx7eI\n"
-        "ely5H+PBNImRvBh2u4GWga6OEXcUNdfaBUcxn+P6548/zpDhyNLzQKk5FwIDAQAB\n"
-        "AoGAR+4WkBuqTUj1FlGsAbHaLKt0UDlWwJknS0eoacWwFEpDxqx19WolfV67aYVA\n"
-        "snBolMKXg7/+0yZMhv8Ofr+XaHkPQplVVn9BwT0rmtEovJXwx+poRP9Bm3emglj/\n"
-        "iYd8EkaXDlIXCtewtQW9JEIctWppntHj3TvA/h7FCXPN6SkCQQD/N7sn5S1gBkVh\n"
-        "dyXQKoyKsZDb7hMIS1q6cKwYCMf2UrsD1/lnr7xXkvORdL213MfueO8g0WkuKfRY\n"
-        "bDD6WGX1AkEA9hxiOlsgvermqLJkOlJffbSaM8n/6wtnM0HV+Vd9NfSBOmxFDXPO\n"
-        "vrvdgiDPENhbqTJSQVDsfzHilTpK7lEvWwJBAJLxHoOg0tg3pBiyxgWtic+M3q+R\n"
-        "ykl7QViY6KzJ2X98MIrM/Z7yMollZXE4+sVLwZ0O6fdGOr3GkBWc7TImVUUCQQC7\n"
-        "pf6bQfof9Ce0fnf/I+ldHkPost7nJsWkBlGQkM2OQwP5OK4ZyK/dK76DxmI7FMwm\n"
-        "oJCo7nuzq6R4ZX7WYJ47AkBavxBDo/e9/0Vk5yrloGKW3f8RQXBJLcCkVUGyyJ3D\n"
-        "3gu/nafW4hzjSJniTjC1fOj0eb0OSg1JAvqHTYAnUsI7\n"
-        "-----END RSA PRIVATE KEY-----";
+    std::string prv =
+        "-----BEGIN RSA PRIVATE KEY-----\n"
+        "MIICWwIBAAKBgQDDgmPurTQa3wbnlM+9nCEQvhDviYRvSC9TL5lAMBCmBSl93v0U\n"
+        "BXWsqO+fmAINm5QJa89hF5N7Q4xtvfSJUPIeyzowTOEGM4U3FnJtlsNQsoNbFlNy\n"
+        "QLoZZmmY4ljG6/YqX+JGBgS9/J8uvaDWkvs+ktkORygfNz4Gi5DERT7eeQIDAQAB\n"
+        "AoGAARIqx/js6yTDnesjxC8hwzy3TQic0Bs+Hx+IoGBjBvXKR2U8T6rD/UEjpuUn\n"
+        "RbnPcsnDZg3CAg/ZqhQ7TbFC0kPo+S6+wKsZGDWUUvnpMkdcZUqXel8GFhdnmeIh\n"
+        "22vYthP4TCbolxwXlwvuhu0PLZWhRO/Z+g37T3QENexqGv0CQQDmqJ9PDoUj5eUR\n"
+        "wWEqEPraoU6ARBUUX5EhmTT9g9/BXnhwumIOksDHcBqNUwNOlKCUlWfBOelO93Ys\n"
+        "PRW3QyejAkEA2P0tW/8iU4j+0a6DV+TUYFDTjD29y8KPw0Aj59591xD5eIPK3IgU\n"
+        "91vnmtvU/QR26PnMOx4OAPk9a7BtN62zMwJAIFV0950edtjMUr/cAgydTbadDYf9\n"
+        "uHxpGN+kOQGahT3b/llyU36o/YwufK8tYH+fPxTulXyrwwEXlL3/ZFBKpwJAeLGS\n"
+        "Wlp2WGqZ+j2MdwYkDxLGKHprKHwnBN6XWjCKZGbfrGX6H2Jd7xyinaNrO/UQwxO2\n"
+        "wqc7+NSpkk3G4jJuuwJAODYlk2Q+djE4jkjDc4xiqsQGBQlI2dlgzjRjIF4HWiLx\n"
+        "bIrI0uCCbGItx++hlvmDx7G8anBmIFfBWIaKdX0aWw==\n"
+        "-----END RSA PRIVATE KEY-----\n";
+
     std::string message = "message test";
 
     auto keyPrv = CKM::Key::create(CKM::RawBuffer(prv.begin(), prv.end()), CKM::Password());
@@ -2745,15 +2727,21 @@ RUNNER_TEST(T1810_verify_get_certificate_chain)
     // this certificate has been signed using PKCS chain
     std::string im =
         "-----BEGIN CERTIFICATE-----\n"
-        "MIIBozCCAQwCAQEwDQYJKoZIhvcNAQEFBQAwHDEaMBgGA1UEAwwRc2VydmVyQHRl\n"
-        "c3RtZS5jb20wHhcNMTUxMjA5MTA0NjU0WhcNMjUxMjA2MTA0NjU0WjAYMRYwFAYD\n"
-        "VQQDDA1lZUB0ZXN0bWUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDP\n"
-        "+fNsZB1Vlmhnk0IwYDs7Pw9E38KQfTt/egqqRFN6IvIt0CCDBXqnPTujuvlO2OyL\n"
-        "XVuALnIBmTDm5Oz+oz+qiY6/XrVS/CoACNZyMo6ihG9OeocvDbU3jXEaPGL6ib/x\n"
-        "jlms0aA9d5L9TO2lEzEP7bFKgHCB8FWINcxSP5zl1QIDAQABMA0GCSqGSIb3DQEB\n"
-        "BQUAA4GBAKBpVJMkdK6/qnAz7d7Bul/BhhSLEYbNPdxRiUj3U2dt0GJgswMu2SNT\n"
-        "/3NXB8V8mnnXR6cWn5bmjyA7ZpQEKAatS/KEQ9wfLXyCgYDRebX71mVKAI3XcyxB\n"
-        "p2qsOWWaJhuHmC1GVjx3foL+RDrmRo6BiucNHMIuvrd1W36eKdhj\n"
+        "MIICxDCCAi0CFGHuCEUksqn0Rr3SXdhn+TlnL804MA0GCSqGSIb3DQEBCwUAMGEx\n"
+        "CzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRl\n"
+        "cm5ldCBXaWRnaXRzIFB0eSBMdGQxGjAYBgNVBAMMEXNlcnZlckB0ZXN0bWUuY29t\n"
+        "MB4XDTE5MDYxMzEyMTkyNloXDTI5MDYxMDEyMTkyNlowXTELMAkGA1UEBhMCQVUx\n"
+        "EzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMg\n"
+        "UHR5IEx0ZDEWMBQGA1UEAwwNZWVAdGVzdG1lLmNvbTCCASIwDQYJKoZIhvcNAQEB\n"
+        "BQADggEPADCCAQoCggEBAK3/XvE3uc2EhzwmsAfq6KEw52J8kCAB9Rma/qjkw6ZT\n"
+        "yUYmSQvmcK8wSDt015Y/ekYLereCeWNLNkFlQeZC7LHT6T1mGnxNIgL3oUS2c+15\n"
+        "FEYX9QJIN/CoJYQ/tmiQPa1OJz4prUFwqAzM1kRtHGfcAGmQHfgu77P3ljAJzfsW\n"
+        "2beVHM+MTNSybkGHql28Z93bp382k5FQXegkxbozsKBMk37QjKiqes29J/ET0Huy\n"
+        "yzOkf+XvbizIPRvMt/2guw9sgRb7YrM2M+igmHIHxfzxuqzpPr+bmcqQdyFdVkAK\n"
+        "Qcx930HbfjHJ5k5vcovPLQ3LvSnYVCTe7aCAAmMzKXsCAwEAATANBgkqhkiG9w0B\n"
+        "AQsFAAOBgQBfFMim/9zLd+EeZyeYA0vy3C9YuNJI+KsZlKAfrFDQNeIT/qg/GQM4\n"
+        "o7I3TIHQ62tdEx6nBJs0DKSAmhRh4yc+P1KHMzIQIgSjftqS3Z+AKbJn6vOpWNTq\n"
+        "cexnpexaNn69dbqJZsjr0fHsGAkh5n96icAB4VZyFncEknZKbTdd0g==\n"
         "-----END CERTIFICATE-----\n";
 
     auto cert = CKM::Certificate::create(CKM::RawBuffer(im.begin(), im.end()), CKM::DataFormat::FORM_PEM);
diff --git a/src/ckm/unprivileged/sign-verify.cpp b/src/ckm/unprivileged/sign-verify.cpp
new file mode 100644 (file)
index 0000000..c1a7b44
--- /dev/null
@@ -0,0 +1,492 @@
+/*
+ *  Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  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
+ */
+/*
+ * @file       sign-verify.cpp
+ * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
+ * @version    1.0
+ */
+
+#include <string>
+#include <vector>
+#include <unordered_map>
+
+#include <dpl/test/test_runner.h>
+#include <ckm-common.h>
+#include <ckmc/ckmc-manager.h>
+#include <ckmc/ckmc-control.h>
+#include <ckm/ckm-type.h>
+#include <ckm/ckm-manager.h>
+
+using namespace CKM;
+
+namespace {
+
+const char* PASSWORD = "test-password";
+const uid_t UID = 5001;
+
+struct KeyAliasPair
+{
+    Alias prv;
+    Alias pub;
+};
+
+enum Algo {
+    RSA,
+    DSA,
+    ECDSA
+};
+
+// algo names
+const std::unordered_map<Algo, std::string> ALGO2STR = {
+        { RSA,   "RSA" },
+        { DSA,   "DSA" },
+        { ECDSA, "ECDSA" },
+};
+
+// keys
+std::unordered_map<Algo, std::unordered_map<size_t, std::vector<KeyAliasPair>>> KEYS;
+
+enum KeyIdx {
+    PRIMARY = 0,
+    PASSWORD_PROTECTED = 1,
+
+    KEY_IDX_MAX
+};
+
+// hash algo names
+const std::unordered_map<ckmc_hash_algo_e, std::string> HASH2STR = {
+#ifndef TZ_BACKEND
+        // no hash is not supported in TZ
+        { CKMC_HASH_NONE,   "NONE" },
+#endif
+        { CKMC_HASH_SHA1,   "SHA1" },
+        { CKMC_HASH_SHA256, "SHA256" },
+        { CKMC_HASH_SHA384, "SHA384" },
+        { CKMC_HASH_SHA512, "SHA512" },
+};
+
+// padding names
+const std::unordered_map<ckmc_rsa_padding_algo_e, std::string> PAD2STR = {
+#ifndef TZ_BACKEND
+        // no padding is not supported in TZ
+        { CKMC_NONE_PADDING,    "NONE" },
+#endif
+        { CKMC_PKCS1_PADDING,   "PKCS1" },
+#ifndef TZ_BACKEND
+        // X9.31 is not supported in TZ
+        { CKMC_X931_PADDING,    "X931" },
+#endif
+};
+
+const int EC_PRIME192V1 = static_cast<int>(ElipticCurve::prime192v1);
+const int EC_PRIME256V1 = static_cast<int>(ElipticCurve::prime256v1);
+const int EC_SECP384R1 = static_cast<int>(ElipticCurve::secp384r1);
+
+// test  messages
+RawBufferPtr MESSAGE_SHORT;
+std::unordered_map<size_t, RawBufferPtr> MESSAGES;
+RawBufferPtr MESSAGE_LONG;
+
+class SignVerifyGroupFixture: public DPL::Test::TestGroup
+{
+public:
+    void Init() override
+    {
+        remove_user_data(UID);
+        int ret = ckmc_unlock_user_key(UID, "db-pass");
+        if (ret != CKMC_ERROR_NONE)
+            RUNNER_ERROR_MSG("DB unlock failed: " << CKMCErrorToString(ret));
+
+        // Policy backend to use in subsequent operations (global for each test case)
+#ifdef TZ_BACKEND
+        m_backend = PolicyBackend::FORCE_HARDWARE;
+#else
+        m_backend = PolicyBackend::FORCE_SOFTWARE;
+#endif
+
+        // generate keys
+        m_manager = Manager::create();
+        generateKeys(RSA, 1024);
+        generateKeys(RSA, 2048);
+        generateKeys(RSA, 4096);
+        generateKeys(DSA, 1024);
+#ifndef TZ_BACKEND
+        /*
+         * For DSA with SHA1 only 1024-bit keys are supported and TZ does not currently support
+         * anything else than SHA1 for DSA.
+         */
+        generateKeys(DSA, 2048);
+        generateKeys(DSA, 3072);
+        generateKeys(DSA, 4096);
+#endif
+#ifndef TZ_BACKEND
+        // ECDSA is not yet supported on TZ
+        generateKeys(ECDSA, EC_PRIME192V1);
+        generateKeys(ECDSA, EC_PRIME256V1);
+        generateKeys(ECDSA, EC_SECP384R1);
+#endif
+
+        MESSAGE_SHORT = create_raw_buffer(createRandomBufferCAPI(512/8));
+
+        // Set first byte to 0 to avoid "data too large for modulus" error in unpadded RSA
+        MESSAGES[1024] = create_raw_buffer(createRandomBufferCAPI(1024/8));
+        MESSAGES[1024]->data[0] = 0;
+        MESSAGES[2048] = create_raw_buffer(createRandomBufferCAPI(2048/8));
+        MESSAGES[2048]->data[0] = 0;
+        MESSAGES[3072] = create_raw_buffer(createRandomBufferCAPI(3072/8));
+        MESSAGES[3072]->data[0] = 0;
+        MESSAGES[4096]= create_raw_buffer(createRandomBufferCAPI(4096/8));
+        MESSAGES[4096]->data[0] = 0;
+
+        MESSAGE_LONG = create_raw_buffer(createRandomBufferCAPI(1000));
+    }
+
+    void generateKeys(Algo type, size_t bitLen)
+    {
+        for (int i = 0; i < KEY_IDX_MAX; i++)
+        {
+            Policy prvPolicy(Password(), false, m_backend);
+            Policy pubPolicy(Password(), true, m_backend);
+            if (i == PASSWORD_PROTECTED) {
+                prvPolicy.password.assign(PASSWORD);
+                pubPolicy.password.assign(PASSWORD);
+            }
+
+            KeyAliasPair alias;
+            alias.prv = ALGO2STR.at(type) + std::string("_") + std::to_string(bitLen) +
+                        std::string("_") + std::to_string(i);
+            alias.pub = std::string("pub") + alias.prv;
+            int ret;
+            switch (type)
+            {
+            case RSA:
+                ret = m_manager->createKeyPairRSA(bitLen,
+                                                  alias.prv, alias.pub,
+                                                  prvPolicy, pubPolicy);
+                break;
+            case DSA:
+                ret = m_manager->createKeyPairDSA(bitLen,
+                                                  alias.prv, alias.pub,
+                                                  prvPolicy, pubPolicy);
+                break;
+            case ECDSA:
+                ret = m_manager->createKeyPairECDSA(static_cast<ElipticCurve>(bitLen),
+                                                    alias.prv, alias.pub,
+                                                    prvPolicy, pubPolicy);
+                break;
+            default:
+                ret = CKM_API_ERROR_UNKNOWN;
+            }
+            if (ret != CKM_API_SUCCESS)
+                RUNNER_ERROR_MSG("key creation failed. Type: " << ALGO2STR.at(type) <<
+                                 " bits: " << bitLen << " error: " <<  APICodeToString(ret));
+
+            KEYS[type][bitLen].push_back(alias);
+        }
+    }
+
+    void Finish() override
+    {
+        for (const auto &type : KEYS) {
+            for (const auto &entry : type.second) {
+                for (const auto &keyPair : entry.second) {
+                    m_manager->removeAlias(keyPair.prv);
+                    m_manager->removeAlias(keyPair.pub);
+                }
+            }
+        }
+
+        MESSAGE_SHORT.reset();
+
+        int ret = ckmc_lock_user_key(UID);
+        if (ret != CKMC_ERROR_NONE)
+            RUNNER_ERROR_MSG("DB lock failed: " << CKMCErrorToString(ret));
+        remove_user_data(UID);
+    }
+private:
+    ManagerShPtr m_manager;
+    PolicyBackend m_backend;
+};
+
+std::string params2str(const Alias& alias,
+                       const ckmc_hash_algo_e hash,
+                       const ckmc_rsa_padding_algo_e padding,
+                       const RawBufferPtr& message)
+{
+    std::stringstream ss;
+    ss << " Alias: " <<  alias << ", hash algo: " << HASH2STR.at(hash) <<
+          ", padding: " << PAD2STR.at(padding) << ", message len: " << message->size << "B.";
+    return ss.str();
+}
+
+void signExpect(int expected,
+                const Alias& alias,
+                const char* pw,
+                const RawBufferPtr& message,
+                const ckmc_hash_algo_e hash,
+                const ckmc_rsa_padding_algo_e padding,
+                RawBufferPtr& signature)
+{
+    ckmc_raw_buffer_s* cSignature = nullptr;
+
+    int ret = ckmc_create_signature(alias.c_str(), pw, *message, hash, padding, &cSignature);
+    RUNNER_ASSERT_MSG(ret == expected, "Unexpected result during signature creation." <<
+                                       params2str(alias, hash, padding, message) <<
+                                       " Expected: " << CKMCErrorToString(expected) <<
+                                       " got: " << CKMCErrorToString(ret));
+    if (ret == CKMC_ERROR_NONE) {
+        RUNNER_ASSERT_MSG(cSignature != nullptr && cSignature->size > 0,
+                          "Empty signature returned." <<
+                          params2str(alias, hash, padding, message));
+        signature = create_raw_buffer(cSignature);
+    } else {
+        RUNNER_ASSERT_MSG(cSignature == nullptr,
+                          "Non-empty signature returned." <<
+                          params2str(alias, hash, padding, message));
+    }
+}
+
+void signInvalid(const Alias& alias,
+                 const char* pw,
+                 const RawBufferPtr& message,
+                 const ckmc_hash_algo_e hash,
+                 const ckmc_rsa_padding_algo_e padding)
+{
+    RawBufferPtr signature;
+    signExpect(CKMC_ERROR_INVALID_PARAMETER, alias, pw, message, hash, padding, signature);
+}
+
+void verifyExpect(int expected,
+                  const Alias& alias,
+                  const char* pw,
+                  const RawBufferPtr& message,
+                  const ckmc_hash_algo_e hash,
+                  const ckmc_rsa_padding_algo_e padding,
+                  const RawBufferPtr& signature)
+{
+    int ret = ckmc_verify_signature(alias.c_str(), pw, *message, *signature, hash, padding);
+    RUNNER_ASSERT_MSG(ret == expected, "Unexpected result during signature verification." <<
+                                       params2str(alias, hash, padding, message) <<
+                                       " Expected: " << CKMCErrorToString(expected) <<
+                                       " got: " << CKMCErrorToString(ret));
+}
+
+void signVerify(const KeyAliasPair& aliasPair,
+                const char* pw,
+                const RawBufferPtr& message,
+                const ckmc_hash_algo_e hash,
+                const ckmc_rsa_padding_algo_e padding)
+{
+    RawBufferPtr signature;
+    signExpect(CKMC_ERROR_NONE, aliasPair.prv, pw, message, hash, padding, signature);
+
+    RUNNER_ASSERT_MSG(signature->size > 0, "Empty signature returned");
+
+    verifyExpect(CKMC_ERROR_NONE, aliasPair.pub, pw, message, hash, padding, signature);
+
+    // modify 1 bit of the signature
+    signature->data[0] ^= 0x01;
+
+    // expect verification failure
+    verifyExpect(CKMC_ERROR_VERIFICATION_FAILED,
+                 aliasPair.pub,
+                 pw,
+                 message,
+                 hash,
+                 padding,
+                 signature);
+}
+// test given key pair against all hash and padding algos
+void testSignVerify(Algo algo, size_t keyBits, int idx)
+{
+#ifdef TZ_BACKEND
+    if (algo == DSA && keyBits > 1024)
+        RUNNER_IGNORED_MSG("For DSA with SHA1 only 1024-bit keys are supported and TZ does not"\
+                           " currently support anything else than SHA1 for DSA.");
+    if (algo == ECDSA)
+        RUNNER_IGNORED_MSG("ECDSA is not yet supported in TZ");
+#endif
+
+    std::string pw;
+    if (idx == PASSWORD_PROTECTED)
+        pw = PASSWORD;
+
+    const KeyAliasPair& keys = KEYS[algo][keyBits][idx];
+
+    // iterate over hash algorithms
+    for (const auto& hash : HASH2STR) {
+#ifdef TZ_BACKEND
+        // in case of DSA only SHA1 is supported on TZ
+        if (algo == DSA && hash.first != CKMC_HASH_SHA1)
+            continue;
+#endif
+
+        // iterate over padding algorithms
+        for (const auto& pad : PAD2STR) {
+            auto expectSuccess = [&](const RawBufferPtr& msg) {
+                signVerify(keys, pw.c_str(), msg, hash.first, pad.first);
+            };
+            auto expectInvalid = [&](const RawBufferPtr& msg) {
+                signInvalid(keys.prv, pw.c_str(), msg, hash.first, pad.first);
+            };
+
+            // padding is for RSA only, other algos should ignore it
+            if (algo == RSA && pad.first == CKMC_NONE_PADDING) {
+                if (hash.first == CKMC_HASH_NONE) {
+                    // no hash + no padding + key matching message
+                    expectSuccess(MESSAGES.at(keyBits));
+                }
+                // no padding + short message
+                expectInvalid(MESSAGE_SHORT);
+
+                // no padding + long message
+                expectInvalid(MESSAGE_LONG);
+
+            } else {
+                if (hash.first == CKMC_HASH_NONE) {
+                    // no hash + padding + long message
+                    expectInvalid(MESSAGE_LONG);
+
+                    // no hash + padding + short message
+                    if (algo == RSA)
+                        expectSuccess(MESSAGE_SHORT);
+                    else
+                        expectInvalid(MESSAGE_SHORT); // no support for CKMC_HASH_NONE
+                } else {
+                    // hash + padding + short message
+                    expectSuccess(MESSAGE_SHORT);
+
+                    // hash + padding + long message
+                    expectSuccess(MESSAGE_LONG);
+                }
+            }
+        }
+    }
+}
+
+} // namespace anonymous
+
+RUNNER_TEST_GROUP_INIT_ENV(CKM_SIGN_VERIFY, SignVerifyGroupFixture);
+
+
+// RSA
+RUNNER_TEST(TSV_0110_sign_verify_rsa_1024)
+{
+    testSignVerify(RSA, 1024, PRIMARY);
+}
+
+RUNNER_TEST(TSV_0120_sign_verify_rsa_1024_pw)
+{
+    testSignVerify(RSA, 1024, PASSWORD_PROTECTED);
+}
+
+RUNNER_TEST(TSV_0130_sign_verify_rsa_2048)
+{
+    testSignVerify(RSA, 2048, PRIMARY);
+}
+
+RUNNER_TEST(TSV_0140_sign_verify_rsa_2048_pw)
+{
+    testSignVerify(RSA, 2048, PASSWORD_PROTECTED);
+}
+
+RUNNER_TEST(TSV_0150_sign_verify_rsa_4096)
+{
+    testSignVerify(RSA, 4096, PRIMARY);
+}
+
+RUNNER_TEST(TSV_0160_sign_verify_rsa_4096_pw)
+{
+    testSignVerify(RSA, 4096, PASSWORD_PROTECTED);
+}
+
+
+// DSA
+RUNNER_TEST(TSV_0210_sign_verify_dsa_1024)
+{
+    testSignVerify(DSA, 1024, PRIMARY);
+}
+
+RUNNER_TEST(TSV_0220_sign_verify_dsa_1024_pw)
+{
+    testSignVerify(DSA, 1024, PASSWORD_PROTECTED);
+}
+
+RUNNER_TEST(TSV_0230_sign_verify_dsa_2048)
+{
+    testSignVerify(DSA, 2048, PRIMARY);
+}
+
+RUNNER_TEST(TSV_0240_sign_verify_dsa_2048_pw)
+{
+    testSignVerify(DSA, 2048, PASSWORD_PROTECTED);
+}
+
+RUNNER_TEST(TSV_0250_sign_verify_dsa_3072)
+{
+    testSignVerify(DSA, 3072, PRIMARY);
+}
+
+RUNNER_TEST(TSV_0260_sign_verify_dsa_3072_pw)
+{
+    testSignVerify(DSA, 3072, PASSWORD_PROTECTED);
+}
+
+RUNNER_TEST(TSV_0270_sign_verify_dsa_4096)
+{
+    testSignVerify(DSA, 4096, PRIMARY);
+}
+
+RUNNER_TEST(TSV_0280_sign_verify_dsa_4096_pw)
+{
+    testSignVerify(DSA, 4096, PASSWORD_PROTECTED);
+}
+
+
+// ECDSA
+RUNNER_TEST(TSV_0310_sign_verify_ecdsa_PRIME192V1)
+{
+    testSignVerify(ECDSA, EC_PRIME192V1, PRIMARY);
+}
+
+RUNNER_TEST(TSV_0320_sign_verify_ecdsa_PRIME192V1_pw)
+{
+    testSignVerify(ECDSA, EC_PRIME192V1, PASSWORD_PROTECTED);
+}
+
+RUNNER_TEST(TSV_0330_sign_verify_ecdsa_PRIME256V1)
+{
+    testSignVerify(ECDSA, EC_PRIME256V1, PRIMARY);
+}
+
+RUNNER_TEST(TSV_0340_sign_verify_ecdsa_PRIME256V1_pw)
+{
+    testSignVerify(ECDSA, EC_PRIME256V1, PASSWORD_PROTECTED);
+}
+
+RUNNER_TEST(TSV_0350_sign_verify_ecdsa_SECP384R1)
+{
+    testSignVerify(ECDSA, EC_SECP384R1, PRIMARY);
+}
+
+RUNNER_TEST(TSV_0360_sign_verify_ecdsa_SECP384R1_pw)
+{
+    testSignVerify(ECDSA, EC_SECP384R1, PASSWORD_PROTECTED);
+}
+
+// TODO: border cases for padding
+// TODO: invalid arguments
+// TODO: Big data
index 093da6b..1f6e0e8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2019 Samsung Electronics Co., Ltd All Rights Reserved
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
  *    you may not use this file except in compliance with the License.
@@ -34,6 +34,9 @@
 #include "app_install_helper.h"
 
 namespace {
+
+const gid_t FILE_GROUP = 100;
+
     std::string genSkelPath() {
         static std::string skelPkgDir;
         if (!skelPkgDir.empty())
@@ -94,6 +97,18 @@ void AppInstallHelper::setInstallPath(RootType type) const {
     case RootType::SKEL:
         info.path = genSkelPath() + "/" + getPkgId();
         break;
+    case RootType::SHARED:
+        if (m_isLocal)
+            info.path = TzPlatformConfig::appDirPath(getUID()) + ".shared/" + getPkgId();
+        else
+            info.path = TzPlatformConfig::globalAppDir() + "/.shared/" + getPkgId();
+        break;
+    case RootType::SHARED_TMP:
+        if (m_isLocal)
+            info.path = TzPlatformConfig::appDirPath(getUID()) + ".shared_tmp/" + getPkgId();
+        else
+            info.path = TzPlatformConfig::globalAppDir() + "/.shared_tmp/" + getPkgId();
+        break;
     }
 }
 
@@ -110,7 +125,7 @@ std::string AppInstallHelper::getPath(app_install_path_type smType, PathType pTy
         break;
     case PathType::FILE:
         // put files in the directory of the same type
-        path = getInstallDir(rType) + "/" + typeToPath.at(smType) + "_dir0/" + typeToPath.at(smType) + std::to_string(i);
+        path = getPath(smType, PathType::DIR, 0, rType) + "/" + typeToPath.at(smType) + std::to_string(i);
         break;
     }
     return path;
@@ -137,7 +152,11 @@ std::string AppInstallHelper::getPrivatePath(int i, RootType type) const {
 }
 
 std::string AppInstallHelper::getSharedRODir(int i, RootType type) const {
-    return getPath(SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO, PathType::DIR, i, type);
+return getPath(SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO, PathType::DIR, i, type);
+}
+
+std::string AppInstallHelper::getSharedROPath(int i, RootType type) const {
+    return getPath(SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO, PathType::FILE, i, type);
 }
 
 std::string AppInstallHelper::getAppId() const {
@@ -167,8 +186,8 @@ int AppInstallHelper::getGID() const {
 bool AppInstallHelper::createFile(app_install_path_type smType, const std::string &path) {
     if (creat(path.c_str(), 0751) == 0) {
         // Local paths need user change
-        m_fileTypeMap[smType].push_back(std::move(path));
-        if (!m_isLocal || chown(path.c_str(), m_uidGid, m_uidGid) == 0)
+        m_fileTypeMap[smType].push_back(path);
+        if (!m_isLocal || chown(path.c_str(), m_uidGid, FILE_GROUP) == 0)
             return true;
     }
     return false;
@@ -178,8 +197,8 @@ bool AppInstallHelper::createDir(app_install_path_type smType, const std::string
     mktreeSafe(path, 0777);
     // Dont pass base pkg dirs to SM, because transmute will be forced on RO subdirs
     if (!isBasePath)
-        m_dirTypeMap[smType].push_back(std::move(path));
-    if (!m_isLocal || chown(path.c_str(), m_uidGid, m_uidGid) == 0)
+        m_dirTypeMap[smType].push_back(path);
+    if (!m_isLocal || chown(path.c_str(), m_uidGid, FILE_GROUP) == 0)
         return true;
 
     return false;
@@ -202,12 +221,25 @@ void AppInstallHelper::createPath(app_install_path_type smType, PathType pType,
         createDir(smType, path);
         break;
     case PathType::FILE:
-        createPath(smType, PathType::DIR, i, rType);
+        createPath(smType, PathType::DIR, 0, rType);
         createFile(smType, path);
         break;
     }
 }
 
+void AppInstallHelper::createDirLink(app_install_path_type smType, const std::string &dest, int i,
+                                     RootType rType)
+{
+    createInstallDir(rType);
+    std::string linkPath = getPath(smType, PathType::DIR, i, rType);
+    if (symlink(dest.c_str(), linkPath.c_str()) == 0) {
+        m_fileTypeMap[smType].push_back(linkPath);
+        if (m_isLocal) {
+            chown(linkPath.c_str(), m_uidGid, FILE_GROUP);
+        }
+    }
+}
+
 void AppInstallHelper::createTrustedDir(int i, RootType type) {
     createPath(SECURITY_MANAGER_PATH_TRUSTED_RW, PathType::DIR, i, type);
 }
@@ -225,7 +257,14 @@ void AppInstallHelper::createPrivateFile(int i, RootType type) {
 }
 
 void AppInstallHelper::createSharedRODir(int i, RootType type) {
-    createPath(SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO, PathType::DIR, i, type);
+    createPath(SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO, PathType::DIR, i, RootType::SHARED);
+    createInstallDir(RootType::SHARED_TMP);
+    auto linkPath = getSharedRODir(i, RootType::SHARED);
+    createDirLink(SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO, linkPath, i, type);
+}
+
+void AppInstallHelper::createSharedROFile(int i, RootType type) {
+    createPath(SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO, PathType::FILE, i, type);
 }
 
 void AppInstallHelper::createPrivateRODir(int i, RootType type) {
index e238261..cefeb71 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2019 Samsung Electronics Co., Ltd All Rights Reserved
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
  *    you may not use this file except in compliance with the License.
@@ -90,7 +90,9 @@ struct AppInstallHelper {
     enum RootType {
         BASE,
         SKEL,
-        EXTENDED
+        EXTENDED,
+        SHARED,
+        SHARED_TMP
     };
 
     enum PathType {
@@ -107,6 +109,7 @@ struct AppInstallHelper {
     void createPublicDir(RootType type = RootType::BASE);
     void createPrivateFile(int i = 0, RootType type = RootType::BASE);
     void createSharedRODir(int i = 0, RootType type = RootType::BASE);
+    void createSharedROFile(int i = 0, RootType type = RootType::BASE);
     void createPrivateRODir(int i = 0, RootType type = RootType::BASE);
     void removePaths();
 
@@ -121,6 +124,7 @@ struct AppInstallHelper {
     std::string getPublicDir(RootType type = RootType::BASE) const;
     std::string getPrivatePath(int i = 0, RootType type = RootType::BASE) const;
     std::string getSharedRODir(int i = 0, RootType type = RootType::BASE) const;
+    std::string getSharedROPath(int i = 0, RootType type = RootType::BASE) const;
     const TypePathsMap& getDirsMap() const;
     const TypePathsMap& getFilesMap() const;
 
@@ -155,6 +159,8 @@ protected:
 
     bool createFile(app_install_path_type smType, const std::string &path);
     bool createDir(app_install_path_type smType, const std::string &path, bool isBasePath = false);
+    void createDirLink(app_install_path_type smType, const std::string &dest, int i = 0,
+                       RootType rType = RootType::BASE);
     void createInstallDir(RootType type);
 
     std::string m_appName;
index 6fc5140..dbd00b5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2017-2019 Samsung Electronics Co., Ltd All Rights Reserved
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
  *    you may not use this file except in compliance with the License.
@@ -36,11 +36,6 @@ std::string generatePathROLabel(const std::string &pkgId)
     return generatePathRWLabel(pkgId) + "::RO";
 }
 
-std::string generatePathSharedROLabel(const std::string &pkgId)
-{
-    return generatePathRWLabel(pkgId) + "::SharedRO";
-}
-
 std::string generatePathTrustedLabel(int64_t authorId)
 {
     return "User::Author::" + std::to_string(authorId);
@@ -50,3 +45,8 @@ std::string getPublicPathLabel()
 {
     return "User::Home";
 }
+
+std::string getSharedROPathLabel()
+{
+    return "User::App::Shared";
+}
index 8c99ed4..b4af291 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2017-2019 Samsung Electronics Co., Ltd All Rights Reserved
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
  *    you may not use this file except in compliance with the License.
@@ -20,6 +20,6 @@
 std::string generateProcessLabel(const std::string &appId, const std::string &pkgId, bool isHybrid = false);
 std::string generatePathRWLabel(const std::string &pkgId);
 std::string generatePathROLabel(const std::string &pkgId);
-std::string generatePathSharedROLabel(const std::string &pkgId);
 std::string generatePathTrustedLabel(int64_t authorId);
 std::string getPublicPathLabel();
+std::string getSharedROPathLabel();
index 4a0ff06..82175ce 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2016-2019 Samsung Electronics Co., Ltd All Rights Reserved
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
  *    you may not use this file except in compliance with the License.
@@ -36,7 +36,7 @@
 class ScopedInstaller {
 public:
     ScopedInstaller(const AppInstallHelper &app, bool requestUid = true)
-        : m_appId(app.getAppId()),
+        : m_appIds({app.getAppId()}),
           m_uid(app.getUID()),
           m_installType(app.getInstallType()),
           m_shouldUninstall(true),
@@ -70,9 +70,30 @@ public:
         SecurityManagerTest::Api::install(instReq);
     }
 
+    ScopedInstaller(const std::vector<std::string> &appIds, const std::string &pkgId)
+        : m_appIds(appIds),
+          m_uid(0),
+          m_installType(SM_APP_INSTALL_NONE),
+          m_shouldUninstall(true),
+          m_requestUid(false),
+          m_creatorPid(getpid())
+    {
+        SecurityManagerTest::InstallRequest instReq;
+
+        instReq.setPkgId(pkgId);
+        for (unsigned int i = 0; i < appIds.size(); i++) {
+            if (i > 0)
+                instReq.nextApp();
+
+            instReq.setAppId(appIds[i]);
+        }
+
+        SecurityManagerTest::Api::install(instReq);
+    }
+
     ScopedInstaller(const ScopedInstaller &) = delete;
     ScopedInstaller(ScopedInstaller &&other)
-        : m_appId(std::move(other.m_appId)),
+        : m_appIds(std::move(other.m_appIds)),
           m_uid(other.m_uid),
           m_installType(other.m_installType),
           m_shouldUninstall(other.m_shouldUninstall),
@@ -97,7 +118,12 @@ public:
         if (!m_shouldUninstall)
             return;
         SecurityManagerTest::InstallRequest uninstReq;
-        uninstReq.setAppId(m_appId);
+        for (unsigned int i = 0; i < m_appIds.size(); i++) {
+            if (i > 0)
+                uninstReq.nextApp();
+
+            uninstReq.setAppId(m_appIds[i]);
+        }
         if (m_requestUid)
             uninstReq.setUid(m_uid);
         if (m_installType != SM_APP_INSTALL_NONE)
@@ -107,7 +133,7 @@ public:
     }
 
 protected:
-    std::string m_appId;
+    std::vector<std::string> m_appIds;
     uid_t m_uid;
     app_install_type m_installType;
     bool m_shouldUninstall;
index 47872bc..aa642fe 100644 (file)
@@ -68,7 +68,10 @@ OnlycapSet smackGetOnlycap()
                        break;
 
                last = onlycap.find_first_of(SEPARATORS, first + 1);
-               onlycapSet.insert(onlycap.substr(first, last - first));
+               if (last == std::string::npos)
+                       onlycapSet.insert(onlycap.substr(first));
+               else
+                       onlycapSet.insert(onlycap.substr(first, last - first));
        }
        return onlycapSet;
 }
@@ -122,7 +125,6 @@ ScopedProcessLabel::ScopedProcessLabel(std::string label, bool restore) :
                        newOnlycap.insert(m_label);
                        smackSetOnlycap(newOnlycap);
                } else {
-                       m_originalLabel.clear();
                        m_originalOnlycap.clear();
                }
        }
@@ -135,7 +137,8 @@ ScopedProcessLabel::~ScopedProcessLabel()
        if (!m_originalLabel.empty()) {
                try {
                        smackSetLabelForSelf(m_originalLabel);
-                       smackSetOnlycap(m_originalOnlycap);
+                       if (!m_originalOnlycap.empty())
+                               smackSetOnlycap(m_originalOnlycap);
                } catch (const DPL::Test::TestException& e) {
                        RUNNER_ERROR_MSG("Test exception occurred: " << e.GetMessage());
                } catch (const std::exception& e) {
index c571d5f..4441ace 100644 (file)
@@ -283,10 +283,10 @@ void ServiceManager::executeMethod(const std::string &method, const std::string
 
 void ServiceManager::startService(bool withSockets)
 {
-    executeMethod("StartUnit", m_serviceName);
     if (withSockets)
         for (const auto &socket : m_socketsNames)
             executeMethod("StartUnit", socket);
+    executeMethod("StartUnit", m_serviceName);
 }
 
 void ServiceManager::stopService(bool withSockets)
index e8c5bba..4516755 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2015 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2019 Samsung Electronics Co., Ltd. All rights reserved
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
  *    you may not use this file except in compliance with the License.
@@ -123,6 +123,15 @@ void dropProcessPrivileges(lib_retcode expectedResult)
                           << " Expected result: " << expectedResult);
 }
 
+void prepareAppCandidate(lib_retcode expectedResult)
+{
+    int result = security_manager_prepare_app_candidate();
+    RUNNER_ASSERT_MSG((lib_retcode) result == expectedResult,
+                      "preparing app candidate process returned wrong value."
+                          << " Result: " << result << ";"
+                          << " Expected result: " << expectedResult);
+}
+
 void prepareApp(const std::string &appId, lib_retcode expectedResult)
 {
     int result = security_manager_prepare_app(appId.c_str());
index 1b4d2e1..a623ab8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2015 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2019 Samsung Electronics Co., Ltd. All rights reserved
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
  *    you may not use this file except in compliance with the License.
@@ -37,6 +37,7 @@ void setProcessLabel(const std::string &appId, lib_retcode expectedResult = SECU
 void setProcessGroups(const std::string &appId, lib_retcode expectedResult = SECURITY_MANAGER_SUCCESS);
 void dropProcessPrivileges(lib_retcode expectedResult = SECURITY_MANAGER_SUCCESS);
 void prepareApp(const std::string &appId, lib_retcode expectedResult = SECURITY_MANAGER_SUCCESS);
+void prepareAppCandidate(lib_retcode expectedResult = SECURITY_MANAGER_SUCCESS);
 void cleanupApp(const std::string &appId, uid_t uid, pid_t pid, lib_retcode expectedResult = SECURITY_MANAGER_SUCCESS);
 void addUser(const UserRequest &request, lib_retcode expectedResult = SECURITY_MANAGER_SUCCESS);
 void deleteUser(const UserRequest &request, lib_retcode expectedResult = SECURITY_MANAGER_SUCCESS);
index 6e06150..b6fa1a1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2019 Samsung Electronics Co., Ltd All Rights Reserved
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
  *    you may not use this file except in compliance with the License.
@@ -70,7 +70,6 @@ void InstallRequest::setAppId(std::string appId, lib_retcode expectedResult)
                           << " App id: " << appId << ";"
                           << " Result: " << result << ";"
                           << " Expected result: " << expectedResult);
-    m_appId = std::move(appId);
 }
 
 void InstallRequest::setPkgId(std::string pkgId, lib_retcode expectedResult)
@@ -167,10 +166,17 @@ void InstallRequest::setHybrid(lib_retcode expectedResult)
                        << " Expected result: " << expectedResult);
 }
 
+void InstallRequest::nextApp(lib_retcode expectedResult)
+{
+    int result = security_manager_app_inst_req_next(m_req);
+    RUNNER_ASSERT_MSG((lib_retcode)result == expectedResult,
+                        "security_manager_app_inst_req_next() returned wrong value."
+                        << " Result: " << result << ";"
+                        << " Expected result: " << expectedResult);
+}
+
 std::ostream& operator<<(std::ostream &os, const InstallRequest &request)
 {
-    if (!request.m_appId.empty())
-        os << "app id: " << request.m_appId << "; ";
     if (!request.m_pkgId.empty())
         os << "pkg id: " << request.m_pkgId << "; ";
     if (!request.m_privileges.empty()) {
index 4efb5c9..d58d43e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2019 Samsung Electronics Co., Ltd All Rights Reserved
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
  *    you may not use this file except in compliance with the License.
@@ -42,7 +42,6 @@ public:
     InstallRequest& operator=(const InstallRequest&) = delete;
     InstallRequest(InstallRequest &&other)
         : m_req(std::move(other.m_req)),
-          m_appId(std::move(other.m_appId)),
           m_pkgId(std::move(other.m_pkgId)),
           m_authorId(std::move(other.m_authorId)),
           m_privileges(std::move(other.m_privileges)),
@@ -67,6 +66,7 @@ public:
     void setAuthorId(std::string authorId, lib_retcode expectedResult= SECURITY_MANAGER_SUCCESS);
     void setInstallType(const enum app_install_type &type, lib_retcode expectedResult = SECURITY_MANAGER_SUCCESS);
     void setHybrid(lib_retcode expectedResult = SECURITY_MANAGER_SUCCESS);
+    void nextApp(lib_retcode expectedResult = SECURITY_MANAGER_SUCCESS);
     std::string getPkgId() const { return m_pkgId; }
     std::string getAppTizenVersion() const { return m_tizenVer; }
     app_inst_req *get() { return m_req; }
@@ -77,7 +77,6 @@ private:
     app_inst_req *m_req;
 
     std::string m_tizenVer;
-    std::string m_appId;
     std::string m_pkgId;
     std::string m_authorId;
     PrivilegeVector m_privileges;
index dcf9d30..8336767 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2015-2020 Samsung Electronics Co., Ltd. All rights reserved
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
  *    you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@
  * @brief       A crippled abstraction of widely praised, but often misused communication mechanism
  */
 
+#include <poll.h>
 #include <stdexcept>
 #include <unistd.h>
 
@@ -76,15 +77,33 @@ void SynchronizationPipe::claimChildEp() {
 }
 
 void SynchronizationPipe::post() {
-    RUNNER_ASSERT_MSG(m_epClaimed == true, "Endpoint not claimed");
-    auto ret = TEMP_FAILURE_RETRY(write(m_writeEp, "#", 1));
-    RUNNER_ASSERT_ERRNO_MSG(ret > 0, "Write failed ret = " << ret);
+    post("#", 1);
 }
 
 void SynchronizationPipe::wait() {
+    char dummy;
+    wait(&dummy, 1);
+}
+
+void SynchronizationPipe::pollForWait() {
+    RUNNER_ASSERT_MSG(m_epClaimed == true, "Endpoint not claimed");
+
+    pollfd fds[1];
+    fds->fd = m_readEp;
+    fds->events = POLLIN;
+    auto ret = TEMP_FAILURE_RETRY(poll(fds, 1, -1));
+    RUNNER_ASSERT_ERRNO(ret > 0);
+}
+
+void SynchronizationPipe::post(const void *data, size_t size) {
+    RUNNER_ASSERT_MSG(m_epClaimed == true, "Endpoint not claimed");
+    auto ret = TEMP_FAILURE_RETRY(write(m_writeEp, data, size));
+    RUNNER_ASSERT_ERRNO_MSG(ret > 0 && size_t(ret) == size, "Write failed size = " << size << " ret = " << ret);
+}
+
+void SynchronizationPipe::wait(void *data, size_t size) {
     RUNNER_ASSERT_MSG(m_epClaimed == true, "Endpoint not claimed");
 
-    char buf;
-    auto ret = TEMP_FAILURE_RETRY(read(m_readEp, &buf, 1));
-    RUNNER_ASSERT_ERRNO_MSG(ret > 0, "Read failed ret = " << ret);
+    auto ret = TEMP_FAILURE_RETRY(read(m_readEp, data, size));
+    RUNNER_ASSERT_ERRNO_MSG(ret > 0 && size_t(ret) == size, "Read failed size = " << size << " ret = " << ret);
 }
index e072ca2..099323d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2015-2020 Samsung Electronics Co., Ltd. All rights reserved
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
  *    you may not use this file except in compliance with the License.
@@ -33,6 +33,10 @@ public:
 
     void post();
     void wait();
+    void pollForWait();
+
+    void post(const void *data, size_t size);
+    void wait(void *data, size_t size);
 
 private:
     int m_pipeCP[2];    // Child -> Parent
index 2eb4a00..bfb46d9 100644 (file)
@@ -38,7 +38,7 @@
 #include <string.h>
 
 const uid_t APP_UID     = 5001;
-const gid_t APP_GID     = 5001;
+const gid_t APP_GID     = 100;
 const uid_t APP_UID_2   = 5200;
 const gid_t APP_GID_2   = 5200;
 const uid_t DB_ALARM_UID = 6001;
index 57fc289..885b3e1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2015 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2020 Samsung Electronics Co., Ltd. All rights reserved
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
  *    you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
 #include <cynara-client-async.h>
 
 #include <exception>
+#include <poll.h>
 #include <unistd.h>
 
 namespace CynaraTestClientAsync {
@@ -129,31 +130,22 @@ void Client::process(int expectedResult,
     if (m_statusMonitor.getStatus() == DISCONNECTED)
         return;
 
-    int fd = m_statusMonitor.getFd();
-    fd_set fds;
-    timeval tv;
-    FD_ZERO(&fds);
-    FD_SET(fd, &fds);
-    tv.tv_sec = timeoutSeconds;
-    tv.tv_usec = 0;
-
-    int ret;
-    if (m_statusMonitor.getStatus() == READ)
-        ret = TEMP_FAILURE_RETRY(select(fd + 1, &fds, NULL, NULL, &tv));
-    else
-        ret = TEMP_FAILURE_RETRY(select(fd + 1, &fds, &fds, NULL, &tv));
+    pollfd fds[1];
+    fds->fd = m_statusMonitor.getFd();
+    fds->events = POLLIN | (m_statusMonitor.getStatus() == READ ? 0 : POLLOUT);
+    int ret = TEMP_FAILURE_RETRY(poll(fds, 1, timeoutSeconds * 1000));
 
     if (ret == 0) {
         RUNNER_ASSERT_MSG(timeoutExpectation != EXPECT_NO_TIMEOUT,
-                             "Unexpected select timeout."
+                             "Unexpected poll timeout."
                              << " ret = " << ret);
         return;
     }
     RUNNER_ASSERT_ERRNO_MSG(ret > 0,
-                               "Select returned error:"
+                               "Poll returned error:"
                                << " ret = " << ret);
     RUNNER_ASSERT_MSG(timeoutExpectation != EXPECT_TIMEOUT,
-                         "Select returned positive value, when timeout was expected."
+                         "Poll returned positive value, when timeout was expected."
                          << " ret = " << ret);
 
     RUNNER_DEFER_SCOPE(ret = cynara_async_process(m_cynara););
index d08d2e0..a731e07 100644 (file)
@@ -24,6 +24,8 @@
 #define DPL_TEST_CASE_H
 
 #include <string>
+#include <set>
+#include <memory>
 
 #include <dpl/test/performance_result.h>
 
@@ -63,7 +65,8 @@ private:
     PerformanceResultPtr m_performance;
 };
 
-typedef TestCase* TestCasePtr;
+typedef std::shared_ptr<TestCase> TestCasePtr;
+typedef std::list<TestCasePtr> TestCaseSet;
 
 } // namespace Test
 } // namespace DPL
diff --git a/src/framework/include/dpl/test/test_group.h b/src/framework/include/dpl/test/test_group.h
new file mode 100644 (file)
index 0000000..3d9321d
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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.
+ */
+/*
+ * @file        test_group.h
+ * @author      Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
+ * @version     1.0
+ * @brief       Base/default class describing a group of tests
+ */
+
+#ifndef DPL_TEST_GROUP_H
+#define DPL_TEST_GROUP_H
+
+#include <string>
+#include <functional>
+
+#include <dpl/test/test_case.h>
+
+namespace DPL {
+namespace Test {
+
+class TestGroup
+{
+public:
+    TestGroup() {}
+
+    virtual ~TestGroup()
+    {
+    }
+
+    const TestCaseSet& GetTests() const
+    {
+        return m_tests;
+    }
+
+    void RemoveIf(const std::function<bool(const TestCasePtr)>& predFn)
+    {
+        m_tests.remove_if(predFn);
+    }
+
+    void Add(TestCase* test)
+    {
+        m_tests.emplace_back(test);
+    }
+
+    virtual void Init() {};
+    virtual void Finish() {};
+
+private:
+    std::string m_name;
+    TestCaseSet m_tests;
+};
+
+typedef TestGroup* TestGroupPtr;
+
+} // namespace Test
+} // namespace DPL
+
+#endif // DPL_TEST_CASE_H
index 93809ae..e96d88b 100644 (file)
 #include <exception>
 #include <functional>
 #include <iostream>
-#include <list>
 #include <map>
 #include <queue>
 #include <set>
 #include <sstream>
 #include <string>
 #include <vector>
+#include <memory>
 
 #include <dpl/atomic.h>
 #include <dpl/availability.h>
@@ -46,7 +46,7 @@
 #include <dpl/gdbbacktrace.h>
 #include <dpl/singleton.h>
 #include <dpl/test/performance_result.h>
-#include <dpl/test/test_case.h>
+#include <dpl/test/test_group.h>
 #include <dpl/test/test_case_extended.h>
 #include <dpl/test/test_exception.h>
 #include <dpl/test/test_failed.h>
@@ -86,17 +86,13 @@ class TestRunner
     ~TestRunner();
 
   private:
-    typedef std::list<TestCasePtr> TestCaseList;
-    typedef std::map<std::string, TestCaseList> TestCaseGroupMap;
-    typedef std::set<TestCasePtr> TestCaseSet;
+    typedef std::map<std::string, TestGroup*> TestCaseGroupMap;
 
     TestCaseGroupMap m_testGroups;
-    TestCaseSet m_testCaseSet;
 
     TestCasePtr m_currentTestCase;
 
-
-    std::string m_currentGroup;
+    TestGroupPtr m_currentGroup;
 
     // Terminate without any logs.
     // Some test requires to call fork function.
@@ -124,8 +120,8 @@ class TestRunner
     void CollectResult(const std::string& id, const TestResult &result);
 
   public:
-    void InitGroup(const char* name);
-    void RegisterTest(TestCasePtr testCase);
+    void InitGroup(const char* name, TestGroup* group = nullptr);
+    void RegisterTest(TestCase* testCase);
     int ExecTestRunner(int argc, char *argv[]);
     typedef std::vector<std::string> ArgsList;
     int ExecTestRunner(ArgsList args);
@@ -204,6 +200,15 @@ protected:
 } // Test
 } // namespace DPL
 
+#define RUNNER_TEST_GROUP_INIT_ENV(GroupName, GroupEnv)                                 \
+    static int Static##GroupName##Init()                                                \
+    {                                                                                   \
+        DPL::Test::TestRunnerSingleton::Instance().InitGroup(#GroupName, new GroupEnv); \
+        return 0;                                                                       \
+    }                                                                                   \
+    const int DPL_UNUSED Static##GroupName##InitVar =                                   \
+        Static##GroupName##Init();
+
 #define RUNNER_TEST_GROUP_INIT(GroupName)                                 \
     static int Static##GroupName##Init()                                  \
     {                                                                     \
index 636a7cf..6adc2ef 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2011-2020 Samsung Electronics Co., Ltd. All rights reserved
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
  *    you may not use this file except in compliance with the License.
@@ -58,7 +58,7 @@ void AssertProc(const char *condition,
         INTERNAL_LOG("### Function: " << function);
         INTERNAL_LOG(
             "################################################################################");
-    } catch (Exception) {
+    } catch (Exception&) {
         // Just ignore possible double errors
     }
 
index dab84f8..796fb4e 100644 (file)
@@ -21,6 +21,8 @@
  * @brief       Source file containing ConsoleCollector class definition
  */
 
+#include <cstdio>
+
 #include <fstream>
 #include <sstream>
 
@@ -56,6 +58,7 @@ std::string ConsoleCollector::CollectorSpecificHelp() const
 void ConsoleCollector::CollectCurrentTestGroupName(const std::string& name)
 {
     printf("Starting group %s\n", name.c_str());
+    fflush(stdout);
     m_currentGroup = name;
 }
 
@@ -68,6 +71,7 @@ void ConsoleCollector::Finish()
         PrintStats(group.first, group.second);
     }
     PrintStats("All tests together", m_stats);
+    fflush(stdout);
 }
 
 void ConsoleCollector::CollectResult(const std::string& id, const TestResult &result)
@@ -109,6 +113,7 @@ void ConsoleCollector::CollectResult(const std::string& id, const TestResult &re
     default:
         Assert(false && "Bad status");
     }
+    fflush(stdout);
     m_stats.AddTest(result.GetFailStatus());
     m_groupsStats[m_currentGroup].AddTest(result.GetFailStatus());
 }
index dc033a4..26a11d2 100644 (file)
@@ -82,15 +82,18 @@ TestResult::FailStatus TryCatch(const std::function<void(void)> &func, std::stri
     return TestResult::FailStatus::NONE;
 }
 
-void TestRunner::RegisterTest(TestCasePtr testCase)
+void TestRunner::RegisterTest(TestCase* testCase)
 {
-    m_testGroups[m_currentGroup].push_back(testCase);
-    m_testCaseSet.insert(testCase);
+    m_currentGroup->Add(testCase);
 }
 
-void TestRunner::InitGroup(const char* name)
+void TestRunner::InitGroup(const char* name, TestGroup* group)
 {
-    m_currentGroup = name;
+    if (group == nullptr)
+        group = new TestGroup();
+
+    m_testGroups[name] = group;
+    m_currentGroup = group;
 }
 
 void TestRunner::normalizeXMLTag(std::string& str, const std::string& testcase)
@@ -119,11 +122,12 @@ bool TestRunner::filterGroupsByXmls(const std::vector<std::string> & files)
     std::string testsuite;
     if(!m_testGroups.empty())
     {
-        for(TestCaseGroupMap::const_iterator cit = m_testGroups.begin(); cit != m_testGroups.end(); ++cit)
+        for(auto cit = m_testGroups.begin(); cit != m_testGroups.end(); ++cit)
         {
-            if(!cit->second.empty())
+            const TestCaseSet& tl = cit->second->GetTests();
+            if(!tl.empty())
             {
-                for(TestCaseList::const_iterator cj = cit->second.begin(); cj != cit->second.end(); ++cj)
+                for(auto cj = tl.begin(); cj != tl.end(); ++cj)
                 {
                     std::string name = (*cj)->GetName();
                     std::string::size_type st = name.find('_');
@@ -209,15 +213,9 @@ bool TestRunner::filterGroupsByXmls(const std::vector<std::string> & files)
 bool TestRunner::filterByXML(std::map<std::string, bool> & casesMap)
 {
     for (auto &group : m_testGroups) {
-        TestCaseList newList;
-        for (auto &tc : group.second)
-        {
-            if (casesMap.find(tc->GetName()) != casesMap.end()) {
-                casesMap[tc->GetName()] = true;
-                newList.push_back(tc);
-            }
-        }
-        group.second = newList;
+        group.second->RemoveIf([&](const TestCasePtr test){
+            return (casesMap.find(test->GetName()) == casesMap.end());
+        });
     }
     for (auto &cs : casesMap)
     {
@@ -276,6 +274,7 @@ void TestRunner::RunTestCase(TestCasePtr testCase)
             if (!testReason.empty())
                 testReason += "\n";
             testReason += finishReason;
+            break;
         case TestResult::FailStatus::NONE:
             if (!cleanupReason.empty()) {
                 if (!testReason.empty())
@@ -305,20 +304,21 @@ void TestRunner::RunTests()
 
     unsigned count = 0;
     for (auto &group : m_testGroups) {
-        count += group.second.size();
+        count += group.second->GetTests().size();
     }
     fprintf(stderr, "%sFound %d testcases...%s\n", GREEN_BEGIN, count, GREEN_END);
     fprintf(stderr, "%s%s%s\n", GREEN_BEGIN, "Running tests...", GREEN_END);
     for (auto &group : m_testGroups) {
-        TestCaseList list = group.second;
-        if (!list.empty()) {
+        const TestCaseSet& set = group.second->GetTests();
+        if (!set.empty()) {
+            group.second->Init();
+
             for (auto &collector : m_collectors) {
                 collector.second->CollectCurrentTestGroupName(group.first);
             }
-            list.sort([](const TestCasePtr &a, const TestCasePtr &b) { return (*a < *b); });
 
-            for (TestCaseList::const_iterator iterator = list.begin();
-                 iterator != list.end();
+            for (TestCaseSet::const_iterator iterator = set.begin();
+                 iterator != set.end();
                  ++iterator)
             {
                 TestCasePtr test = *iterator;
@@ -334,6 +334,7 @@ void TestRunner::RunTests()
                     return;
                 }
             }
+            group.second->Finish();
         }
     }
 
@@ -415,8 +416,8 @@ std::string TestRunner::getConcatedFailReason(const std::string &reason)
 
 TestRunner::~TestRunner()
 {
-    for(auto &t : m_testCaseSet)
-        delete t;
+    for(auto &g : m_testGroups)
+        delete g.second;
 }
 
 void TestRunner::CollectResult(const std::string& id, const TestResult& result)
@@ -553,7 +554,7 @@ int TestRunner::ExecTestRunner(ArgsList args)
         if (arg.find(startCmd) == 0) {
             arg.erase(0, startCmd.length());
             for (auto &group : m_testGroups) {
-                for (auto &tc : group.second) {
+                for (auto &tc : group.second->GetTests()) {
                     if (tc->GetName() == arg) {
                         m_startTestId = arg;
                         break;
@@ -572,13 +573,14 @@ int TestRunner::ExecTestRunner(ArgsList args)
             return 0;
         } else if (arg.find(groupId) == 0) {
             arg.erase(0, groupId.length());
-            TestCaseGroupMap::iterator found = m_testGroups.find(arg);
-            if (found != m_testGroups.end()) {
-                std::string name = found->first;
-                TestCaseList newList = found->second;
-                m_testGroups.clear();
-                m_testGroups[name] = newList;
-            } else {
+            for (auto it = m_testGroups.begin(); it != m_testGroups.end();) {
+                if (it->first == arg)
+                    it++;
+                else
+                    it = m_testGroups.erase(it);
+            }
+
+            if (m_testGroups.empty()) {
                 fprintf(stderr, "Group %s not found\n", arg.c_str());
                 InvalidArgs();
                 Usage();
@@ -595,7 +597,14 @@ int TestRunner::ExecTestRunner(ArgsList args)
             return 0;
         } else if (arg.find(listInGroup) == 0) {
             arg.erase(0, listInGroup.length());
-            for (auto &test : m_testGroups[arg]) {
+            auto it = m_testGroups.find(arg);
+            if (it == m_testGroups.end()) {
+                fprintf(stderr, "Group %s not found\n", arg.c_str());
+                InvalidArgs();
+                Usage();
+                return -1;
+            }
+            for (auto &test : it->second->GetTests()) {
                 printf("ID:%s\n", test->GetName().c_str());
             }
             return 0;
@@ -640,14 +649,9 @@ int TestRunner::ExecTestRunner(ArgsList args)
 
             pcrecpp::RE re(arg.c_str());
             for (auto &group : m_testGroups) {
-                TestCaseList newList;
-                for (auto &tc : group.second)
-                {
-                    if (re.PartialMatch(tc->GetName())) {
-                        newList.push_back(tc);
-                    }
-                }
-                group.second = newList;
+                group.second->RemoveIf([&](const TestCasePtr& test){
+                    return !re.PartialMatch(test->GetName());
+                });
             }
         } else if (arg.find(test) == 0) {
             arg.erase(0, test.length());
@@ -670,14 +674,9 @@ int TestRunner::ExecTestRunner(ArgsList args)
 
             pcrecpp::RE re(arg.c_str());
             for (auto &group : m_testGroups) {
-                TestCaseList newList;
-                for (auto &tc : group.second)
-                {
-                    if (re.FullMatch(tc->GetName())) {
-                        newList.push_back(tc);
-                    }
-                }
-                group.second = newList;
+                group.second->RemoveIf([&](const TestCasePtr& test){
+                    return !re.FullMatch(test->GetName());
+                });
             }
         } else if(arg.find(onlyFromXML) == 0) {
             arg.erase(0, onlyFromXML.length());
@@ -718,7 +717,7 @@ int TestRunner::ExecTestRunner(ArgsList args)
     if(justList)
     {
         for (auto &group : m_testGroups) {
-            for (auto &tc : group.second) {
+            for (auto &tc : group.second->GetTests()) {
                 printf("ID:%s:%s\n", group.first.c_str(), tc->GetName().c_str());
             }
         }
diff --git a/src/nether-tests/CMakeLists.txt b/src/nether-tests/CMakeLists.txt
new file mode 100644 (file)
index 0000000..5cf7915
--- /dev/null
@@ -0,0 +1,79 @@
+# Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+#
+#   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.
+#
+# @file        CMakeLists.txt
+# @author      Piotr Sawicki (p.sawicki2@partner.samsung.com)
+# @brief       CMake configuration file
+#
+
+INCLUDE(FindPkgConfig)
+
+SET(TARGET_NETHER_TESTS "nether-tests")
+
+SET(NETHER_TESTS_SOURCES
+    ${PROJECT_SOURCE_DIR}/src/nether-tests/nether_tests.cpp
+    ${PROJECT_SOURCE_DIR}/src/common/tests_common.cpp
+    ${PROJECT_SOURCE_DIR}/src/common/tzplatform.cpp
+    ${PROJECT_SOURCE_DIR}/src/common/sm_api.cpp
+    ${PROJECT_SOURCE_DIR}/src/common/sm_request.cpp
+    ${PROJECT_SOURCE_DIR}/src/common/sm_user_request.cpp
+    ${PROJECT_SOURCE_DIR}/src/common/sm_policy_request.cpp
+    ${PROJECT_SOURCE_DIR}/src/common/app_install_helper.cpp
+    ${PROJECT_SOURCE_DIR}/src/security-manager-tests/common/sm_commons.cpp
+    ${PROJECT_SOURCE_DIR}/src/security-manager-tests/common/policy_configuration.cpp
+    ${PROJECT_SOURCE_DIR}/src/security-manager-tests/common/template_parser.cpp
+    ${PROJECT_SOURCE_DIR}/src/cynara-tests/common/cynara_test_client.cpp
+   )
+
+INCLUDE_DIRECTORIES(SYSTEM
+    ${SEC_MGR_TESTS_DEP_INCLUDE_DIRS}
+   )
+
+INCLUDE_DIRECTORIES(SYSTEM
+    ${CYNARA_TARGET_DEP_INCLUDE_DIRS}
+    )
+
+INCLUDE_DIRECTORIES(
+    ${PROJECT_SOURCE_DIR}/src/common/
+    ${PROJECT_SOURCE_DIR}/src/security-manager-tests/common/
+    ${PROJECT_SOURCE_DIR}/src/cynara-tests/common/
+   )
+
+FIND_PACKAGE(Threads)
+
+ADD_EXECUTABLE(${TARGET_NETHER_TESTS} ${NETHER_TESTS_SOURCES})
+
+TARGET_LINK_LIBRARIES(${TARGET_NETHER_TESTS}
+    ${SEC_MGR_TESTS_DEP_LIBRARIES}
+    dpl-test-framework
+    tests-common
+    ${CMAKE_THREAD_LIBS_INIT}
+    )
+
+INSTALL(TARGETS ${TARGET_NETHER_TESTS} DESTINATION /usr/bin)
+
+INSTALL(FILES
+    ${PROJECT_SOURCE_DIR}/src/nether-tests/setup-nether-tests-nns.sh
+    ${PROJECT_SOURCE_DIR}/src/nether-tests/teardown-nether-tests-nns.sh
+    ${PROJECT_SOURCE_DIR}/src/nether-tests/setup-nether-tests-dns.sh
+    ${PROJECT_SOURCE_DIR}/src/nether-tests/teardown-nether-tests-dns.sh
+    DESTINATION bin
+    PERMISSIONS OWNER_READ
+                OWNER_WRITE
+                OWNER_EXECUTE
+                GROUP_READ
+                GROUP_EXECUTE
+                WORLD_READ
+                WORLD_EXECUTE
+    )
diff --git a/src/nether-tests/nether_tests.cpp b/src/nether-tests/nether_tests.cpp
new file mode 100644 (file)
index 0000000..69bf807
--- /dev/null
@@ -0,0 +1,1441 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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.
+ */
+
+/*
+ * @file        nether_tests.cpp
+ * @author      Piotr Sawicki (p.sawicki2@partner.samsung.com)
+ * @version     1.0
+ * @brief       Tests for Nether service
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <linux/netlink.h>
+#include <netdb.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <sys/mount.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <condition_variable>
+#include <string>
+#include <thread>
+#include <vector>
+
+#include <scoped_installer.h>
+#include <sm_commons.h>
+#include <tests_common.h>
+#include <dpl/test/safe_cleanup.h>
+
+
+using namespace SecurityManagerTest;
+using namespace DPL::Test;
+
+const std::string INTERNET_ACCESS_PRIVILEGE = "http://tizen.org/privilege/internet";
+const std::string NETHER_NETNS_NAME_NONE = "";
+const std::string NETHER_NETNS_NAME_TEST = "nether_test_network_ns";
+const std::string NETNS_RUN_DIR = "/var/run/netns"; // taken from iproute2
+const std::string NETHER_NETNS_SETUP_COMMAND = "/usr/bin/setup-nether-tests-nns.sh " + NETHER_NETNS_NAME_TEST;
+const std::string NETHER_NETNS_TEARDOWN_COMMAND = "/usr/bin/teardown-nether-tests-nns.sh " + NETHER_NETNS_NAME_TEST;
+const std::string NETHER_DNS_SETUP_COMMAND = "/usr/bin/setup-nether-tests-dns.sh";
+const std::string NETHER_DNS_TEARDOWN_COMMAND = "/usr/bin/teardown-nether-tests-dns.sh";
+
+
+const ssize_t NET_BUFFER_SIZE = 2048;
+const int UDP_MESSAGES_COUNT = 20000;
+const int TCP_MESSAGES_COUNT = 20000;
+
+const uint16_t UDP_TEST_PORT = 12000;
+const uint16_t TCP_TEST_PORT = 12000;
+
+const std::string REMOTE_INTERFACE_ADDRESS = "10.1.0.2";
+const std::string REMOTE_INTERFACE_NAME = "veth1";
+const std::string LOCAL_HOST_TEST_SERVER_ADDRESS = "127.0.0.1";
+const std::string LOCAL_TEST_MCAST_GROUP = "225.0.0.250";
+const std::string DNS_TEST_ADDRESS = "www.samsung.com";
+const std::string ANY_INTERFACE = "";
+
+const char TTL_MCAST_RESTRIC_SUBNET = 1;
+
+const int MONITOR_TIMEOUT = 1000; // ms
+
+enum class NetherInternetAccess {
+    ACCESS_GRANTED,
+    ACCESS_DENIED
+};
+
+
+void runShellScriptInChildAndWait(const std::string &command)
+{
+    RUNNER_ASSERT_MSG(system(command.c_str()) != -1, "Couldn't run command: " << command);
+}
+
+
+class ScopedShellScriptRunner final {
+public:
+    ScopedShellScriptRunner(const std::string &setupCmd, const std::string &teardownCmd)
+    : m_teardownCmd(teardownCmd)
+    {
+        runShellScriptInChildAndWait(setupCmd);
+    }
+
+    ~ScopedShellScriptRunner()
+    {
+        SafeCleanup::run([this]() {
+            runShellScriptInChildAndWait(m_teardownCmd);
+        });
+    }
+
+    ScopedShellScriptRunner(const ScopedShellScriptRunner &) = delete;
+    ScopedShellScriptRunner &operator=(const ScopedShellScriptRunner &) = delete;
+
+private:
+    std::string m_teardownCmd;
+};
+
+
+void createChildProcess(const std::function<int(int)> &procedure, pid_t &childPid, int &childPipeFd)
+{
+    int pipeFd[2];
+    RUNNER_ASSERT_ERRNO_MSG(pipe2(pipeFd, O_DIRECT) == 0, "pipe() failed");
+
+    pid_t pid = fork();
+    RUNNER_ASSERT_ERRNO_MSG(pid != -1, "fork() failed");
+
+    if (pid != 0) {
+        // parent code
+        TEMP_FAILURE_RETRY(close(pipeFd[1]));
+
+        childPipeFd = pipeFd[0];
+        childPid = pid;
+    } else {
+        // child code
+        TestRunnerSingleton::Instance().Terminate();
+
+        close(STDIN_FILENO);
+        close(STDOUT_FILENO);
+        close(STDERR_FILENO);
+
+        close(pipeFd[0]);
+
+        int retStatus = EXIT_FAILURE;
+
+        int devNullFd = TEMP_FAILURE_RETRY(open("/dev/null", O_WRONLY));
+        if (devNullFd == -1) {
+            goto end;
+        }
+
+        if (TEMP_FAILURE_RETRY(dup2(devNullFd, STDIN_FILENO)) == -1) {
+            goto end;
+        }
+
+        if (TEMP_FAILURE_RETRY(dup2(devNullFd, STDOUT_FILENO)) == -1) {
+            goto end;
+        }
+
+        if (TEMP_FAILURE_RETRY(dup2(devNullFd, STDERR_FILENO)) == -1) {
+            goto end;
+        }
+
+        retStatus = procedure(pipeFd[1]);
+end:
+        exit(retStatus);
+    }
+}
+
+
+int switchToNetworkNamespace(const std::string &netnsName)
+{
+    if (netnsName == NETHER_NETNS_NAME_NONE) {
+        return 0;
+    }
+
+    const std::string netnsPath { NETNS_RUN_DIR + "/" + netnsName };
+    if (netnsPath.length() >= PATH_MAX) {
+        return -1;
+    }
+
+    int netNsFd = open(netnsPath.c_str(), O_RDONLY);
+    if (netNsFd == -1) {
+        return -1;
+    }
+
+    // uses an existing network name-space (previously created by "ip netns" command)
+    if (setns(netNsFd, CLONE_NEWNET) == -1) {
+        close(netNsFd);
+        return -1;
+    }
+
+    return 0;
+}
+
+
+class TemporaryNormalTestUser
+{
+public:
+    TemporaryNormalTestUser(const std::string &userName)
+    : m_user(userName, GUM_USERTYPE_NORMAL, false)
+    {
+        m_user.create();
+    }
+
+    uid_t getUid() const
+    {
+        return m_user.getUid();
+    }
+
+private:
+    TemporaryTestUser m_user;
+};
+
+
+class InternetLocalAppInstallHelper : public AppInstallHelper
+{
+public:
+    InternetLocalAppInstallHelper(const std::string &namePrefix, uid_t uid, NetherInternetAccess access)
+    : AppInstallHelper(namePrefix, uid)
+    {
+        setInstallType(app_install_type::SM_APP_INSTALL_LOCAL);
+        if (access == NetherInternetAccess::ACCESS_GRANTED) {
+            addPrivilege(INTERNET_ACCESS_PRIVILEGE);
+        }
+    }
+};
+
+
+class AppContext
+{
+public:
+    AppContext()
+    : m_appId{}
+    , m_appUID(-1)
+    , m_appGID(-1)
+    {
+    }
+
+    AppContext(const std::string &appId, uid_t appUID, gid_t appGID)
+    : m_appId(appId)
+    , m_appUID(appUID)
+    , m_appGID(appGID)
+    {
+    }
+
+    const std::string &appId() const
+    {
+        return m_appId;
+    }
+
+    void setAppId(const std::string &appId)
+    {
+        m_appId = appId;
+    }
+
+    uid_t getUID() const
+    {
+        return m_appUID;
+    }
+
+    void setUID(uid_t appUID)
+    {
+        m_appUID = appUID;
+    }
+
+    gid_t getGID() const
+    {
+        return m_appGID;
+    }
+
+    void setGID(gid_t appGID)
+    {
+        m_appGID = appGID;
+    }
+
+private:
+    std::string m_appId;
+    uid_t m_appUID;
+    gid_t m_appGID;
+};
+
+
+class ScopedAppContext : public AppContext
+{
+public:
+    ScopedAppContext(const std::string &appPrefix, NetherInternetAccess access)
+    : m_user(appPrefix + "_user")
+    , m_installHelper(appPrefix + "_app_normal", m_user.getUid(), access)
+    , m_scopedInstaller(m_installHelper)
+    {
+        setAppId(m_installHelper.getAppId());
+        setUID(m_installHelper.getUID());
+        setGID(m_installHelper.getGID());
+    }
+
+private:
+    TemporaryNormalTestUser m_user;
+    InternetLocalAppInstallHelper m_installHelper;
+    ScopedInstaller m_scopedInstaller;
+};
+
+
+void runProcedureInNetAppContext(
+    const std::string &appPrefix,
+    const std::function<void(void)> &procedure,
+    const NetherInternetAccess access = NetherInternetAccess::ACCESS_DENIED)
+{
+    ScopedAppContext scopedAppContext(appPrefix, access);
+
+    auto smackLabel = scopedAppContext.appId();
+    auto appUID = scopedAppContext.getUID();
+    auto appGID = scopedAppContext.getGID();
+
+    // run client procedure in app context
+    runInChildParentWait([=]() {
+        Api::setProcessLabel(smackLabel);
+        RUNNER_ASSERT_ERRNO_MSG(drop_root_privileges(appUID, appGID) == 0,
+                                "drop_root_privileges() failed");
+        procedure();
+    });
+}
+
+
+class NetServer
+{
+public:
+    NetServer()
+    : m_monitorIsRunning(false)
+    , m_receivedBytes(0ull)
+    , m_serverPid(-1)
+    , m_serverPipeFd(-1)
+    {}
+
+    NetServer(const NetServer &) = delete;
+    NetServer &operator=(const NetServer &) = delete;
+
+    virtual ~NetServer()
+    {
+        SafeCleanup::run([this]() {
+            stop();
+        });
+    }
+
+    void start(const std::string &netnsName = NETHER_NETNS_NAME_NONE)
+    {
+        std::unique_lock<std::mutex> lock(m_monitorMutex);
+
+        RUNNER_ASSERT_MSG(!m_monitorIsRunning, "Monitor thread is already running");
+
+        createChildProcess([=] (int pipeFd) -> int {
+            if (netnsName != NETHER_NETNS_NAME_NONE) {
+                if (switchToNetworkNamespace(netnsName) == -1) {
+                    exit(EXIT_FAILURE);
+                }
+            }
+            return serverProcedure(pipeFd);
+        }, m_serverPid, m_serverPipeFd);
+
+        waitForServer();
+
+        m_monitorThread = std::move(std::thread(&NetServer::monitorThreadProc, this));
+
+        m_monitorSyncPoint.wait(lock, [this]() {
+           return m_monitorIsRunning;
+        });
+    }
+
+    void stop()
+    {
+        stopMonitor();
+        closeServerPipe();
+        stopServerProcess();
+    }
+
+    uint64_t getReceivedBytes() const
+    {
+        RUNNER_ASSERT_MSG(!isAlive(), "Cannot read statistics. Server is still running: " << (*this));
+        return m_receivedBytes;
+    }
+
+    bool isAlive() const
+    {
+        int status;
+        return waitpid(m_serverPid, &status, WNOHANG) == 0;
+    }
+
+    virtual int serverProcedure(int) = 0;
+
+    virtual std::string getDescription() const = 0;
+
+protected:
+    void notifyManager(int pipeFd)
+    {
+        char c = 'X';
+        ssize_t ret = TEMP_FAILURE_RETRY(write(pipeFd, &c, sizeof(c)));
+        if (ret == -1) {
+            exit(EXIT_FAILURE);
+        }
+    }
+
+private:
+    void waitForServer() const
+    {
+        pollfd pfd { m_serverPipeFd, POLLIN, 0 };
+
+        int ret = TEMP_FAILURE_RETRY(poll(&pfd, 1, MONITOR_TIMEOUT));
+        RUNNER_ASSERT_ERRNO_MSG(ret >= 0, "poll() failed");
+
+        if (pfd.revents & POLLIN) {
+            char c;
+            ssize_t len = TEMP_FAILURE_RETRY(read(m_serverPipeFd, &c, sizeof(c)));
+            RUNNER_ASSERT_ERRNO_MSG(len >= 0, "Read pipe failed");
+        }
+    }
+
+    ssize_t collectStatistics()
+    {
+        char buffer[NET_BUFFER_SIZE];
+
+        ssize_t ret = TEMP_FAILURE_RETRY(read(m_serverPipeFd, buffer, sizeof(buffer)));
+        if (ret > 0) {
+            m_receivedBytes += static_cast<uint64_t>(ret);
+        }
+
+        return ret;
+    }
+
+    void closeServerPipe()
+    {
+        if (m_serverPipeFd == -1) {
+            return;
+        }
+
+        close(m_serverPipeFd);
+        m_serverPipeFd = -1;
+    }
+
+    void stopServerProcess()
+    {
+        if (m_serverPid == -1) {
+            return;
+        }
+
+        if (!isAlive()) {
+            m_serverPid = -1;
+            return;
+        }
+
+        RUNNER_ASSERT_ERRNO_MSG(kill(m_serverPid, SIGTERM) == 0, "kill() failed");
+
+        int status;
+        do {
+            pid_t ret = TEMP_FAILURE_RETRY(waitpid(m_serverPid, &status, WUNTRACED | WCONTINUED));
+            RUNNER_ASSERT_ERRNO_MSG(ret != -1, "waitpid() failed");
+        } while (!WIFEXITED(status) && !WIFSIGNALED(status));
+
+        m_serverPid = -1;
+    }
+
+    void stopMonitor()
+    {
+        {
+            std::lock_guard<std::mutex> lock(m_monitorMutex);
+            m_monitorIsRunning = false;
+        }
+
+        if (m_monitorThread.joinable()) {
+            m_monitorThread.join();
+        }
+    }
+
+    void monitorThreadProc()
+    {
+        std::unique_lock<std::mutex> lock(m_monitorMutex);
+        m_monitorIsRunning = true;
+        lock.unlock();
+
+        m_monitorSyncPoint.notify_one();
+
+        lock.lock();
+
+        pollfd pollFd{ m_serverPipeFd, POLLIN, 0 };
+
+        while (m_monitorIsRunning) {
+
+            lock.unlock();
+
+            int ret = TEMP_FAILURE_RETRY(poll(&pollFd, 1, MONITOR_TIMEOUT));
+            if (ret == -1) {
+                lock.lock();
+                break;
+            }
+
+            if (ret > 0 && (pollFd.revents & POLLIN)) {
+                if (collectStatistics() == -1) {
+                    lock.lock();
+                    break;
+                }
+            }
+
+            lock.lock();
+        }
+
+        m_monitorIsRunning = false;
+        lock.unlock();
+    }
+
+    // monitor variables
+    std::thread m_monitorThread;
+    bool m_monitorIsRunning;
+    std::mutex m_monitorMutex;
+    std::condition_variable m_monitorSyncPoint;
+
+    // server variables
+    uint64_t m_receivedBytes;
+    pid_t m_serverPid;
+    int m_serverPipeFd;
+
+    friend std::ostream &operator<<(std::ostream &os, const NetServer &);
+};
+
+
+std::ostream &operator<<(std::ostream &os, const NetServer &server)
+{
+    os << server.getDescription();
+    return os;
+}
+
+
+class UDPServer : public NetServer
+{
+public:
+    UDPServer(uint16_t port, int protocol = IPPROTO_UDP)
+    : NetServer{}
+    , m_port(port)
+    , m_protocol(protocol)
+    {}
+
+    virtual ~UDPServer() {}
+
+    virtual std::string getDescription() const override
+    {
+        return "UDPServer port: " + std::to_string(m_port);
+    }
+
+    virtual bool applyExtraSocketOptions(int)
+    {
+        return true;
+    }
+
+    virtual int serverProcedure(int pipeFd) override
+    {
+        FdUniquePtr pipePtr(&pipeFd);
+
+        int sockFd = socket(AF_INET, SOCK_DGRAM, m_protocol);
+        if (sockFd == -1) {
+            exit(EXIT_FAILURE);
+        }
+
+        SockUniquePtr sockPtr(&sockFd);
+
+        int optionValue = 1;
+        if (setsockopt(sockFd, SOL_SOCKET, SO_REUSEADDR, static_cast<const void *>(&optionValue) , sizeof(int)) == -1) {
+            exit(EXIT_FAILURE);
+        }
+
+        struct sockaddr_in serverAddress;
+        memset(&serverAddress, 0, sizeof(serverAddress));
+        serverAddress.sin_family = AF_INET;
+        serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
+        serverAddress.sin_port = htons(m_port);
+
+        if (bind(sockFd, reinterpret_cast<struct sockaddr *>(&serverAddress), sizeof(serverAddress)) == -1) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (!applyExtraSocketOptions(sockFd)) {
+            exit(EXIT_FAILURE);
+        }
+
+        struct sockaddr_in clntAddress;
+        socklen_t clntAddressLength = static_cast<socklen_t>(sizeof(clntAddress));
+        char receiveBuffer[NET_BUFFER_SIZE];
+
+        notifyManager(pipeFd);
+
+        while (true) {
+            ssize_t len = TEMP_FAILURE_RETRY(recvfrom(sockFd, receiveBuffer, sizeof(receiveBuffer), 0,
+                    reinterpret_cast<struct sockaddr *>(&clntAddress), &clntAddressLength));
+
+            if (len == -1) {
+                exit(EXIT_FAILURE);
+            }
+
+            if (len == 0) {
+                continue;
+            }
+
+            do {
+                ssize_t pos = 0;
+                ssize_t ret = TEMP_FAILURE_RETRY(write(pipeFd, &receiveBuffer[pos], len));
+                if (ret == -1) {
+                    exit(EXIT_FAILURE);
+                }
+
+                len -= ret;
+                pos += ret;
+            } while (len != 0);
+        }
+
+        return EXIT_SUCCESS;
+    }
+
+private:
+    uint16_t m_port;
+    int m_protocol;
+};
+
+
+class UDPServerApp : public UDPServer
+{
+public:
+    UDPServerApp(uint16_t port, int protocol, const AppContext &appContext)
+    : UDPServer(port, protocol)
+    , m_appContext(appContext)
+    {
+    }
+
+    virtual int serverProcedure(int pipeFd) override
+    {
+        Api::setProcessLabel(m_appContext.appId());
+        RUNNER_ASSERT_ERRNO_MSG(drop_root_privileges(m_appContext.getUID(), m_appContext.getGID()) == 0,
+                                "drop_root_privileges() failed");
+
+        return UDPServer::serverProcedure(pipeFd);
+    }
+
+private:
+    AppContext m_appContext;
+};
+
+class UDPMulticastServer : public UDPServer
+{
+public:
+    UDPMulticastServer(uint16_t port, int protocol,
+            const std::string &mcastGroup, const std::string &networkInterface)
+    : UDPServer(port, protocol)
+    , m_mcastGroup(mcastGroup)
+    , m_networkInterface(networkInterface)
+    {
+    }
+
+    bool applyExtraSocketOptions(int sockFd) override
+    {
+        struct ip_mreq multicastRequest;
+        memset(&multicastRequest, 0, sizeof(multicastRequest));
+
+        in_addr_t mcastGroupAddr = inet_addr(m_mcastGroup.c_str());
+        if (!IN_MULTICAST(ntohl(mcastGroupAddr))) {
+            return false;
+        }
+
+        multicastRequest.imr_multiaddr.s_addr = mcastGroupAddr;
+
+        if (m_networkInterface == ANY_INTERFACE) {
+            multicastRequest.imr_interface.s_addr = INADDR_ANY;
+        } else {
+            struct ifreq interfaceRequest;
+            memset(&interfaceRequest, 0, sizeof(interfaceRequest));
+
+            interfaceRequest.ifr_addr.sa_family = AF_INET;
+            strncpy(interfaceRequest.ifr_name, m_networkInterface.c_str(), IFNAMSIZ);
+            interfaceRequest.ifr_name[IFNAMSIZ - 1] = '\0';
+
+            if (ioctl(sockFd, SIOCGIFADDR, &interfaceRequest) == -1) {
+                return false;
+            }
+
+            struct sockaddr_in *addr = reinterpret_cast<struct sockaddr_in *>(&interfaceRequest.ifr_addr);
+            multicastRequest.imr_interface.s_addr = addr->sin_addr.s_addr;
+        }
+
+        return setsockopt(sockFd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+                static_cast<const void *>(&multicastRequest), sizeof(multicastRequest)) == 0;
+    }
+
+private:
+    std::string m_mcastGroup;
+    std::string m_networkInterface;
+};
+
+
+class UDPMulticastServerApp : public UDPMulticastServer
+{
+public:
+    UDPMulticastServerApp(uint16_t port, int protocol, const std::string &mcastGroup, const std::string &networkInterface,
+            const AppContext &appContext)
+    : UDPMulticastServer(port, protocol, mcastGroup, networkInterface)
+    , m_appContext(appContext)
+    {
+    }
+
+    virtual int serverProcedure(int pipeFd) override
+    {
+        Api::setProcessLabel(m_appContext.appId());
+        RUNNER_ASSERT_ERRNO_MSG(drop_root_privileges(m_appContext.getUID(), m_appContext.getGID()) == 0,
+                                "drop_root_privileges() failed");
+
+        return UDPServer::serverProcedure(pipeFd);
+    }
+
+private:
+    AppContext m_appContext;
+};
+
+
+class TCPServer : public NetServer
+{
+public:
+    explicit TCPServer(uint16_t port)
+    : NetServer{}
+    , m_port(port)
+    {}
+
+    virtual ~TCPServer() {}
+
+    virtual std::string getDescription() const override
+    {
+        return "TCPServer port: " + std::to_string(m_port);
+    }
+
+    virtual int serverProcedure(int pipeFd) override
+    {
+        FdUniquePtr pipePtr(&pipeFd);
+
+        int sockFd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+        if (sockFd == -1) {
+            exit(EXIT_FAILURE);
+        }
+
+        SockUniquePtr sockPtr(&sockFd);
+
+        int optionValue = 1;
+        if (setsockopt(sockFd, SOL_SOCKET, SO_REUSEADDR, static_cast<const void *>(&optionValue) , sizeof(int)) == -1) {
+            exit(EXIT_FAILURE);
+        }
+
+        struct sockaddr_in serverAddress;
+        memset(&serverAddress, 0, sizeof(serverAddress));
+        serverAddress.sin_family = AF_INET;
+        serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
+        serverAddress.sin_port = htons(m_port);
+
+        if (bind(sockFd, reinterpret_cast<struct sockaddr *>(&serverAddress), sizeof(serverAddress)) == -1) {
+            exit(EXIT_FAILURE);
+        }
+
+        if (listen(sockFd, 1) == -1) {
+            exit(EXIT_FAILURE);
+        }
+
+        struct sockaddr_in clntAddress;
+        socklen_t clntAddressLength = static_cast<socklen_t>(sizeof(clntAddress));
+        char receiveBuffer[NET_BUFFER_SIZE];
+
+        notifyManager(pipeFd);
+
+        while (true) {
+            int acceptedSocketFd = TEMP_FAILURE_RETRY(accept(sockFd, reinterpret_cast<struct sockaddr *>(&clntAddress),
+                    &clntAddressLength));
+            if (acceptedSocketFd == -1) {
+                exit(EXIT_FAILURE);
+            }
+
+            SockUniquePtr acceptSockPtr(&acceptedSocketFd);
+
+            while (true) {
+                ssize_t len = TEMP_FAILURE_RETRY(recv(acceptedSocketFd, receiveBuffer, sizeof(receiveBuffer), 0));
+                if (len == -1) {
+                    exit(EXIT_FAILURE);
+                }
+
+                if (len == 0) {
+                    break;
+                }
+
+                do {
+                    ssize_t pos = 0;
+                    ssize_t ret = TEMP_FAILURE_RETRY(write(pipeFd, &receiveBuffer[pos], len));
+                    if (ret == -1) {
+                        exit(EXIT_FAILURE);
+                    }
+
+                    len -= ret;
+                    pos += ret;
+                } while (len != 0);
+            }
+        }
+
+        return EXIT_SUCCESS;
+    }
+
+private:
+    uint16_t m_port;
+};
+
+
+class TCPServerApp : public TCPServer
+{
+public:
+    TCPServerApp(int port, const AppContext &appContext)
+    : TCPServer(port)
+    , m_appContext(appContext)
+    {
+    }
+
+    virtual int serverProcedure(int pipeFd) override
+    {
+        Api::setProcessLabel(m_appContext.appId());
+        RUNNER_ASSERT_ERRNO_MSG(drop_root_privileges(m_appContext.getUID(), m_appContext.getGID()) == 0,
+                                "drop_root_privileges() failed");
+
+        return TCPServer::serverProcedure(pipeFd);
+    }
+
+private:
+    AppContext m_appContext;
+};
+
+
+class NetClient
+{
+public:
+    NetClient(const std::string &appPrefix, NetherInternetAccess access, int msgCount)
+    : m_appPrefix(appPrefix)
+    , m_access(access)
+    , m_msgCount(msgCount)
+    {
+    }
+
+    NetClient(const NetClient &) = delete;
+    NetClient &operator=(const NetClient &) = delete;
+
+    void start()
+    {
+        runProcedureInNetAppContext(m_appPrefix, [this]() { clientProcedure(); } , m_access);
+    }
+
+    virtual void clientProcedure() = 0;
+
+protected:
+    std::string m_appPrefix;
+    NetherInternetAccess m_access;
+    int m_msgCount;
+};
+
+class UDPClientApp : public NetClient
+{
+public:
+    UDPClientApp(const std::string &appPrefix, NetherInternetAccess access, int msgCount,
+            int protocol, const std::string &hostName, uint16_t port)
+    : NetClient(appPrefix, access, msgCount)
+    , m_protocol(protocol)
+    , m_hostName(hostName)
+    , m_port(port)
+    {
+    }
+
+    virtual bool applyExtraSocketOptions(int)
+    {
+        return true;
+    }
+
+private:
+    virtual void clientProcedure() override
+    {
+        int sockFd = socket(AF_INET, SOCK_DGRAM, m_protocol);
+        RUNNER_ASSERT_ERRNO_MSG(sockFd >= 0, "socket() failed");
+        SockUniquePtr sockPtr(&sockFd);
+
+        struct hostent *server = gethostbyname(m_hostName.c_str());
+        RUNNER_ASSERT_MSG(server != nullptr, "Couldn't find host " << m_hostName
+                << " h_errno = " << hstrerror(h_errno));
+
+        RUNNER_ASSERT_MSG (applyExtraSocketOptions(sockFd), "Couldn't prepare socket");
+
+        struct sockaddr_in serverAddress;
+        memset(&serverAddress, 0, sizeof(serverAddress));
+        serverAddress.sin_family = AF_INET;
+        memcpy(&serverAddress.sin_addr.s_addr, server->h_addr, server->h_length);
+        serverAddress.sin_port = htons(m_port);
+
+        char sendBuffer[NET_BUFFER_SIZE];
+
+        memset(sendBuffer, 'X', sizeof(sendBuffer));
+        size_t serverAddressLength = sizeof(serverAddress);
+
+        int msgCount = m_msgCount;
+        while (msgCount-- > 0) {
+            ssize_t len = sizeof(sendBuffer);
+            ssize_t pos = 0;
+            do {
+                ssize_t ret = TEMP_FAILURE_RETRY(sendto(sockFd, &sendBuffer[pos], len, 0,
+                        reinterpret_cast<struct sockaddr *>(&serverAddress), serverAddressLength));
+                RUNNER_ASSERT_ERRNO_MSG(ret >= 0, "sendto() failed");
+                len -= ret;
+                pos += ret;
+            } while (len != 0);
+        }
+    }
+
+    int m_protocol;
+    std::string m_hostName;
+    uint16_t m_port;
+};
+
+class UDPMulticastClientApp : public UDPClientApp
+{
+public:
+    UDPMulticastClientApp(const std::string &appPrefix, NetherInternetAccess access, int msgCount,
+            int protocol, const std::string &hostName, uint16_t port, char ttl, bool enableLoop)
+    : UDPClientApp(appPrefix, access, msgCount, protocol, hostName, port)
+    , m_ttl(ttl)
+    , m_enableLoop(enableLoop)
+    {
+    }
+
+    virtual bool applyExtraSocketOptions(int sockFd) override
+    {
+        if (setsockopt(sockFd, IPPROTO_IP, IP_MULTICAST_TTL, static_cast<void *>(&m_ttl), sizeof(m_ttl)) == -1) {
+            return false;
+        }
+
+        char multicastEnableLoop = m_enableLoop ? 1 : 0;
+        return setsockopt(sockFd, IPPROTO_IP, IP_MULTICAST_LOOP, static_cast<void *>(&multicastEnableLoop),
+                sizeof(multicastEnableLoop)) == 0;
+    }
+
+private:
+    char m_ttl;
+    bool m_enableLoop;
+};
+
+class TCPClientApp : public NetClient
+{
+public:
+    TCPClientApp(const std::string &appPrefix, NetherInternetAccess access, int msgCount,
+            const std::string &hostName, int port, bool expectConnectionError)
+    : NetClient(appPrefix, access, msgCount)
+    , m_hostName(hostName)
+    , m_port(port)
+    , m_expectConnectionError(expectConnectionError)
+    {
+    }
+
+private:
+    virtual void clientProcedure() override
+    {
+        int sockFd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+        RUNNER_ASSERT_ERRNO_MSG(sockFd >= 0, "socket() failed");
+        SockUniquePtr sockPtr(&sockFd);
+
+        struct hostent *server = gethostbyname(m_hostName.c_str());
+        RUNNER_ASSERT_MSG(server != nullptr, "Couldn't find host " << m_hostName
+                << " h_errno = " << hstrerror(h_errno));
+
+        struct sockaddr_in serverAddress;
+        memset(&serverAddress, 0, sizeof(serverAddress));
+        serverAddress.sin_family = AF_INET;
+        memcpy(&serverAddress.sin_addr.s_addr, server->h_addr, server->h_length);
+        serverAddress.sin_port = htons(m_port);
+        size_t serverAddressLength = sizeof(serverAddress);
+
+        int ret = TEMP_FAILURE_RETRY(connect(sockFd,
+                reinterpret_cast<struct sockaddr *>(&serverAddress),serverAddressLength));
+        if (ret == -1 && m_expectConnectionError) {
+            return;
+        }
+
+        RUNNER_ASSERT_ERRNO_MSG(ret == 0, "Couldn't connect to " << m_hostName);
+
+        char sendBuffer[NET_BUFFER_SIZE];
+        memset(sendBuffer, 'X', sizeof(sendBuffer));
+
+        int msgCount = m_msgCount;
+        while (msgCount-- > 0) {
+            ssize_t len = sizeof(sendBuffer);
+            ssize_t pos = 0;
+            do {
+                ssize_t ret = TEMP_FAILURE_RETRY(send(sockFd, &sendBuffer[pos], len, 0));
+                RUNNER_ASSERT_ERRNO_MSG(ret >= 0, "send() failed");
+                len -= ret;
+                pos += ret;
+            } while (len != 0);
+        }
+    }
+
+    std::string m_hostName;
+    uint16_t m_port;
+    bool m_expectConnectionError;
+};
+
+
+RUNNER_TEST_GROUP_INIT(NETHER_REMOTE_CONNECTION)
+
+
+RUNNER_CHILD_TEST(nether_check_udp_connection_internet_access_granted)
+{
+    ScopedShellScriptRunner networkNSRunner(NETHER_NETNS_SETUP_COMMAND,
+                                            NETHER_NETNS_TEARDOWN_COMMAND);
+
+    UDPServer udpServer(UDP_TEST_PORT);
+    udpServer.start(NETHER_NETNS_NAME_TEST);
+
+    UDPClientApp udpClientApp("nether_test_uciag", NetherInternetAccess::ACCESS_GRANTED, UDP_MESSAGES_COUNT,
+        IPPROTO_UDP, REMOTE_INTERFACE_ADDRESS, UDP_TEST_PORT);
+    udpClientApp.start();
+
+    RUNNER_ASSERT_MSG(udpServer.isAlive(), "UDP server was not running");
+    udpServer.stop();
+    RUNNER_ASSERT_MSG(udpServer.getReceivedBytes() > 0, "UDP server didn't receive any data");
+}
+
+
+RUNNER_CHILD_TEST(nether_check_udp_connection_internet_access_denied)
+{
+    ScopedShellScriptRunner networkNSRunner(NETHER_NETNS_SETUP_COMMAND,
+                                            NETHER_NETNS_TEARDOWN_COMMAND);
+
+    UDPServer udpServer(UDP_TEST_PORT);
+    udpServer.start(NETHER_NETNS_NAME_TEST);
+
+    UDPClientApp udpClientApp("nether_test_uciad", NetherInternetAccess::ACCESS_DENIED, UDP_MESSAGES_COUNT,
+        IPPROTO_UDP, REMOTE_INTERFACE_ADDRESS, UDP_TEST_PORT);
+    udpClientApp.start();
+
+    RUNNER_ASSERT_MSG(udpServer.isAlive(), "UDP server was not running");
+    udpServer.stop();
+    RUNNER_ASSERT_MSG(udpServer.getReceivedBytes() == 0, "UDP server received some data");
+}
+
+
+RUNNER_CHILD_TEST(nether_check_udp_lite_connection_internet_access_granted)
+{
+    ScopedShellScriptRunner networkNSRunner(NETHER_NETNS_SETUP_COMMAND,
+                                            NETHER_NETNS_TEARDOWN_COMMAND);
+
+    UDPServer udpLiteServer(UDP_TEST_PORT, IPPROTO_UDPLITE);
+    udpLiteServer.start(NETHER_NETNS_NAME_TEST);
+
+    UDPClientApp udpClientApp("nether_test_ulciag", NetherInternetAccess::ACCESS_GRANTED, UDP_MESSAGES_COUNT,
+        IPPROTO_UDPLITE, REMOTE_INTERFACE_ADDRESS, UDP_TEST_PORT);
+    udpClientApp.start();
+
+    RUNNER_ASSERT_MSG(udpLiteServer.isAlive(), "UDPLite server was not running");
+    udpLiteServer.stop();
+    RUNNER_ASSERT_MSG(udpLiteServer.getReceivedBytes() > 0, "UDPLite server didn't receive any data");
+}
+
+
+RUNNER_CHILD_TEST(nether_check_udp_lite_connection_internet_access_denied)
+{
+    ScopedShellScriptRunner networkNSRunner(NETHER_NETNS_SETUP_COMMAND,
+                                            NETHER_NETNS_TEARDOWN_COMMAND);
+
+    UDPServer udpLiteServer(UDP_TEST_PORT, IPPROTO_UDPLITE);
+    udpLiteServer.start(NETHER_NETNS_NAME_TEST);
+
+    UDPClientApp udpClientApp("nether_test_ulciad", NetherInternetAccess::ACCESS_DENIED, UDP_MESSAGES_COUNT,
+        IPPROTO_UDPLITE, REMOTE_INTERFACE_ADDRESS, UDP_TEST_PORT);
+    udpClientApp.start();
+
+    RUNNER_ASSERT_MSG(udpLiteServer.isAlive(), "UDP server was not running");
+    udpLiteServer.stop();
+    RUNNER_ASSERT_MSG(udpLiteServer.getReceivedBytes() == 0, "UDP server received some data");
+}
+
+
+RUNNER_CHILD_TEST(nether_check_tcp_connection_internet_access_granted)
+{
+    ScopedShellScriptRunner networkNSRunner(NETHER_NETNS_SETUP_COMMAND,
+                                            NETHER_NETNS_TEARDOWN_COMMAND);
+
+    TCPServer tcpServer(TCP_TEST_PORT);
+    tcpServer.start(NETHER_NETNS_NAME_TEST);
+
+    TCPClientApp tcpClientApp("nether_test_tciag", NetherInternetAccess::ACCESS_GRANTED, TCP_MESSAGES_COUNT,
+        REMOTE_INTERFACE_ADDRESS, TCP_TEST_PORT, false);
+    tcpClientApp.start();
+
+    RUNNER_ASSERT_MSG(tcpServer.isAlive(), "TCP server was not running");
+    tcpServer.stop();
+    RUNNER_ASSERT_MSG(tcpServer.getReceivedBytes() > 0, "TCP server didn't receive any data");
+}
+
+
+RUNNER_CHILD_TEST(nether_check_tcp_connection_internet_access_denied)
+{
+    ScopedShellScriptRunner networkNSRunner(NETHER_NETNS_SETUP_COMMAND,
+                                            NETHER_NETNS_TEARDOWN_COMMAND);
+
+    TCPServer tcpServer(TCP_TEST_PORT);
+    tcpServer.start(NETHER_NETNS_NAME_TEST);
+
+    TCPClientApp tcpClientApp("nether_test_tciad", NetherInternetAccess::ACCESS_DENIED, TCP_MESSAGES_COUNT,
+        REMOTE_INTERFACE_ADDRESS, TCP_TEST_PORT, true);
+    tcpClientApp.start();
+
+    RUNNER_ASSERT_MSG(tcpServer.isAlive(), "TCP server was not running");
+    tcpServer.stop();
+    RUNNER_ASSERT_MSG(tcpServer.getReceivedBytes() == 0, "TCP server received some data");
+}
+
+// Communication between application and local service
+RUNNER_TEST_GROUP_INIT(NETHER_LOCAL_SERVICE_CONNECTION)
+
+
+RUNNER_CHILD_TEST(nether_check_udp_local_connection_internet_access_granted)
+{
+    UDPServer udpLiteServer(UDP_TEST_PORT, IPPROTO_UDP);
+    udpLiteServer.start();
+
+    UDPClientApp udpClientApp("nether_test_ulciag", NetherInternetAccess::ACCESS_GRANTED, UDP_MESSAGES_COUNT,
+        IPPROTO_UDP, LOCAL_HOST_TEST_SERVER_ADDRESS, UDP_TEST_PORT);
+    udpClientApp.start();
+
+    RUNNER_ASSERT_MSG(udpLiteServer.isAlive(), "UDP server was not running");
+    udpLiteServer.stop();
+    RUNNER_ASSERT_MSG(udpLiteServer.getReceivedBytes() > 0, "UDP server didn't receive any data");
+}
+
+
+RUNNER_CHILD_TEST(nether_check_udp_local_connection_internet_access_denied)
+{
+    UDPServer udpLiteServer(UDP_TEST_PORT, IPPROTO_UDP);
+    udpLiteServer.start();
+
+    UDPClientApp udpClientApp("nether_test_ulciad", NetherInternetAccess::ACCESS_DENIED, UDP_MESSAGES_COUNT,
+        IPPROTO_UDP, LOCAL_HOST_TEST_SERVER_ADDRESS, UDP_TEST_PORT);
+    udpClientApp.start();
+
+    RUNNER_ASSERT_MSG(udpLiteServer.isAlive(), "UDP server was not running");
+    udpLiteServer.stop();
+    RUNNER_ASSERT_MSG(udpLiteServer.getReceivedBytes() > 0, "UDP server didn't receive any data");
+}
+
+
+RUNNER_CHILD_TEST(nether_check_udp_lite_local_connection_internet_access_granted)
+{
+    UDPServer udpLiteServer(UDP_TEST_PORT, IPPROTO_UDPLITE);
+    udpLiteServer.start();
+
+    UDPClientApp udpClientApp("nether_test_ullciag", NetherInternetAccess::ACCESS_GRANTED, UDP_MESSAGES_COUNT,
+        IPPROTO_UDPLITE, LOCAL_HOST_TEST_SERVER_ADDRESS, UDP_TEST_PORT);
+    udpClientApp.start();
+
+    RUNNER_ASSERT_MSG(udpLiteServer.isAlive(), "UDP server was not running");
+    udpLiteServer.stop();
+    RUNNER_ASSERT_MSG(udpLiteServer.getReceivedBytes() > 0, "UDP server didn't receive any data");
+}
+
+
+RUNNER_CHILD_TEST(nether_check_udp_lite_local_connection_internet_access_denied)
+{
+    UDPServer udpLiteServer(UDP_TEST_PORT, IPPROTO_UDPLITE);
+    udpLiteServer.start();
+
+    UDPClientApp udpClientApp("nether_test_ullciad", NetherInternetAccess::ACCESS_DENIED, UDP_MESSAGES_COUNT,
+        IPPROTO_UDPLITE, LOCAL_HOST_TEST_SERVER_ADDRESS, UDP_TEST_PORT);
+    udpClientApp.start();
+
+    RUNNER_ASSERT_MSG(udpLiteServer.isAlive(), "UDP server was not running");
+    udpLiteServer.stop();
+    RUNNER_ASSERT_MSG(udpLiteServer.getReceivedBytes() > 0, "UDP server didn't receive any data");
+}
+
+
+RUNNER_CHILD_TEST(nether_check_tcp_local_connection_internet_access_granted)
+{
+    TCPServer tcpServer(TCP_TEST_PORT);
+    tcpServer.start();
+
+    TCPClientApp tcpClientApp("nether_test_tlciad", NetherInternetAccess::ACCESS_GRANTED, TCP_MESSAGES_COUNT,
+        LOCAL_HOST_TEST_SERVER_ADDRESS, TCP_TEST_PORT, false);
+    tcpClientApp.start();
+
+    RUNNER_ASSERT_MSG(tcpServer.isAlive(), "TCP server was not running");
+    tcpServer.stop();
+    RUNNER_ASSERT_MSG(tcpServer.getReceivedBytes() > 0, "TCP server didn't receive any data");
+}
+
+
+RUNNER_CHILD_TEST(nether_check_tcp_local_connection_internet_access_denied)
+{
+    TCPServer tcpServer(TCP_TEST_PORT);
+    tcpServer.start();
+
+    TCPClientApp tcpClientApp("nether_test_tlciad", NetherInternetAccess::ACCESS_DENIED, TCP_MESSAGES_COUNT,
+        LOCAL_HOST_TEST_SERVER_ADDRESS, TCP_TEST_PORT, false);
+    tcpClientApp.start();
+
+    RUNNER_ASSERT_MSG(tcpServer.isAlive(), "TCP server was not running");
+    tcpServer.stop();
+    RUNNER_ASSERT_MSG(tcpServer.getReceivedBytes() > 0, "TCP server didn't receive any data");
+}
+
+
+// Applications mustn't communicate with each other even if access to the Internet is granted.
+RUNNER_TEST_GROUP_INIT(NETHER_LOCAL_INTER_APP_CONNECTION)
+
+
+RUNNER_CHILD_TEST(nether_check_udp_local_inter_app_connection_internet_access_granted)
+{
+    ScopedAppContext appContext("nether_test_uliaciag_a", NetherInternetAccess::ACCESS_GRANTED);
+    UDPServerApp udpServerApp(UDP_TEST_PORT, IPPROTO_UDP, appContext);
+    udpServerApp.start();
+
+    UDPClientApp udpClientApp("nether_test_uliaciag_b", NetherInternetAccess::ACCESS_GRANTED, UDP_MESSAGES_COUNT,
+        IPPROTO_UDP, LOCAL_HOST_TEST_SERVER_ADDRESS, UDP_TEST_PORT);
+    udpClientApp.start();
+
+    RUNNER_ASSERT_MSG(udpServerApp.isAlive(), "UDP server was not running");
+    udpServerApp.stop();
+    RUNNER_ASSERT_MSG(udpServerApp.getReceivedBytes() == 0, "UDP server received some data");
+}
+
+
+RUNNER_CHILD_TEST(nether_check_udp_local_inter_app_connection_internet_access_denied)
+{
+    ScopedAppContext appContext("nether_test_uliaciad_a", NetherInternetAccess::ACCESS_DENIED);
+    UDPServerApp udpServerApp(UDP_TEST_PORT, IPPROTO_UDP, appContext);
+    udpServerApp.start();
+
+    UDPClientApp udpClientApp("nether_test_uliaciad_b", NetherInternetAccess::ACCESS_DENIED, UDP_MESSAGES_COUNT,
+        IPPROTO_UDP, LOCAL_HOST_TEST_SERVER_ADDRESS, UDP_TEST_PORT);
+    udpClientApp.start();
+
+    RUNNER_ASSERT_MSG(udpServerApp.isAlive(), "UDP server was not running");
+    udpServerApp.stop();
+    RUNNER_ASSERT_MSG(udpServerApp.getReceivedBytes() == 0, "UDP server received some data");
+}
+
+
+RUNNER_CHILD_TEST(nether_check_udp_lite_local_inter_app_connection_internet_access_granted)
+{
+    ScopedAppContext appContext("nether_test_ulliaciag_a", NetherInternetAccess::ACCESS_GRANTED);
+    UDPServerApp udpLiteServerApp(UDP_TEST_PORT, IPPROTO_UDPLITE, appContext);
+    udpLiteServerApp.start();
+
+    UDPClientApp udpClientApp("nether_ulliaciag_b", NetherInternetAccess::ACCESS_GRANTED, UDP_MESSAGES_COUNT,
+        IPPROTO_UDPLITE, LOCAL_HOST_TEST_SERVER_ADDRESS, UDP_TEST_PORT);
+    udpClientApp.start();
+
+    RUNNER_ASSERT_MSG(udpLiteServerApp.isAlive(), "UDP server was not running");
+    udpLiteServerApp.stop();
+    RUNNER_ASSERT_MSG(udpLiteServerApp.getReceivedBytes() == 0, "UDP server received some data");
+}
+
+
+RUNNER_CHILD_TEST(nether_check_udp_lite_local_inter_app_connection_internet_access_denied)
+{
+    ScopedAppContext appContext("nether_test_ulliaciad_a", NetherInternetAccess::ACCESS_DENIED);
+    UDPServerApp udpLiteServerApp(UDP_TEST_PORT, IPPROTO_UDPLITE, appContext);
+    udpLiteServerApp.start();
+
+    UDPClientApp udpClientApp("nether_ulliaciad_b", NetherInternetAccess::ACCESS_DENIED, UDP_MESSAGES_COUNT,
+        IPPROTO_UDPLITE, LOCAL_HOST_TEST_SERVER_ADDRESS, UDP_TEST_PORT);
+    udpClientApp.start();
+
+    RUNNER_ASSERT_MSG(udpLiteServerApp.isAlive(), "UDP server was not running");
+    udpLiteServerApp.stop();
+    RUNNER_ASSERT_MSG(udpLiteServerApp.getReceivedBytes() == 0, "UDP server received some data");
+}
+
+
+RUNNER_CHILD_TEST(nether_check_tcp_local_inter_app_connection_internet_access_granted)
+{
+    ScopedAppContext appContext("nether_test_tliaciag_a", NetherInternetAccess::ACCESS_GRANTED);
+    TCPServerApp tcpServerApp(TCP_TEST_PORT, appContext);
+    tcpServerApp.start();
+
+    TCPClientApp tcpClientApp("nether_test_tliaciag_b", NetherInternetAccess::ACCESS_GRANTED, TCP_MESSAGES_COUNT,
+        LOCAL_HOST_TEST_SERVER_ADDRESS, TCP_TEST_PORT, true);
+    tcpClientApp.start();
+
+    RUNNER_ASSERT_MSG(tcpServerApp.isAlive(), "TCP server was not running");
+    tcpServerApp.stop();
+    RUNNER_ASSERT_MSG(tcpServerApp.getReceivedBytes() == 0, "TCP server received some data");
+}
+
+
+RUNNER_CHILD_TEST(nether_check_tcp_local_inter_app_connection_internet_access_denied)
+{
+    ScopedAppContext appContext("nether_test_tliaciad_a", NetherInternetAccess::ACCESS_DENIED);
+    TCPServerApp tcpServerApp(TCP_TEST_PORT, appContext);
+    tcpServerApp.start();
+
+    TCPClientApp tcpClientApp("nether_test_tliaciad_b", NetherInternetAccess::ACCESS_DENIED, TCP_MESSAGES_COUNT,
+        LOCAL_HOST_TEST_SERVER_ADDRESS, TCP_TEST_PORT, true);
+    tcpClientApp.start();
+
+    RUNNER_ASSERT_MSG(tcpServerApp.isAlive(), "TCP server was not running");
+    tcpServerApp.stop();
+    RUNNER_ASSERT_MSG(tcpServerApp.getReceivedBytes() == 0, "TCP server received some data");
+}
+
+
+RUNNER_TEST_GROUP_INIT(NETHER_MULTICAST)
+
+
+RUNNER_CHILD_TEST(nether_check_multicast_inter_app_connection_access_granted)
+{
+    // one app acts as a server (receiver), the second as a sender
+    ScopedAppContext appContext("nether_test_miacag_a", NetherInternetAccess::ACCESS_GRANTED);
+    UDPMulticastServerApp udpMulticastServerApp(UDP_TEST_PORT, IPPROTO_UDP, LOCAL_TEST_MCAST_GROUP,
+        ANY_INTERFACE, appContext);
+    udpMulticastServerApp.start();
+
+    UDPMulticastClientApp udpMulticastClientApp("nether_test_miacag_b", NetherInternetAccess::ACCESS_GRANTED,
+        UDP_MESSAGES_COUNT, IPPROTO_UDP, LOCAL_TEST_MCAST_GROUP, UDP_TEST_PORT, TTL_MCAST_RESTRIC_SUBNET, true);
+    udpMulticastClientApp.start();
+
+    RUNNER_ASSERT_MSG(udpMulticastServerApp.isAlive(), "UDP multicast server was not running");
+    udpMulticastServerApp.stop();
+    RUNNER_ASSERT_MSG(udpMulticastServerApp.getReceivedBytes() > 0, "UDP multicast server didn't receive any data");
+}
+
+
+RUNNER_CHILD_TEST(nether_check_multicast_inter_app_connection_access_denied)
+{
+    ScopedAppContext appContext("nether_test_miacad_a", NetherInternetAccess::ACCESS_DENIED);
+    UDPMulticastServerApp udpMulticastServerApp(UDP_TEST_PORT, IPPROTO_UDP, LOCAL_TEST_MCAST_GROUP,
+        ANY_INTERFACE, appContext);
+    udpMulticastServerApp.start();
+
+    UDPMulticastClientApp udpMulticastClientApp("nether_test_miacad_b", NetherInternetAccess::ACCESS_DENIED,
+        UDP_MESSAGES_COUNT, IPPROTO_UDP, LOCAL_TEST_MCAST_GROUP, UDP_TEST_PORT, TTL_MCAST_RESTRIC_SUBNET, true);
+    udpMulticastClientApp.start();
+
+    RUNNER_ASSERT_MSG(udpMulticastServerApp.isAlive(), "UDP multicast server was not running");
+    udpMulticastServerApp.stop();
+    RUNNER_ASSERT_MSG(udpMulticastServerApp.getReceivedBytes() == 0, "UDP multicast server received some data");
+}
+
+
+RUNNER_CHILD_TEST(nether_check_multicast_remote_connection_app_sender_access_granted)
+{
+    ScopedShellScriptRunner networkNSRunner(NETHER_NETNS_SETUP_COMMAND,
+                                            NETHER_NETNS_TEARDOWN_COMMAND);
+
+    UDPMulticastServer udpMulticastServer(UDP_TEST_PORT, IPPROTO_UDP, LOCAL_TEST_MCAST_GROUP, REMOTE_INTERFACE_NAME);
+    udpMulticastServer.start(NETHER_NETNS_NAME_TEST);
+
+    UDPMulticastClientApp udpMulticastClientApp("nether_test_mrcasag", NetherInternetAccess::ACCESS_GRANTED,
+        UDP_MESSAGES_COUNT, IPPROTO_UDP, LOCAL_TEST_MCAST_GROUP, UDP_TEST_PORT, TTL_MCAST_RESTRIC_SUBNET, false);
+    udpMulticastClientApp.start();
+
+    RUNNER_ASSERT_MSG(udpMulticastServer.isAlive(), "UDP multicast server was not running");
+    udpMulticastServer.stop();
+    RUNNER_ASSERT_MSG(udpMulticastServer.getReceivedBytes() > 0, "UDP multicast server didn't receive any data");
+}
+
+
+RUNNER_CHILD_TEST(nether_check_multicast_remote_connection_app_sender_access_denied)
+{
+    ScopedShellScriptRunner networkNSRunner(NETHER_NETNS_SETUP_COMMAND,
+                                            NETHER_NETNS_TEARDOWN_COMMAND);
+
+    UDPMulticastServer udpMulticastServer(UDP_TEST_PORT, IPPROTO_UDP, LOCAL_TEST_MCAST_GROUP, REMOTE_INTERFACE_NAME);
+    udpMulticastServer.start(NETHER_NETNS_NAME_TEST);
+
+    UDPMulticastClientApp udpMulticastClientApp("nether_test_mrcasad", NetherInternetAccess::ACCESS_DENIED,
+        UDP_MESSAGES_COUNT, IPPROTO_UDP, LOCAL_TEST_MCAST_GROUP, UDP_TEST_PORT, TTL_MCAST_RESTRIC_SUBNET, false);
+    udpMulticastClientApp.start();
+
+    RUNNER_ASSERT_MSG(udpMulticastServer.isAlive(), "UDP multicast server was not running");
+    udpMulticastServer.stop();
+    RUNNER_ASSERT_MSG(udpMulticastServer.getReceivedBytes() == 0, "UDP multicast server received some data");
+}
+
+
+RUNNER_TEST_GROUP_INIT(NETHER_LOCAL_DNS_CONNECTION)
+
+
+RUNNER_CHILD_TEST(nether_check_gethostbyname_internet_access_granted)
+{
+    ScopedShellScriptRunner networkDNSRunner(NETHER_DNS_SETUP_COMMAND,
+                                             NETHER_DNS_TEARDOWN_COMMAND);
+
+    const auto getHostAddress = [](void) {
+      struct hostent *server = gethostbyname(DNS_TEST_ADDRESS.c_str());
+      RUNNER_ASSERT_MSG(server != nullptr, "Couldn't find host "
+              << DNS_TEST_ADDRESS << " h_errno = " << h_errno);
+    };
+    runProcedureInNetAppContext("nether_test_giag", getHostAddress, NetherInternetAccess::ACCESS_GRANTED);
+}
+
+
+RUNNER_CHILD_TEST(nether_check_gethostbyname_internet_access_denied)
+{
+    ScopedShellScriptRunner networkDNSRunner(NETHER_DNS_SETUP_COMMAND,
+                                             NETHER_DNS_TEARDOWN_COMMAND);
+
+    const auto getHostAddress = [](void) {
+      struct hostent *server = gethostbyname(DNS_TEST_ADDRESS.c_str());
+      RUNNER_ASSERT_MSG(server == nullptr, "Host was found " << DNS_TEST_ADDRESS);
+    };
+
+    runProcedureInNetAppContext("nether_test_giad", getHostAddress, NetherInternetAccess::ACCESS_DENIED);
+}
+
+
+void checkRawSocket(void)
+{
+    const std::vector<int> protocols {
+        IPPROTO_ICMP,
+        IPPROTO_IGMP
+    };
+
+    for (const auto protocol : protocols) {
+        int sockFd = socket(AF_INET, SOCK_RAW, protocol);
+        RUNNER_ASSERT_ERRNO_MSG(sockFd == -1, "RAW socket was successfully created for protocol " << protocol);
+    }
+};
+
+
+RUNNER_TEST_GROUP_INIT(NETHER_RAW_SOCKET)
+
+
+RUNNER_CHILD_TEST(nether_check_raw_socket_access_granted)
+{
+    runProcedureInNetAppContext("nether_test_rsag", checkRawSocket, NetherInternetAccess::ACCESS_GRANTED);
+}
+
+
+RUNNER_CHILD_TEST(nether_check_raw_socket_access_denied)
+{
+    runProcedureInNetAppContext("nether_test_rsad", checkRawSocket, NetherInternetAccess::ACCESS_DENIED);
+}
+
+
+int main(int argc, char *argv[])
+{
+    return DPL::Test::TestRunnerSingleton::Instance().ExecTestRunner(argc, argv);
+}
diff --git a/src/nether-tests/setup-nether-tests-dns.sh b/src/nether-tests/setup-nether-tests-dns.sh
new file mode 100644 (file)
index 0000000..c3e1fea
--- /dev/null
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+#####################################################################
+# Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+#
+#    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.
+#####################################################################
+
+# make sure the filesystem is mounted in RW mode
+rw
+
+# backup old resolv.conf
+cp /etc/resolv.conf /etc/resolv.conf.back
+
+# configure Connman as a local DNS server
+echo "nameserver 127.0.0.1" > /etc/resolv.conf
diff --git a/src/nether-tests/setup-nether-tests-nns.sh b/src/nether-tests/setup-nether-tests-nns.sh
new file mode 100644 (file)
index 0000000..6ddf174
--- /dev/null
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+#####################################################################
+# Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+#
+#    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.
+#####################################################################
+
+if [[ $# -eq 0 ]] ; then
+    scrname=`basename "$0"`
+    echo "Usage: $scrname <network namespace name>"
+    exit 0
+fi
+
+ip netns add $1
+ip link add veth0 type veth peer name veth1
+ip link set veth1 netns $1
+ip netns exec $1 ifconfig lo 127.0.0.1
+ip netns exec $1 ifconfig veth1 10.1.0.2 netmask 255.255.255.252
+ip netns exec $1 route add -net 224.0.0.0 netmask 224.0.0.0 veth1
+
+# force mtu size (we want to test that Nether's rules can deal with fragmentation)
+ifconfig veth0 mtu 1500
+ifconfig veth0 10.1.0.1 netmask 255.255.255.252
+route add -net 224.0.0.0 netmask 240.0.0.0 veth0
+
+# force ARP response
+ping -c 1 10.1.0.2 > /dev/null
diff --git a/src/nether-tests/teardown-nether-tests-dns.sh b/src/nether-tests/teardown-nether-tests-dns.sh
new file mode 100644 (file)
index 0000000..0d240f6
--- /dev/null
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+#####################################################################
+# Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+#
+#    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.
+#####################################################################
+
+# restore old resolv.conf
+mv /etc/resolv.conf.back /etc/resolv.conf
+
+
diff --git a/src/nether-tests/teardown-nether-tests-nns.sh b/src/nether-tests/teardown-nether-tests-nns.sh
new file mode 100644 (file)
index 0000000..455db1a
--- /dev/null
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+#####################################################################
+# Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+#
+#    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.
+#####################################################################
+
+if [[ $# -eq 0 ]] ; then
+    scrname=`basename "$0"`
+    echo "Usage: $scrname <network namespace name>"
+    exit 0
+fi
+
+ifconfig veth0 down
+ip netns exec $1 ifconfig veth1 down
+ip netns exec $1 ifconfig lo down
+
+ip link delete veth0
+ip netns delete $1
diff --git a/src/ode/CMakeLists.txt b/src/ode/CMakeLists.txt
new file mode 100644 (file)
index 0000000..f7fd464
--- /dev/null
@@ -0,0 +1,55 @@
+#
+#  Copyright (c) 2017-2018 Samsung Electronics Co., Ltd All Rights Reserved
+#
+#  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
+#
+#  @file   CMakeLists.txt
+#  @author Pawel Kowalski (p.kowalski2@partner.samsung.com)
+#
+
+MESSAGE(STATUS "")
+MESSAGE(STATUS "Generating makefile for the ODE tests...")
+
+FILE(GLOB  ode_tests_SRCS *.cpp)
+
+OPTION("EMULATOR" ON)
+IF(EMULATOR)
+    ADD_DEFINITIONS("-DEMULATOR")
+ENDIF(EMULATOR)
+
+## Setup target ################################################################
+SET(ODE_TESTS "ode-tests")
+ADD_EXECUTABLE(${ODE_TESTS} ${ode_tests_SRCS})
+
+## Link libraries ##############################################################
+PKG_CHECK_MODULES(ODE_TESTS_DEPS REQUIRED
+    ode
+    security-manager
+    dbus-1
+    libgum
+)
+
+INCLUDE_DIRECTORIES(SYSTEM
+    ${ODE_TESTS_DEPS_INCLUDE_DIRS}
+    ${PROJECT_SOURCE_DIR}/src/common/
+)
+
+TARGET_LINK_LIBRARIES(
+    ${ODE_TESTS}
+    ${ODE_TESTS_DEPS_LIBRARIES}
+    dpl-test-framework
+    tests-common
+)
+
+## Install #####################################################################
+INSTALL(TARGETS ${ODE_TESTS} DESTINATION bin)
diff --git a/src/ode/ode-tests-common.cpp b/src/ode/ode-tests-common.cpp
new file mode 100644 (file)
index 0000000..fd82703
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ *  Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  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
+ *
+ *  @file   ode-tests-common.cpp
+ *  @author Pawel Kowalski (p.kowalski2@partner.samsung.com)
+ *  @brief  Tests for the ODE API
+ */
+
+#include <unistd.h>
+
+#include <iostream>
+#include <string>
+#include <utility>
+
+#include <dpl/log/log.h>
+
+#include <ode/keys.h>
+#include <ode/internal-encryption.h>
+#include "ode-tests-common.h"
+
+#define ERRORDESCRIBE(name) case name: return #name
+
+const char* ODEErrorToString(int error) {
+    switch(error) {
+        ERRORDESCRIBE(ODE_ERROR_NONE);
+        ERRORDESCRIBE(ODE_ERROR_INVALID_PARAMETER);
+        ERRORDESCRIBE(ODE_ERROR_CONNECTION_REFUSED);
+        ERRORDESCRIBE(ODE_ERROR_PERMISSION_DENIED);
+        ERRORDESCRIBE(ODE_ERROR_NO_SUCH_FILE);
+        ERRORDESCRIBE(ODE_ERROR_NO_SUCH_DEVICE);
+        ERRORDESCRIBE(ODE_ERROR_KEY_REJECTED);
+        ERRORDESCRIBE(ODE_ERROR_NO_DATA);
+        ERRORDESCRIBE(ODE_ERROR_RESOURCE_BUSY);
+        ERRORDESCRIBE(ODE_ERROR_UNKNOWN);
+        default: return "Error not defined";
+    }
+}
+
+#undef ERRORDESCRIBE
+
+// helper classes
+
+HelperKeys::HelperKeys(const char* device, const char* password, bool initialize) {
+    dev = device;
+    pass = password;
+
+    if (initialize) {
+        bool result;
+        assert_positive(ode_key_is_initialized, dev, &result);
+
+        if (!result) {
+            assert_positive(ode_key_init, dev, pass, ODE_KEY_DEFAULT_256BIT);
+        }
+    }
+}
+
+HelperKeys::~HelperKeys() {
+    ode_key_remove_master_key(dev);
+    ode_key_remove(dev, pass);
+}
+
+HelperInternalEncryption::HelperInternalEncryption(const char* password) {
+    pass = password;
+
+    bool result;
+    assert_positive(ode_internal_encryption_is_password_initialized, &result);
+
+    if (!result) {
+        assert_positive(ode_internal_encryption_init_password, pass);
+    }
+}
+
+HelperInternalEncryption::~HelperInternalEncryption() {
+    ode_internal_encryption_umount();
+    ode_internal_encryption_clean_password(pass);
+}
+
+std::unique_ptr<ServiceManager, std::function<void(ServiceManager*)>> createScopedOdeStopper() {
+    auto sm_start = [](ServiceManager* sm) {
+        try {
+            sm->startService(true);
+            delete sm;
+            sleep(1);
+            //TODO: startService should wait until the sm is really started but it does not
+            // because of that the sleep is needed
+        } catch (...) {
+            RUNNER_ERROR_MSG("Unexpected exception during service startup");
+        }
+    };
+    std::unique_ptr<ServiceManager, decltype(sm_start)> sm_stop(
+            new ServiceManager("ode.service", { "ode.socket" }),
+            std::move(sm_start));
+
+    sm_stop->stopService(true);
+
+    return sm_stop;
+}
diff --git a/src/ode/ode-tests-common.h b/src/ode/ode-tests-common.h
new file mode 100644 (file)
index 0000000..0151b9c
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ *  Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  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
+ *
+ *  @file   ode-tests-common.h
+ *  @author Pawel Kowalski (p.kowalski2@partner.samsung.com)
+ *  @brief  Tests for the ODE API
+ */
+
+#pragma once
+
+#include <utility>
+#include <functional>
+#include <memory>
+
+#include <service_manager.h>
+
+#include <dpl/test/test_runner.h>
+
+#define RUNNER_TEST_DUMMY(Proc, ...) \
+    void Proc(std::tuple<__VA_ARGS__> &optionalArgsTuple DPL_UNUSED)
+
+#ifndef EMULATOR
+#define RUNNER_TEST_DEVICE(...) RUNNER_TEST(__VA_ARGS__)
+#else
+#define RUNNER_TEST_DEVICE(...) RUNNER_TEST_DUMMY(__VA_ARGS__)
+#endif
+
+#include <ode/common.h>
+
+const char* ODEErrorToString(int error);
+
+// RUNNER_ASSERT wrappers
+
+template <typename F, typename... Args>
+void assert_result(int expected, F&& func, Args... args)
+{
+    int ret = func(args...);
+    RUNNER_ASSERT_MSG(ret == expected,
+        "Expected: " << ODEErrorToString(expected) << "(" << expected << ")"
+        " got: " << ODEErrorToString(ret) << "(" << ret << ")");
+}
+
+template <typename F, typename... Args>
+void assert_positive(F&& func, Args... args)
+{
+    assert_result(ODE_ERROR_NONE, std::move(func), args...);
+}
+
+template <typename F, typename... Args>
+void assert_invalid_parameter(F&& func, Args... args)
+{
+    assert_result(ODE_ERROR_INVALID_PARAMETER, std::move(func), args...);
+}
+
+template <typename F, typename... Args>
+void assert_connection_refused(F&& func, Args... args)
+{
+    assert_result(ODE_ERROR_CONNECTION_REFUSED, std::move(func), args...);
+}
+
+template <typename F, typename... Args>
+void assert_permission_denied(F&& func, Args... args)
+{
+    assert_result(ODE_ERROR_PERMISSION_DENIED, std::move(func), args...);
+}
+
+template <typename F, typename... Args>
+void assert_no_such_file(F&& func, Args... args)
+{
+    assert_result(ODE_ERROR_NO_SUCH_FILE, std::move(func), args...);
+}
+
+template <typename F, typename... Args>
+void assert_no_such_device(F&& func, Args... args)
+{
+    assert_result(ODE_ERROR_NO_SUCH_DEVICE, std::move(func), args...);
+}
+
+template <typename F, typename... Args>
+void assert_key_rejected(F&& func, Args... args)
+{
+    assert_result(ODE_ERROR_KEY_REJECTED, std::move(func), args...);
+}
+
+template <typename F, typename... Args>
+void assert_no_data(F&& func, Args... args)
+{
+    assert_result(ODE_ERROR_NO_DATA, std::move(func), args...);
+}
+
+template <typename F, typename... Args>
+void assert_resource_busy(F&& func, Args... args)
+{
+    assert_result(ODE_ERROR_RESOURCE_BUSY, std::move(func), args...);
+}
+
+// helper classes
+
+class HelperKeys {
+    const char* dev;
+    const char* pass;
+
+public:
+    HelperKeys(const char* device, const char* password, bool initialize = true);
+    ~HelperKeys();
+};
+
+class HelperInternalEncryption {
+    const char* pass;
+
+public:
+    HelperInternalEncryption(const char* password);
+    ~HelperInternalEncryption();
+};
+
+std::unique_ptr<ServiceManager, std::function<void(ServiceManager*)>> createScopedOdeStopper();
diff --git a/src/ode/ode-tests-external-encryption.cpp b/src/ode/ode-tests-external-encryption.cpp
new file mode 100644 (file)
index 0000000..1e5d55a
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ *  Copyright (c) 2017-2018 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  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
+ *
+ *  @file   ode-tests-external-encryption.cpp
+ *  @author Pawel Kowalski (p.kowalski2@partner.samsung.com)
+ *  @brief  Tests for the ODE API
+ */
+
+#include "dpl/test/test_runner.h"
+
+RUNNER_TEST_GROUP_INIT(T0000_ODE_API_EXTERNAL_ENCRYPTION);
\ No newline at end of file
diff --git a/src/ode/ode-tests-internal-encryption.cpp b/src/ode/ode-tests-internal-encryption.cpp
new file mode 100644 (file)
index 0000000..881ecaa
--- /dev/null
@@ -0,0 +1,304 @@
+/*
+ *  Copyright (c) 2017-2018 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  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
+ *
+ *  @file   ode-tests-internal-encryption.cpp
+ *  @author Pawel Kowalski (p.kowalski2@partner.samsung.com)
+ *  @brief  Tests for the ODE API
+ */
+
+#include <memory>
+#include <string>
+
+#include <dpl/test/test_runner.h>
+#include <dpl/test/test_runner_child.h>
+#include <dpl/log/log.h>
+#include <temp_test_user.h>
+#include <app_install_helper.h>
+#include <tests_common.h>
+#include <scoped_installer.h>
+#include <service_manager.h>
+
+#include <ode/internal-encryption.h>
+#include "ode-tests-common.h"
+
+namespace OdeTestsInternalEncryption {
+
+const char * password = "abc123";
+const char * password_new = "def456";
+
+RUNNER_TEST_GROUP_INIT(T1000_ODE_API_INTERNAL_ENCRYPTION);
+
+RUNNER_TEST_DEVICE(T1001_internal_encryption_set_mount_password_1_invalid_parameter)
+{
+    HelperInternalEncryption helper(password);
+
+    // password set to empty string
+    assert_invalid_parameter(ode_internal_encryption_set_mount_password, "");
+    // password set to NULL
+    assert_invalid_parameter(ode_internal_encryption_set_mount_password, nullptr);
+}
+
+RUNNER_TEST_DEVICE(T1002_internal_encryption_set_mount_password_2_key_rejected)
+{
+    HelperInternalEncryption helper(password);
+
+    // try to set the mount password different than the init password
+    assert_key_rejected(ode_internal_encryption_set_mount_password, password_new);
+}
+
+RUNNER_TEST_DEVICE(T1003_internal_encryption_mount_1_no_such_device)
+{
+    HelperInternalEncryption helper(password);
+
+    // set mount password
+    assert_positive(ode_internal_encryption_set_mount_password, password);
+
+    assert_no_such_device(ode_internal_encryption_mount);
+}
+
+RUNNER_TEST(T1004_internal_encryption_mount_2_no_data)
+{
+    assert_no_data(ode_internal_encryption_mount);
+}
+
+RUNNER_TEST_DEVICE(T1005_internal_encryption_umount_1_no_such_device)
+{
+    HelperInternalEncryption helper(password);
+
+    // set mount password
+    assert_positive(ode_internal_encryption_set_mount_password, password);
+
+    assert_no_such_device(ode_internal_encryption_umount);
+}
+
+RUNNER_TEST_DEVICE(T1006_internal_encryption_encrypt_1_invalid_parameter)
+{
+    RUNNER_IGNORED_MSG("Test ignored because the ODE_ERROR_NONE is returned "
+                       "instead of the ODE_ERROR_INVALID_PARAMETER in case "
+                       "when options are set to NULL. Because no error is "
+                       "returned, the device is encrypted. "
+                       "Needs improvement in ode module.");
+
+    HelperInternalEncryption helper(password);
+
+    // password set to empty string
+    assert_invalid_parameter(ode_internal_encryption_encrypt, "", 0);
+    // password set to NULL
+    assert_invalid_parameter(ode_internal_encryption_encrypt, nullptr, 0);
+
+    // options set to NULL
+    assert_invalid_parameter(ode_internal_encryption_encrypt, password, NULL);
+    /*
+     * TODO:
+     * Maybe also value of the options (even if it is uint) should be checked
+     * and only 0 or 1 should be available. Alternatively options should be bool
+     * or if more options may be available in the future - enum. Currently, if
+     * options is set to any value different than 0, fast encryption is enabled.
+     * Otherwise it is disabled. Needs improvement in ode.
+     */
+}
+
+RUNNER_TEST_DEVICE(T1007_internal_encryption_encrypt_2_key_rejected)
+{
+    HelperInternalEncryption helper(password);
+
+    // try to encrypt using the password different than the init password
+    assert_key_rejected(ode_internal_encryption_encrypt, password_new, 0);
+}
+
+RUNNER_TEST(T1008_internal_encryption_encrypt_3_no_such_device)
+{
+    RUNNER_IGNORED_MSG("Test ignored because the ODE_ERROR_NO_SUCH_FILE is returned "
+                       "instead of the ODE_ERROR_NO_SUCH_DEVICE. "
+                       "Needs improvement in ode module.");
+
+    assert_no_such_device(ode_internal_encryption_encrypt, password, 0);
+}
+
+RUNNER_TEST_DEVICE(T1009_internal_encryption_decrypt_1_invalid_parameter)
+{
+    RUNNER_IGNORED_MSG("Test ignored because the ODE_ERROR_NO_SUCH_DEVICE is returned "
+                       "instead of the ODE_ERROR_INVALID_PARAMETER. "
+                       "Needs improvement in ode module.");
+
+    HelperInternalEncryption helper(password);
+
+    // password set to empty string
+    assert_invalid_parameter(ode_internal_encryption_decrypt, "");
+    // password set to NULL
+    assert_invalid_parameter(ode_internal_encryption_decrypt, nullptr);
+}
+
+RUNNER_TEST_DEVICE(T1010_internal_encryption_decrypt_2_key_rejected)
+{
+    RUNNER_IGNORED_MSG("Test ignored because the ODE_ERROR_NO_SUCH_DEVICE is returned "
+                       "instead of the ODE_ERROR_KEY_REJECTED. "
+                       "Needs improvement in ode module.");
+
+    HelperInternalEncryption helper(password);
+
+    // try to decrypt using the password different than the init password
+    assert_key_rejected(ode_internal_encryption_decrypt, password_new);
+}
+
+RUNNER_TEST_DEVICE(T1011_internal_encryption_decrypt_3_no_such_device)
+{
+    HelperInternalEncryption helper(password);
+
+    assert_no_such_device(ode_internal_encryption_decrypt, password);
+}
+
+RUNNER_TEST_DEVICE(T1012_internal_encryption_recovery_1_no_such_device)
+{
+    RUNNER_IGNORED_MSG("Test ignored because the ODE_ERROR_UNKNOWN is returned "
+                       "instead of the ODE_ERROR_NO_SUCH_DEVICE. "
+                       "Needs improvement in ode module.");
+
+    HelperInternalEncryption helper(password);
+
+    assert_no_such_device(ode_internal_encryption_recovery);
+}
+
+RUNNER_TEST(T1013_internal_encryption_is_password_initialized_1_invalid_parameter)
+{
+    // result set to NULL
+    assert_invalid_parameter(ode_internal_encryption_is_password_initialized, nullptr);
+}
+
+RUNNER_TEST(T1014_internal_encryption_init_password_1_invalid_parameter)
+{
+    // password set to empty string
+    assert_invalid_parameter(ode_internal_encryption_init_password, "");
+    // password set to NULL
+    assert_invalid_parameter(ode_internal_encryption_init_password, nullptr);
+}
+
+RUNNER_TEST(T1015_internal_encryption_clean_password_1_invalid_parameter)
+{
+    // password set to empty string
+    assert_invalid_parameter(ode_internal_encryption_clean_password, "");
+    // password set to NULL
+    assert_invalid_parameter(ode_internal_encryption_clean_password, nullptr);
+}
+
+RUNNER_TEST_DEVICE(T1016_internal_encryption_change_password_1_invalid_parameter)
+{
+    HelperInternalEncryption helper(password);
+
+    // old password set to empty string
+    assert_invalid_parameter(ode_internal_encryption_change_password, "", password_new);
+    // old password set to NULL
+    assert_invalid_parameter(ode_internal_encryption_change_password, nullptr, password_new);
+
+    // new password set to empty string
+    assert_invalid_parameter(ode_internal_encryption_change_password, password_new, "");
+    // new password set to NULL
+    assert_invalid_parameter(ode_internal_encryption_change_password, password_new, nullptr);
+}
+
+RUNNER_TEST_DEVICE(T1017_internal_encryption_change_password_2_key_rejected)
+{
+    HelperInternalEncryption helper(password);
+
+    assert_key_rejected(ode_internal_encryption_change_password, password_new, password);
+}
+
+RUNNER_TEST(T1018_internal_encryption_verify_password_1_invalid_parameter)
+{
+    bool result;
+    // password set to empty string
+    assert_invalid_parameter(ode_internal_encryption_verify_password, "", &result);
+    // password set to NULL
+    assert_invalid_parameter(ode_internal_encryption_verify_password, nullptr, &result);
+
+    // result set to NULL
+    assert_invalid_parameter(ode_internal_encryption_verify_password, password, nullptr);
+    assert_invalid_parameter(ode_internal_encryption_verify_password, password_new, nullptr);
+}
+
+RUNNER_TEST(T1019_internal_encryption_get_state_1_invalid_parameter)
+{
+    // state set to NULL
+    assert_invalid_parameter(ode_internal_encryption_get_state, nullptr);
+}
+
+RUNNER_TEST(T1020_internal_encryption_connection_refused)
+{
+    auto sm_stop = createScopedOdeStopper();
+
+    unsigned int options = 0;
+    bool result;
+    int state;
+
+    assert_connection_refused(ode_internal_encryption_set_mount_password, password);
+    assert_connection_refused(ode_internal_encryption_mount);
+    assert_connection_refused(ode_internal_encryption_umount);
+    assert_connection_refused(ode_internal_encryption_encrypt, password, options);
+    assert_connection_refused(ode_internal_encryption_decrypt, password);
+    assert_connection_refused(ode_internal_encryption_recovery);
+    assert_connection_refused(ode_internal_encryption_is_password_initialized, &result);
+    assert_connection_refused(ode_internal_encryption_init_password, password);
+    assert_connection_refused(ode_internal_encryption_clean_password, password);
+    assert_connection_refused(ode_internal_encryption_change_password, password, password_new);
+    assert_connection_refused(ode_internal_encryption_verify_password, password, &result);
+    assert_connection_refused(ode_internal_encryption_get_state, &state);
+}
+
+RUNNER_CHILD_TEST(T1021_internal_encryption_permission_denied)
+{
+    RUNNER_IGNORED_MSG("Test ignored because the ODE_ERROR_UNKNOWN is returned "
+                       "instead of the ODE_ERROR_PERMISSION_DENIED. "
+                       "Needs improvement in ode module.");
+
+    TemporaryTestUser adminUserToSwitch("ode_test_T1021_user", GUM_USERTYPE_ADMIN);
+    adminUserToSwitch.create();
+
+    AppInstallHelper appInstallHelper("ode_test_T1021_app_install_helper",
+        adminUserToSwitch.getUid());
+
+    ScopedInstaller scopedInstaller(appInstallHelper);
+
+    pid_t pid = fork();
+    if (pid != 0) {
+        waitPid(pid);
+    } else { //child process
+        SecurityManagerTest::Api::setProcessLabel(appInstallHelper.getAppId());
+        RUNNER_ASSERT_ERRNO_MSG(drop_root_privileges(adminUserToSwitch.getUid(),
+            adminUserToSwitch.getGid()) == 0,
+            "drop_root_privileges failed");
+
+        unsigned int options = 0;
+        bool result;
+        int state;
+
+        // check if there is access to unprotected function
+        assert_positive(ode_internal_encryption_is_password_initialized, &result);
+        assert_positive(ode_internal_encryption_get_state, &state);
+
+        // check if there is no access to protected function
+        assert_permission_denied(ode_internal_encryption_set_mount_password, password);
+        assert_permission_denied(ode_internal_encryption_mount);
+        assert_permission_denied(ode_internal_encryption_umount);
+        assert_permission_denied(ode_internal_encryption_encrypt, password, options);
+        assert_permission_denied(ode_internal_encryption_decrypt, password);
+        assert_permission_denied(ode_internal_encryption_recovery);
+        assert_permission_denied(ode_internal_encryption_init_password, password);
+        assert_permission_denied(ode_internal_encryption_clean_password, password);
+        assert_permission_denied(ode_internal_encryption_change_password, password, password_new);
+        assert_permission_denied(ode_internal_encryption_verify_password, password, &result);
+    }
+}
+
+} // namespace OdeTestsInternalEncryption
diff --git a/src/ode/ode-tests-keys.cpp b/src/ode/ode-tests-keys.cpp
new file mode 100644 (file)
index 0000000..3596a29
--- /dev/null
@@ -0,0 +1,351 @@
+/*
+ *  Copyright (c) 2017-2018 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  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
+ *
+ *  @file   ode-tests-keys.cpp
+ *  @author Pawel Kowalski (p.kowalski2@partner.samsung.com)
+ *  @brief  Tests for the ODE API
+ */
+
+#include <memory>
+
+#include <dpl/test/test_runner.h>
+#include <dpl/test/test_runner_child.h>
+#include <temp_test_user.h>
+#include <app_install_helper.h>
+#include <tests_common.h>
+#include <scoped_installer.h>
+
+#include <ode/keys.h>
+#include "ode-tests-common.h"
+
+namespace OdeTestsKeys {
+
+const std::string PRIVILEGE_INTERNAL_USERMANAGEMENT =
+    "http://tizen.org/privilege/internal/usermanagement";
+const std::string PRIVILEGE_INTERNAL_DEFAULT_PLATFORM =
+    "http://tizen.org/privilege/internal/default/platform";
+
+const char* device1 = "/dev/vda1";
+const char* device2 = "/dev/vda2";
+
+const char* password = "abc123";
+const char* password_new = "def456";
+
+// TODO: obtain existing block devices from /proc/mounts
+
+RUNNER_TEST_GROUP_INIT(T2000_ODE_API_KEYS);
+
+/*
+ * If at least one of the parameters in invalid, then the INVALID_PARAM error
+ * is returned.
+ */
+RUNNER_TEST(T2001_ode_key_is_initialized_1_invalid_parameter)
+{
+    bool result;
+
+    // device set to empty string
+    assert_invalid_parameter(ode_key_is_initialized, "", &result);
+    // device set to NULL
+    assert_invalid_parameter(ode_key_is_initialized, nullptr, &result);
+
+    // result set to NULL
+    assert_invalid_parameter(ode_key_is_initialized, device1, nullptr);
+}
+
+/*
+ * The third argument of the ode_key_init function is the type of key
+ * initialization method used. It may be ODE_KEY_DEFAULT_256BIT (1) or
+ * ODE_KEY_DEFAULT_512BIT (2). So if value different than 1 or 2 is passed,
+ * invalid parameter error is returned by the function.
+ * Invalid parameter error is returned also if empty strings or null pointers
+ * are passed as the arguments of the function.
+ */
+RUNNER_TEST(T2002_ode_key_init_1_invalid_parameter)
+{
+    // device set to empty string
+    assert_invalid_parameter(ode_key_init, "", password, ODE_KEY_DEFAULT_256BIT);
+    // device set to NULL
+    assert_invalid_parameter(ode_key_init, nullptr, password, ODE_KEY_DEFAULT_256BIT);
+
+    // password set to empty string
+    assert_invalid_parameter(ode_key_init, device1, "", ODE_KEY_DEFAULT_256BIT);
+    // password set to NULL
+    assert_invalid_parameter(ode_key_init, device1, nullptr, ODE_KEY_DEFAULT_256BIT);
+
+    // if the key will be initialized, the helper will remove it after the test execution
+    HelperKeys helper(device1, password, false);
+    // invalid type of key
+    assert_invalid_parameter(ode_key_init, device1, password, static_cast<ode_key_gen_params_e>(0));
+    assert_invalid_parameter(ode_key_init, device1, password, static_cast<ode_key_gen_params_e>(3));
+}
+
+/*
+ * TODO: ode_key_init should return invalid param in case of double init
+ *
+ * Calling ode_key_init() second time for given device should fail (now it just
+ * overwrites the existing key).
+ */
+RUNNER_TEST(T2003_ode_key_init_2_invalid_parameter_double_init)
+{
+    RUNNER_IGNORED_MSG("Test ignored because no error is returned in case of "
+                       "the double init, while the ODE_ERROR_INVALID_PARAMETER "
+                       "should be returned.");
+
+    HelperKeys helper(device1, password);
+
+    assert_invalid_parameter(ode_key_init, device1, password, ODE_KEY_DEFAULT_256BIT);
+}
+
+/*
+ * Invalid parameter error is returned if empty strings or null pointers
+ * are passed as the arguments of the function.
+ */
+RUNNER_TEST(T2004_ode_key_remove_1_invalid_parameter)
+{
+    HelperKeys helper(device1, password);
+
+    // device set to empty string
+    assert_invalid_parameter(ode_key_remove, "", password);
+    // device set to NULL
+    assert_invalid_parameter(ode_key_remove, nullptr, password);
+
+    // password set to empty string
+    assert_invalid_parameter(ode_key_remove, device1, "");
+    // password set to NULL
+    assert_invalid_parameter(ode_key_remove, device1, nullptr);
+}
+
+/*
+ * If the password is wrong, then the key cannot be removed and the error
+ * should be returned by the ode_key_remove function.
+ */
+RUNNER_TEST(T2005_ode_key_remove_2_rejected)
+{
+    const char* password_wrong = "abc321";
+
+    HelperKeys helper(device1, password);
+
+    assert_key_rejected(ode_key_remove, device1, password_wrong);
+}
+
+/*
+ * If no key exists for the given device, then the error should be returned by
+ * the ode_key_remove function.
+ */
+RUNNER_TEST(T2006_ode_key_remove_3_no_such_file)
+{
+    assert_no_such_file(ode_key_remove, device1, password);
+    assert_no_such_file(ode_key_remove, device2, password);
+}
+
+/*
+ * Invalid parameter error is returned if empty strings or null pointers
+ * are passed as the arguments of the function.
+ */
+RUNNER_TEST(T2007_ode_key_change_password_1_invalid_parameter)
+{
+    HelperKeys helper(device1, password);
+
+    // device set to empty string
+    assert_invalid_parameter(ode_key_change_password, "", password, password_new);
+    // device set to NULL
+    assert_invalid_parameter(ode_key_change_password, nullptr, password, password_new);
+
+    // old password set to empty string
+    assert_invalid_parameter(ode_key_change_password, device1, "", password_new);
+    // old password set to NULL
+    assert_invalid_parameter(ode_key_change_password, device1, nullptr, password_new);
+
+    // new password set to empty string
+    assert_invalid_parameter(ode_key_change_password, device1, password, "");
+    // new password set to NULL
+    assert_invalid_parameter(ode_key_change_password, device1, password, nullptr);
+}
+
+/*
+ * If the current password is wrong (for example the developer mistook the
+ * string with the current password with the new one), then the password cannot
+ * be changed and the error is returned by the ode_key_change_password
+ * function.
+ */
+RUNNER_TEST(T2008_ode_key_change_password_2_key_rejected)
+{
+    HelperKeys helper(device1, password);
+
+    assert_key_rejected(ode_key_change_password, device1, password_new, password);
+}
+
+/*
+ * If no key exists for the given device, then the password cannot be changed
+ * and the error is returned by the ode_key_change_password function.
+ */
+RUNNER_TEST(T2009_ode_key_change_password_3_no_such_file)
+{
+    assert_no_such_file(ode_key_change_password, device1, password, password_new);
+    assert_no_such_file(ode_key_change_password, device2, password, password_new);
+}
+
+/*
+ * Invalid parameter error is returned if empty strings or null pointers
+ * are passed as the arguments of the function.
+ */
+RUNNER_TEST(T2010_ode_key_verify_password_1_invalid_parameter)
+{
+    HelperKeys helper(device1, password);
+
+    bool result;
+
+    // device set to empty string
+    assert_invalid_parameter(ode_key_verify_password, "", password, &result);
+    // device set to NULL
+    assert_invalid_parameter(ode_key_verify_password, nullptr, password, &result);
+
+    // password set to empty string
+    assert_invalid_parameter(ode_key_verify_password, device1, "", &result);
+    // password set to NULL
+    assert_invalid_parameter(ode_key_verify_password, device1, nullptr, &result);
+
+    // result set to NULL
+    assert_invalid_parameter(ode_key_verify_password, device1, password, nullptr);
+}
+
+RUNNER_TEST(T2011_ode_key_verify_password_2_no_such_file)
+{
+    bool result;
+
+    assert_no_such_file(ode_key_verify_password, device1, password, &result);
+    assert_no_such_file(ode_key_verify_password, device2, password, &result);
+}
+
+/*
+ * Invalid parameter error is returned if empty strings or null pointers
+ * are passed as the arguments of the function.
+ */
+RUNNER_TEST(T2012_ode_key_store_master_key_1_invalid_parameter)
+{
+    HelperKeys helper(device1, password);
+
+    // device set to empty string
+    assert_invalid_parameter(ode_key_store_master_key, "", password);
+    // device set to NULL
+    assert_invalid_parameter(ode_key_store_master_key, nullptr, password);
+
+    // password set to empty string
+    assert_invalid_parameter(ode_key_store_master_key, device1, "");
+    // password set to NULL
+    assert_invalid_parameter(ode_key_store_master_key, device1, nullptr);
+}
+
+/*
+ * If the password passed into the ode_key_store_master_key function is wrong,
+ * then the key cannot be stored and ODE_ERROR_KEY_REJECTED should be returned
+ * by the storing function.
+ */
+RUNNER_TEST(T2013_ode_key_store_master_key_2_key_rejected)
+{
+    HelperKeys helper(device1, password);
+
+    assert_key_rejected(ode_key_store_master_key, device1, password_new);
+}
+
+RUNNER_TEST(T2014_ode_key_store_master_key_3_no_such_file)
+{
+    assert_no_such_file(ode_key_store_master_key, device1, password);
+    assert_no_such_file(ode_key_store_master_key, device2, password);
+}
+
+/*
+ * Invalid parameter error is returned if empty strings or null pointers
+ * are passed as the arguments of the function.
+ */
+RUNNER_TEST(T2015_ode_key_remove_master_key_1_invalid_parameter)
+{
+    HelperKeys helper(device1, password);
+
+    assert_positive(ode_key_store_master_key, device1, password);
+
+    // device set to empty string
+    assert_invalid_parameter(ode_key_remove_master_key, "");
+    // device set to NULL
+    assert_invalid_parameter(ode_key_remove_master_key, nullptr);
+}
+
+/*
+ * If the ode service is not active during the try of using the API functions,
+ * then the connection should be refused and the error should be returned by
+ * the API function.
+ */
+RUNNER_TEST(T2016_ode_keys_connection_refused)
+{
+    HelperKeys helper(device1, password);
+
+    auto sm_stop = createScopedOdeStopper();
+
+    bool result;
+
+    assert_connection_refused(ode_key_is_initialized, device1, &result);
+    assert_connection_refused(ode_key_init, device1, password, ODE_KEY_DEFAULT_256BIT);
+    assert_connection_refused(ode_key_remove, device1, password);
+    assert_connection_refused(ode_key_change_password, device1, password, password_new);
+    assert_connection_refused(ode_key_verify_password, device1, password, &result);
+    assert_connection_refused(ode_key_store_master_key, device1, password);
+    assert_connection_refused(ode_key_remove_master_key, device1);
+}
+
+/*
+ * When the unprivileged process (without the privilege internal/default/platform)
+ * tries to use protected API functions, then the PERMISSION_DENIED error is
+ * returned.
+ *
+ * TODO: permission denied should be returned instead of unknown error
+ */
+RUNNER_CHILD_TEST(T2017_ode_keys_permission_denied)
+{
+    RUNNER_IGNORED_MSG("Test ignored because the ODE_ERROR_UNKNOWN is returned "
+                       "instead of the ODE_ERROR_PERMISSION_DENIED.");
+
+    TemporaryTestUser adminUserToSwitch("ode_test_T2016_user", GUM_USERTYPE_ADMIN);
+    adminUserToSwitch.create();
+
+    AppInstallHelper appInstallHelper("ode_test_T2016_app_install_helper",
+        adminUserToSwitch.getUid());
+
+    ScopedInstaller scopedInstaller(appInstallHelper);
+
+    pid_t pid = fork();
+    if (pid != 0) {
+        waitPid(pid);
+    } else { //child process
+        SecurityManagerTest::Api::setProcessLabel(appInstallHelper.getAppId());
+        RUNNER_ASSERT_ERRNO_MSG(drop_root_privileges(adminUserToSwitch.getUid(),
+            adminUserToSwitch.getGid()) == 0,
+            "drop_root_privileges failed");
+
+        bool result;
+
+        // check if there is access to unprotected function
+        assert_positive(ode_key_is_initialized, device1, &result);
+
+        // check if there is no access to protected function
+        assert_permission_denied(ode_key_init, device1, password, ODE_KEY_DEFAULT_256BIT);
+        assert_permission_denied(ode_key_remove, device1, password);
+        assert_permission_denied(ode_key_change_password, device1, password, password_new);
+        assert_permission_denied(ode_key_verify_password, device1, password, &result);
+        assert_permission_denied(ode_key_store_master_key, device1, password);
+        assert_permission_denied(ode_key_remove_master_key, device1);
+    }
+}
+
+} // namespace OdeTestsKeys
diff --git a/src/ode/ode-tests-luks.cpp b/src/ode/ode-tests-luks.cpp
new file mode 100644 (file)
index 0000000..6e79858
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ *  Copyright (c) 2017-2018 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  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
+ *
+ *  @file   ode-tests-luks.cpp
+ *  @author Pawel Kowalski (p.kowalski2@partner.samsung.com)
+ *  @brief  Tests for the ODE API
+ */
+
+#include "dpl/test/test_runner.h"
+
+RUNNER_TEST_GROUP_INIT(T3000_ODE_API_LUKS);
\ No newline at end of file
diff --git a/src/ode/ode-tests-secure-erase.cpp b/src/ode/ode-tests-secure-erase.cpp
new file mode 100644 (file)
index 0000000..19b62ec
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ *  Copyright (c) 2017-2018 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  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
+ *
+ *  @file   ode-tests-secure-erase.cpp
+ *  @author Pawel Kowalski (p.kowalski2@partner.samsung.com)
+ *  @brief  Tests for the ODE API
+ */
+
+#include "dpl/test/test_runner.h"
+
+RUNNER_TEST_GROUP_INIT(T4000_ODE_API_SECURE_ERASE);
\ No newline at end of file
diff --git a/src/ode/ode-tests.cpp b/src/ode/ode-tests.cpp
new file mode 100644 (file)
index 0000000..040d7a9
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ *  Copyright (c) 2017-2018 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  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
+ *
+ *  @file   ode-test.cpp
+ *  @author Pawel Kowalski (p.kowalski2@partner.samsung.com)
+ *  @brief  Tests for the ODE API
+ */
+
+#include <dpl/test/test_runner.h>
+#include <dpl/log/log.h>
+
+int main (int argc, char *argv[])
+{
+    DPL::Log::LogSystemSingleton::Instance().SetTag("SECURITY_TESTS_ODE");
+    int status = DPL::Test::TestRunnerSingleton::Instance().ExecTestRunner(argc, argv);
+    return status;
+}
index 46e51d8..cf08aa4 100644 (file)
@@ -57,6 +57,7 @@ SET(SEC_MGR_SOURCES
     ${PROJECT_SOURCE_DIR}/src/security-manager-tests/security_manager_tests.cpp
     ${PROJECT_SOURCE_DIR}/src/security-manager-tests/common/policy_configuration.cpp
     ${PROJECT_SOURCE_DIR}/src/security-manager-tests/common/sm_commons.cpp
+    ${PROJECT_SOURCE_DIR}/src/security-manager-tests/common/template_parser.cpp
     ${PROJECT_SOURCE_DIR}/src/cynara-tests/common/cynara_test_client.cpp
     ${PROJECT_SOURCE_DIR}/src/cynara-tests/common/cynara_test_admin.cpp
     ${PROJECT_SOURCE_DIR}/src/cynara-tests/plugins/plugins.cpp
index b8b389b..16db76c 100644 (file)
 #include <grp.h>
 #include <string>
 #include <sys/capability.h>
+#include <sys/prctl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
 #include <unordered_map>
 #include <cstdlib>
 
+#include <array>
 #include <unordered_set>
+#include <utility>
 #include <vector>
 
 #include <security-manager-types.h>
 #include <policy_configuration.h>
 #include "tzplatform.h"
 #include <label_generator.h>
+#include <template_parser.h>
+#include <temp_test_user.h>
 
 using namespace SecurityManagerTest;
 
+#define CONF_DIR "/usr/share/security-manager/policy/"
+#define SMACK_RULES_PATH "/sys/fs/smackfs/load2"
+
+#define ALLOW 0
+#define DENY -1
+
 // Common DB/nftw checks
 
 // nftw doesn't allow passing user data to functions. Work around by using global variable
@@ -181,7 +192,75 @@ void sm_app_has_privileges(const AppInstallHelper &app,
     }
 }
 
-static void check_app(const std::string &appId, const std::string &pkgId, bool shouldBeInstalled)
+static void check_app_smack_accesses(const std::string &appId, const std::string &pkgId,
+                                     bool isHybrid = false)
+{
+    static const std::vector<AccessRequest> rules[] =
+        {parseSmackRulesFile(CONF_DIR "pkg-rules-template.smack"),
+         parseSmackRulesFile(CONF_DIR "app-rules-template.smack")};
+
+    const std::pair<std::string, std::string> switchAliases[] =
+        {std::make_pair("~PATH_RW~", generatePathRWLabel(pkgId)),
+         std::make_pair("~PATH_RO~", generatePathROLabel(pkgId)),
+         std::make_pair("~PATH_SHARED_RO~", getSharedROPathLabel()),
+         std::make_pair("~PROCESS~", generateProcessLabel(appId, pkgId, isHybrid))};
+
+    for (auto rule : rules[isHybrid]) {
+        if (rule.object == "~PATH_TRUSTED~") {
+            continue;
+        }
+
+        for (const auto &alias : switchAliases) {
+            if (rule.subject == alias.first) {
+                rule.subject = alias.second;
+            }
+            if (rule.object == alias.first) {
+                rule.object = alias.second;
+            }
+        }
+
+        if (rule.object == "_") {
+            rule.access = "rx" + rule.access;
+        }
+
+        check_exact_smack_accesses(rule.subject, rule.object, rule.access);
+    }
+}
+
+static void assert_no_label_in_rule(const AccessRequest &rule, const std::string &label)
+{
+    RUNNER_ASSERT_MSG(rule.object != label && rule.subject != label,
+                      "Smack rule left after uninstallation process." <<
+                      " Subject: " << rule.subject <<
+                      " object: " << rule.object <<
+                      " access: " << rule.access);
+}
+
+static void check_pkg_smack_rules_after_uninstall(const std::string &appId, const std::string &pkgId)
+{
+    const std::vector<AccessRequest> rules(std::move(parseSmackRulesFile(SMACK_RULES_PATH)));
+    const std::string labels[] = {generatePathRWLabel(pkgId),
+                                  generatePathROLabel(pkgId),
+                                  generateProcessLabel(appId, pkgId, true),
+                                  generateProcessLabel(appId, pkgId)};
+    for (const auto &rule : rules) {
+        for (const auto &label : labels) {
+            assert_no_label_in_rule(rule, label);
+        }
+    }
+}
+
+static void check_hybrid_app_smack_rules_after_uninstall(const std::string &appId, const std::string &pkgId)
+{
+    const std::vector<AccessRequest> rules(std::move(parseSmackRulesFile(SMACK_RULES_PATH)));
+    const std::string appLabel = generateProcessLabel(appId, pkgId, true);
+    for (const auto &rule : rules) {
+        assert_no_label_in_rule(rule, appLabel);
+    }
+}
+
+static void check_app(const std::string &appId, const std::string &pkgId,
+                      bool shouldBeInstalled, bool isHybrid, bool removePkg)
 {
     char *retPkgId;
     int ret = security_manager_get_app_pkgid(&retPkgId, appId.c_str());
@@ -194,14 +273,21 @@ static void check_app(const std::string &appId, const std::string &pkgId, bool s
             RUNNER_ASSERT_MSG(strcmp(pkgId.c_str(), retPkgId) == 0,
                               "The given appId does not belong to the given pkgId.");
         }
+        check_app_smack_accesses(appId, pkgId, isHybrid);
     } else {
         RUNNER_ASSERT_MSG(ret == SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT, "The given appId is installed.");
+
+        if (removePkg) {
+            check_pkg_smack_rules_after_uninstall(appId, pkgId);
+        } else if (isHybrid) {
+            check_hybrid_app_smack_rules_after_uninstall(appId, pkgId);
+        }
     }
 }
 
-void check_app_after_install(const std::string &app_id, const std::string &pkg_id)
+void check_app_after_install(const std::string &app_id, const std::string &pkg_id, bool isHybrid)
 {
-    check_app(app_id, pkg_id, true);
+    check_app(app_id, pkg_id, true, isHybrid, false);
 }
 
 static void check_app_gids(const std::string &app_id, const std::vector<gid_t> &allowed_gids)
@@ -239,8 +325,7 @@ void check_app_after_install(const std::string &app_id, const std::string &pkg_i
                              const privileges_t &denied_privs,
                              bool isHybrid)
 {
-    check_app(app_id, pkg_id, true);
-
+    check_app(app_id, pkg_id, true, isHybrid, false);
     /* Privileges should be granted to all users if root installs app */
     check_app_permissions(app_id, pkg_id, ANY_USER_REPRESENTATION, allowed_privs, denied_privs, isHybrid);
 
@@ -270,15 +355,17 @@ void check_path(const std::string &path, const std::string &label, bool transmut
     RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for " << path);
 }
 
-void check_app_after_uninstall(const std::string &app_id, const std::string &pkg_id)
+void check_app_after_uninstall(const std::string &app_id, const std::string &pkg_id,
+                               bool isHybrid, bool removePkg)
 {
-    check_app(app_id, pkg_id, false);
+    check_app(app_id, pkg_id, false, isHybrid, removePkg);
 }
 
 void check_app_after_uninstall(const std::string &app_id, const std::string &pkg_id,
-                               const privileges_t &privileges, bool isHybrid)
+                               const privileges_t &privileges, bool isHybrid,
+                               bool removePkg)
 {
-    check_app(app_id, pkg_id, false);
+    check_app(app_id, pkg_id, false, isHybrid, removePkg);
 
     /* Privileges should not be granted anymore to any user */
     check_app_permissions(app_id, pkg_id, ANY_USER_REPRESENTATION, {}, privileges, isHybrid);
@@ -355,22 +442,30 @@ void accessCheck(const std::string &id, const std::string &path, int accessType,
                        << " (" << accessTypeToString.at(accessType) << ")");
 }
 
+void accessTest(const std::string &id, const std::string &testPath, int accessType) {
+    int oppositeAccessType = getOppositeAccessType(accessType);
+
+    if (accessType != 0) {
+        accessCheck(id, testPath, accessType, ALLOW);
+    }
+    if (oppositeAccessType != 0) {
+        static const std::vector<int> singleAccessTypes = {R_OK, W_OK, X_OK};
+        for (auto singleAccessType : singleAccessTypes) {
+            if (oppositeAccessType & singleAccessType) {
+                accessCheck(id, testPath, singleAccessType, DENY);
+            }
+        }
+    }
+}
+
 void runAccessTest(const std::string &label, uid_t uid, gid_t gid,
                    const std::string &testPath, int accessType) {
     auto fun = [&](){
-        int oppositeAccessType = getOppositeAccessType(accessType);
         ScopedProcessLabel spl(label, false);
         RUNNER_ASSERT_ERRNO_MSG(0 == drop_root_privileges(uid, gid),
                                 "drop_root_privileges failed.");
 
-        if (accessType != 0)
-            accessCheck(label, testPath, accessType, 0);
-        if (oppositeAccessType != 0) {
-            std::vector<int> singleAccessTypes = {R_OK, W_OK, X_OK};
-            for (auto singleAccessType : singleAccessTypes)
-                if (oppositeAccessType & singleAccessType)
-                    accessCheck(label, testPath, singleAccessType, -1);
-        }
+        accessTest(label, testPath, accessType);
     };
 
     runInChildParentWait(fun);
@@ -378,18 +473,10 @@ void runAccessTest(const std::string &label, uid_t uid, gid_t gid,
 
 void runAccessTest(const AppInstallHelper &app, const std::string &testPath, int accessType) {
     auto fun = [&](){
-        int oppositeAccessType = getOppositeAccessType(accessType);
         Api::setProcessLabel(app.getAppId());
         RUNNER_ASSERT_ERRNO_MSG(0 == drop_root_privileges(app.getUID(), app.getGID()),
                                 "drop_root_privileges failed.");
-        if (accessType != 0)
-            accessCheck(app.getAppId(), testPath, accessType, 0);
-        if (oppositeAccessType != 0) {
-            std::vector<int> singleAccessTypes = {R_OK, W_OK, X_OK};
-            for (auto singleAccessType : singleAccessTypes)
-                if (oppositeAccessType & singleAccessType)
-                    accessCheck(app.getAppId(), testPath, singleAccessType, -1);
-        }
+        accessTest(app.getAppId(), testPath, accessType);
     };
 
     runInChildParentWait(fun);
@@ -429,3 +516,29 @@ int countPrivacyPrivileges(const std::vector<std::string> &privs) {
     return std::count_if(privs.begin(), privs.end(), isPrivilegePrivacy);
 }
 
+int setLauncherSecurityAttributes(uid_t uid, gid_t gid)
+{
+    // Add launcher capabilities (cap_dac_override, cap_setgid, cap_sys_admin, cap_mac_admin),
+    // launcher is user process, we must drop root privileges (cap_setgid, cap_setuid are needed).
+    // By default, the permitted capability set is cleared when credentials change is made
+    // (if a process drops a capability from its permitted set, it can never reacquire that capability),
+    // setting the "keep capabilities" flag prevents it from being cleared.
+    // Effective capability set is always cleared when credential change is made, we need to add them again.
+
+    setCaps("cap_dac_override+ep cap_setgid+ep cap_sys_admin+ep cap_mac_admin+ep cap_setuid+ep");
+    int ret = prctl(PR_SET_KEEPCAPS, 1, 0, 0);
+    if (ret != 0)
+        return ret;
+
+    ret = drop_root_privileges(uid, gid);
+    if (ret != 0)
+        return ret;
+
+    setCaps("cap_dac_override+ep cap_setgid+ep cap_sys_admin+ep cap_mac_admin+ep");
+    return ret;
+}
+int setLauncherSecurityAttributes(TemporaryTestUser &user)
+{
+    return setLauncherSecurityAttributes(user.getUid(), user.getGid());
+}
+
index 902d70c..6840281 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2016-2019 Samsung Electronics Co., Ltd All Rights Reserved
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
  *    you may not use this file except in compliance with the License.
@@ -45,17 +45,19 @@ void check_app_permissions(const std::string &app_id, const std::string &pkg_id,
 void sm_app_has_privileges(const AppInstallHelper &app,
                            const std::vector<std::string> &privileges,
                            int result);
-void check_app_after_install(const std::string &app_id, const std::string &pkg_id);
+void check_app_after_install(const std::string &app_id, const std::string &pkg_id,
+                             bool isHybrid = false);
 void check_app_after_install(const std::string &app_id, const std::string &pkg_id,
                              const privileges_t &allowed_privs,
                              const privileges_t &denied_privs,
                              bool isHybrid = false);
 void check_path(const std::string &path, const std::string &label,
                 bool transmute = true, bool execute = false);
-void check_app_after_uninstall(const std::string &app_id, const std::string &pkg_id);
 void check_app_after_uninstall(const std::string &app_id, const std::string &pkg_id,
-                               const privileges_t &privileges, bool isHybrid = false);
-
+                               bool isHybrid = false, bool removePkg = false);
+void check_app_after_uninstall(const std::string &app_id, const std::string &pkg_id,
+                               const privileges_t &privileges, bool isHybrid = false,
+                               bool removePkg = false);
 std::string access_opposite(std::string &access);
 void check_exact_smack_accesses(const std::string &subject,
                                 const std::string &object,
@@ -63,6 +65,7 @@ void check_exact_smack_accesses(const std::string &subject,
 
 CapsSetsUniquePtr setCaps(const char *cap_string);
 
+void accessTest(const std::string &id, const std::string &testPath, int accessType);
 void runAccessTest(const std::string &label, uid_t uid, gid_t gid,
                    const std::string &testPath, int accessType);
 void runAccessTest(const AppInstallHelper &app, const std::string &testPath, int accessType);
@@ -72,3 +75,6 @@ bool isAskuserDisabled();
 bool isPrivilegePrivacy(const std::string &priv);
 int countPrivacyPrivileges(const PrivilegeVector &privs);
 int countPrivacyPrivileges(const std::vector<std::string> &privs);
+
+int setLauncherSecurityAttributes(uid_t uid, gid_t gid);
+int setLauncherSecurityAttributes(TemporaryTestUser &user);
diff --git a/src/security-manager-tests/common/template_parser.cpp b/src/security-manager-tests/common/template_parser.cpp
new file mode 100644 (file)
index 0000000..83c5b46
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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.
+ */
+/*
+ * @file        template_parser.cpp
+ * @author      Alicja Kluczek <a.kluczek@samsung.com>
+ * @brief       Parsing function for smack rules templates
+ */
+#include "template_parser.h"
+#include <fstream>
+
+std::vector<AccessRequest> parseSmackRulesFile(const std::string &path)
+{
+    std::vector<AccessRequest> rules;
+    std::ifstream rulesFile(path);
+    std::string object, subject, access;
+    while (rulesFile >> subject >> object >> access) {
+        rules.emplace_back(std::move(subject), std::move(object), std::move(access));
+    }
+    return rules;
+}
+
diff --git a/src/security-manager-tests/common/template_parser.h b/src/security-manager-tests/common/template_parser.h
new file mode 100644 (file)
index 0000000..81a3674
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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.
+ */
+/*
+ * @file        template_parser.h
+ * @author      Alicja Kluczek <a.kluczek@samsung.com>
+ * @brief       Parsing function for smack rules templates
+ */
+#include <vector>
+#include <string>
+
+struct AccessRequest {
+    AccessRequest(std::string sub, std::string obj, std::string acc)
+    : subject(std::move(sub)),
+      object(std::move(obj)),
+      access(std::move(acc))
+    {}
+    std::string subject;
+    std::string object;
+    std::string access;
+};
+
+std::vector<AccessRequest> parseSmackRulesFile(const std::string &path);
+
index 5bde91d..8b7a7fc 100644 (file)
@@ -139,7 +139,7 @@ RUNNER_TEST(security_manager_01d_app_install_complicated_dir_tree)
     check_path(privateDir, generatePathRWLabel(pkgId));
     check_path(privateRODir, generatePathROLabel(pkgId), false);
     check_path(publicRODir, getPublicPathLabel());
-    check_path(sharedRODir, generatePathSharedROLabel(pkgId));
+    check_path(sharedRODir, getSharedROPathLabel());
 }
 
 RUNNER_TEST(security_manager_02_app_install_uninstall_full)
@@ -176,7 +176,7 @@ RUNNER_TEST(security_manager_02_app_install_uninstall_full)
         check_path(app.getPrivateDir(), generatePathRWLabel(app.getPkgId()));
         check_path(app.getPrivateRODir(), generatePathROLabel(app.getPkgId()), false);
         check_path(app.getPublicDir(), getPublicPathLabel());
-        check_path(app.getSharedRODir(), generatePathSharedROLabel(app.getPkgId()));
+        check_path(app.getSharedRODir(), getSharedROPathLabel());
     }
 
     check_app_after_uninstall(app.getAppId(), app.getPkgId(), app.getPrivilegesNames());
@@ -508,6 +508,98 @@ RUNNER_TEST(security_manager_09_app_install_constraint_check)
     install(users[0], pkgId[0], appId[0], version[0], author[1], hybrid[0], SECURITY_MANAGER_ERROR_INPUT_PARAM);
 }
 
+RUNNER_TEST(security_manager_09a_install_many_apps_in_single_request)
+{
+    const std::string pkgId = "sm_test_09a_pkg_id_0";
+    const std::vector<std::string> appIds = {"sm_test_09a_app_id_0", "sm_test_09a_app_id_1", "sm_test_09a_app_id_2"};
+
+    {
+        ScopedInstaller appsInstall(appIds, pkgId);
+        // Installing many applications in single request
+        for (const auto &appId : appIds) {
+            check_app_after_install(appId, pkgId);
+        }
+    }
+
+    for (const auto &appId : appIds) {
+        check_app_after_uninstall(appId, pkgId);
+    }
+}
+
+RUNNER_TEST(security_manager_09b_install_many_apps_in_single_request_duplicated_ids)
+{
+    const std::string pkgId = "sm_test_09b_pkg_id_0";
+    const std::string appId = "sm_test_09b_app_id_0";
+
+    {
+        ScopedInstaller appsInstall({appId, appId}, pkgId);
+        check_app_after_install(appId, pkgId);
+    }
+
+    check_app_after_uninstall(appId, pkgId);
+}
+
+RUNNER_TEST(security_manager_09c_update_many_apps_in_single_request_hybrid_package)
+{
+    const std::vector<std::string> appIds = {"sm_test_09c_app_id_0", "sm_test_09c_app_id_1", "sm_test_09c_app_id_2"};
+    const std::string pkgId = "sm_test_09c_pkg_id_0";
+
+    {
+        ScopedInstaller appsInstall(appIds, pkgId);
+        // Package is not hybrid, every app has same policy.
+        for (const auto &appId : appIds) {
+            check_app_after_install(appId, pkgId);
+        }
+
+        // Updating package -- changing set of apps in package and setting hybrid mode
+        InstallRequest updateRequest;
+        updateRequest.setPkgId(pkgId);
+        updateRequest.setAppId(appIds[0]);
+        updateRequest.nextApp();
+        updateRequest.setAppId(appIds[1]);
+        updateRequest.setHybrid();
+
+        Api::update(updateRequest);
+        // Package became hybrid, so every app has its own Smack label
+        check_app_after_install(appIds[0], pkgId, true);
+        check_app_after_install(appIds[1], pkgId, true);
+        // Package became hybrid properly,
+        // so app not included in updated version of package was uninstalled.
+        check_app_after_uninstall(appIds[2], pkgId);
+    }
+
+    for (const auto &appId : appIds) {
+        check_app_after_uninstall(appId, pkgId, true, true);
+    }
+}
+
+RUNNER_TEST(security_manager_09d_uninstall_app_from_hybrid_package)
+{
+    const std::vector<std::string> appIds = {"sm_test_09d_app_id_0", "sm_test_09d_app_id_1", "sm_test_09d_app_id_2"};
+    const std::string pkgId = "sm_test_09d_pkg_id_0";
+    {
+        ScopedInstaller appsInstall(appIds, pkgId);
+
+        InstallRequest updateRequest;
+        updateRequest.setPkgId(pkgId);
+        for (unsigned int i = 0; i < appIds.size(); i++) {
+            if (i > 0) {
+                updateRequest.nextApp();
+            }
+            updateRequest.setAppId(appIds[i]);
+        }
+        updateRequest.setHybrid();
+        Api::update(updateRequest);
+
+        InstallRequest uninstRequest;
+        uninstRequest.setPkgId(pkgId);
+        uninstRequest.setAppId(appIds[0]);
+        Api::uninstall(uninstRequest);
+
+        check_app_after_uninstall(appIds[0], pkgId, true);
+    }
+}
+
 RUNNER_CHILD_TEST(security_manager_10_app_has_privilege)
 {
     const std::vector<std::string> allowedPrivs = {
index 79f75ad..9ff9179 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2016-2020 Samsung Electronics Co., Ltd. All rights reserved
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
  *    you may not use this file except in compliance with the License.
  *    limitations under the License.
  */
 
+#include <poll.h>
 #include <sys/smack.h>
 #include <sys/capability.h>
 #include <sys/prctl.h>
+#include <sys/eventfd.h>
 
+#include <cmath>
 #include <thread>
 #include <string>
 #include <memory>
@@ -118,28 +121,6 @@ struct ThreadWrapper
     std::thread thread;
 };
 
-int setLauncherSecurityAttributes(TemporaryTestUser &user)
-{
-    // Add launcher capabilities (cap_dac_override, cap_setgid, cap_sys_admin, cap_mac_admin),
-    // launcher is user process, we must drop root privileges (cap_setgid, cap_setuid are needed).
-    // By default, the permitted capability set is cleared when credentials change is made
-    // (if a process drops a capability from its permitted set, it can never reacquire that capability),
-    // setting the "keep capabilities" flag prevents it from being cleared.
-    // Effective capability set is always cleared when credential change is made, we need to add them again.
-
-    setCaps("cap_dac_override+ep cap_setgid+ep cap_sys_admin+ep cap_mac_admin+ep cap_setuid+ep");
-    int ret = prctl(PR_SET_KEEPCAPS, 1, 0, 0);
-    if (ret != 0)
-        return ret;
-
-    ret = drop_root_privileges(user.getUid(), user.getGid());
-    if (ret != 0)
-        return ret;
-
-    setCaps("cap_dac_override+ep cap_setgid+ep cap_sys_admin+ep cap_mac_admin+ep");
-    return ret;
-}
-
 ino_t getFileInode(const std::string &path)
 {
     struct stat st;
@@ -186,7 +167,7 @@ RUNNER_CHILD_TEST(security_manager_100_synchronize_credentials_test)
     if (pid == 0) {
         {
             RUNNER_ASSERT_ERRNO_MSG(setLauncherSecurityAttributes(tmpUser) == 0, "launcher failed");
-
+            Api::prepareAppCandidate();
             ThreadWrapper threads[THREADS];
 
             for (size_t i = 0; i < THREADS; i++)
@@ -202,6 +183,34 @@ RUNNER_CHILD_TEST(security_manager_100_synchronize_credentials_test)
     }
 }
 
+RUNNER_CHILD_TEST(security_manager_101_create_namespace_test_n)
+{
+    TemporaryTestUser tmpUser(APP_TEST_USER, GUM_USERTYPE_NORMAL, false);
+    tmpUser.create();
+
+    AppInstallHelper app("app100_n", tmpUser.getUid());
+    ScopedInstaller appInstall(app);
+    const std::string expectedLabel = app.generateAppLabel();
+
+    pid_t pid = fork();
+    RUNNER_ASSERT_ERRNO_MSG(pid >= 0, "Fork failed");
+    if (pid == 0) {
+        {
+            RUNNER_ASSERT_ERRNO_MSG(setLauncherSecurityAttributes(tmpUser) == 0, "launcher failed");
+            ThreadWrapper threads[THREADS];
+
+            for (size_t i = 0; i < THREADS; i++)
+                threads[i].run(i, expectedLabel);
+
+            Api::prepareAppCandidate(SECURITY_MANAGER_ERROR_INPUT_PARAM);
+        }
+        RUNNER_ASSERT_MSG(!thread_errors.empty(), std::endl << thread_errors);
+        exit(0);
+    } else {
+        waitPid(pid);
+    }
+}
+
 RUNNER_CHILD_TEST(security_manager_101_create_namespace_test)
 {
     TemporaryTestUser tmpUser(APP_TEST_USER, GUM_USERTYPE_NORMAL, false);
@@ -216,7 +225,7 @@ RUNNER_CHILD_TEST(security_manager_101_create_namespace_test)
     if (pid == 0) {
         synchPipe.claimParentEp();
         RUNNER_ASSERT_ERRNO_MSG(setLauncherSecurityAttributes(tmpUser) == 0, "launcher failed");
-
+        Api::prepareAppCandidate();
         Api::prepareApp(app.getAppId().c_str());
         synchPipe.post();
         synchPipe.wait();
@@ -262,7 +271,7 @@ RUNNER_CHILD_TEST(security_manager_102_check_propagation_test)
     if (pid == 0) {
         synchPipe.claimParentEp();
         RUNNER_ASSERT_ERRNO_MSG(setLauncherSecurityAttributes(tmpUser) == 0, "launcher failed");
-
+        Api::prepareAppCandidate();
         Api::prepareApp(app.getAppId().c_str());
         synchPipe.post();
         synchPipe.wait();
@@ -308,7 +317,7 @@ RUNNER_CHILD_TEST(security_manager_103_policy_change_test)
     if (pid == 0) {
         synchPipe.claimParentEp();
         RUNNER_ASSERT_ERRNO_MSG(setLauncherSecurityAttributes(tmpUser) == 0, "launcher failed");
-
+        Api::prepareAppCandidate();
         Api::prepareApp(app.getAppId().c_str());
         synchPipe.post();
         synchPipe.wait();
@@ -363,3 +372,194 @@ RUNNER_CHILD_TEST(security_manager_103_policy_change_test)
         Api::cleanupApp(app.getAppId().c_str(), tmpUser.getUid(), pid);
     }
 }
+
+namespace {
+class Timestamp {
+    uint64_t _;
+    explicit Timestamp(uint64_t ts) : _(ts) {}
+public:
+    Timestamp operator-(const Timestamp &other) const {
+        RUNNER_ASSERT(_ > other._);
+        return Timestamp(_ - other._);
+    }
+    Timestamp operator+(const Timestamp &other) const {
+        return Timestamp(_ + other._);
+    }
+    bool operator<(const Timestamp &other) const {
+        return _ < other._;
+    }
+    Timestamp() = default;
+    static Timestamp future(uint64_t ns) {
+        timespec ts;
+        const auto res = clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
+        RUNNER_ASSERT_ERRNO(!res);
+        return Timestamp(ts.tv_sec * 1000000000ULL + ts.tv_nsec + ns);
+    }
+    static Timestamp now() {
+        return future(0);
+    }
+    template <size_t nLowDigitsToSkip = 3>
+    static void report(Timestamp *ts, size_t n) {
+        std::sort(ts, ts+n);
+        uint64_t sum = 0, mn = -1, mx = 0;
+        long double qsum = 0;
+        for (size_t i = 0; i < n; i++) {
+            const auto t = ts[i]._;
+            sum += t;
+            qsum += decltype(qsum)(t) * t;
+            mn = std::min(mn, t);
+            mx = std::max(mx, t);
+        }
+        uint64_t avg = sum / n;
+        auto qstddev = qsum/n - decltype(qsum)(avg)*avg;
+        const auto out = [](const char *desc, uint64_t t) {
+            char raw[20];
+        char s[20 + 20/3 + 1];
+        size_t j = 0, i = 0;
+        do
+            raw[j++] = '0' + t % 10ULL;
+        while (t /= 10ULL);
+        for (;;) {
+            s[i++] = raw[--j];
+            if (j <= nLowDigitsToSkip)
+                break;
+            if (!(j % 3))
+                s[i++] = ' ';
+        }
+        s[i] = '\0';
+        std::cerr << desc << s;
+    };
+    out("min ", mn);
+    out(" max ", mx);
+    out(" avg ", avg);
+    out(" median ", ts[n/2]._);
+    out(" stddev ", std::floor(std::sqrt(qstddev)));
+    std::cerr << '\n';
+    }
+};
+
+template <class T, size_t N>
+constexpr size_t arraySize(T (&)[N]) { return N; }
+} // namespace
+
+RUNNER_TEST(security_manager_200_prepare_app_perf)
+{
+    constexpr int8_t nThreads = 32;
+    constexpr int8_t nConcurrentAppsSamples[] = { 0 /* 1 app w/ nThreads */, 1, 2, 4, 8, 16, 32 };
+    constexpr uint64_t minTotalBenchTime = 60 * 1000ULL*1000*1000; // 60s
+
+    TemporaryTestUser tmpUser(APP_TEST_USER, GUM_USERTYPE_NORMAL, false);
+    tmpUser.create();
+
+    struct App {
+        AppInstallHelper hlp;
+        pid_t pid;
+    };
+
+    std::vector<Timestamp> candidate, prepare, everything;
+
+    std::vector<App> apps;
+    std::vector<ScopedInstaller> appInstalls;
+
+    constexpr auto nAppsMax = nConcurrentAppsSamples[arraySize(nConcurrentAppsSamples) - 1] ?: 1;
+    apps.reserve(nAppsMax);
+    appInstalls.reserve(nAppsMax);
+
+    const auto uid = tmpUser.getUid();
+    for (int i = 0; i < nAppsMax; i++) {
+        apps.emplace_back(App{AppInstallHelper("app200_" + std::to_string(i), uid), 0});
+        auto &hlp = apps.back().hlp;
+        for (const auto &p : { EXTERNAL_STORAGE_PRIVILEGE, MEDIA_STORAGE_PRIVILEGE,
+                std::string("http://tizen.org/privilege/camera"),
+                std::string("http://tizen.org/privilege/internet") })
+            hlp.addPrivilege(p);
+        hlp.createSharedRODir();
+        appInstalls.emplace_back(ScopedInstaller(hlp));
+    }
+
+    for (const auto nConcurrentAppsDesc : nConcurrentAppsSamples) {
+        const auto nConcurrentApps = nConcurrentAppsDesc ?: 1;
+        const auto timeout = Timestamp::future(minTotalBenchTime / arraySize(nConcurrentAppsSamples));
+        do {
+            SynchronizationPipe synchPipe;
+            auto exitEvFd = eventfd(0, 0);
+            RUNNER_ASSERT(exitEvFd >= 0);
+
+            for (int i = 0; i < nConcurrentApps; i++) {
+                auto &app = apps[i];
+                const auto pid = fork();
+                RUNNER_ASSERT_ERRNO_MSG(pid >= 0, "Fork failed");
+                if (pid)
+                    app.pid = pid;
+                else {
+                    synchPipe.claimChildEp();
+                    RUNNER_ASSERT_ERRNO_MSG(setLauncherSecurityAttributes(tmpUser) == 0, "launcher failed");
+
+                    const auto appId = app.hlp.getAppId();
+
+                    synchPipe.post(); // declare readiness to start measuring
+                    synchPipe.pollForWait(); // wait for parent to signal all kids simultaneously
+
+                    const auto candBeg = Timestamp::now();
+                    Api::prepareAppCandidate();
+                    const auto candEnd = Timestamp::now();
+
+                    if (!nConcurrentAppsDesc) {
+                        for (int i = 0; i < nThreads; i++)
+                            std::thread([]{ for (;;) usleep(1000); }).detach();
+                    }
+
+                    const auto prepBeg = Timestamp::now();
+                    Api::prepareApp(appId);
+                    const auto prepEnd = Timestamp::now();
+
+                    const Timestamp ts[2] = { candEnd-candBeg, prepEnd-prepBeg };
+                    synchPipe.post(ts, sizeof ts); // post measurement payload
+
+                    // stay idle until all kids are done to simulate idle apps and reduce benchmark noise
+                    pollfd fds[1];
+                    fds->fd = exitEvFd;
+                    fds->events = POLLIN;
+                    auto ret = TEMP_FAILURE_RETRY(poll(fds, 1, -1));
+                    RUNNER_ASSERT_ERRNO(ret > 0);
+
+                    exit(0);
+                }
+            }
+            synchPipe.claimParentEp();
+
+            for (int i = 0; i < nConcurrentApps; i++) // wait for all kids to be ready to start measurement
+                synchPipe.wait();
+            synchPipe.post(); // signal all kids to start measuring
+
+            for (int i = 0; i < nConcurrentApps; i++) {
+                Timestamp ts[2];
+                synchPipe.wait(ts, sizeof ts);
+                candidate.emplace_back(ts[0]);
+                prepare.emplace_back(ts[1]);
+                everything.emplace_back(ts[0] + ts[1]);
+            }
+
+            RUNNER_ASSERT(!eventfd_write(exitEvFd, 1)); // signal all kids to exit now
+
+            for (int i = 0; i < nConcurrentApps; i++) {
+                const auto &app = apps[i];
+                waitPid(app.pid);
+                Api::cleanupApp(app.hlp.getAppId(), uid, app.pid);
+            }
+        } while (Timestamp::now() < timeout);
+
+        if (!nConcurrentAppsDesc)
+            std::cerr << "additionalThreads " << int(nThreads) << ' ';
+        std::cerr << "nConcurrentApps " << int(nConcurrentApps) << " samples " << candidate.size() << '\n';
+        std::cerr << "  prepareAppCandidate [us]:              ";
+        Timestamp::report(candidate.data(), candidate.size());
+        std::cerr << "  prepareApp [us]:                       ";
+        Timestamp::report(prepare.data(), prepare.size());
+        std::cerr << "  prepareAppCandidate + prepareApp [us]: ";
+        Timestamp::report(everything.data(), everything.size());
+        candidate.clear();
+        prepare.clear();
+        everything.clear();
+    }
+}
index d882c0f..b71ad04 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2016-2019 Samsung Electronics Co., Ltd All Rights Reserved
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
  *    you may not use this file except in compliance with the License.
@@ -15,6 +15,7 @@
  */
 #include <cstdint>
 #include <fcntl.h>
+#include <functional>
 #include <unordered_map>
 #include <string>
 #include <sys/smack.h>
@@ -32,6 +33,7 @@ using namespace SecurityManagerTest;
 namespace {
 
 const uid_t OWNER_UID = 5001;
+const uid_t OWNER_GID = 100;
 
 const std::vector<std::string> versions = {
         "2.4",
@@ -54,6 +56,25 @@ const VersionCombinations versionCombinations = makeVersionCombinations(versions
 
 RUNNER_TEST_GROUP_INIT(SECURITY_MANAGER_SHARED_RO)
 
+static void runAccessTest(uid_t uid, gid_t gid, const std::string &appId,
+                          std::function<void(void)> f)
+{
+    pid_t pid = fork();
+
+    RUNNER_ASSERT_ERRNO_MSG(pid >= 0, "Fork failed");
+    if (pid == 0) {
+        setLauncherSecurityAttributes(uid, gid);
+        Api::prepareAppCandidate();
+        Api::prepareApp(appId.c_str());
+        f();
+        exit(0);
+    } else {
+
+        waitPid(pid);
+        Api::cleanupApp(appId.c_str(), uid, pid);
+    }
+}
+
 /**
  * Check whether owner app have access to own sharedRO dir
  */
@@ -64,10 +85,29 @@ RUNNER_CHILD_TEST(security_manager_76_owner_access)
         app.createSharedRODir();
         ScopedInstaller sharedROPkgApp(app);
 
-        runAccessTest(app, app.getSharedRODir(), R_OK|W_OK|X_OK);
+        runAccessTest(OWNER_UID, OWNER_GID, app.getAppId(), [&]() {
+            accessTest(app.getAppId(), app.getSharedRODir(), R_OK|W_OK|X_OK);
+        });
     }
 }
 
+RUNNER_CHILD_TEST(security_manager_7x_test)
+{
+    AppInstallHelper ownerApp("owner_7x", OWNER_UID);
+    ownerApp.createSharedRODir();
+    ScopedInstaller ownerAppInstall(ownerApp);
+
+    AppInstallHelper otherApp("other_7x", OWNER_UID);
+    otherApp.createSharedRODir();
+    ScopedInstaller otherAppInstall(otherApp);
+
+    runAccessTest(OWNER_UID, OWNER_GID, ownerApp.getAppId(), [&]() {
+        accessTest(ownerApp.getAppId(), ownerApp.getSharedRODir(), R_OK | W_OK | X_OK);
+        accessTest(ownerApp.getAppId(), otherApp.getSharedRODir(), R_OK | X_OK);
+        exit(0);
+    });
+}
+
 /**
  * Check whether app without shared RO path has access to shared RO dir and
  * no access to private directories of application from different package between
@@ -84,9 +124,14 @@ RUNNER_CHILD_TEST(security_manager_77_owner_other_access_version_combinations)
         AppInstallHelper nonSharedApp("sm_test_77_nonshared", OWNER_UID, version.second);
         ScopedInstaller nonSharedAppInstall(nonSharedApp);
 
-        runAccessTest(sharedApp, sharedApp.getSharedRODir(), R_OK|W_OK|X_OK);
-        runAccessTest(nonSharedApp, sharedApp.getPrivateDir(), 0);
-        runAccessTest(nonSharedApp, sharedApp.getSharedRODir(), R_OK|X_OK);
+        runAccessTest(OWNER_UID, OWNER_GID, sharedApp.getAppId(), [&]() {
+            accessTest(sharedApp.getAppId(), sharedApp.getSharedRODir(), R_OK|W_OK|X_OK);
+        });
+
+        runAccessTest(OWNER_UID, OWNER_GID, nonSharedApp.getAppId(), [&]() {
+            accessTest(nonSharedApp.getAppId(), sharedApp.getPrivateDir(), 0);
+            accessTest(nonSharedApp.getAppId(), sharedApp.getSharedRODir(), R_OK|X_OK);
+        });
     }
 }
 
@@ -108,12 +153,17 @@ RUNNER_CHILD_TEST(security_manager_78_another_pkg_shared_ro_have_ro_access_to_sh
         sharedApp2.createPrivateDir();
         ScopedInstaller sharedApp2Install(sharedApp2);
 
-        runAccessTest(sharedApp2, sharedApp1.getSharedRODir(), R_OK|X_OK);
-        runAccessTest(sharedApp1, sharedApp2.getSharedRODir(), R_OK|X_OK);
-        runAccessTest(sharedApp1, sharedApp1.getSharedRODir(), R_OK|W_OK|X_OK);
-        runAccessTest(sharedApp2, sharedApp2.getSharedRODir(), R_OK|W_OK|X_OK);
-        runAccessTest(sharedApp2, sharedApp1.getPrivateDir(), 0);
-        runAccessTest(sharedApp1, sharedApp2.getPrivateDir(), 0);
+        runAccessTest(OWNER_UID, OWNER_GID, sharedApp1.getAppId(), [&]() {
+            accessTest(sharedApp1.getAppId(), sharedApp2.getSharedRODir(), R_OK|X_OK);
+            accessTest(sharedApp1.getAppId(), sharedApp1.getSharedRODir(), R_OK|W_OK|X_OK);
+            accessTest(sharedApp1.getAppId(), sharedApp2.getPrivateDir(), 0);
+        });
+
+        runAccessTest(OWNER_UID, OWNER_GID, sharedApp2.getAppId(), [&]() {
+            accessTest(sharedApp2.getAppId(), sharedApp1.getSharedRODir(), R_OK|X_OK);
+            accessTest(sharedApp2.getAppId(), sharedApp2.getSharedRODir(), R_OK|W_OK|X_OK);
+            accessTest(sharedApp2.getAppId(), sharedApp1.getPrivateDir(), 0);
+        });
     }
 }
 
@@ -134,9 +184,13 @@ RUNNER_CHILD_TEST(security_manager_79a_same_pkg_shared_ro_have_ro_access_to_shar
         sharedApp2.createSharedRODir();
         ScopedInstaller sharedAppInstall2(sharedApp2);
 
-        runAccessTest(sharedApp2, sharedApp1.getSharedRODir(), R_OK|W_OK|X_OK);
-        runAccessTest(sharedApp1, sharedApp2.getSharedRODir(), R_OK|W_OK|X_OK);
-    };
+        runAccessTest(OWNER_UID, OWNER_GID, sharedApp1.getAppId(), [&]() {
+            accessTest(sharedApp1.getAppId(), sharedApp2.getSharedRODir(), R_OK|W_OK|X_OK);
+        });
+        runAccessTest(OWNER_UID, OWNER_GID, sharedApp2.getAppId(), [&]() {
+            accessTest(sharedApp2.getAppId(), sharedApp1.getSharedRODir(), R_OK|W_OK|X_OK);
+        });
+    }
 }
 
 /**
@@ -155,7 +209,9 @@ RUNNER_CHILD_TEST(security_manager_79b_same_pkg_shared_ro_have_ro_access_to_shar
         AppInstallHelper nonSharedApp("sm_test_79b_shared2", sharedPkgName, OWNER_UID, version);
         ScopedInstaller nonSharedAppInstall(nonSharedApp);
 
-        runAccessTest(nonSharedApp, sharedApp.getSharedRODir(), R_OK|W_OK|X_OK);
+        runAccessTest(OWNER_UID, OWNER_GID, nonSharedApp.getAppId(), [&]() {
+            accessTest(nonSharedApp.getAppId(), sharedApp.getSharedRODir(), R_OK|W_OK|X_OK);
+        });
     };
 }
 
@@ -181,14 +237,23 @@ RUNNER_CHILD_TEST(security_manager_80_same_pkg_shared_ro_have_no_access_to_share
         AppInstallHelper nonSharedApp("sm_test_80_nonshared", sharedPkgName, OWNER_UID, version);
         ScopedInstaller nonSharedAppInstall(nonSharedApp);
 
-        runAccessTest(sharedApp2, sharedApp1.getPrivateDir(1), R_OK|W_OK|X_OK);
-        runAccessTest(sharedApp1, sharedApp2.getPrivateDir(2), R_OK|W_OK|X_OK);
-        runAccessTest(nonSharedApp, sharedApp1.getPrivateDir(1), R_OK|W_OK|X_OK);
-        runAccessTest(nonSharedApp, sharedApp2.getPrivateDir(2), R_OK|W_OK|X_OK);
+        runAccessTest(OWNER_UID, OWNER_GID, sharedApp1.getAppId(), [&]() {
+            accessTest(sharedApp1.getAppId(), sharedApp2.getPrivateDir(2), R_OK|W_OK|X_OK);
+        });
+        runAccessTest(OWNER_UID, OWNER_GID, sharedApp2.getAppId(), [&]() {
+            accessTest(sharedApp2.getAppId(), sharedApp1.getPrivateDir(1), R_OK|W_OK|X_OK);
+        });
+
+        runAccessTest(OWNER_UID, OWNER_GID, nonSharedApp.getAppId(), [&]() {
+            accessTest(nonSharedApp.getAppId(), sharedApp1.getPrivateDir(1), R_OK|W_OK|X_OK);
+            accessTest(nonSharedApp.getAppId(), sharedApp2.getPrivateDir(2), R_OK|W_OK|X_OK);
+        });
 
         sharedAppInstall1.uninstallApp();
 
-        runAccessTest(nonSharedApp, sharedApp2.getPrivateDir(2), R_OK|W_OK|X_OK);
+        runAccessTest(OWNER_UID, OWNER_GID, nonSharedApp.getAppId(), [&]() {
+            accessTest(nonSharedApp.getAppId(), sharedApp2.getPrivateDir(2), R_OK|W_OK|X_OK);
+        });
     }
 }
 
@@ -218,16 +283,22 @@ RUNNER_CHILD_TEST(security_manager_81_add_path_to_app_and_check_all)
         sharedRORequest.setUid(sharedApp2.getUID());
         Api::registerPaths(sharedRORequest);
 
-        runAccessTest(sharedApp, sharedApp.getSharedRODir(), R_OK|W_OK|X_OK);
-        runAccessTest(sharedApp, sharedApp.getPrivateDir(), R_OK|W_OK|X_OK);
-
-        runAccessTest(sharedApp2, sharedApp2.getSharedRODir(), R_OK|W_OK|X_OK);
-        runAccessTest(sharedApp2, sharedApp.getSharedRODir(), R_OK|X_OK);
-        runAccessTest(sharedApp2, sharedApp.getPrivateDir(), 0);
-
-        runAccessTest(nonSharedApp, sharedApp.getSharedRODir(), R_OK|X_OK);
-        runAccessTest(nonSharedApp, sharedApp2.getSharedRODir(), R_OK|X_OK);
-        runAccessTest(nonSharedApp, sharedApp.getPrivateDir(), 0);
+        runAccessTest(OWNER_UID, OWNER_GID, sharedApp.getAppId(), [&]() {
+            accessTest(sharedApp.getAppId(), sharedApp.getSharedRODir(), R_OK|W_OK|X_OK);
+            accessTest(sharedApp.getAppId(), sharedApp.getPrivateDir(), R_OK|W_OK|X_OK);
+        });
+
+        runAccessTest(OWNER_UID, OWNER_GID, sharedApp2.getAppId(), [&]() {
+            accessTest(sharedApp2.getAppId(), sharedApp2.getSharedRODir(), R_OK|W_OK|X_OK);
+            accessTest(sharedApp2.getAppId(), sharedApp.getSharedRODir(), R_OK|X_OK);
+            accessTest(sharedApp2.getAppId(), sharedApp.getPrivateDir(), 0);
+        });
+
+        runAccessTest(OWNER_UID, OWNER_GID, nonSharedApp.getAppId(), [&]() {
+            accessTest(nonSharedApp.getAppId(), sharedApp.getSharedRODir(), R_OK|X_OK);
+            accessTest(nonSharedApp.getAppId(), sharedApp2.getSharedRODir(), R_OK|X_OK);
+            accessTest(nonSharedApp.getAppId(), sharedApp.getPrivateDir(), 0);
+        });
     }
 }
 
@@ -270,12 +341,17 @@ RUNNER_CHILD_TEST(security_manager_83_install_uninstall_shared_ro_app_and_check_
         ScopedInstaller nonSharedAppInstall(nonSharedApp);
 
         sharedAppInstall1.uninstallApp();
+        sharedApp1.removePaths();
 
-        runAccessTest(nonSharedApp, sharedApp1.getSharedRODir(), 0);
-        runAccessTest(sharedApp2, sharedApp1.getSharedRODir(), 0);
+        runAccessTest(OWNER_UID, OWNER_GID, nonSharedApp.getAppId(), [&]() {
+            accessTest(nonSharedApp.getAppId(), sharedApp1.getSharedRODir(), 0);
+            accessTest(nonSharedApp.getAppId(), sharedApp2.getSharedRODir(), R_OK|X_OK);
+        });
 
-        runAccessTest(nonSharedApp, sharedApp2.getSharedRODir(), R_OK|X_OK);
-        runAccessTest(sharedApp2, sharedApp2.getSharedRODir(), R_OK|W_OK|X_OK);
+        runAccessTest(OWNER_UID, OWNER_GID, sharedApp2.getAppId(), [&]() {
+            accessTest(sharedApp2.getAppId(), sharedApp1.getSharedRODir(), 0);
+            accessTest(sharedApp2.getAppId(), sharedApp2.getSharedRODir(), R_OK|W_OK|X_OK);
+        });
     }
 }
 
@@ -302,7 +378,12 @@ RUNNER_CHILD_TEST(security_manager_84_install_uninstall_shared_ro_two_apps_in_on
 
         sharedAppInstall1.uninstallApp();
 
-        runAccessTest(nonSharedApp, sharedApp2.getSharedRODir(2), R_OK|X_OK);
-        runAccessTest(sharedApp2, sharedApp2.getSharedRODir(2), R_OK|W_OK|X_OK);
+        runAccessTest(OWNER_UID, OWNER_GID, nonSharedApp.getAppId(), [&]() {
+            accessTest(nonSharedApp.getAppId(), sharedApp2.getSharedRODir(2), R_OK|X_OK);
+        });
+
+        runAccessTest(OWNER_UID, OWNER_GID, sharedApp2.getAppId(), [&]() {
+            accessTest(sharedApp2.getAppId(), sharedApp2.getSharedRODir(2), R_OK|W_OK|X_OK);
+        });
     }
 }
index ba37c8b..26970c0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2016-2019 Samsung Electronics Co., Ltd All Rights Reserved
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
  *    you may not use this file except in compliance with the License.
@@ -347,7 +347,7 @@ RUNNER_TEST(security_manager_66_path_req_check_labels)
     check_path(app.getPrivateDir(), generatePathRWLabel(app.getPkgId()));
     check_path(app.getPrivateRODir(), generatePathROLabel(app.getPkgId()), false);
     check_path(app.getPublicDir(), getPublicPathLabel());
-    check_path(app.getSharedRODir(), generatePathSharedROLabel(app.getPkgId()));
+    check_path(app.getSharedRODir(), getSharedROPathLabel());
 }
 
 RUNNER_TEST(security_manager_67_path_req_shared_ro_3_0)
@@ -367,7 +367,7 @@ RUNNER_TEST(security_manager_67_path_req_shared_ro_3_0)
     preq.addPath(app.getSharedRODir(), SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO);
 
     Api::registerPaths(preq);
-    check_path(app.getSharedRODir(), generatePathSharedROLabel(app.getPkgId()));
+    check_path(app.getSharedRODir(), getSharedROPathLabel());
 }
 
 RUNNER_TEST(security_manager_68_path_req_shared_ro_2_X)
@@ -387,7 +387,7 @@ RUNNER_TEST(security_manager_68_path_req_shared_ro_2_X)
     preq.addPath(app.getSharedRODir(), SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO);
 
     Api::registerPaths(preq);
-    check_path(app.getSharedRODir(), generatePathSharedROLabel(app.getPkgId()));
+    check_path(app.getSharedRODir(), getSharedROPathLabel());
 }
 
 RUNNER_TEST(security_manager_69_path_req_trusted_rw_no_author)
index 12c5f87..3584e95 100644 (file)
@@ -57,6 +57,7 @@ runTest security-manager
 runTest cynara
 runTest ckm
 runTest yaca
+runTest nether
 
 printSummary
 
index 45dd3b5..1cf60b6 100644 (file)
@@ -56,11 +56,17 @@ case $1 in
     echo
     yaca-test "${@:2}"
     ;;
+"nether")
+    echo "========================================================================="
+    echo "NETHER TESTS"
+    echo
+    nether-tests "${@:2}"
+    ;;
 *)
     echo "Correct using:"
     echo "    security_test.sh <module> <args_for_module>"
     echo
-    echo "modules: smack, security-manager, cynara, ckm, yaca"
+    echo "modules: smack, security-manager, cynara, ckm, yaca, nether"
     ;;
 
 esac
diff --git a/src/yaca/test-vectors/sign_param_comb.txt b/src/yaca/test-vectors/sign_param_comb.txt
new file mode 100644 (file)
index 0000000..3dda1bb
--- /dev/null
@@ -0,0 +1,415 @@
+# YACA_KEY_LENGTH_EC_PRIME192V1 - 805306560
+# YACA_KEY_LENGTH_EC_PRIME256V1 - 805306624
+# YACA_KEY_LENGTH_EC_SECP256K1  - 824180992
+# YACA_KEY_LENGTH_EC_SECP384R1  - 823132544
+# YACA_KEY_LENGTH_EC_SECP521R1  - 823132681
+
+key_type=EC_PRIV
+key_len_bits=805306560
+padding=
+algo=SHA1
+
+key_type=EC_PRIV
+key_len_bits=805306560
+padding=
+algo=SHA224
+
+key_type=EC_PRIV
+key_len_bits=805306560
+padding=
+algo=SHA256
+
+key_type=EC_PRIV
+key_len_bits=805306560
+padding=
+algo=SHA384
+
+key_type=EC_PRIV
+key_len_bits=805306560
+padding=
+algo=SHA512
+
+key_type=EC_PRIV
+key_len_bits=805306624
+padding=
+algo=SHA1
+
+key_type=EC_PRIV
+key_len_bits=805306624
+padding=
+algo=SHA224
+
+key_type=EC_PRIV
+key_len_bits=805306624
+padding=
+algo=SHA256
+
+key_type=EC_PRIV
+key_len_bits=805306624
+padding=
+algo=SHA384
+
+key_type=EC_PRIV
+key_len_bits=805306624
+padding=
+algo=SHA512
+
+key_type=EC_PRIV
+key_len_bits=824180992
+padding=
+algo=SHA1
+
+key_type=EC_PRIV
+key_len_bits=824180992
+padding=
+algo=SHA224
+
+key_type=EC_PRIV
+key_len_bits=824180992
+padding=
+algo=SHA256
+
+key_type=EC_PRIV
+key_len_bits=824180992
+padding=
+algo=SHA384
+
+key_type=EC_PRIV
+key_len_bits=824180992
+padding=
+algo=SHA512
+
+key_type=EC_PRIV
+key_len_bits=823132544
+padding=
+algo=SHA1
+
+key_type=EC_PRIV
+key_len_bits=823132544
+padding=
+algo=SHA224
+
+key_type=EC_PRIV
+key_len_bits=823132544
+padding=
+algo=SHA256
+
+key_type=EC_PRIV
+key_len_bits=823132544
+padding=
+algo=SHA384
+
+key_type=EC_PRIV
+key_len_bits=823132544
+padding=
+algo=SHA512
+
+key_type=EC_PRIV
+key_len_bits=823132681
+padding=
+algo=SHA1
+
+key_type=EC_PRIV
+key_len_bits=823132681
+padding=
+algo=SHA224
+
+key_type=EC_PRIV
+key_len_bits=823132681
+padding=
+algo=SHA256
+
+key_type=EC_PRIV
+key_len_bits=823132681
+padding=
+algo=SHA384
+
+key_type=EC_PRIV
+key_len_bits=823132681
+padding=
+algo=SHA512
+
+key_type=DSA_PRIV
+key_len_bits=512
+padding=
+algo=SHA1
+
+key_type=DSA_PRIV
+key_len_bits=512
+padding=
+algo=SHA224
+
+key_type=DSA_PRIV
+key_len_bits=512
+padding=
+algo=SHA256
+
+key_type=DSA_PRIV
+key_len_bits=512
+padding=
+algo=SHA384
+
+key_type=DSA_PRIV
+key_len_bits=512
+padding=
+algo=SHA512
+
+key_type=DSA_PRIV
+key_len_bits=1024
+padding=
+algo=SHA1
+
+key_type=DSA_PRIV
+key_len_bits=1024
+padding=
+algo=SHA224
+
+key_type=DSA_PRIV
+key_len_bits=1024
+padding=
+algo=SHA256
+
+key_type=DSA_PRIV
+key_len_bits=1024
+padding=
+algo=SHA384
+
+key_type=DSA_PRIV
+key_len_bits=1024
+padding=
+algo=SHA512
+
+key_type=DSA_PRIV
+key_len_bits=2048
+padding=
+algo=SHA1
+
+key_type=DSA_PRIV
+key_len_bits=2048
+padding=
+algo=SHA224
+
+key_type=DSA_PRIV
+key_len_bits=2048
+padding=
+algo=SHA256
+
+key_type=DSA_PRIV
+key_len_bits=2048
+padding=
+algo=SHA384
+
+key_type=DSA_PRIV
+key_len_bits=2048
+padding=
+algo=SHA512
+
+key_type=RSA_PRIV
+key_len_bits=512
+padding=PKCS1
+algo=MD5
+
+key_type=RSA_PRIV
+key_len_bits=512
+padding=PKCS1
+algo=SHA1
+
+key_type=RSA_PRIV
+key_len_bits=512
+padding=PKCS1
+algo=SHA224
+
+key_type=RSA_PRIV
+key_len_bits=512
+padding=PKCS1
+algo=SHA256
+
+key_type=RSA_PRIV
+key_len_bits=512
+padding=PKCS1_PSS
+algo=MD5
+
+key_type=RSA_PRIV
+key_len_bits=512
+padding=PKCS1_PSS
+algo=SHA1
+
+key_type=RSA_PRIV
+key_len_bits=512
+padding=PKCS1_PSS
+algo=SHA224
+
+key_type=RSA_PRIV
+key_len_bits=512
+padding=PKCS1_PSS
+algo=SHA256
+
+key_type=RSA_PRIV
+key_len_bits=512
+padding=X931
+algo=SHA1
+
+key_type=RSA_PRIV
+key_len_bits=512
+padding=X931
+algo=SHA256
+
+key_type=RSA_PRIV
+key_len_bits=1024
+padding=PKCS1
+algo=MD5
+
+key_type=RSA_PRIV
+key_len_bits=1024
+padding=PKCS1
+algo=SHA1
+
+key_type=RSA_PRIV
+key_len_bits=1024
+padding=PKCS1
+algo=SHA224
+
+key_type=RSA_PRIV
+key_len_bits=1024
+padding=PKCS1
+algo=SHA256
+
+key_type=RSA_PRIV
+key_len_bits=1024
+padding=PKCS1
+algo=SHA384
+
+key_type=RSA_PRIV
+key_len_bits=1024
+padding=PKCS1
+algo=SHA512
+
+key_type=RSA_PRIV
+key_len_bits=1024
+padding=PKCS1_PSS
+algo=MD5
+
+key_type=RSA_PRIV
+key_len_bits=1024
+padding=PKCS1_PSS
+algo=SHA1
+
+key_type=RSA_PRIV
+key_len_bits=1024
+padding=PKCS1_PSS
+algo=SHA224
+
+key_type=RSA_PRIV
+key_len_bits=1024
+padding=PKCS1_PSS
+algo=SHA256
+
+key_type=RSA_PRIV
+key_len_bits=1024
+padding=PKCS1_PSS
+algo=SHA384
+
+key_type=RSA_PRIV
+key_len_bits=1024
+padding=PKCS1_PSS
+algo=SHA512
+
+key_type=RSA_PRIV
+key_len_bits=1024
+padding=X931
+algo=SHA1
+
+key_type=RSA_PRIV
+key_len_bits=1024
+padding=X931
+algo=SHA256
+
+key_type=RSA_PRIV
+key_len_bits=1024
+padding=X931
+algo=SHA384
+
+key_type=RSA_PRIV
+key_len_bits=1024
+padding=X931
+algo=SHA512
+
+key_type=RSA_PRIV
+key_len_bits=2048
+padding=PKCS1
+algo=MD5
+
+key_type=RSA_PRIV
+key_len_bits=2048
+padding=PKCS1
+algo=SHA1
+
+key_type=RSA_PRIV
+key_len_bits=2048
+padding=PKCS1
+algo=SHA224
+
+key_type=RSA_PRIV
+key_len_bits=2048
+padding=PKCS1
+algo=SHA256
+
+key_type=RSA_PRIV
+key_len_bits=2048
+padding=PKCS1
+algo=SHA384
+
+key_type=RSA_PRIV
+key_len_bits=2048
+padding=PKCS1
+algo=SHA512
+
+key_type=RSA_PRIV
+key_len_bits=2048
+padding=PKCS1_PSS
+algo=MD5
+
+key_type=RSA_PRIV
+key_len_bits=2048
+padding=PKCS1_PSS
+algo=SHA1
+
+key_type=RSA_PRIV
+key_len_bits=2048
+padding=PKCS1_PSS
+algo=SHA224
+
+key_type=RSA_PRIV
+key_len_bits=2048
+padding=PKCS1_PSS
+algo=SHA256
+
+key_type=RSA_PRIV
+key_len_bits=2048
+padding=PKCS1_PSS
+algo=SHA384
+
+key_type=RSA_PRIV
+key_len_bits=2048
+padding=PKCS1_PSS
+algo=SHA512
+
+key_type=RSA_PRIV
+key_len_bits=2048
+padding=X931
+algo=SHA1
+
+key_type=RSA_PRIV
+key_len_bits=2048
+padding=X931
+algo=SHA256
+
+key_type=RSA_PRIV
+key_len_bits=2048
+padding=X931
+algo=SHA384
+
+key_type=RSA_PRIV
+key_len_bits=2048
+padding=X931
+algo=SHA512
index 0e28fc0..f472dd6 100644 (file)
@@ -149,6 +149,18 @@ RUNNER_TEST(T2040_yaca_digest_get_output_length_invalid_param, YacaTest)
     YACA_INVALID_PARAM(yaca_context_get_output_length(ctx_ptr.get(), 42, &out_len));
 }
 
+RUNNER_TEST(T2045_yaca_digest_call_order_invalid_param)
+{
+    char output[512];
+    size_t out_len;
+    CtxPtr ctx = digest_init(YACA_DIGEST_SHA512);
+
+    YACA_SUCCESS(yaca_digest_update(ctx.get(), DATA.data(), DATA.size()));
+    YACA_SUCCESS(yaca_digest_finalize(ctx.get(), output, &out_len));
+
+    YACA_INVALID_PARAM(yaca_digest_update(ctx.get(), DATA.data(), DATA.size()));
+}
+
 RUNNER_TEST(T2050_yaca_digest_get_output_length, YacaTest)
 {
     digest_length_test(YACA_DIGEST_MD5,    128);
index d27cc5e..9ab048f 100644 (file)
@@ -90,17 +90,17 @@ public:
     void set_padding(yaca_padding_e padding)
     {
         YACA_SUCCESS(yaca_context_set_property(m_enCtxPtr.get(), YACA_PROPERTY_PADDING,
-                                               (char*)(&padding), sizeof(padding)));
+                                               (void*)(&padding), sizeof(padding)));
         YACA_SUCCESS(yaca_context_set_property(m_decCtxPtr.get(), YACA_PROPERTY_PADDING,
-                                               (char*)(&padding), sizeof(padding)));
+                                               (void*)(&padding), sizeof(padding)));
     }
 
     void set_effective_key_bits(size_t key_bits)
     {
         YACA_SUCCESS(yaca_context_set_property(m_enCtxPtr.get(), YACA_PROPERTY_RC2_EFFECTIVE_KEY_BITS,
-                                               (char*)(&key_bits), sizeof(key_bits)));
+                                               (void*)(&key_bits), sizeof(key_bits)));
         YACA_SUCCESS(yaca_context_set_property(m_decCtxPtr.get(), YACA_PROPERTY_RC2_EFFECTIVE_KEY_BITS,
-                                               (char*)(&key_bits), sizeof(key_bits)));
+                                               (void*)(&key_bits), sizeof(key_bits)));
     }
 
     int set_tag_len(yaca_block_cipher_mode_e bcm, size_t tag_len)
@@ -367,7 +367,7 @@ void aes_gcm_test_output(const Buffer &input,
                                   : null_key();
 
     size_t tag_len = tag.size();
-    auto tag_output = create_yaca_buffer(tag_len);
+    char *tag_output;
 
     // encryption
     Buffer encrypt_output;
@@ -393,12 +393,13 @@ void aes_gcm_test_output(const Buffer &input,
     YACA_SUCCESS(yaca_context_set_property(enc_ctx_ptr.get(), YACA_PROPERTY_GCM_TAG_LEN,
                                            (void*)&tag_len, sizeof(tag_len)));
     YACA_SUCCESS(yaca_context_get_property(enc_ctx_ptr.get(), YACA_PROPERTY_GCM_TAG,
-                                           (void**)tag_output.get(), &tag_len));
+                                           (void**)&tag_output, &tag_len));
+    ChrPtr tag_ptr = wrap_ptr(tag_output);
 
     YACA_ASSERT_MSG(output.size() == encrypt_output.size(), "Ciphertext size after encrypt differs\n");
     YACA_ASSERT_MSG(output == encrypt_output, "Ciphertext after encrypt differs\n");
     YACA_ASSERT_MSG(tag.size() == tag_len, "Tag size after encrypt differs\n");
-    YACA_ASSERT_MSG(yaca_memcmp(tag.data(), tag_output.get(), tag_len) == YACA_ERROR_NONE,
+    YACA_ASSERT_MSG(yaca_memcmp(tag.data(), tag_output, tag_len) == YACA_ERROR_NONE,
                     "Tag after encrypt differs\n");
 
     // decryption
@@ -440,7 +441,7 @@ void aes_ccm_test_output(const Buffer &input,
                                   : null_key();
 
     size_t tag_len = tag.size();
-    auto tag_output = create_yaca_buffer(tag_len);
+    char *tag_output;
 
     // encryption
     Buffer encrypt_output;
@@ -469,12 +470,13 @@ void aes_ccm_test_output(const Buffer &input,
     encrypt_output.insert(encrypt_output.end(), final_ptr.get(), final_ptr.get() + final_len);
 
     YACA_SUCCESS(yaca_context_get_property(enc_ctx_ptr.get(), YACA_PROPERTY_CCM_TAG,
-                                           (void**)tag_output.get(), &tag_len));
+                                           (void**)&tag_output, &tag_len));
+    ChrPtr tag_ptr = wrap_ptr(tag_output);
 
     YACA_ASSERT_MSG(output.size() == encrypt_output.size(), "Ciphertext size after encrypt differs \n");
     YACA_ASSERT_MSG(output == encrypt_output, "ciphertext after encrypt differs\n");
     YACA_ASSERT_MSG(tag.size() == tag_len, "Tag size after encrypt differs\n");
-    YACA_ASSERT_MSG(yaca_memcmp(tag.data(), tag_output.get(), tag_len) == YACA_ERROR_NONE,
+    YACA_ASSERT_MSG(yaca_memcmp(tag.data(), tag_output, tag_len) == YACA_ERROR_NONE,
                     "Tag after encrypt differs\n");
 
     // decryption
@@ -747,6 +749,22 @@ RUNNER_TEST(T3075_yaca_key_wrap_unwrap_invalid_param, YacaTest)
                                            unwrapped.get(), &unwrapped_len));
 }
 
+RUNNER_TEST(T3077_yaca_get_iv_bit_length, YacaTest)
+{
+    size_t iv_bit_len;
+    YACA_SUCCESS(yaca_encrypt_get_iv_bit_length(YACA_ENCRYPT_AES, YACA_BCM_CBC, YACA_KEY_LENGTH_256BIT,
+                                                &iv_bit_len));
+    YACA_ASSERT_MSG(iv_bit_len == YACA_KEY_LENGTH_IV_128BIT, "Invalid IV bit length.");
+
+    YACA_SUCCESS(yaca_encrypt_get_iv_bit_length(YACA_ENCRYPT_AES, YACA_BCM_ECB, YACA_KEY_LENGTH_256BIT,
+                                                &iv_bit_len));
+    YACA_ASSERT_MSG(iv_bit_len == 0, "Invalid IV bit length.");
+
+    YACA_SUCCESS(yaca_encrypt_get_iv_bit_length(YACA_ENCRYPT_3DES_3TDEA, YACA_BCM_CBC, YACA_KEY_LENGTH_192BIT,
+                                                &iv_bit_len));
+    YACA_ASSERT_MSG(iv_bit_len == YACA_KEY_LENGTH_IV_64BIT, "Invalid IV bit length.");
+}
+
 RUNNER_TEST(T3080_yaca_encrypt_decrypt_init_param_comb, YacaTest)
 {
     auto tvv = loadTestVector("encrypt_param_comb.txt");
@@ -786,7 +804,7 @@ RUNNER_TEST(T3110_yaca_aes_gcm_call_order_invalid_param, YacaTest)
 {
     KeyIvPair key_iv_pair;
     size_t tag_len = 14;
-    auto tag = create_yaca_buffer(tag_len);
+    char *tag;
     auto aad = random_buffer(16);
     Buffer encrypt_output;
     Buffer decrypt_output;
@@ -800,9 +818,9 @@ RUNNER_TEST(T3110_yaca_aes_gcm_call_order_invalid_param, YacaTest)
     auto final_ptr = out_buf_alloc(enc_ctx_ptr, 0, final_len);
 
     YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx_ptr.get(), YACA_PROPERTY_GCM_TAG,
-                                                 tag.get(), tag_len));
+                                                 tag, tag_len));
     YACA_INVALID_PARAM(yaca_context_get_property(enc_ctx_ptr.get(), YACA_PROPERTY_GCM_TAG,
-                                                 (void**)tag.get(), &tag_len));
+                                                 (void**)&tag, &tag_len));
     YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx_ptr.get(), YACA_PROPERTY_GCM_TAG_LEN,
                                                  (void*)&tag_len, sizeof(tag_len)));
 
@@ -816,9 +834,9 @@ RUNNER_TEST(T3110_yaca_aes_gcm_call_order_invalid_param, YacaTest)
     YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx_ptr.get(), YACA_PROPERTY_GCM_AAD,
                                                  aad.data(), aad.size()));
     YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx_ptr.get(), YACA_PROPERTY_GCM_TAG,
-                                                 tag.get(), tag_len));
+                                                 tag, tag_len));
     YACA_INVALID_PARAM(yaca_context_get_property(enc_ctx_ptr.get(), YACA_PROPERTY_GCM_TAG,
-                                                 (void**)tag.get(), &tag_len));
+                                                 (void**)&tag, &tag_len));
     YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx_ptr.get(), YACA_PROPERTY_GCM_TAG_LEN,
                                                  (void*)&tag_len, sizeof(tag_len)));
 
@@ -828,11 +846,13 @@ RUNNER_TEST(T3110_yaca_aes_gcm_call_order_invalid_param, YacaTest)
     YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx_ptr.get(), YACA_PROPERTY_GCM_AAD,
                                                  aad.data(), aad.size()));
     YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx_ptr.get(), YACA_PROPERTY_GCM_TAG,
-                                                 tag.get(), tag_len));
+                                                 tag, tag_len));
     YACA_SUCCESS(yaca_context_set_property(enc_ctx_ptr.get(), YACA_PROPERTY_GCM_TAG_LEN,
                                            (void*)&tag_len, sizeof(tag_len)));
     YACA_SUCCESS(yaca_context_get_property(enc_ctx_ptr.get(), YACA_PROPERTY_GCM_TAG,
-                                           (void**)tag.get(), &tag_len));
+                                           (void**)&tag, &tag_len));
+    ChrPtr tag_ptr = wrap_ptr(tag);
+
     YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx_ptr.get(), YACA_PROPERTY_GCM_TAG_LEN,
                                                  (void*)&tag_len, sizeof(tag_len)));
 
@@ -843,7 +863,7 @@ RUNNER_TEST(T3110_yaca_aes_gcm_call_order_invalid_param, YacaTest)
     final_ptr = out_buf_alloc(dec_ctx_ptr, 0, final_len);
 
     YACA_INVALID_PARAM(yaca_context_get_property(dec_ctx_ptr.get(), YACA_PROPERTY_GCM_TAG,
-                                                 (void**)tag.get(), &tag_len));
+                                                 (void**)&tag, &tag_len));
     YACA_INVALID_PARAM(yaca_context_set_property(dec_ctx_ptr.get(), YACA_PROPERTY_GCM_TAG_LEN,
                                                  (void*)&tag_len, sizeof(tag_len)));
 
@@ -859,12 +879,11 @@ RUNNER_TEST(T3110_yaca_aes_gcm_call_order_invalid_param, YacaTest)
     YACA_INVALID_PARAM(yaca_context_set_property(dec_ctx_ptr.get(), YACA_PROPERTY_GCM_TAG_LEN,
                                                  (void*)&tag_len, sizeof(tag_len)));
     YACA_INVALID_PARAM(yaca_context_get_property(dec_ctx_ptr.get(), YACA_PROPERTY_GCM_TAG,
-                                                 (void**)tag.get(), &tag_len));
+                                                 (void**)&tag, &tag_len));
     YACA_INVALID_PARAM(yaca_context_set_property(dec_ctx_ptr.get(), YACA_PROPERTY_GCM_TAG,
-                                                 tag.get(), tag_len + 42));
+                                                 tag, tag_len + 42));
 
-    YACA_SUCCESS(yaca_context_set_property(dec_ctx_ptr.get(), YACA_PROPERTY_GCM_TAG,
-                                           tag.get(), tag_len));
+    YACA_SUCCESS(yaca_context_set_property(dec_ctx_ptr.get(), YACA_PROPERTY_GCM_TAG, tag, tag_len));
 
     YACA_SUCCESS(yaca_decrypt_finalize(dec_ctx_ptr.get(), final_ptr.get(), &final_len));
     decrypt_output.insert(decrypt_output.end(), final_ptr.get(), final_ptr.get() + final_len);
@@ -872,11 +891,11 @@ RUNNER_TEST(T3110_yaca_aes_gcm_call_order_invalid_param, YacaTest)
     YACA_INVALID_PARAM(yaca_context_set_property(dec_ctx_ptr.get(), YACA_PROPERTY_GCM_AAD,
                                                  aad.data(), aad.size()));
     YACA_INVALID_PARAM(yaca_context_set_property(dec_ctx_ptr.get(), YACA_PROPERTY_GCM_TAG,
-                                                 tag.get(), tag_len));
+                                                 tag, tag_len));
     YACA_INVALID_PARAM(yaca_context_set_property(dec_ctx_ptr.get(), YACA_PROPERTY_GCM_TAG_LEN,
                                                  (void*)&tag_len, sizeof(tag_len)));
     YACA_INVALID_PARAM(yaca_context_get_property(dec_ctx_ptr.get(), YACA_PROPERTY_GCM_TAG,
-                                                 (void**)tag.get(), &tag_len));
+                                                 (void**)&tag, &tag_len));
 
     YACA_ASSERT_MSG(DATA.size() == decrypt_output.size(), "Size after encrypt-decrypt differs\n");
     YACA_ASSERT_MSG(DATA == decrypt_output, "Text after encrypt-decrypt has changed\n");
@@ -887,7 +906,7 @@ RUNNER_TEST(T3120_yaca_aes_ccm_call_order_invalid_param, YacaTest)
     KeyPtr key = generate_key(YACA_KEY_TYPE_SYMMETRIC, YACA_KEY_LENGTH_256BIT);
     KeyPtr iv = generate_key(YACA_KEY_TYPE_IV, YACA_KEY_LENGTH_IV_64BIT);
     size_t tag_len = 16;
-    auto tag = create_yaca_buffer(tag_len);
+    char *tag;
     auto aad = random_buffer(16);
     Buffer encrypt_output;
     Buffer decrypt_output;
@@ -900,9 +919,9 @@ RUNNER_TEST(T3120_yaca_aes_ccm_call_order_invalid_param, YacaTest)
     auto final_ptr = out_buf_alloc(enc_ctx_ptr, 0, final_len);
 
     YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx_ptr.get(), YACA_PROPERTY_CCM_TAG,
-                                                 tag.get(), tag_len));
+                                                 tag, tag_len));
     YACA_INVALID_PARAM(yaca_context_get_property(enc_ctx_ptr.get(), YACA_PROPERTY_CCM_TAG,
-                                                 (void**)tag.get(), &tag_len));
+                                                 (void**)&tag, &tag_len));
     YACA_SUCCESS(yaca_context_set_property(enc_ctx_ptr.get(), YACA_PROPERTY_CCM_TAG_LEN,
                                            (void*)&tag_len, sizeof(tag_len)));
 
@@ -919,11 +938,11 @@ RUNNER_TEST(T3120_yaca_aes_ccm_call_order_invalid_param, YacaTest)
     YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx_ptr.get(), YACA_PROPERTY_CCM_AAD,
                                                  aad.data(), aad.size()));
     YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx_ptr.get(), YACA_PROPERTY_CCM_TAG,
-                                                 tag.get(), tag_len));
+                                                 tag, tag_len));
     YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx_ptr.get(), YACA_PROPERTY_CCM_TAG_LEN,
                                                  (void*)&tag_len, sizeof(tag_len)));
     YACA_INVALID_PARAM(yaca_context_get_property(enc_ctx_ptr.get(), YACA_PROPERTY_CCM_TAG,
-                                                 (void**)tag.get(), &tag_len));
+                                                 (void**)&tag, &tag_len));
 
     YACA_SUCCESS(yaca_encrypt_finalize(enc_ctx_ptr.get(), final_ptr.get(), &final_len));
     encrypt_output.insert(encrypt_output.end(), final_ptr.get(), final_ptr.get() + final_len);
@@ -931,11 +950,12 @@ RUNNER_TEST(T3120_yaca_aes_ccm_call_order_invalid_param, YacaTest)
     YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx_ptr.get(), YACA_PROPERTY_CCM_AAD,
                                                  aad.data(), aad.size()));
     YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx_ptr.get(), YACA_PROPERTY_CCM_TAG,
-                                                 tag.get(), tag_len));
+                                                 tag, tag_len));
     YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx_ptr.get(), YACA_PROPERTY_CCM_TAG_LEN,
                                                  (void*)&tag_len, sizeof(tag_len)));
     YACA_SUCCESS(yaca_context_get_property(enc_ctx_ptr.get(), YACA_PROPERTY_CCM_TAG,
-                                           (void**)tag.get(), &tag_len));
+                                           (void**)&tag, &tag_len));
+    ChrPtr tag_ptr = wrap_ptr(tag);
 
     // decryption
     auto dec_ctx_ptr = decrypt_init(YACA_ENCRYPT_AES, YACA_BCM_CCM, key, iv);
@@ -945,19 +965,18 @@ RUNNER_TEST(T3120_yaca_aes_ccm_call_order_invalid_param, YacaTest)
     YACA_INVALID_PARAM(yaca_context_set_property(dec_ctx_ptr.get(), YACA_PROPERTY_CCM_TAG_LEN,
                                                  (void*)&tag_len, sizeof(tag_len)));
     YACA_INVALID_PARAM(yaca_context_get_property(dec_ctx_ptr.get(), YACA_PROPERTY_CCM_TAG,
-                                                 (void**)tag.get(), &tag_len));
+                                                 (void**)&tag, &tag_len));
     YACA_INVALID_PARAM(yaca_context_set_property(dec_ctx_ptr.get(), YACA_PROPERTY_CCM_TAG,
-                                                 tag.get(), tag_len + 42));
+                                                 tag, tag_len + 42));
 
-    YACA_SUCCESS(yaca_context_set_property(dec_ctx_ptr.get(), YACA_PROPERTY_CCM_TAG,
-                                           tag.get(), tag_len));
+    YACA_SUCCESS(yaca_context_set_property(dec_ctx_ptr.get(), YACA_PROPERTY_CCM_TAG, tag, tag_len));
 
     YACA_SUCCESS(yaca_decrypt_update(dec_ctx_ptr.get(), NULL, encrypt_output.size(),
                                      NULL, &update_len));
     YACA_SUCCESS(yaca_context_set_property(dec_ctx_ptr.get(), YACA_PROPERTY_CCM_AAD,
                                            aad.data(), aad.size()));
     YACA_INVALID_PARAM(yaca_context_set_property(dec_ctx_ptr.get(), YACA_PROPERTY_CCM_TAG,
-                                                 tag.get(), tag_len));
+                                                 tag, tag_len));
 
     YACA_SUCCESS(yaca_decrypt_update(dec_ctx_ptr.get(), encrypt_output.data(), encrypt_output.size(),
                                      update_ptr.get(), &update_len));
@@ -966,11 +985,11 @@ RUNNER_TEST(T3120_yaca_aes_ccm_call_order_invalid_param, YacaTest)
     YACA_INVALID_PARAM(yaca_context_set_property(dec_ctx_ptr.get(), YACA_PROPERTY_CCM_AAD,
                                                  aad.data(), aad.size()));
     YACA_INVALID_PARAM(yaca_context_set_property(dec_ctx_ptr.get(), YACA_PROPERTY_CCM_TAG,
-                                                 tag.get(), tag_len));
+                                                 tag, tag_len));
     YACA_INVALID_PARAM(yaca_context_set_property(dec_ctx_ptr.get(), YACA_PROPERTY_CCM_TAG_LEN,
                                                  (void*)&tag_len, sizeof(tag_len)));
     YACA_INVALID_PARAM(yaca_context_get_property(dec_ctx_ptr.get(), YACA_PROPERTY_CCM_TAG,
-                                                 (void**)tag.get(), &tag_len));
+                                                 (void**)&tag, &tag_len));
 
     YACA_SUCCESS(yaca_decrypt_finalize(dec_ctx_ptr.get(), final_ptr.get(), &final_len));
     decrypt_output.insert(decrypt_output.end(), final_ptr.get(), final_ptr.get() + final_len);
@@ -978,11 +997,11 @@ RUNNER_TEST(T3120_yaca_aes_ccm_call_order_invalid_param, YacaTest)
     YACA_INVALID_PARAM(yaca_context_set_property(dec_ctx_ptr.get(), YACA_PROPERTY_CCM_AAD,
                                                  aad.data(), aad.size()));
     YACA_INVALID_PARAM(yaca_context_set_property(dec_ctx_ptr.get(), YACA_PROPERTY_CCM_TAG,
-                                                 tag.get(), tag_len));
+                                                 tag, tag_len));
     YACA_INVALID_PARAM(yaca_context_set_property(dec_ctx_ptr.get(), YACA_PROPERTY_CCM_TAG_LEN,
                                                  (void*)&tag_len, sizeof(tag_len)));
     YACA_INVALID_PARAM(yaca_context_get_property(dec_ctx_ptr.get(), YACA_PROPERTY_CCM_TAG,
-                                                 (void**)tag.get(), &tag_len));
+                                                 (void**)&tag, &tag_len));
 
     YACA_ASSERT_MSG(DATA.size() == decrypt_output.size(), "Size after encrypt-decrypt differs\n");
     YACA_ASSERT_MSG(DATA == decrypt_output, "Text after encrypt-decrypt has changed\n");
@@ -1053,3 +1072,422 @@ RUNNER_TEST(T3150_yaca_aes_gcm_ccm_output_comparison, YacaTest)
                             : aes_ccm_test_output(input, algo, bcm, key, iv, aad, tag, output);
     }
 }
+
+RUNNER_TEST(T3160_yaca_set_get_padding_invalid_param, YacaTest)
+{
+    KeyIvPair key_iv_pair;
+    CtxPtr enc_ctx = encrypt_init(YACA_ENCRYPT_AES, YACA_BCM_CBC,
+                                  key_iv_pair.key, key_iv_pair.iv);
+
+    yaca_padding_e padding = YACA_PADDING_NONE;
+    size_t padding_len;
+
+    YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx.get(), static_cast<yaca_property_e>(-1),
+                                                 (void*)(&padding), sizeof(padding)));
+    YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx.get(), YACA_PROPERTY_PADDING,
+                                                 nullptr, sizeof(padding)));
+    YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx.get(), YACA_PROPERTY_PADDING,
+                                                 (void*)(&padding), 0));
+    YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx.get(), YACA_PROPERTY_PADDING,
+                                                 (void*)(&padding), sizeof(char)));
+
+    YACA_INVALID_PARAM(yaca_context_get_property(enc_ctx.get(), YACA_PROPERTY_PADDING,
+                                                 (void**)(&padding), &padding_len));
+
+    size_t output_len = get_output_length(enc_ctx);
+    Buffer output(output_len);
+    YACA_SUCCESS(yaca_encrypt_finalize(enc_ctx.get(), output.data(), &output_len));
+    YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx.get(), YACA_PROPERTY_PADDING,
+                                                 (void*)(&padding), sizeof(padding)));
+
+    std::vector<yaca_block_cipher_mode_e> bcms = {YACA_BCM_OFB, YACA_BCM_CFB, YACA_BCM_GCM,
+                                                  YACA_BCM_CTR, YACA_BCM_CBC};
+    std::vector<yaca_padding_e> paddings = {YACA_PADDING_PKCS1, YACA_PADDING_PKCS1_PSS,
+                                            YACA_PADDING_X931, YACA_PADDING_PKCS1_SSLV23,
+                                            YACA_PADDING_PKCS1_OAEP};
+
+    for (yaca_block_cipher_mode_e bcm : bcms) {
+        enc_ctx = encrypt_init(YACA_ENCRYPT_AES, bcm, key_iv_pair.key, key_iv_pair.iv);
+
+        for (yaca_padding_e padding : paddings) {
+            YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx.get(), YACA_PROPERTY_PADDING,
+                                                         (void*)(&padding), sizeof(padding)));
+        }
+    }
+}
+
+RUNNER_TEST(T3170_yaca_set_get_rc2_key_bits_invalid_param, YacaTest)
+{
+    size_t effective_key_bits;
+    size_t effective_key_bits_len;
+    KeyPtr key = generate_key(YACA_KEY_TYPE_SYMMETRIC, YACA_KEY_LENGTH_UNSAFE_128BIT);
+    CtxPtr enc_ctx = encrypt_init(YACA_ENCRYPT_UNSAFE_RC2, YACA_BCM_ECB, key, null_key());
+
+    effective_key_bits = 0;
+    YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx.get(),
+                                                 YACA_PROPERTY_RC2_EFFECTIVE_KEY_BITS,
+                                                 (void*)(&effective_key_bits),
+                                                 sizeof(effective_key_bits)));
+    effective_key_bits = 1025;
+    YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx.get(),
+                                                 YACA_PROPERTY_RC2_EFFECTIVE_KEY_BITS,
+                                                 (void*)(&effective_key_bits),
+                                                 sizeof(effective_key_bits)));
+
+    effective_key_bits = 128;
+    YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx.get(),
+                                                 YACA_PROPERTY_RC2_EFFECTIVE_KEY_BITS,
+                                                 (void*)(&effective_key_bits), sizeof(char)));
+
+    YACA_INVALID_PARAM(yaca_context_get_property(enc_ctx.get(),
+                                                 YACA_PROPERTY_RC2_EFFECTIVE_KEY_BITS,
+                                                 (void**)(&effective_key_bits),
+                                                 &effective_key_bits_len));
+
+    size_t output_len = get_output_length(enc_ctx, DATA.size());
+    Buffer output(output_len);
+    YACA_SUCCESS(yaca_encrypt_update(enc_ctx.get(), DATA.data(), DATA.size(),
+                                     output.data(), &output_len));
+    YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx.get(),
+                                                 YACA_PROPERTY_RC2_EFFECTIVE_KEY_BITS,
+                                                 (void*)(&effective_key_bits),
+                                                 sizeof(effective_key_bits)));
+
+    std::vector<yaca_encrypt_algorithm_e> algos = {YACA_ENCRYPT_AES, YACA_ENCRYPT_UNSAFE_3DES_2TDEA,
+                                                   YACA_ENCRYPT_CAST5};
+
+    for (yaca_encrypt_algorithm_e algo : algos) {
+        enc_ctx = encrypt_init(algo, YACA_BCM_ECB, key, null_key());
+
+        YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx.get(),
+                                                     YACA_PROPERTY_RC2_EFFECTIVE_KEY_BITS,
+                                                     (void*)(&effective_key_bits),
+                                                     sizeof(effective_key_bits)));
+    }
+}
+
+RUNNER_TEST(T3180_yaca_set_get_gcm_properties_invalid_param, YacaTest)
+{
+    KeyPtr key = generate_key(YACA_KEY_TYPE_SYMMETRIC, YACA_KEY_LENGTH_192BIT);
+    KeyPtr iv = generate_key(YACA_KEY_TYPE_IV, YACA_KEY_LENGTH_IV_128BIT);
+    KeyPtr gcm_iv = generate_key(YACA_KEY_TYPE_IV, YACA_KEY_LENGTH_IV_64BIT);
+
+    size_t aad_len = 16;
+    Buffer aad = random_buffer(aad_len);
+    size_t tag_len = 16;
+    char *tag;
+
+    size_t update_len, final_len;
+
+    // CTR
+    CtxPtr enc_ctx = encrypt_init(YACA_ENCRYPT_AES, YACA_BCM_CTR, key, iv);
+    YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx.get(), YACA_PROPERTY_GCM_AAD,
+                                                 aad.data(), aad.size()));
+
+    Buffer encrypt_output;
+    ChrPtr update = out_buf_alloc(enc_ctx, DATA.size(), update_len);
+    ChrPtr final = out_buf_alloc(enc_ctx, 0, final_len);
+    YACA_SUCCESS(yaca_encrypt_update(enc_ctx.get(), DATA.data(), DATA.size(),
+                                     update.get(), &update_len));
+    YACA_SUCCESS(yaca_encrypt_finalize(enc_ctx.get(), final.get(), &final_len));
+    encrypt_output.insert(encrypt_output.end(), update.get(), update.get() + update_len);
+    encrypt_output.insert(encrypt_output.end(), final.get(), final.get() + final_len);
+
+    YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx.get(), YACA_PROPERTY_GCM_TAG_LEN,
+                                                 (void*)(&tag_len), sizeof(tag_len)));
+    YACA_INVALID_PARAM(yaca_context_get_property(enc_ctx.get(), YACA_PROPERTY_GCM_TAG,
+                                                 (void**)&tag, &tag_len));
+
+    CtxPtr dec_ctx = decrypt_init(YACA_ENCRYPT_AES, YACA_BCM_CTR, key, iv);
+    YACA_INVALID_PARAM(yaca_context_set_property(dec_ctx.get(), YACA_PROPERTY_GCM_AAD,
+                                                 aad.data(), aad.size()));
+
+    update = out_buf_alloc(dec_ctx, encrypt_output.size(), update_len);
+    final = out_buf_alloc(dec_ctx, 0, final_len);
+
+    YACA_SUCCESS(yaca_decrypt_update(dec_ctx.get(), encrypt_output.data(), encrypt_output.size(),
+                                     update.get(), &update_len));
+
+    YACA_INVALID_PARAM(yaca_context_set_property(dec_ctx.get(), YACA_PROPERTY_GCM_TAG,
+                                                 tag, tag_len));
+
+    YACA_SUCCESS(yaca_decrypt_finalize(dec_ctx.get(), final.get(), &final_len));
+
+    // GCM
+    enc_ctx = encrypt_init(YACA_ENCRYPT_AES, YACA_BCM_GCM, key, gcm_iv);
+    YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx.get(), YACA_PROPERTY_CCM_AAD,
+                                                 aad.data(), aad.size()));
+    YACA_INVALID_PARAM(yaca_context_get_property(enc_ctx.get(), YACA_PROPERTY_GCM_AAD,
+                                                 (void**)aad.data(), &aad_len));
+
+    encrypt_output.clear();
+    update = out_buf_alloc(enc_ctx, DATA.size(), update_len);
+    final = out_buf_alloc(enc_ctx, 0, final_len);
+    YACA_SUCCESS(yaca_encrypt_update(enc_ctx.get(), DATA.data(), DATA.size(),
+                                     update.get(), &update_len));
+    YACA_SUCCESS(yaca_encrypt_finalize(enc_ctx.get(), final.get(), &final_len));
+    encrypt_output.insert(encrypt_output.end(), update.get(), update.get() + update_len);
+    encrypt_output.insert(encrypt_output.end(), final.get(), final.get() + final_len);
+
+    YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx.get(), YACA_PROPERTY_CCM_TAG_LEN,
+                                                 (void*)(&tag_len), sizeof(tag_len)));
+    YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx.get(), YACA_PROPERTY_GCM_TAG_LEN,
+                                                 (void*)(&tag_len), sizeof(char)));
+
+    YACA_INVALID_PARAM(yaca_context_get_property(enc_ctx.get(), YACA_PROPERTY_CCM_TAG,
+                                                 (void**)&tag, &tag_len));
+    YACA_INVALID_PARAM(yaca_context_get_property(enc_ctx.get(), YACA_PROPERTY_GCM_TAG,
+                                                 nullptr, &tag_len));
+    YACA_INVALID_PARAM(yaca_context_get_property(enc_ctx.get(), YACA_PROPERTY_GCM_TAG,
+                                                 (void**)&tag, nullptr));
+
+    YACA_SUCCESS(yaca_context_get_property(enc_ctx.get(), YACA_PROPERTY_GCM_TAG,
+                                           (void**)&tag, &tag_len));
+    ChrPtr tag_ptr = wrap_ptr(tag);
+
+    dec_ctx = decrypt_init(YACA_ENCRYPT_AES, YACA_BCM_GCM, key, gcm_iv);
+    YACA_INVALID_PARAM(yaca_context_set_property(dec_ctx.get(), YACA_PROPERTY_CCM_AAD,
+                                                 aad.data(), aad.size()));
+    YACA_INVALID_PARAM(yaca_context_get_property(dec_ctx.get(), YACA_PROPERTY_GCM_AAD,
+                                                 (void**)aad.data(), &aad_len));
+
+    update = out_buf_alloc(dec_ctx, encrypt_output.size(), update_len);
+    final = out_buf_alloc(dec_ctx, 0, final_len);
+
+    YACA_SUCCESS(yaca_decrypt_update(dec_ctx.get(), encrypt_output.data(), encrypt_output.size(),
+                                     update.get(), &update_len));
+
+    YACA_INVALID_PARAM(yaca_context_set_property(dec_ctx.get(), YACA_PROPERTY_CCM_TAG,
+                                                 tag, tag_len));
+
+    YACA_SUCCESS(yaca_context_set_property(dec_ctx.get(), YACA_PROPERTY_GCM_TAG, tag, tag_len));
+
+    YACA_SUCCESS(yaca_decrypt_finalize(dec_ctx.get(), final.get(), &final_len));
+}
+
+RUNNER_TEST(T3190_yaca_set_get_ccm_properties_invalid_param, YacaTest)
+{
+    KeyPtr key = generate_key(YACA_KEY_TYPE_SYMMETRIC, YACA_KEY_LENGTH_192BIT);
+    KeyPtr iv = generate_key(YACA_KEY_TYPE_IV, YACA_KEY_LENGTH_IV_64BIT);
+
+    size_t aad_len = 16;
+    Buffer aad = random_buffer(aad_len);
+    size_t tag_len = 12;
+    char *tag;
+
+    size_t update_len, final_len;
+
+    // CFB
+    CtxPtr enc_ctx = encrypt_init(YACA_ENCRYPT_3DES_3TDEA, YACA_BCM_CFB, key, iv);
+    YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx.get(), YACA_PROPERTY_CCM_TAG_LEN,
+                                                 (void*)(&tag_len), sizeof(tag_len)));
+
+    YACA_INVALID_PARAM(yaca_encrypt_update(enc_ctx.get(), NULL, DATA.size(), NULL, &update_len));
+    YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx.get(), YACA_PROPERTY_CCM_AAD,
+                                                 aad.data(), aad.size()));
+
+    Buffer encrypt_output;
+    ChrPtr update = out_buf_alloc(enc_ctx, DATA.size(), update_len);
+    ChrPtr final = out_buf_alloc(enc_ctx, 0, final_len);
+    YACA_SUCCESS(yaca_encrypt_update(enc_ctx.get(), DATA.data(), DATA.size(),
+                                     update.get(), &update_len));
+    YACA_SUCCESS(yaca_encrypt_finalize(enc_ctx.get(), final.get(), &final_len));
+    encrypt_output.insert(encrypt_output.end(), update.get(), update.get() + update_len);
+    encrypt_output.insert(encrypt_output.end(), final.get(), final.get() + final_len);
+
+    YACA_INVALID_PARAM(yaca_context_get_property(enc_ctx.get(), YACA_PROPERTY_CCM_TAG,
+                                                 (void**)&tag, &tag_len));
+
+    CtxPtr dec_ctx = decrypt_init(YACA_ENCRYPT_3DES_3TDEA, YACA_BCM_CFB, key, iv);
+    YACA_INVALID_PARAM(yaca_context_set_property(dec_ctx.get(), YACA_PROPERTY_CCM_TAG,
+                                                 tag, tag_len));
+    YACA_INVALID_PARAM(yaca_decrypt_update(dec_ctx.get(), NULL, encrypt_output.size(), NULL,
+                                           &update_len));
+    YACA_INVALID_PARAM(yaca_context_set_property(dec_ctx.get(), YACA_PROPERTY_CCM_AAD,
+                                                 aad.data(), aad.size()));
+
+    update = out_buf_alloc(dec_ctx, encrypt_output.size(), update_len);
+    final = out_buf_alloc(dec_ctx, 0, final_len);
+
+    YACA_SUCCESS(yaca_decrypt_update(dec_ctx.get(), encrypt_output.data(), encrypt_output.size(),
+                                     update.get(), &update_len));
+    YACA_SUCCESS(yaca_decrypt_finalize(dec_ctx.get(), final.get(), &final_len));
+
+    // CCM
+    enc_ctx = encrypt_init(YACA_ENCRYPT_AES, YACA_BCM_CCM, key, iv);
+    YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx.get(), YACA_PROPERTY_GCM_TAG_LEN,
+                                                 (void*)(&tag_len), sizeof(tag_len)));
+    YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx.get(), YACA_PROPERTY_CCM_TAG_LEN,
+                                                 (void*)(&tag_len), sizeof(char)));
+
+    YACA_SUCCESS(yaca_encrypt_update(enc_ctx.get(), NULL, DATA.size(), NULL, &update_len));
+    YACA_INVALID_PARAM(yaca_context_set_property(enc_ctx.get(), YACA_PROPERTY_GCM_AAD,
+                                                 aad.data(), aad.size()));
+    YACA_INVALID_PARAM(yaca_context_get_property(enc_ctx.get(), YACA_PROPERTY_CCM_AAD,
+                                                 (void**)aad.data(), &aad_len));
+
+    YACA_SUCCESS(yaca_context_set_property(enc_ctx.get(), YACA_PROPERTY_CCM_AAD,
+                                           aad.data(), aad.size()));
+
+    encrypt_output.clear();
+    update = out_buf_alloc(enc_ctx, DATA.size(), update_len);
+    final = out_buf_alloc(enc_ctx, 0, final_len);
+    YACA_SUCCESS(yaca_encrypt_update(enc_ctx.get(), DATA.data(), DATA.size(),
+                                     update.get(), &update_len));
+    YACA_SUCCESS(yaca_encrypt_finalize(enc_ctx.get(), final.get(), &final_len));
+    encrypt_output.insert(encrypt_output.end(), update.get(), update.get() + update_len);
+    encrypt_output.insert(encrypt_output.end(), final.get(), final.get() + final_len);
+
+    YACA_INVALID_PARAM(yaca_context_get_property(enc_ctx.get(), YACA_PROPERTY_GCM_TAG,
+                                                 (void**)&tag, &tag_len));
+    YACA_INVALID_PARAM(yaca_context_get_property(enc_ctx.get(), YACA_PROPERTY_CCM_TAG,
+                                                 nullptr, &tag_len));
+    YACA_INVALID_PARAM(yaca_context_get_property(enc_ctx.get(), YACA_PROPERTY_CCM_TAG,
+                                                 (void**)&tag, nullptr));
+
+    YACA_SUCCESS(yaca_context_get_property(enc_ctx.get(), YACA_PROPERTY_CCM_TAG,
+                                           (void**)&tag, &tag_len));
+    ChrPtr tag_ptr = wrap_ptr(tag);
+
+    dec_ctx = decrypt_init(YACA_ENCRYPT_AES, YACA_BCM_CCM, key, iv);
+    YACA_INVALID_PARAM(yaca_context_set_property(dec_ctx.get(), YACA_PROPERTY_GCM_TAG,
+                                                 tag, tag_len));
+
+    YACA_SUCCESS(yaca_context_set_property(dec_ctx.get(), YACA_PROPERTY_CCM_TAG, tag, tag_len));
+
+    YACA_SUCCESS(yaca_decrypt_update(dec_ctx.get(), NULL, encrypt_output.size(), NULL,
+                                     &update_len));
+    YACA_INVALID_PARAM(yaca_context_set_property(dec_ctx.get(), YACA_PROPERTY_GCM_AAD,
+                                                 aad.data(), aad.size()));
+
+    YACA_SUCCESS(yaca_context_set_property(dec_ctx.get(), YACA_PROPERTY_CCM_AAD,
+                                           aad.data(), aad.size()));
+
+    update = out_buf_alloc(dec_ctx, encrypt_output.size(), update_len);
+    final = out_buf_alloc(dec_ctx, 0, final_len);
+    YACA_SUCCESS(yaca_decrypt_update(dec_ctx.get(), encrypt_output.data(), encrypt_output.size(),
+                                     update.get(), &update_len));
+    YACA_SUCCESS(yaca_decrypt_finalize(dec_ctx.get(), final.get(), &final_len));
+}
+
+RUNNER_TEST(T3200_yaca_set_invalid_gcm_tag_aad, YacaTest)
+{
+    KeyPtr key = generate_key(YACA_KEY_TYPE_SYMMETRIC, YACA_KEY_LENGTH_192BIT);
+    KeyPtr iv = generate_key(YACA_KEY_TYPE_IV, YACA_KEY_LENGTH_IV_64BIT);
+
+    size_t aad_len = 16;
+    Buffer aad = random_buffer(aad_len);
+    size_t tag_len = 16;
+    char *tag;
+
+    CtxPtr enc_ctx = encrypt_init(YACA_ENCRYPT_AES, YACA_BCM_GCM, key, iv);
+
+    Buffer encrypt_output;
+    size_t update_len, final_len;
+    ChrPtr update = out_buf_alloc(enc_ctx, DATA.size(), update_len);
+    ChrPtr final = out_buf_alloc(enc_ctx, 0, final_len);
+
+    YACA_SUCCESS(yaca_context_set_property(enc_ctx.get(), YACA_PROPERTY_GCM_AAD,
+                                           aad.data(), aad.size()));
+    YACA_SUCCESS(yaca_encrypt_update(enc_ctx.get(), DATA.data(), DATA.size(),
+                                     update.get(), &update_len));
+    YACA_SUCCESS(yaca_encrypt_finalize(enc_ctx.get(), final.get(), &final_len));
+    YACA_SUCCESS(yaca_context_get_property(enc_ctx.get(), YACA_PROPERTY_GCM_TAG,
+                                           (void**)&tag, &tag_len));
+    ChrPtr tag_ptr = wrap_ptr(tag);
+
+    encrypt_output.insert(encrypt_output.end(), update.get(), update.get() + update_len);
+    encrypt_output.insert(encrypt_output.end(), final.get(), final.get() + final_len);
+
+    CtxPtr dec_ctx = decrypt_init(YACA_ENCRYPT_AES, YACA_BCM_GCM, key, iv);
+    update = out_buf_alloc(dec_ctx, encrypt_output.size(), update_len);
+    final = out_buf_alloc(dec_ctx, 0, final_len);
+
+    // Invalid AAD
+    YACA_SUCCESS(yaca_context_set_property(dec_ctx.get(), YACA_PROPERTY_GCM_AAD, tag, aad.size()));
+
+    YACA_SUCCESS(yaca_decrypt_update(dec_ctx.get(), encrypt_output.data(), encrypt_output.size(),
+                                     update.get(), &update_len));
+
+    // Valid TAG
+    YACA_SUCCESS(yaca_context_set_property(dec_ctx.get(), YACA_PROPERTY_GCM_TAG, tag, tag_len));
+
+    YACA_INVALID_PARAM(yaca_decrypt_finalize(dec_ctx.get(), final.get(), &final_len));
+
+    dec_ctx = decrypt_init(YACA_ENCRYPT_AES, YACA_BCM_GCM, key, iv);
+
+    // Valid AAD
+    YACA_SUCCESS(yaca_context_set_property(dec_ctx.get(), YACA_PROPERTY_GCM_AAD,
+                                           aad.data(), aad.size()));
+
+    YACA_SUCCESS(yaca_decrypt_update(dec_ctx.get(), encrypt_output.data(), encrypt_output.size(),
+                                     update.get(), &update_len));
+
+    // Invalid TAG
+    YACA_SUCCESS(yaca_context_set_property(dec_ctx.get(), YACA_PROPERTY_GCM_TAG,
+                                           aad.data(), tag_len));
+
+    YACA_INVALID_PARAM(yaca_decrypt_finalize(dec_ctx.get(), final.get(), &final_len));
+}
+
+RUNNER_TEST(T3210_yaca_set_invalid_ccm_tag_aad, YacaTest)
+{
+    KeyPtr key = generate_key(YACA_KEY_TYPE_SYMMETRIC, YACA_KEY_LENGTH_192BIT);
+    KeyPtr iv = generate_key(YACA_KEY_TYPE_IV, YACA_KEY_LENGTH_IV_64BIT);
+
+    size_t aad_len = 16;
+    Buffer aad = random_buffer(aad_len);
+    size_t tag_len = 12;
+    char *tag;
+
+    CtxPtr enc_ctx = encrypt_init(YACA_ENCRYPT_AES, YACA_BCM_CCM, key, iv);
+
+    Buffer encrypt_output;
+    size_t update_len, final_len;
+    ChrPtr update = out_buf_alloc(enc_ctx, DATA.size(), update_len);
+    ChrPtr final = out_buf_alloc(enc_ctx, 0, final_len);
+
+    YACA_SUCCESS(yaca_encrypt_update(enc_ctx.get(), NULL, DATA.size(), NULL, &update_len));
+    YACA_SUCCESS(yaca_context_set_property(enc_ctx.get(), YACA_PROPERTY_CCM_AAD,
+                                           aad.data(), aad.size()));
+    YACA_SUCCESS(yaca_encrypt_update(enc_ctx.get(), DATA.data(), DATA.size(),
+                                     update.get(), &update_len));
+    YACA_SUCCESS(yaca_encrypt_finalize(enc_ctx.get(), final.get(), &final_len));
+    YACA_SUCCESS(yaca_context_get_property(enc_ctx.get(), YACA_PROPERTY_CCM_TAG,
+                                           (void**)&tag, &tag_len));
+    ChrPtr tag_ptr = wrap_ptr(tag);
+
+    encrypt_output.insert(encrypt_output.end(), update.get(), update.get() + update_len);
+    encrypt_output.insert(encrypt_output.end(), final.get(), final.get() + final_len);
+
+    CtxPtr dec_ctx = decrypt_init(YACA_ENCRYPT_AES, YACA_BCM_CCM, key, iv);
+    update = out_buf_alloc(dec_ctx, encrypt_output.size(), update_len);
+    final = out_buf_alloc(dec_ctx, 0, final_len);
+
+    // Invalid TAG
+    YACA_SUCCESS(yaca_context_set_property(dec_ctx.get(), YACA_PROPERTY_CCM_TAG,
+                                           aad.data(), tag_len));
+
+    // Valid AAD
+    YACA_SUCCESS(yaca_decrypt_update(dec_ctx.get(), NULL, encrypt_output.size(), NULL,
+                                     &update_len));
+    YACA_SUCCESS(yaca_context_set_property(dec_ctx.get(), YACA_PROPERTY_CCM_AAD,
+                                           aad.data(), aad.size()));
+
+    YACA_INVALID_PARAM(yaca_decrypt_update(dec_ctx.get(), encrypt_output.data(), encrypt_output.size(),
+                                           update.get(), &update_len));
+
+    dec_ctx = decrypt_init(YACA_ENCRYPT_AES, YACA_BCM_CCM, key, iv);
+
+    // Valid TAG
+    YACA_SUCCESS(yaca_context_set_property(dec_ctx.get(), YACA_PROPERTY_CCM_TAG, tag, tag_len));
+
+    // Invalid AAD
+    YACA_SUCCESS(yaca_decrypt_update(dec_ctx.get(), NULL, encrypt_output.size(), NULL,
+                                     &update_len));
+    YACA_SUCCESS(yaca_context_set_property(dec_ctx.get(), YACA_PROPERTY_CCM_AAD,
+                                           tag, aad.size()));
+
+    YACA_INVALID_PARAM(yaca_decrypt_update(dec_ctx.get(), encrypt_output.data(), encrypt_output.size(),
+                                           update.get(), &update_len));
+}
index 89634ac..3fcd2a5 100644 (file)
@@ -194,7 +194,7 @@ void test_rsa_padding(const KeyPair& kp, const PaddingInfo& pi, EncryptionType e
         expected = YACA_ERROR_INVALID_PARAMETER;
         if (p.padding == YACA_PADDING_NONE ||
             (et == ET_PUB && ((p.padding == YACA_PADDING_PKCS1 && padding == YACA_PADDING_PKCS1_SSLV23) ||
-                              (p.padding == YACA_PADDING_PKCS1_SSLV23 && padding == YACA_PADDING_PKCS1))))
+                              (p.padding == padding))))
             expected = YACA_ERROR_NONE;
 
         YACA_RESULT(expected, decrypt(p.padding, dec_key.get(),
index 0a8d77b..49a2d04 100644 (file)
@@ -58,15 +58,21 @@ RUNNER_TEST_GROUP_INIT(T6000_YACA_SIGN);
 RUNNER_TEST(T6010_yaca_sign_init_invalid_param, YacaTest)
 {
     yaca_context_h ctx = YACA_CONTEXT_NULL;
-    KeyPtr prv = generate_key(YACA_KEY_TYPE_RSA_PRIV, YACA_KEY_LENGTH_1024BIT);
-    KeyPtr pub = extract_public_key(prv);
+    KeyPair rsa(YACA_KEY_TYPE_RSA_PRIV, YACA_KEY_LENGTH_512BIT);
+    KeyPair dsa(YACA_KEY_TYPE_DSA_PRIV, YACA_KEY_LENGTH_1024BIT);
+    KeyPair ec(YACA_KEY_TYPE_EC_PRIV, YACA_KEY_LENGTH_EC_SECP384R1);
     KeyPtr sym = generate_key(YACA_KEY_TYPE_SYMMETRIC, YACA_KEY_LENGTH_256BIT);
 
-    YACA_INVALID_PARAM(yaca_sign_initialize(nullptr, YACA_DIGEST_MD5, prv.get()));
-    YACA_INVALID_PARAM(yaca_sign_initialize(&ctx, static_cast<yaca_digest_algorithm_e>(-1), prv.get()));
+    YACA_INVALID_PARAM(yaca_sign_initialize(nullptr, YACA_DIGEST_MD5, rsa.prv.get()));
+    YACA_INVALID_PARAM(yaca_sign_initialize(&ctx, static_cast<yaca_digest_algorithm_e>(-1),
+                                            rsa.prv.get()));
     YACA_INVALID_PARAM(yaca_sign_initialize(&ctx, YACA_DIGEST_MD5, YACA_KEY_NULL));
-    YACA_INVALID_PARAM(yaca_sign_initialize(&ctx, YACA_DIGEST_MD5, pub.get()));
+    YACA_INVALID_PARAM(yaca_sign_initialize(&ctx, YACA_DIGEST_MD5, rsa.pub.get()));
     YACA_INVALID_PARAM(yaca_sign_initialize(&ctx, YACA_DIGEST_MD5, sym.get()));
+    YACA_INVALID_PARAM(yaca_sign_initialize(&ctx, YACA_DIGEST_SHA384, rsa.prv.get()));
+    YACA_INVALID_PARAM(yaca_sign_initialize(&ctx, YACA_DIGEST_SHA512, rsa.prv.get()));
+    YACA_INVALID_PARAM(yaca_sign_initialize(&ctx, YACA_DIGEST_MD5, dsa.prv.get()));
+    YACA_INVALID_PARAM(yaca_sign_initialize(&ctx, YACA_DIGEST_MD5, ec.prv.get()));
 }
 
 RUNNER_TEST(T6020_yaca_sign_hmac_init_invalid_param, YacaTest)
@@ -124,15 +130,21 @@ RUNNER_TEST(T6050_yaca_sign_final_invalid_param, YacaTest)
 RUNNER_TEST(T6060_yaca_verify_init_invalid_param)
 {
     yaca_context_h ctx = YACA_CONTEXT_NULL;
-    KeyPtr prv = generate_key(YACA_KEY_TYPE_RSA_PRIV, YACA_KEY_LENGTH_1024BIT);
-    KeyPtr pub = extract_public_key(prv);
+    KeyPair rsa(YACA_KEY_TYPE_RSA_PRIV, YACA_KEY_LENGTH_512BIT);
+    KeyPair dsa(YACA_KEY_TYPE_DSA_PRIV, YACA_KEY_LENGTH_1024BIT);
+    KeyPair ec(YACA_KEY_TYPE_EC_PRIV, YACA_KEY_LENGTH_EC_SECP384R1);
     KeyPtr sym = generate_key(YACA_KEY_TYPE_SYMMETRIC, YACA_KEY_LENGTH_256BIT);
 
-    YACA_INVALID_PARAM(yaca_verify_initialize(nullptr, YACA_DIGEST_MD5, pub.get()));
-    YACA_INVALID_PARAM(yaca_verify_initialize(&ctx, static_cast<yaca_digest_algorithm_e>(-1), prv.get()));
+    YACA_INVALID_PARAM(yaca_verify_initialize(nullptr, YACA_DIGEST_MD5, rsa.pub.get()));
+    YACA_INVALID_PARAM(yaca_verify_initialize(&ctx, static_cast<yaca_digest_algorithm_e>(-1),
+                                              rsa.prv.get()));
     YACA_INVALID_PARAM(yaca_verify_initialize(&ctx, YACA_DIGEST_MD5, YACA_KEY_NULL));
-    YACA_INVALID_PARAM(yaca_verify_initialize(&ctx, YACA_DIGEST_MD5, prv.get()));
+    YACA_INVALID_PARAM(yaca_verify_initialize(&ctx, YACA_DIGEST_MD5, rsa.prv.get()));
     YACA_INVALID_PARAM(yaca_verify_initialize(&ctx, YACA_DIGEST_MD5, sym.get()));
+    YACA_INVALID_PARAM(yaca_verify_initialize(&ctx, YACA_DIGEST_SHA384, rsa.pub.get()));
+    YACA_INVALID_PARAM(yaca_verify_initialize(&ctx, YACA_DIGEST_SHA512, rsa.pub.get()));
+    YACA_INVALID_PARAM(yaca_verify_initialize(&ctx, YACA_DIGEST_MD5, dsa.pub.get()));
+    YACA_INVALID_PARAM(yaca_verify_initialize(&ctx, YACA_DIGEST_MD5, ec.pub.get()));
 }
 
 RUNNER_TEST(T6070_yaca_verify_update_invalid_param)
@@ -141,9 +153,9 @@ RUNNER_TEST(T6070_yaca_verify_update_invalid_param)
     KeyPtr pub = extract_public_key(prv);
     CtxPtr ctx = verify_init(YACA_DIGEST_MD5, pub);
 
-    YACA_INVALID_PARAM(yaca_sign_update(YACA_CONTEXT_NULL, lorem16, LOREM16_SIZE));
-    YACA_INVALID_PARAM(yaca_sign_update(ctx.get(), nullptr, LOREM16_SIZE));
-    YACA_INVALID_PARAM(yaca_sign_update(ctx.get(), lorem16, 0));
+    YACA_INVALID_PARAM(yaca_verify_update(YACA_CONTEXT_NULL, lorem16, LOREM16_SIZE));
+    YACA_INVALID_PARAM(yaca_verify_update(ctx.get(), nullptr, LOREM16_SIZE));
+    YACA_INVALID_PARAM(yaca_verify_update(ctx.get(), lorem16, 0));
 }
 
 RUNNER_TEST(T6080_yaca_verify_final_invalid_param)
@@ -170,6 +182,30 @@ RUNNER_TEST(T6090_yaca_sign_get_output_length_invalid_param)
     YACA_INVALID_PARAM(yaca_context_get_output_length(ctx.get(), 0, nullptr));
 }
 
+RUNNER_TEST(T6095_yaca_sign_verify_call_order_invalid_param)
+{
+    KeyPtr key = generate_key(YACA_KEY_TYPE_RSA_PRIV, YACA_KEY_LENGTH_1024BIT);
+    KeyPtr key_pub = extract_public_key(key);
+    CtxPtr ctx_sgn = sign_init(YACA_DIGEST_SHA1, key);
+    CtxPtr ctx_vrf = verify_init(YACA_DIGEST_SHA1, key_pub);
+    size_t output_len = get_output_length(ctx_sgn);
+    Buffer output(output_len);
+    yaca_padding_e padding = YACA_PADDING_PKCS1_PSS;
+
+    YACA_SUCCESS(yaca_sign_finalize(ctx_sgn.get(), output.data(), &output_len));
+    YACA_SUCCESS(yaca_verify_finalize(ctx_vrf.get(), output.data(), output_len));
+
+    YACA_INVALID_PARAM(yaca_sign_update(ctx_sgn.get(), output.data(), output_len));
+    YACA_INVALID_PARAM(yaca_context_set_property(ctx_sgn.get(), YACA_PROPERTY_PADDING,
+                                                 static_cast<void*>(&padding),
+                                                 sizeof(yaca_padding_e)));
+
+    YACA_INVALID_PARAM(yaca_verify_update(ctx_vrf.get(), output.data(), output_len));
+    YACA_INVALID_PARAM(yaca_context_set_property(ctx_vrf.get(), YACA_PROPERTY_PADDING,
+                                                 static_cast<void*>(&padding),
+                                                 sizeof(yaca_padding_e)));
+}
+
 RUNNER_TEST(T6100_yaca_sign_set_property_invalid_param)
 {
     KeyPtr key = generate_key(YACA_KEY_TYPE_RSA_PRIV, YACA_KEY_LENGTH_512BIT);
@@ -205,6 +241,16 @@ RUNNER_TEST(T6100_yaca_sign_set_property_invalid_param)
                                                      0));
     }
 
+    padding = YACA_PADDING_X931;
+    ctx_sgn = sign_init(YACA_DIGEST_MD5, key);
+    YACA_INVALID_PARAM(yaca_context_set_property(ctx_sgn.get(), YACA_PROPERTY_PADDING,
+                                                 static_cast<void*>(&padding),
+                                                 sizeof(yaca_padding_e)));
+    ctx_sgn = sign_init(YACA_DIGEST_SHA224, key);
+    YACA_INVALID_PARAM(yaca_context_set_property(ctx_sgn.get(), YACA_PROPERTY_PADDING,
+                                                 static_cast<void*>(&padding),
+                                                 sizeof(yaca_padding_e)));
+
     YACA_INVALID_PARAM(yaca_context_set_property(ctx_dsa.get(), YACA_PROPERTY_PADDING,
                                                  static_cast<void*>(&padding),
                                                  sizeof(yaca_padding_e)));
@@ -214,7 +260,6 @@ RUNNER_TEST(T6100_yaca_sign_set_property_invalid_param)
     YACA_INVALID_PARAM(yaca_context_set_property(ctx_digest.get(), YACA_PROPERTY_PADDING,
                                                  static_cast<void*>(&padding),
                                                  sizeof(yaca_padding_e)));
-
 }
 
 RUNNER_TEST(T6120_yaca_sign_get_output_length)
@@ -229,7 +274,6 @@ RUNNER_TEST(T6120_yaca_sign_get_output_length)
     };
 
     const std::vector<yaca_key_bit_length_e> lengths = {
-        YACA_KEY_LENGTH_512BIT,
         YACA_KEY_LENGTH_1024BIT,
         YACA_KEY_LENGTH_2048BIT,
         YACA_KEY_LENGTH_3072BIT,
@@ -495,7 +539,8 @@ RUNNER_TEST(T6180_yaca_sign_verify_padding_test_vectors, YacaTest)
             CtxPtr ctx = sign_init(algo, key_prv);
             size_t output_len = get_output_length(ctx);
             YACA_SUCCESS(yaca_context_set_property(ctx.get(), YACA_PROPERTY_PADDING,
-                                                   static_cast<void*>(&padding), sizeof(padding)));
+                                                   static_cast<void*>(&padding),
+                                                   sizeof(yaca_padding_e)));
 
             if (input.size() > 0) {
                 for (size_t i = 0; i < repeats; i++)
@@ -510,7 +555,8 @@ RUNNER_TEST(T6180_yaca_sign_verify_padding_test_vectors, YacaTest)
 
             ctx = verify_init(algo, key_pub);
             YACA_SUCCESS(yaca_context_set_property(ctx.get(), YACA_PROPERTY_PADDING,
-                                                   static_cast<void*>(&padding), sizeof(padding)));
+                                                   static_cast<void*>(&padding),
+                                                   sizeof(yaca_padding_e)));
 
             if (input.size() > 0)
                 for (size_t i = 0; i < repeats; i++)
@@ -555,3 +601,32 @@ RUNNER_TEST(T6180_yaca_sign_verify_padding_test_vectors, YacaTest)
         }
     }
 }
+
+RUNNER_TEST(T6190_yaca_sign_param_combinations, YacaTest)
+{
+    auto tvv = loadTestVector("sign_param_comb.txt");
+
+    for (const auto& tv : tvv) {
+        yaca_key_type_e key_type;
+        size_t key_len;
+        yaca_padding_e padding;
+        yaca_digest_algorithm_e algo;
+
+        tv.get("key_type", key_type);
+        tv.get("key_len_bits", key_len);
+        if (key_type == YACA_KEY_TYPE_RSA_PRIV)
+            tv.get("padding", padding);
+        tv.get("algo", algo);
+
+        KeyPtr key = generate_key(key_type, key_len);
+        CtxPtr ctx = sign_init(algo, key);
+
+        if (key_type == YACA_KEY_TYPE_RSA_PRIV)
+           YACA_SUCCESS(yaca_context_set_property(ctx.get(), YACA_PROPERTY_PADDING,
+                                                  (void*)&padding, sizeof(yaca_padding_e)));
+
+        size_t output_len = get_output_length(ctx);
+        Buffer output(output_len);
+        YACA_SUCCESS(yaca_sign_finalize(ctx.get(), output.data(), &output_len));
+    }
+}
index b145a67..49b8b51 100644 (file)
@@ -120,6 +120,16 @@ std::unordered_map<std::string, yaca_kdf_e> str2kdf = {
     std::make_pair("X962", YACA_KDF_X962)
 };
 
+std::unordered_map<std::string, yaca_padding_e> str2padding = {
+    std::make_pair("NONE",         YACA_PADDING_NONE),
+    std::make_pair("X931",         YACA_PADDING_X931),
+    std::make_pair("PKCS1",        YACA_PADDING_PKCS1),
+    std::make_pair("PKCS1_PSS",    YACA_PADDING_PKCS1_PSS),
+    std::make_pair("PKCS1_OAEP",   YACA_PADDING_PKCS1_OAEP),
+    std::make_pair("PKCS1_SSLV23", YACA_PADDING_PKCS1_SSLV23),
+    std::make_pair("PKCS7",        YACA_PADDING_PKCS7)
+};
+
 } // anonymous namespace
 
 void TestVector::add(const std::string &key, const std::string &val)
@@ -174,6 +184,11 @@ void TestVector::get(const std::string &key, yaca_kdf_e &val) const
     val = str2kdf.at(value(key));
 }
 
+void TestVector::get(const std::string &key, yaca_padding_e &val) const
+{
+    val = str2padding.at(value(key));
+}
+
 void TestVector::reset()
 {
     m_data.clear();
index 1e34481..06ee01b 100644 (file)
@@ -57,6 +57,8 @@ public:
     void get(const std::string &key, yaca_block_cipher_mode_e &val) const;
     /* special case for kdf */
     void get(const std::string &key, yaca_kdf_e &val) const;
+    /* special case for padding */
+    void get(const std::string &key, yaca_padding_e &val) const;
 
     void reset();