[hwaes] Add hwaes service
This is a mock hwaes service, which leverages boringssl to
perform AES operations. The mock hwaes service also demonstrates
the usage of hwaes lib for server side.
Bug: 182963097
Test: com.android.trusty.hwaes.test
Change-Id: Ib44efa4fc48ad8af62f2407c140f1cafa9a47f02
diff --git a/hwaes/main.c b/hwaes/main.c
new file mode 100644
index 0000000..6e24821
--- /dev/null
+++ b/hwaes/main.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define TLOG_TAG "hwaes_srv"
+
+#include <assert.h>
+#include <lib/hwaes_server/hwaes_server.h>
+#include <lib/tipc/tipc_srv.h>
+#include <lk/err_ptr.h>
+#include <stdlib.h>
+#include <string.h>
+#include <trusty_log.h>
+#include <uapi/err.h>
+
+#include <openssl/evp.h>
+
+static EVP_CIPHER_CTX* cipher_ctx;
+
+static void crypt_init(void) {
+ assert(!cipher_ctx);
+
+ cipher_ctx = EVP_CIPHER_CTX_new();
+ assert(cipher_ctx);
+}
+
+static void crypt_shutdown(void) {
+ EVP_CIPHER_CTX_free(cipher_ctx);
+ cipher_ctx = NULL;
+}
+
+static uint32_t hwaes_check_arg_helper(size_t len, const uint8_t* data_ptr) {
+ if (len == 0 || data_ptr == NULL) {
+ return HWAES_ERR_INVALID_ARGS;
+ }
+ return HWAES_NO_ERROR;
+}
+
+static uint32_t hwaes_check_arg_in(const struct hwaes_arg_in* arg) {
+ return hwaes_check_arg_helper(arg->len, arg->data_ptr);
+}
+
+static uint32_t hwaes_check_arg_out(const struct hwaes_arg_out* arg) {
+ return hwaes_check_arg_helper(arg->len, arg->data_ptr);
+}
+
+uint32_t hwaes_aes_op(const struct hwaes_aes_op_args* args) {
+ int evp_ret;
+ uint32_t rc;
+ const EVP_CIPHER* cipher;
+ int out_data_size;
+
+ if (args->mode != HWAES_CBC_MODE) {
+ TLOGE("the mode is not implemented yet\n");
+ return HWAES_ERR_NOT_IMPLEMENTED;
+ }
+
+ if (args->padding != HWAES_NO_PADDING) {
+ TLOGE("the padding type is not implemented yet\n");
+ return HWAES_ERR_NOT_IMPLEMENTED;
+ }
+
+ rc = hwaes_check_arg_in(&args->key);
+ if (rc != HWAES_NO_ERROR) {
+ TLOGE("key argument is missing\n");
+ return rc;
+ }
+
+ rc = hwaes_check_arg_in(&args->text_in);
+ if (rc != HWAES_NO_ERROR) {
+ TLOGE("text_in argument is missing\n");
+ return rc;
+ }
+
+ rc = hwaes_check_arg_out(&args->text_out);
+ if (rc != HWAES_NO_ERROR) {
+ TLOGE("text_out argument is missing\n");
+ return rc;
+ }
+
+ /*
+ * The current implementation does not support padding.
+ * So the size of input buffer is the same as output buffer.
+ */
+ if (args->text_in.len != args->text_out.len) {
+ TLOGE("text_in_len (%zd) is not equal to text_out_len (%zd)\n",
+ args->text_in.len, args->text_out.len);
+ return HWAES_ERR_INVALID_ARGS;
+ }
+
+ switch (args->key.len) {
+ case 16:
+ cipher = EVP_aes_128_cbc();
+ break;
+ case 32:
+ cipher = EVP_aes_256_cbc();
+ break;
+ default:
+ TLOGE("invalid key length: (%zd)\n", args->key.len);
+ return HWAES_ERR_INVALID_ARGS;
+ }
+
+ assert(cipher_ctx);
+ EVP_CIPHER_CTX_reset(cipher_ctx);
+
+ evp_ret = EVP_CipherInit_ex(cipher_ctx, cipher, NULL, NULL, NULL,
+ args->encrypt);
+ if (!evp_ret) {
+ TLOGE("EVP_CipherInit_ex failed\n");
+ return HWAES_ERR_GENERIC;
+ }
+
+ if (args->text_in.len % EVP_CIPHER_CTX_block_size(cipher_ctx)) {
+ TLOGE("text_in_len (%zd) is not block aligned\n", args->text_in.len);
+ return HWAES_ERR_INVALID_ARGS;
+ }
+
+ if (EVP_CIPHER_CTX_iv_length(cipher_ctx) != args->iv.len) {
+ TLOGE("invalid iv length: (%zd)\n", args->iv.len);
+ return HWAES_ERR_INVALID_ARGS;
+ }
+
+ evp_ret = EVP_CipherInit_ex(cipher_ctx, cipher, NULL, args->key.data_ptr,
+ args->iv.data_ptr, args->encrypt);
+ if (!evp_ret) {
+ TLOGE("EVP_CipherInit_ex failed\n");
+ return HWAES_ERR_GENERIC;
+ }
+
+ evp_ret = EVP_CIPHER_CTX_set_padding(cipher_ctx, 0);
+ if (!evp_ret) {
+ TLOGE("EVP_CIPHER_CTX_set_padding failed\n");
+ return HWAES_ERR_GENERIC;
+ }
+
+ evp_ret = EVP_CipherUpdate(cipher_ctx, args->text_out.data_ptr,
+ &out_data_size, args->text_in.data_ptr,
+ args->text_in.len);
+ if (!evp_ret) {
+ TLOGE("EVP_CipherUpdate failed\n");
+ return HWAES_ERR_GENERIC;
+ }
+
+ /*
+ * The assert fails if the memory corruption happens.
+ */
+ assert(out_data_size == (int)args->text_out.len);
+
+ /*
+ * Currently we don't support padding.
+ */
+ evp_ret = EVP_CipherFinal_ex(cipher_ctx, NULL, &out_data_size);
+ if (!evp_ret) {
+ TLOGE("EVP_CipherFinal_ex failed\n");
+ return HWAES_ERR_GENERIC;
+ }
+
+ return HWAES_NO_ERROR;
+}
+
+int main(void) {
+ int rc;
+ struct tipc_hset* hset;
+
+ hset = tipc_hset_create();
+ if (IS_ERR(hset)) {
+ TLOGE("failed (%d) to create handle set\n", PTR_ERR(hset));
+ return EXIT_FAILURE;
+ }
+
+ rc = add_hwaes_service(hset);
+ if (rc != NO_ERROR) {
+ TLOGE("failed (%d) to initialize hwaes service\n", rc);
+ return EXIT_FAILURE;
+ }
+
+ crypt_init();
+ rc = tipc_run_event_loop(hset);
+
+ TLOGE("hwaes server going down: (%d)\n", rc);
+ crypt_shutdown();
+ if (rc != NO_ERROR) {
+ return EXIT_FAILURE;
+ }
+ EXIT_SUCCESS;
+}
diff --git a/hwaes/manifest.json b/hwaes/manifest.json
new file mode 100644
index 0000000..ef87dcc
--- /dev/null
+++ b/hwaes/manifest.json
@@ -0,0 +1,5 @@
+{
+ "uuid": "6f4a2303-f4f8-431d-82d1-3ec52aebbb89",
+ "min_heap": 4096,
+ "min_stack":40960
+}
diff --git a/hwaes/rules.mk b/hwaes/rules.mk
new file mode 100644
index 0000000..66d3ec3
--- /dev/null
+++ b/hwaes/rules.mk
@@ -0,0 +1,32 @@
+#
+# Copyright (C) 2020 The Android Open Source Project
+#
+# 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.
+#
+
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+MODULE := $(LOCAL_DIR)
+
+MANIFEST := $(LOCAL_DIR)/manifest.json
+
+MODULE_SRCS := \
+ $(LOCAL_DIR)/main.c \
+
+MODULE_DEPS := \
+ trusty/user/base/lib/libc-trusty \
+ trusty/user/base/lib/hwaes/srv \
+ trusty/user/base/lib/tipc \
+ external/boringssl \
+
+include make/module.mk