libese: initial commit
libese is a low level library for enabling embedded secure
element use from Java or embedded usecases.
This commit defines the client API, the hardware abstraction API,
and supplies functional implementation of the T=1 protocol (frequently
used as the wire protocol for SPI attached smart cards/eSEs).
Included in this is one hardware reference implementation using
a NXP PN80T developer board wired to a HiKey 6220.
Test: baseline unittests; manual run of the examples/ese_nxp_sample; use
of relay with hardware
Bug: 34193615
Change-Id: I98037793bc29b3730c5301ee9cd5e6cd7465117d
diff --git a/libese/ese.c b/libese/ese.c
new file mode 100644
index 0000000..1e49e22
--- /dev/null
+++ b/libese/ese.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include <ese/ese.h>
+#include <ese/log.h>
+
+#include "ese_private.h"
+
+static const char kUnknownHw[] = "unknown hw";
+static const char kNullEse[] = "NULL EseInterface";
+static const char *kEseErrorMessages[] = {
+ "Hardware supplied no transceive implementation.",
+ "Timed out polling for value.",
+};
+#define ESE_MESSAGES(x) (sizeof(x) / sizeof((x)[0]))
+
+/* TODO(wad): Make the default visibility on this one default default? */
+API const char *ese_name(struct EseInterface *ese) {
+ if (!ese)
+ return kNullEse;
+ if (ese->ops->name)
+ return ese->ops->name;
+ return kUnknownHw;
+}
+
+API int ese_open(struct EseInterface *ese, void *hw_opts) {
+ if (!ese)
+ return -1;
+ ALOGV("opening interface '%s'", ese_name(ese));
+ if (ese->ops->open)
+ return ese->ops->open(ese, hw_opts);
+ return 0;
+}
+
+API const char *ese_error_message(struct EseInterface *ese) {
+ return ese->error.message;
+}
+
+API int ese_error_code(struct EseInterface *ese) { return ese->error.code; }
+
+API int ese_error(struct EseInterface *ese) { return ese->error.is_err; }
+
+API void ese_set_error(struct EseInterface *ese, int code) {
+ if (!ese)
+ return;
+ /* Negative values are reserved for API wide messages. */
+ ese->error.code = code;
+ ese->error.is_err = 1;
+ if (code < 0) {
+ code = -(code + 1); /* Start at 0. */
+ if ((size_t)(code) >= ESE_MESSAGES(kEseErrorMessages)) {
+ LOG_ALWAYS_FATAL("Unknown global error code passed to ese_set_error(%d)",
+ code);
+ }
+ ese->error.message = kEseErrorMessages[code];
+ return;
+ }
+ if ((size_t)(code) >= ese->errors_count) {
+ LOG_ALWAYS_FATAL("Unknown hw error code passed to ese_set_error(%d)", code);
+ }
+ ese->error.message = ese->errors[code];
+}
+
+/* Blocking. */
+API int ese_transceive(struct EseInterface *ese, uint8_t *const tx_buf,
+ size_t tx_len, uint8_t *rx_buf, size_t rx_max) {
+ size_t recvd = 0;
+ if (!ese)
+ return -1;
+ while (1) {
+ if (ese->ops->transceive) {
+ recvd = ese->ops->transceive(ese, tx_buf, tx_len, rx_buf, rx_max);
+ break;
+ }
+ if (ese->ops->hw_transmit && ese->ops->hw_receive) {
+ ese->ops->hw_transmit(ese, tx_buf, tx_len, 1);
+ if (ese->error.is_err)
+ break;
+ recvd = ese->ops->hw_receive(ese, rx_buf, rx_max, 1);
+ break;
+ }
+ ese_set_error(ese, -1);
+ break;
+ }
+ if (ese->error.is_err)
+ return -1;
+ return recvd;
+}
+
+API int ese_close(struct EseInterface *ese) {
+ if (!ese)
+ return -1;
+ ALOGV("closing interface '%s'", ese_name(ese));
+ if (!ese->ops->close)
+ return 0;
+ return ese->ops->close(ese);
+}