From 55225c368de7ac08bb6acb021004740bfb997ec4 Mon Sep 17 00:00:00 2001 From: yeji01kim Date: Wed, 4 May 2016 15:24:26 +0900 Subject: [PATCH] Add container encryption Change-Id: I216d7911258d884f73cf32a3bc945028bc603361 Signed-off-by: yeji01kim --- common/CMakeLists.txt | 0 common/filesystem.cpp | 0 packaging/device-policy-manager.spec | 2 + server/zone.cpp | 0 zone/CMakeLists.txt | 2 + zone/volume/CMakeLists.txt | 32 ++++ zone/volume/ecryptfs.h | 107 ++++++++++++ zone/volume/kernel-keyring.cpp | 46 +++++ zone/volume/kernel-keyring.h | 42 +++++ zone/volume/key-generator.cpp | 321 +++++++++++++++++++++++++++++++++++ zone/volume/key-generator.h | 54 ++++++ zone/volume/key-manager.cpp | 92 ++++++++++ zone/volume/key-manager.h | 35 ++++ zone/volume/main.cpp | 193 +++++++++++++++++++++ 14 files changed, 926 insertions(+) mode change 100644 => 100755 common/CMakeLists.txt mode change 100644 => 100755 common/filesystem.cpp mode change 100644 => 100755 server/zone.cpp mode change 100644 => 100755 zone/CMakeLists.txt create mode 100644 zone/volume/CMakeLists.txt create mode 100755 zone/volume/ecryptfs.h create mode 100755 zone/volume/kernel-keyring.cpp create mode 100755 zone/volume/kernel-keyring.h create mode 100755 zone/volume/key-generator.cpp create mode 100755 zone/volume/key-generator.h create mode 100755 zone/volume/key-manager.cpp create mode 100644 zone/volume/key-manager.h create mode 100644 zone/volume/main.cpp diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt old mode 100644 new mode 100755 diff --git a/common/filesystem.cpp b/common/filesystem.cpp old mode 100644 new mode 100755 diff --git a/packaging/device-policy-manager.spec b/packaging/device-policy-manager.spec index 639672c..d6eb010 100755 --- a/packaging/device-policy-manager.spec +++ b/packaging/device-policy-manager.spec @@ -33,6 +33,7 @@ BuildRequires: pkgconfig(capi-network-connection) BuildRequires: pkgconfig(capi-network-bluetooth) BuildRequires: pkgconfig(capi-system-system-settings) BuildRequires: pkgconfig(notification) +BuildRequires: pkgconfig(key-manager) %if "%{profile}" != "tv" BuildRequires: pkgconfig(capi-location-manager) @@ -309,6 +310,7 @@ mv /etc/pam.d/systemd-user.keep /etc/pam.d/systemd-user %defattr(600,root,root,700) %attr(700,root,root) %{_libdir}/security/pam_*.so %attr(700,root,root) %{_sbindir}/zone-admin-cli +%attr(700,root,root) %{_sbindir}/zone-volume-manager %attr(700,root,root) %dir %{TZ_SYS_ETC}/dpm/zone %attr(600,root,root) %config %{TZ_SYS_ETC}/dpm/zone/owner.xml %attr(644,root,root) /opt/data/dpm/zone-indicator.png diff --git a/server/zone.cpp b/server/zone.cpp old mode 100644 new mode 100755 diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt old mode 100644 new mode 100755 index 9daa363..e09371f --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -17,11 +17,13 @@ SET(ZONE_MODULE ${DPM_ZONE}/module) SET(ZONE_LIBS ${DPM_ZONE}/libs) SET(ZONE_CLI ${DPM_ZONE}/cli) +SET(ZONE_VOLUME ${DPM_ZONE}/volume) SET(ZONE_SETUP_WIZARD ${DPM_ZONE}/setup-wizard) SET(ZONE_LAUNCHER ${DPM_ZONE}/kaskit) ADD_SUBDIRECTORY(${ZONE_MODULE}) ADD_SUBDIRECTORY(${ZONE_LIBS}) ADD_SUBDIRECTORY(${ZONE_CLI}) +ADD_SUBDIRECTORY(${ZONE_VOLUME}) ADD_SUBDIRECTORY(${ZONE_SETUP_WIZARD}) ADD_SUBDIRECTORY(${ZONE_LAUNCHER}) diff --git a/zone/volume/CMakeLists.txt b/zone/volume/CMakeLists.txt new file mode 100644 index 0000000..23b85b7 --- /dev/null +++ b/zone/volume/CMakeLists.txt @@ -0,0 +1,32 @@ +# +# Copyright (c) 2016 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. +# +SET(ZONE_VOLUME_MANAGER_TARGET "zone-volume-manager") + +SET(ZONE_VOLUME_MANAGER_SOURCES key-manager.cpp + key-generator.cpp + kernel-keyring.cpp + main.cpp +) + +PKG_CHECK_MODULES(ZONE_VOLUME_MANAGER_DEPS REQUIRED key-manager) + +ADD_EXECUTABLE(${ZONE_VOLUME_MANAGER_TARGET} ${ZONE_VOLUME_MANAGER_SOURCES}) + +INCLUDE_DIRECTORIES(SYSTEM ${ZONE_VOLUME_MANAGER_DEPS_INCLUDE_DIRS} ${ZONE_LIBS} ${DPM_COMMON}) + +TARGET_LINK_LIBRARIES(${ZONE_VOLUME_MANAGER_TARGET} ${ZONE_VOLUME_MANAGER_DEPS_LIBRARIES} dpm-common) + +INSTALL(TARGETS ${ZONE_VOLUME_MANAGER_TARGET} DESTINATION sbin) diff --git a/zone/volume/ecryptfs.h b/zone/volume/ecryptfs.h new file mode 100755 index 0000000..561ffdf --- /dev/null +++ b/zone/volume/ecryptfs.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2015 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 + */ + +#ifndef __ECRYPTFS_H__ +#define __ECRYPTFS_H__ + +#include +#include + +// this is versions of ecryptfs module +#define ECRYPTFS_MAJOR_VERSION 0x00 +#define ECRYPTFS_MINOR_VERSION 0x04 +#define ECRYPTFS_VERSION ((ECRYPTFS_MAJOR_VERSION << 8) | ECRYPTFS_MINOR_VERSION) + +#define ECRYPTFS_MAX_PKI_NAME_BYTES 16 +#define ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET 0x02 + +#define PGP_DIGEST_ALGO_SHA512 10 + +#define ECRYPTFS_FEK_CIPHER "aes" +#define ECRYPTFS_MOUNT_DEVICE "ecryptfs" + +#define ECRYPTFS_MAX_OPTIONS 1024 + +#define ECRYPTFS_MAX_SIG_SIZE 8 +#define ECRYPTFS_MAX_SIG_HEX (ECRYPTFS_MAX_SIG_SIZE*2) +#define ECRYPTFS_PASSWORD_SIG_SIZE ECRYPTFS_MAX_SIG_HEX + +#define ECRYPTFS_MAX_KEY_SIZE 32 +#define ECRYPTFS_MAX_KEY_HEX (ECRYPTFS_MAX_KEY_SIZE * 2) + +#define ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES 512 +#define ECRYPTFS_MAX_PKI_NAME_BYTES 16 + +#define ECRYPTFS_MAX_SALT_SIZE 4 +#define ECRYPTFS_MAX_SALT_HEX 8 + +#define ECRYPTFS_PWD_PAYLOAD_TYPE 0 // password + +struct ecryptfs_session_key { +#define ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT 0x00000001 +#define ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT 0x00000002 +#define ECRYPTFS_CONTAINS_DECRYPTED_KEY 0x00000004 +#define ECRYPTFS_CONTAINS_ENCRYPTED_KEY 0x00000008 + int32_t flags; + int32_t encrypted_key_size; + int32_t decrypted_key_size; + u_int8_t encrypted_key[ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES]; + u_int8_t decrypted_key[ECRYPTFS_MAX_KEY_HEX]; +}; + +struct ecryptfs_password { + int32_t password_bytes; + int32_t hash_algo; + int32_t hash_iterations; + int32_t session_key_encryption_key_bytes; +#define ECRYPTFS_PERSISTENT_PASSWORD 0x01 +#define ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET 0x02 + u_int32_t flags; + /* Iterated-hash concatenation of salt and passphrase */ + u_int8_t session_key_encryption_key[ECRYPTFS_MAX_KEY_HEX]; + u_int8_t signature[ECRYPTFS_PASSWORD_SIG_SIZE + 1]; + /* Always in expanded hex */ + u_int8_t salt[ECRYPTFS_MAX_SALT_SIZE]; +}; + +enum ecryptfs_token_types { + ECRYPTFS_PASSWORD, + ECRYPTFS_PRIVATE_KEY +}; + +struct ecryptfs_private_key { + u_int32_t key_size; + u_int32_t data_len; + u_int8_t signature[ECRYPTFS_PASSWORD_SIG_SIZE + 1]; + char pki_type[ECRYPTFS_MAX_PKI_NAME_BYTES + 1]; + u_int8_t data[]; +}; + +struct ecryptfs_auth_tok { + u_int16_t version; /* 8-bit major and 8-bit minor */ + u_int16_t token_type; +#define ECRYPTFS_ENCRYPT_ONLY 0x00000001 + u_int32_t flags; + struct ecryptfs_session_key session_key; + u_int8_t reserved[32]; + union { + struct ecryptfs_password password; + struct ecryptfs_private_key private_key; + } token; +} __attribute__((packed)); + +typedef struct ecryptfs_auth_tok ecryptfs_payload; +#endif diff --git a/zone/volume/kernel-keyring.cpp b/zone/volume/kernel-keyring.cpp new file mode 100755 index 0000000..c2b99a4 --- /dev/null +++ b/zone/volume/kernel-keyring.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2015 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 + */ + +#include +#include +#include +#include + +#include "kernel-keyring.h" + +#ifndef KEYCTL_SEARCH +#define KEYCTL_SEARCH 10 +#endif + +KeySerial KernelKeyRing::add(const char *type, const char* description, const void* payload, size_t plen, KeySerial ringid) +{ + return ::syscall(__NR_add_key, type, description, payload, plen, ringid); +} + +long KernelKeyRing::search(KeySerial ringid, const char* type, const char* description, KeySerial destringid) +{ + return ::syscall(__NR_keyctl, KEYCTL_SEARCH, ringid, type, description, destringid); +} + +long KernelKeyRing::link(KeySerial keyid, KeySerial ringid) +{ + return ::syscall(__NR_keyctl, KEYCTL_LINK, keyid, ringid); +} + +long KernelKeyRing::unlink(KeySerial keyid, KeySerial ringid) +{ + return ::syscall(__NR_keyctl, KEYCTL_UNLINK, keyid, ringid); +} diff --git a/zone/volume/kernel-keyring.h b/zone/volume/kernel-keyring.h new file mode 100755 index 0000000..05d35f9 --- /dev/null +++ b/zone/volume/kernel-keyring.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2015 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 + */ + +#ifndef __KERNEL_KEY_RING_H__ +#define __KERNEL_KEY_RING_H__ + +#include +#include + +#include + +typedef int32_t KeySerial; + +class KernelKeyRing { +public: + KernelKeyRing() = delete; + KernelKeyRing(const KernelKeyRing&) = delete; + KernelKeyRing(KernelKeyRing&&) = delete; + + KernelKeyRing& operator=(const KernelKeyRing&) = delete; + KernelKeyRing& operator=(KernelKeyRing&&) = delete; + + static KeySerial add(const char* type, const char* description, const void* payload, size_t plen, KeySerial ringid); + static long search(KeySerial ringid, const char* type, const char* description, KeySerial destringid); + static long link(KeySerial keyid, KeySerial ringid); + static long unlink(KeySerial keyid, KeySerial ringid); +}; + +#endif //!__KERNEL_KEY_RING_H__ diff --git a/zone/volume/key-generator.cpp b/zone/volume/key-generator.cpp new file mode 100755 index 0000000..4814411 --- /dev/null +++ b/zone/volume/key-generator.cpp @@ -0,0 +1,321 @@ +/* + * Copyright (c) 2015 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 + */ + + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "exception.h" +#include "key-generator.h" + +#include "error.h" +#include "exception.h" + +#define RAND_READ_BYTES 8 +#define PBKDF2_ITERATION 1000 +#define SHA_BLOCKSIZE 64 + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +#if defined (BYTE_ORDER) && defined(BIG_ENDIAN) && (BYTE_ORDER == BIG_ENDIAN) +#define WORDS_BIGENDIAN 1 +#endif +#ifdef _BIG_ENDIAN +#define WORDS_BIGENDIAN 1 +#endif + +#ifdef WORDS_BIGENDIAN +#define blk0(i) block->l[i] +#else +#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xff00ff00) \ + |(rol(block->l[i],8)&0x00ff00ff)) +#endif +#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ + ^block->l[(i+2)&15]^block->l[i&15],1)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v, w, x, y, z, i) \ + z+=((w&(x^y))^y)+blk0(i)+0x5a827999+rol(v,5);w=rol(w,30); +#define R1(v, w, x, y, z, i) \ + z+=((w&(x^y))^y)+blk(i)+0x5a827999+rol(v,5);w=rol(w,30); +#define R2(v, w, x, y, z, i) \ + z+=(w^x^y)+blk(i)+0x6ed9eba1+rol(v,5);w=rol(w,30); +#define R3(v, w, x, y, z, i) \ + z+=(((w|x)&y)|(w&x))+blk(i)+0x8f1bbcdc+rol(v,5);w=rol(w,30); +#define R4(v, w, x, y, z, i) \ + z+=(w^x^y)+blk(i)+0xca62c1d6+rol(v,5);w=rol(w,30); + +#define __min__(a, b) (((a) < (b)) ? (a) : (b)) + +std::string KeyGenerator::hexConvert(unsigned char* src, int srcLen) +{ + std::ostringstream ss; + + for (int i = 0; i state[0] = 0x67452301; + context->state[1] = 0xefcdab89; + context->state[2] = 0x98badcfe; + context->state[3] = 0x10325476; + context->state[4] = 0xc3d2e1f0; + context->count[0] = context->count[1] = 0; +} + +void KeyGenerator::sha1Update(SHA1_CTX* context, const void* p, unsigned int len) +{ + const unsigned char* data = (unsigned char*)p; + unsigned int i, j; + + j = (context->count[0] >> 3) & 63; + if ((context->count[0] += (len << 3)) < (len << 3)) { + context->count[1]++; + } + context->count[1] += (len >> 29); + if ((j + len) > 63) { + ::memcpy(&context->buffer[j], data, (i = 64 - j)); + sha1Transform(context->state, context->buffer); + for (; i + 63 < len; i += 64) { + sha1Transform(context->state, data + i); + } + j = 0; + } else i = 0; + + ::memcpy(&context->buffer[j], &data[i], len - i); +} + +void KeyGenerator::sha1Final(unsigned char digest[SHA1_DIGEST_SIZE], SHA1_CTX* context) +{ + unsigned int i; + unsigned char finalcount[8]; + for (i = 0; i < 8; i++) { + finalcount[i] = (unsigned char) ((context->count[(i >= 4 ? 0 : 1)] + >> ((3 - (i & 3)) * 8)) & 255); + } + sha1Update(context, (unsigned char*) "\200", 1); + while ((context->count[0] & 504) != 448) { + sha1Update(context, (unsigned char*) "\0", 1); + } + sha1Update(context, finalcount, 8); + /* Should cause SHA1_Transform */ + for (i = 0; i < SHA1_DIGEST_SIZE; i++) { + digest[i] = (unsigned char) + ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); + } + /* Wipe variables */ + i = 0; + ::memset(context->buffer, 0, 64); + ::memset(context->state, 0, 20); + ::memset(context->count, 0, 8); + ::memset(finalcount, 0, 8); /* SWR */ + +#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite its own static vars */ + transform(context->state, context->buffer); +#endif +} + +void KeyGenerator::sha1Transform(unsigned int state[5], const unsigned char buffer[64]) +{ + uint32_t a, b, c, d, e; + typedef union { + unsigned char c[64]; + unsigned int l[16]; + } CHAR64LONG16; + CHAR64LONG16 *block; + +#ifdef SHA1HANDSOFF + CHAR64LONG16 workspace; + block = &workspace; + ::memcpy(block, buffer, 64); +#else + block = (CHAR64LONG16*)buffer; +#endif + + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a, b, c, d, e, 0); R0(e, a, b, c, d, 1); R0(d, e, a, b, c, 2); R0(c, d, e, a, b, 3); + R0(b, c, d, e, a, 4); R0(a, b, c, d, e, 5); R0(e, a, b, c, d, 6); R0(d, e, a, b, c, 7); + R0(c, d, e, a, b, 8); R0(b, c, d, e, a, 9); R0(a, b, c, d, e, 10); R0(e, a, b, c, d, 11); + R0(d, e, a, b, c, 12); R0(c, d, e, a, b, 13); R0(b, c, d, e, a, 14); R0(a, b, c, d, e, 15); + R1(e, a, b, c, d, 16); R1(d, e, a, b, c, 17); R1(c, d, e, a, b, 18); R1(b, c, d, e, a, 19); + R2(a, b, c, d, e, 20); R2(e, a, b, c, d, 21); R2(d, e, a, b, c, 22); R2(c, d, e, a, b, 23); + R2(b, c, d, e, a, 24); R2(a, b, c, d, e, 25); R2(e, a, b, c, d, 26); R2(d, e, a, b, c, 27); + R2(c, d, e, a, b, 28); R2(b, c, d, e, a, 29); R2(a, b, c, d, e, 30); R2(e, a, b, c, d, 31); + R2(d, e, a, b, c, 32); R2(c, d, e, a, b, 33); R2(b, c, d, e, a, 34); R2(a, b, c, d, e, 35); + R2(e, a, b, c, d, 36); R2(d, e, a, b, c, 37); R2(c, d, e, a, b, 38); R2(b, c, d, e, a, 39); + R3(a, b, c, d, e, 40); R3(e, a, b, c, d, 41); R3(d, e, a, b, c, 42); R3(c, d, e, a, b, 43); + R3(b, c, d, e, a, 44); R3(a, b, c, d, e, 45); R3(e, a, b, c, d, 46); R3(d, e, a, b, c, 47); + R3(c, d, e, a, b, 48); R3(b, c, d, e, a, 49); R3(a, b, c, d, e, 50); R3(e, a, b, c, d, 51); + R3(d, e, a, b, c, 52); R3(c, d, e, a, b, 53); R3(b, c, d, e, a, 54); R3(a, b, c, d, e, 55); + R3(e, a, b, c, d, 56); R3(d, e, a, b, c, 57); R3(c, d, e, a, b, 58); R3(b, c, d, e, a, 59); + R4(a, b, c, d, e, 60); R4(e, a, b, c, d, 61); R4(d, e, a, b, c, 62); R4(c, d, e, a, b, 63); + R4(b, c, d, e, a, 64); R4(a, b, c, d, e, 65); R4(e, a, b, c, d, 66); R4(d, e, a, b, c, 67); + R4(c, d, e, a, b, 68); R4(b, c, d, e, a, 69); R4(a, b, c, d, e, 70); R4(e, a, b, c, d, 71); + R4(d, e, a, b, c, 72); R4(c, d, e, a, b, 73); R4(b, c, d, e, a, 74); R4(a, b, c, d, e, 75); + R4(e, a, b, c, d, 76); R4(d, e, a, b, c, 77); R4(c, d, e, a, b, 78); R4(b, c, d, e, a, 79); + + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + + /* Wipe variables */ + a = b = c = d = e = 0; +} + +void KeyGenerator::sha1Hmac(const unsigned char* key, int keyLen, const unsigned char* data, int dataLen, unsigned char out[SHA1_DIGEST_SIZE]) +{ + SHA1_CTX ctx; + unsigned char buf[SHA_BLOCKSIZE], outPad[SHA_BLOCKSIZE], inPad[SHA_BLOCKSIZE]; + unsigned char tempKey[SHA1_DIGEST_SIZE]; + int i; + + ::memset(buf, 0, SHA_BLOCKSIZE); + + if (keyLen > SHA_BLOCKSIZE) { + sha1Init(&ctx); + sha1Update(&ctx, key, keyLen); + sha1Final(tempKey, &ctx); + key = tempKey; + keyLen = SHA1_DIGEST_SIZE; + } + + ::memcpy(buf, key, keyLen); + ::memset(inPad, 0, SHA_BLOCKSIZE); + ::memset(outPad, 0, SHA_BLOCKSIZE); + + for (i=0; i> 24) & 0xff); + itmp[saltLen + 1] = (unsigned char)((i >> 16) & 0xff); + itmp[saltLen + 2] = (unsigned char)((i >> 8) & 0xff); + itmp[saltLen + 3] = (unsigned char)(i & 0xff); + + sha1Hmac((unsigned char*)pass, passLen, itmp, saltLen+4, digtmp1); + ::memcpy(digtmp2, digtmp1, SHA1_DIGEST_SIZE); + + for (j=1; j + +#include + +#include "key-manager.h" + +#include "exception.h" + +#define addAliasPrefix(alias) \ + (ckmcIdSystem + ckmcIdSeperator + alias) + +namespace { + +const std::string ckmcIdSystem = ckmc_owner_id_system; +const std::string ckmcIdSeperator = ckmc_owner_id_separator; + +} //namespace + +bool KeyManager::isKeyExist(const std::string& keyName) +{ + int ret; + ckmc_raw_buffer_s* keyData = NULL; + std::string ckmAlias = addAliasPrefix(keyName); + + ret = ::ckmc_get_data(ckmAlias.c_str(), NULL, &keyData); + ::ckmc_buffer_free(keyData); + + return (ret != CKMC_ERROR_DB_ALIAS_UNKNOWN); +} + +void KeyManager::addKey(const std::string& keyName, const std::string& data) +{ + int ret; + const std::string ckmAlias = addAliasPrefix(keyName); + ckmc_raw_buffer_s keyData; + ckmc_policy_s keyPolicy; + + keyData.data = (unsigned char*)data.c_str(); + keyData.size = data.size(); + + keyPolicy.password = NULL; + keyPolicy.extractable = true; + + ret = ::ckmc_save_data(ckmAlias.c_str(), keyData, keyPolicy); + if (ret != 0) { + throw runtime::Exception("Failed to add key data"); + } +} + +std::string KeyManager::getKey(const std::string& keyName) +{ + int ret; + const std::string ckmAlias = addAliasPrefix(keyName); + ckmc_raw_buffer_s* keyData; + std::string result; + + ret = ::ckmc_get_data(ckmAlias.c_str(), NULL, &keyData); + if (ret != CKMC_ERROR_NONE) { + throw runtime::Exception("Failed to get key data"); + } + + result = std::string(reinterpret_cast(keyData->data), keyData->size); + + ::ckmc_buffer_free(keyData); + + return result; +} + +void KeyManager::removeKey(const std::string& keyName) +{ + const std::string ckmAlias = addAliasPrefix(keyName); + + if (::ckmc_remove_data(ckmAlias.c_str()) != 0) { + throw runtime::Exception("Failed to remove key data"); + } +} diff --git a/zone/volume/key-manager.h b/zone/volume/key-manager.h new file mode 100644 index 0000000..2bdf74d --- /dev/null +++ b/zone/volume/key-manager.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2015 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 + */ + +#ifndef __ZONE_KEY_MANAGER_H__ +#define __ZONE_KEY_MANAGER_H__ + +class KeyManager { +public: + KeyManager() = delete; + KeyManager(const KeyManager&) = delete; + KeyManager(KeyManager&&) = delete; + + KeyManager& operator=(const KeyManager&) = delete; + KeyManager& operator=(KeyManager&&) = delete; + + static bool isKeyExist(const std::string& keyName); + static void addKey(const std::string& keyName, const std::string& data); + static std::string getKey(const std::string& keyName); + static void removeKey(const std::string& keyName); +}; + +#endif //!__ZONE_KEY_MANAGER_H__*/ diff --git a/zone/volume/main.cpp b/zone/volume/main.cpp new file mode 100644 index 0000000..7592cb9 --- /dev/null +++ b/zone/volume/main.cpp @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2015 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 + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "ecryptfs.h" +#include "kernel-keyring.h" +#include "key-manager.h" +#include "key-generator.h" + +#include "error.h" +#include "exception.h" +#include "audit/logger.h" + +int generateKey(const std::string& keyName) +{ + if (KeyManager::isKeyExist(keyName)) { + ERROR("Key already registered"); + return -1; + } + + try { + std::string pass = KeyGenerator::generateKey(ECRYPTFS_MAX_KEY_SIZE); + std::string salt = KeyGenerator::generateKey(ECRYPTFS_MAX_SALT_SIZE); + std::string wrappedKey = KeyGenerator::wrapKey(pass, salt, ECRYPTFS_MAX_KEY_SIZE); + + KeyManager::addKey(keyName, wrappedKey); + } catch (runtime::Exception& e) { + ERROR(e.what()); + return -1; + } + + return 0; +} + +ecryptfs_payload* generateToken(char* key) +{ + struct ecryptfs_password* tokenKey; + + unsigned char keyBuffer[ECRYPTFS_MAX_KEY_SIZE]; + + ecryptfs_payload* authToken = (ecryptfs_payload *)::malloc(sizeof(ecryptfs_payload)); + if (authToken == NULL) { + return NULL; + } + + ::memset(authToken, 0, sizeof(ecryptfs_payload)); + ::memcpy(keyBuffer, key, ECRYPTFS_MAX_KEY_SIZE); + + tokenKey = &authToken->token.password; + + authToken->version = ECRYPTFS_VERSION; + authToken->token_type = ECRYPTFS_PWD_PAYLOAD_TYPE; + tokenKey->session_key_encryption_key_bytes = ECRYPTFS_MAX_KEY_SIZE; + tokenKey->flags = ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET; + ::memcpy(tokenKey->session_key_encryption_key, keyBuffer, ECRYPTFS_MAX_KEY_SIZE); + ::memcpy(tokenKey->signature, keyBuffer, ECRYPTFS_MAX_SIG_HEX); + + return authToken; +} + +int mountEcryptfs(const std::string& src, const std::string& keyName) +{ + int rc; + char ecryptfsOpts[1024]; + ecryptfs_payload* authTok = NULL; + + std::string key; + try { + key = KeyManager::getKey(keyName); + } catch (runtime::Exception& e) { + ERROR(e.what()); + return -1; + } + + if (KernelKeyRing::link(KEY_SPEC_USER_KEYRING, KEY_SPEC_SESSION_KEYRING) != 0) { + ERROR("Failed to link key"); + return -1; + } + + if ((authTok = generateToken((char*)key.c_str())) == NULL) { + ERROR("Failed to generate Token"); + return -1; + } + + const char* signature = (const char*)authTok->token.password.signature; + rc = KernelKeyRing::search(KEY_SPEC_USER_KEYRING, + "user", + signature, + 0); + if (rc == -1 && errno != ENOKEY) { + ERROR("Failed to find key"); + return -1; + } + if (rc == -1) { + rc = KernelKeyRing::add("user", + signature, + (void*)authTok, + sizeof(ecryptfs_payload), + KEY_SPEC_USER_KEYRING); + if (rc == -1) { + ERROR("Failed to add key"); + return -1; + } + } + + ::snprintf(ecryptfsOpts, 1024, + "ecryptfs_passthrough," + "ecryptfs_cipher=aes," + "ecryptfs_key_bytes=%d," + "ecryptfs_sig=%s," + "smackfsroot=*,smackfsdef=*", + ECRYPTFS_MAX_KEY_SIZE, signature); + + rc = ::mount(src.c_str(), src.c_str(), "ecryptfs", MS_NODEV, ecryptfsOpts); + if (rc != 0) { + ERROR(runtime::GetSystemErrorMessage()); + return -1; + } + + return 0; +} + +int mountEcryptfsToAll() +{ + return 0; +} + +void usage(const std::string& prog) +{ + std::cout << "Usage: " << prog << std::endl + << "-a : Automount" << std::endl + << "-g name : Generate key for zone" << std::endl + << "-m name : Apply filesystem encrytion to zone" << std::endl; +} + +int main(int argc, char* argv[]) +{ + int opt, index, ret = -1; + struct option options[] = { + {"automount", no_argument, 0, 'a'}, + {"generate", required_argument, 0, 'g'}, + {"mount", required_argument, 0, 'm'}, + {0, 0, 0, 0} + }; + + while ((opt = getopt_long(argc, argv, "ag:m:", options, &index)) != -1) { + switch (opt) { + case 'a': + ret = mountEcryptfsToAll(); + break; + case 'g': + ret = generateKey(optarg); + break; + case 'm': + ret = mountEcryptfs("/home/" + std::string(optarg), optarg); + break; + default: + std::cerr << "unknown" << std::endl; + usage(argv[0]); + break; + } + } + + if (ret != 0) { + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} -- 2.7.4