diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7b9e20c..7abe779 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -38,6 +38,7 @@ set(SOURCES ${SOURCES}
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/openpgp.c
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/files.c
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/piv.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/openpgp/management.c
)
set(INCLUDES ${INCLUDES}
diff --git a/src/openpgp/files.h b/src/openpgp/files.h
index e75e1f2..e6fd717 100644
--- a/src/openpgp/files.h
+++ b/src/openpgp/files.h
@@ -161,4 +161,6 @@
#define EF_PIV_RETIRED19 0xc11f
#define EF_PIV_RETIRED20 0xc120
+#define EF_DEV_CONF 0x1122
+
#endif
diff --git a/src/openpgp/management.c b/src/openpgp/management.c
new file mode 100644
index 0000000..751f8b0
--- /dev/null
+++ b/src/openpgp/management.c
@@ -0,0 +1,154 @@
+/*
+ * This file is part of the Pico FIDO distribution (https://github.com/polhenarejos/pico-fido).
+ * Copyright (c) 2022 Pol Henarejos.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include "pico_keys.h"
+#include "apdu.h"
+#include "version.h"
+#include "files.h"
+#include "asn1.h"
+#include "management.h"
+
+int man_process_apdu();
+int man_unload();
+
+const uint8_t man_aid[] = {
+ 8,
+ 0xa0, 0x00, 0x00, 0x05, 0x27, 0x47, 0x11, 0x17
+};
+
+extern void init_piv();
+int man_select(app_t *a) {
+ a->process_apdu = man_process_apdu;
+ a->unload = man_unload;
+ sprintf((char *) res_APDU, "%d.%d.0", PIV_VERSION_MAJOR, PIV_VERSION_MINOR);
+ res_APDU_size = strlen((char *) res_APDU);
+ apdu.ne = res_APDU_size;
+ init_piv();
+ return CCID_OK;
+}
+
+void __attribute__((constructor)) man_ctor() {
+ register_app(man_select, man_aid);
+}
+
+int man_unload() {
+ return CCID_OK;
+}
+
+bool cap_supported(uint16_t cap) {
+ file_t *ef = search_dynamic_file(EF_DEV_CONF);
+ if (file_has_data(ef)) {
+ uint16_t tag = 0x0;
+ uint8_t *tag_data = NULL, *p = NULL;
+ uint16_t tag_len = 0;
+ asn1_ctx_t ctxi;
+ asn1_ctx_init(file_get_data(ef), file_get_size(ef), &ctxi);
+ while (walk_tlv(&ctxi, &p, &tag, &tag_len, &tag_data)) {
+ if (tag == TAG_USB_ENABLED) {
+ uint16_t ecaps = tag_data[0];
+ if (tag_len == 2) {
+ ecaps = (tag_data[0] << 8) | tag_data[1];
+ }
+ return ecaps & cap;
+ }
+ }
+ }
+ return true;
+}
+
+int man_get_config() {
+ file_t *ef = search_dynamic_file(EF_DEV_CONF);
+ res_APDU_size = 0;
+ res_APDU[res_APDU_size++] = 0; // Overall length. Filled later
+ res_APDU[res_APDU_size++] = TAG_USB_SUPPORTED;
+ res_APDU[res_APDU_size++] = 1;
+ res_APDU[res_APDU_size++] = CAP_PIV | CAP_OPENPGP;
+ res_APDU[res_APDU_size++] = TAG_SERIAL;
+ res_APDU[res_APDU_size++] = 4;
+#ifndef ENABLE_EMULATION
+ pico_get_unique_board_id_string((char *) res_APDU + res_APDU_size, 4);
+#endif
+ res_APDU_size += 4;
+ res_APDU[res_APDU_size++] = TAG_FORM_FACTOR;
+ res_APDU[res_APDU_size++] = 1;
+ res_APDU[res_APDU_size++] = 0x01;
+ res_APDU[res_APDU_size++] = TAG_VERSION;
+ res_APDU[res_APDU_size++] = 3;
+ res_APDU[res_APDU_size++] = PIV_VERSION_MAJOR;
+ res_APDU[res_APDU_size++] = PIV_VERSION_MINOR;
+ res_APDU[res_APDU_size++] = 0;
+ res_APDU[res_APDU_size++] = TAG_NFC_SUPPORTED;
+ res_APDU[res_APDU_size++] = 1;
+ res_APDU[res_APDU_size++] = 0x00;
+ if (!file_has_data(ef)) {
+ res_APDU[res_APDU_size++] = TAG_USB_ENABLED;
+ res_APDU[res_APDU_size++] = 1;
+ res_APDU[res_APDU_size++] = CAP_PIV | CAP_OPENPGP;
+ res_APDU[res_APDU_size++] = TAG_DEVICE_FLAGS;
+ res_APDU[res_APDU_size++] = 1;
+ res_APDU[res_APDU_size++] = FLAG_EJECT;
+ res_APDU[res_APDU_size++] = TAG_CONFIG_LOCK;
+ res_APDU[res_APDU_size++] = 1;
+ res_APDU[res_APDU_size++] = 0x00;
+ res_APDU[res_APDU_size++] = TAG_NFC_ENABLED;
+ res_APDU[res_APDU_size++] = 1;
+ res_APDU[res_APDU_size++] = 0x00;
+ }
+ else {
+ memcpy(res_APDU + res_APDU_size, file_get_data(ef), file_get_size(ef));
+ res_APDU_size += file_get_size(ef);
+ }
+ res_APDU[0] = res_APDU_size - 1;
+ return 0;
+}
+
+int cmd_read_config() {
+ man_get_config();
+ return SW_OK();
+}
+
+int cmd_write_config() {
+ if (apdu.data[0] != apdu.nc - 1) {
+ return SW_WRONG_DATA();
+ }
+ file_t *ef = file_new(EF_DEV_CONF);
+ file_put_data(ef, apdu.data + 1, apdu.nc - 1);
+ low_flash_available();
+ return SW_OK();
+}
+
+#define INS_READ_CONFIG 0x1D
+#define INS_WRITE_CONFIG 0x1C
+
+static const cmd_t cmds[] = {
+ { INS_READ_CONFIG, cmd_read_config },
+ { INS_WRITE_CONFIG, cmd_write_config },
+ { 0x00, 0x0 }
+};
+
+int man_process_apdu() {
+ if (CLA(apdu) != 0x00) {
+ return SW_CLA_NOT_SUPPORTED();
+ }
+ for (const cmd_t *cmd = cmds; cmd->ins != 0x00; cmd++) {
+ if (cmd->ins == INS(apdu)) {
+ int r = cmd->cmd_handler();
+ return r;
+ }
+ }
+ return SW_INS_NOT_SUPPORTED();
+}
diff --git a/src/openpgp/management.h b/src/openpgp/management.h
new file mode 100644
index 0000000..6a5ff0d
--- /dev/null
+++ b/src/openpgp/management.h
@@ -0,0 +1,55 @@
+/*
+ * This file is part of the Pico FIDO distribution (https://github.com/polhenarejos/pico-fido).
+ * Copyright (c) 2022 Pol Henarejos.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef _MANAGEMENT_H_
+#define _MANAGEMENT_H_
+
+#include
+#ifndef ENABLE_EMULATION
+#include "pico/stdlib.h"
+#endif
+
+#define TAG_USB_SUPPORTED 0x01
+#define TAG_SERIAL 0x02
+#define TAG_USB_ENABLED 0x03
+#define TAG_FORM_FACTOR 0x04
+#define TAG_VERSION 0x05
+#define TAG_AUTO_EJECT_TIMEOUT 0x06
+#define TAG_CHALRESP_TIMEOUT 0x07
+#define TAG_DEVICE_FLAGS 0x08
+#define TAG_APP_VERSIONS 0x09
+#define TAG_CONFIG_LOCK 0x0A
+#define TAG_UNLOCK 0x0B
+#define TAG_REBOOT 0x0C
+#define TAG_NFC_SUPPORTED 0x0D
+#define TAG_NFC_ENABLED 0x0E
+
+#define CAP_OTP 0x01
+#define CAP_U2F 0x02
+#define CAP_FIDO2 0x200
+#define CAP_OATH 0x20
+#define CAP_PIV 0x10
+#define CAP_OPENPGP 0x08
+#define CAP_HSMAUTH 0x100
+
+#define FLAG_REMOTE_WAKEUP 0x40
+#define FLAG_EJECT 0x80
+
+extern bool cap_supported(uint16_t cap);
+extern int man_get_config();
+
+#endif //_MANAGEMENT_H
diff --git a/src/openpgp/piv.c b/src/openpgp/piv.c
index 6ca4af2..5914e1a 100644
--- a/src/openpgp/piv.c
+++ b/src/openpgp/piv.c
@@ -70,10 +70,6 @@ uint8_t yk_aid[] = {
8,
0xA0, 0x00, 0x00, 0x05, 0x27, 0x20, 0x1, 0x1
};
-uint8_t mgmt_aid[] = {
- 8,
- 0xA0, 0x00, 0x00, 0x05, 0x27, 0x47, 0x11, 0x17
-};
bool has_pwpiv = false;
uint8_t session_pwpiv[32];
@@ -318,7 +314,6 @@ int piv_select_aid(app_t *a) {
void __attribute__((constructor)) piv_ctor() {
register_app(piv_select_aid, piv_aid);
register_app(piv_select_aid, yk_aid);
- register_app(piv_select_aid, mgmt_aid);
}
static int cmd_version() {