mirror of
https://github.com/estkme-group/lpac
synced 2024-07-02 14:56:39 +02:00
[WIP] remove dlfcn interface driver (curl on Windows still require dlfcn)
This commit is contained in:
parent
4095ab5a15
commit
96f47f2d52
|
@ -1,4 +1,5 @@
|
|||
cmake_minimum_required (VERSION 3.8)
|
||||
|
||||
project (lpac
|
||||
VERSION 1.0.1
|
||||
HOMEPAGE_URL "https://github.com/estkme-group/lpac"
|
||||
|
@ -13,10 +14,6 @@ if (APPLE)
|
|||
set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64")
|
||||
endif()
|
||||
|
||||
if(CYGWIN)
|
||||
add_definitions(-DHAVE_TIMEGM=1)
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
include(GNUInstallDirs)
|
||||
if(NOT CMAKE_INSTALL_RPATH)
|
||||
|
@ -24,6 +21,13 @@ if(UNIX)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
add_subdirectory(dlfcn-win32)
|
||||
set(DL_LIBRARY dlfcn-win32)
|
||||
else()
|
||||
set(DL_LIBRARY dl)
|
||||
endif()
|
||||
|
||||
if(CPACK_GENERATOR)
|
||||
set(CPACK_PACKAGE_VENDOR "eSTK.me Group")
|
||||
|
||||
|
@ -31,20 +35,13 @@ if(CPACK_GENERATOR)
|
|||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc")
|
||||
set(CPACK_DEBIAN_PACKAGE_RECOMMENDS "libcurl, libpcsclite, pcscd")
|
||||
|
||||
set(CPACK_RPM_PACKAGE_LICENSE "AGPL-3.0-only AND LGPL-2.0-only AND MIT")
|
||||
set(CPACK_RPM_PACKAGE_LICENSE "AGPL-3.0-only AND LGPL-2.0-only")
|
||||
set(CPACK_RPM_PACKAGE_AUTOREQ "yes")
|
||||
set(CPACK_RPM_PACKAGE_REQUIRES "libcurl, libpcsclite, pcscd")
|
||||
|
||||
include(CPack)
|
||||
endif()
|
||||
|
||||
if(MINGW)
|
||||
add_subdirectory(dlfcn-win32)
|
||||
set(DL_LIBRARY dlfcn-win32)
|
||||
else()
|
||||
set(DL_LIBRARY dl)
|
||||
endif()
|
||||
add_subdirectory(cjson)
|
||||
add_subdirectory(euicc)
|
||||
add_subdirectory(interface)
|
||||
add_subdirectory(src)
|
||||
|
|
|
@ -489,6 +489,5 @@ A: The verification of SM-DP+ servers of telecom operators is diverse. Please ch
|
|||
|
||||
- lpac (/src): AGPL-3.0
|
||||
- libeuicc (/euicc): LGPL-v2
|
||||
- interfaces (/interface): MIT
|
||||
|
||||
Copyright (c) 2023-2024 eSTKme Group
|
||||
|
|
|
@ -1,12 +1,6 @@
|
|||
#pragma once
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#define EUICC_SHARED_EXPORT __declspec(dllexport) __cdecl
|
||||
#else
|
||||
#define EUICC_SHARED_EXPORT
|
||||
#endif
|
||||
|
||||
struct euicc_ctx;
|
||||
|
||||
struct euicc_apdu_interface
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
add_subdirectory(apdu)
|
||||
add_subdirectory(http)
|
|
@ -1,21 +0,0 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2023 estkme-group
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -1,188 +0,0 @@
|
|||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#include <dlfcn-win32/dlfcn.h>
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#include <euicc/interface.h>
|
||||
|
||||
/* BEGIN MINIMAL CURL DEFINE */
|
||||
#if defined (_WIN32) || defined (__CYGWIN__)
|
||||
#define LIBCURL_DEFAULT_PATH "libcurl.dll"
|
||||
#elif defined(__APPLE__)
|
||||
#define LIBCURL_DEFAULT_PATH "libcurl.4.dylib"
|
||||
#else
|
||||
#define LIBCURL_DEFAULT_PATH "libcurl.so.4"
|
||||
#endif
|
||||
|
||||
#define CURL_GLOBAL_DEFAULT ((1 << 0) | (1 << 1))
|
||||
#define CURLE_OK 0
|
||||
#define CURLOPT_URL 10002
|
||||
#define CURLOPT_WRITEFUNCTION 20011
|
||||
#define CURLOPT_WRITEDATA 10001
|
||||
#define CURLOPT_SSL_VERIFYPEER 64
|
||||
#define CURLOPT_SSL_VERIFYHOST 81
|
||||
#define CURLOPT_HTTPHEADER 10023
|
||||
#define CURLOPT_POSTFIELDS 10015
|
||||
#define CURLOPT_POSTFIELDSIZE 60
|
||||
#define CURLINFO_RESPONSE_CODE 2097154
|
||||
|
||||
typedef void CURL;
|
||||
typedef int CURLcode;
|
||||
typedef int CURLoption;
|
||||
typedef int CURLINFO;
|
||||
|
||||
static void *libcurl_interface_dlhandle = NULL;
|
||||
|
||||
static struct libcurl_interface
|
||||
{
|
||||
CURLcode (*curl_global_init)(long flags);
|
||||
CURL *(*curl_easy_init)(void);
|
||||
CURLcode (*curl_easy_setopt)(CURL *curl, CURLoption option, ...);
|
||||
CURLcode (*curl_easy_perform)(CURL *curl);
|
||||
CURLcode (*curl_easy_getinfo)(CURL *curl, CURLINFO info, ...);
|
||||
const char *(*curl_easy_strerror)(CURLcode);
|
||||
void (*curl_easy_cleanup)(CURL *curl);
|
||||
|
||||
struct curl_slist *(*curl_slist_append)(struct curl_slist *list, const char *data);
|
||||
void (*curl_slist_free_all)(struct curl_slist *list);
|
||||
} libcurl;
|
||||
/* END MINIMAL CURL DEFINE */
|
||||
|
||||
struct http_trans_response_data
|
||||
{
|
||||
uint8_t *data;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
static size_t http_trans_write_callback(void *contents, size_t size, size_t nmemb, void *userp)
|
||||
{
|
||||
size_t realsize = size * nmemb;
|
||||
struct http_trans_response_data *mem = (struct http_trans_response_data *)userp;
|
||||
|
||||
mem->data = realloc(mem->data, mem->size + realsize + 1);
|
||||
if (mem->data == NULL)
|
||||
{
|
||||
/* out of memory! */
|
||||
printf("not enough memory (realloc returned NULL)\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(&(mem->data[mem->size]), contents, realsize);
|
||||
mem->size += realsize;
|
||||
mem->data[mem->size] = 0;
|
||||
|
||||
return realsize;
|
||||
}
|
||||
|
||||
static int http_interface_transmit(struct euicc_ctx *ctx, const char *url, uint32_t *rcode, uint8_t **rx, uint32_t *rx_len, const uint8_t *tx, uint32_t tx_len, const char **h)
|
||||
{
|
||||
int fret = 0;
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
struct http_trans_response_data responseData = {0};
|
||||
struct curl_slist *headers = NULL, *nheaders = NULL;
|
||||
long response_code;
|
||||
|
||||
(*rx) = NULL;
|
||||
(*rcode) = 0;
|
||||
|
||||
curl = libcurl.curl_easy_init();
|
||||
if (!curl)
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
|
||||
libcurl.curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||
libcurl.curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http_trans_write_callback);
|
||||
libcurl.curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&responseData);
|
||||
libcurl.curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
libcurl.curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||
for (int i = 0; h[i] != NULL; i++)
|
||||
{
|
||||
nheaders = libcurl.curl_slist_append(headers, h[i]);
|
||||
if (nheaders == NULL)
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
headers = nheaders;
|
||||
}
|
||||
libcurl.curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
||||
|
||||
if (tx != NULL)
|
||||
{
|
||||
libcurl.curl_easy_setopt(curl, CURLOPT_POSTFIELDS, tx);
|
||||
libcurl.curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, tx_len);
|
||||
}
|
||||
|
||||
res = libcurl.curl_easy_perform(curl);
|
||||
|
||||
if (res != CURLE_OK)
|
||||
{
|
||||
fprintf(stderr, "curl_easy_perform() failed: %s\n", libcurl.curl_easy_strerror(res));
|
||||
goto err;
|
||||
}
|
||||
|
||||
libcurl.curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
|
||||
*rcode = response_code;
|
||||
*rx = responseData.data;
|
||||
*rx_len = responseData.size;
|
||||
|
||||
fret = 0;
|
||||
goto exit;
|
||||
|
||||
err:
|
||||
fret = -1;
|
||||
free(responseData.data);
|
||||
exit:
|
||||
libcurl.curl_easy_cleanup(curl);
|
||||
libcurl.curl_slist_free_all(headers);
|
||||
return fret;
|
||||
}
|
||||
|
||||
EUICC_SHARED_EXPORT int libhttpinterface_init(struct euicc_http_interface *ifstruct)
|
||||
{
|
||||
const char *libcurl_path;
|
||||
|
||||
memset(ifstruct, 0, sizeof(struct euicc_http_interface));
|
||||
|
||||
if (!(libcurl_path = getenv("LIBCURL")))
|
||||
{
|
||||
libcurl_path = LIBCURL_DEFAULT_PATH;
|
||||
}
|
||||
|
||||
if (!(libcurl_interface_dlhandle = dlopen(libcurl_path, RTLD_LAZY)))
|
||||
{
|
||||
fprintf(stderr, "libcurl env missing, current: LIBCURL=%s err:%s\n", libcurl_path, dlerror());
|
||||
return -1;
|
||||
}
|
||||
|
||||
libcurl.curl_global_init = dlsym(libcurl_interface_dlhandle, "curl_global_init");
|
||||
libcurl.curl_easy_init = dlsym(libcurl_interface_dlhandle, "curl_easy_init");
|
||||
libcurl.curl_easy_setopt = dlsym(libcurl_interface_dlhandle, "curl_easy_setopt");
|
||||
libcurl.curl_easy_perform = dlsym(libcurl_interface_dlhandle, "curl_easy_perform");
|
||||
libcurl.curl_easy_getinfo = dlsym(libcurl_interface_dlhandle, "curl_easy_getinfo");
|
||||
libcurl.curl_easy_strerror = dlsym(libcurl_interface_dlhandle, "curl_easy_strerror");
|
||||
libcurl.curl_easy_cleanup = dlsym(libcurl_interface_dlhandle, "curl_easy_cleanup");
|
||||
libcurl.curl_slist_append = dlsym(libcurl_interface_dlhandle, "curl_slist_append");
|
||||
libcurl.curl_slist_free_all = dlsym(libcurl_interface_dlhandle, "curl_slist_free_all");
|
||||
|
||||
if (libcurl.curl_global_init(CURL_GLOBAL_DEFAULT) != CURLE_OK)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
ifstruct->transmit = http_interface_transmit;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EUICC_SHARED_EXPORT int libhttpinterface_main(int argc, char **argv)
|
||||
{
|
||||
return 0;
|
||||
}
|
|
@ -5,16 +5,25 @@ else()
|
|||
endif()
|
||||
|
||||
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} DIR_LPAC_SRCS)
|
||||
|
||||
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/applet DIR_LPAC_SRCS)
|
||||
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/applet/chip DIR_LPAC_SRCS)
|
||||
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/applet/notification DIR_LPAC_SRCS)
|
||||
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/applet/profile DIR_LPAC_SRCS)
|
||||
|
||||
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/driver DIR_LPAC_SRCS)
|
||||
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/driver/apdu DIR_LPAC_SRCS)
|
||||
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/driver/http DIR_LPAC_SRCS)
|
||||
|
||||
find_package(PCSCLite)
|
||||
find_package(curl)
|
||||
|
||||
add_executable(lpac ${DIR_LPAC_SRCS})
|
||||
set_target_properties(lpac PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/output"
|
||||
BUILD_RPATH "${RPATH_BINARY_PATH}"
|
||||
)
|
||||
target_link_libraries(lpac euicc ${DL_LIBRARY})
|
||||
target_link_libraries(lpac euicc PCSCLite::PCSCLite curl ${DL_LIBRARY})
|
||||
target_include_directories(lpac PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
|
||||
|
||||
find_package(Git)
|
||||
|
|
|
@ -1,144 +0,0 @@
|
|||
#include "dlsym_interface.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#include <dlfcn-win32/dlfcn.h>
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#if defined (_WIN32) || defined (__CYGWIN__)
|
||||
#define INTERFACELIB_EXTENSION "dll"
|
||||
#elif defined(__APPLE__)
|
||||
#define INTERFACELIB_EXTENSION "dylib"
|
||||
#else
|
||||
#define INTERFACELIB_EXTENSION "so"
|
||||
#endif
|
||||
|
||||
static struct applet_entry applet_apdu = {
|
||||
.name = "apdu",
|
||||
.main = NULL,
|
||||
};
|
||||
|
||||
static struct applet_entry applet_http = {
|
||||
.name = "http",
|
||||
.main = NULL,
|
||||
};
|
||||
|
||||
static const struct applet_entry *applets[] = {
|
||||
&applet_apdu,
|
||||
&applet_http,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const char *libapduinterface_path = NULL;
|
||||
static void *apdu_interface_dlhandle = NULL;
|
||||
struct euicc_apdu_interface dlsym_apdu_interface = {0};
|
||||
static int (*libapduinterface_init)(struct euicc_apdu_interface *ifstruct) = NULL;
|
||||
static int (*libapduinterface_main)(int argc, char **argv) = NULL;
|
||||
|
||||
static const char *libhttpinterface_path = NULL;
|
||||
static void *http_interface_dlhandle = NULL;
|
||||
struct euicc_http_interface dlsym_http_interface = {0};
|
||||
static int (*libhttpinterface_init)(struct euicc_http_interface *ifstruct) = NULL;
|
||||
static int (*libhttpinterface_main)(int argc, char **argv) = NULL;
|
||||
|
||||
static void dlsym_interfaces_get_path(void)
|
||||
{
|
||||
if (!(libapduinterface_path = getenv("APDU_INTERFACE")))
|
||||
{
|
||||
libapduinterface_path = "libapduinterface_pcsc." INTERFACELIB_EXTENSION;
|
||||
}
|
||||
|
||||
if (!(libhttpinterface_path = getenv("HTTP_INTERFACE")))
|
||||
{
|
||||
libhttpinterface_path = "libhttpinterface_curl." INTERFACELIB_EXTENSION;
|
||||
}
|
||||
}
|
||||
|
||||
static int dlsym_interface_get_dlhandle(void)
|
||||
{
|
||||
if (!(apdu_interface_dlhandle = dlopen(libapduinterface_path, RTLD_LAZY)))
|
||||
{
|
||||
apdu_interface_dlhandle = NULL;
|
||||
fprintf(stderr, "APDU interface env missing, current: APDU_INTERFACE=%s err:%s\n", libapduinterface_path, dlerror());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(http_interface_dlhandle = dlopen(libhttpinterface_path, RTLD_LAZY)))
|
||||
{
|
||||
http_interface_dlhandle = NULL;
|
||||
fprintf(stderr, "HTTP interface env missing, current: HTTP_INTERFACE=%s err:%s\n", libhttpinterface_path, dlerror());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dlsym_interface_init()
|
||||
{
|
||||
dlsym_interfaces_get_path();
|
||||
|
||||
if (dlsym_interface_get_dlhandle())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (apdu_interface_dlhandle)
|
||||
{
|
||||
libapduinterface_init = dlsym(apdu_interface_dlhandle, "libapduinterface_init");
|
||||
if (!libapduinterface_init)
|
||||
{
|
||||
fprintf(stderr, "APDU library broken: missing libapduinterface_init\n");
|
||||
return -1;
|
||||
}
|
||||
if (libapduinterface_init(&dlsym_apdu_interface) < 0)
|
||||
{
|
||||
fprintf(stderr, "APDU library init error\n");
|
||||
return -1;
|
||||
}
|
||||
libapduinterface_main = dlsym(apdu_interface_dlhandle, "libapduinterface_main");
|
||||
if (!libapduinterface_main)
|
||||
{
|
||||
fprintf(stderr, "APDU library broken: missing libapduinterface_main\n");
|
||||
return -1;
|
||||
}
|
||||
applet_apdu.main = libapduinterface_main;
|
||||
}
|
||||
|
||||
if (http_interface_dlhandle)
|
||||
{
|
||||
libhttpinterface_init = dlsym(http_interface_dlhandle, "libhttpinterface_init");
|
||||
if (!libhttpinterface_init)
|
||||
{
|
||||
fprintf(stderr, "HTTP library broken: missing libhttpinterface_init\n");
|
||||
return -1;
|
||||
}
|
||||
if (libhttpinterface_init(&dlsym_http_interface) < 0)
|
||||
{
|
||||
fprintf(stderr, "HTTP library init error\n");
|
||||
return -1;
|
||||
}
|
||||
libhttpinterface_main = dlsym(http_interface_dlhandle, "libhttpinterface_main");
|
||||
if (!libhttpinterface_main)
|
||||
{
|
||||
fprintf(stderr, "HTTP library broken: missing libhttpinterface_main\n");
|
||||
return -1;
|
||||
}
|
||||
applet_http.main = libhttpinterface_main;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dlsym_interface_applet_main(int argc, char **argv)
|
||||
{
|
||||
return applet_entry(argc, argv, applets);
|
||||
}
|
||||
|
||||
struct applet_entry applet_dlsym_interface = {
|
||||
.name = "driver",
|
||||
.main = dlsym_interface_applet_main,
|
||||
};
|
|
@ -1,9 +0,0 @@
|
|||
#pragma once
|
||||
#include <euicc/interface.h>
|
||||
#include <applet.h>
|
||||
|
||||
extern struct euicc_apdu_interface dlsym_apdu_interface;
|
||||
extern struct euicc_http_interface dlsym_http_interface;
|
||||
extern struct applet_entry applet_dlsym_interface;
|
||||
|
||||
int dlsym_interface_init(void);
|
126
src/driver.c
Normal file
126
src/driver.c
Normal file
|
@ -0,0 +1,126 @@
|
|||
#include "driver.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef LPAC_WITH_APDU_GBINDER_HIDL
|
||||
#include "driver/apdu/gbinder_hidl.h"
|
||||
#endif
|
||||
|
||||
#ifndef LPAC_WITHOUT_APDU_PCSC
|
||||
#include "driver/apdu/pcsc.h"
|
||||
#endif
|
||||
#ifndef LPAC_WITHOUT_APDU_AT
|
||||
#include "driver/apdu/at.h"
|
||||
#endif
|
||||
#ifndef LPAC_WITHOUT_HTTP_CURL
|
||||
#include "driver/http/curl.h"
|
||||
#endif
|
||||
#include "driver/apdu/stdio.h"
|
||||
#include "driver/http/stdio.h"
|
||||
|
||||
static const struct lpac_driver *drivers[] = {
|
||||
#ifdef LPAC_WITH_APDU_GBINDER_HIDL
|
||||
&driver_apdu_gbinder_hidl,
|
||||
#endif
|
||||
#ifndef LPAC_WITHOUT_APDU_PCSC
|
||||
&driver_apdu_pcsc,
|
||||
#endif
|
||||
#ifndef LPAC_WITHOUT_APDU_AT
|
||||
&driver_apdu_at,
|
||||
#endif
|
||||
#ifndef LPAC_WITHOUT_HTTP_CURL
|
||||
&driver_http_curl,
|
||||
#endif
|
||||
&driver_apdu_stdio,
|
||||
&driver_http_stdio,
|
||||
NULL,
|
||||
};
|
||||
|
||||
struct euicc_apdu_interface driver_interface_apdu;
|
||||
struct euicc_http_interface driver_interface_http;
|
||||
static struct applet_entry applet_apdu = {
|
||||
.name = "apdu",
|
||||
.main = NULL,
|
||||
};
|
||||
static struct applet_entry applet_http = {
|
||||
.name = "http",
|
||||
.main = NULL,
|
||||
};
|
||||
|
||||
static const struct lpac_driver *_driver_apdu = NULL;
|
||||
static const struct lpac_driver *_driver_http = NULL;
|
||||
|
||||
static const struct lpac_driver *_find_driver(enum lpac_driver_type type, const char *name)
|
||||
{
|
||||
for (int i = 0; drivers[i] != NULL; i++)
|
||||
{
|
||||
const struct lpac_driver *d = drivers[i];
|
||||
if (d->type != type)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (name == NULL)
|
||||
{
|
||||
return d;
|
||||
}
|
||||
if (strcmp(d->name, name) == 0)
|
||||
{
|
||||
return d;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int driver_init()
|
||||
{
|
||||
_driver_apdu = _find_driver(DRIVER_APDU, getenv("LPAC_APDU"));
|
||||
if (_driver_apdu == NULL)
|
||||
{
|
||||
fprintf(stderr, "No APDU driver found\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
_driver_http = _find_driver(DRIVER_HTTP, getenv("LPAC_HTTP"));
|
||||
if (_driver_http == NULL)
|
||||
{
|
||||
fprintf(stderr, "No HTTP driver found\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
_driver_apdu->init(&driver_interface_apdu);
|
||||
_driver_http->init(&driver_interface_http);
|
||||
|
||||
applet_apdu.main = _driver_apdu->main;
|
||||
applet_http.main = _driver_http->main;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void driver_fini()
|
||||
{
|
||||
if (_driver_apdu != NULL)
|
||||
{
|
||||
_driver_apdu->fini();
|
||||
}
|
||||
if (_driver_http != NULL)
|
||||
{
|
||||
_driver_http->fini();
|
||||
}
|
||||
}
|
||||
|
||||
static int dlsym_interface_applet_main(int argc, char **argv)
|
||||
{
|
||||
static const struct applet_entry *applets[] = {
|
||||
&applet_apdu,
|
||||
&applet_http,
|
||||
NULL,
|
||||
};
|
||||
return applet_entry(argc, argv, applets);
|
||||
}
|
||||
|
||||
struct applet_entry driver_applet = {
|
||||
.name = "driver",
|
||||
.main = dlsym_interface_applet_main,
|
||||
};
|
27
src/driver.h
Normal file
27
src/driver.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
#pragma once
|
||||
#include <stddef.h>
|
||||
#include <inttypes.h>
|
||||
#include <euicc/interface.h>
|
||||
#include <applet.h>
|
||||
|
||||
enum lpac_driver_type
|
||||
{
|
||||
DRIVER_APDU,
|
||||
DRIVER_HTTP,
|
||||
};
|
||||
|
||||
struct lpac_driver
|
||||
{
|
||||
enum lpac_driver_type type;
|
||||
const char *name;
|
||||
int (*init)(void *interface);
|
||||
int (*main)(int argc, char **argv);
|
||||
void (*fini)(void);
|
||||
};
|
||||
|
||||
extern struct euicc_apdu_interface driver_interface_apdu;
|
||||
extern struct euicc_http_interface driver_interface_http;
|
||||
extern struct applet_entry driver_applet;
|
||||
|
||||
int driver_init(void);
|
||||
void driver_fini(void);
|
|
@ -10,7 +10,7 @@ if(LPAC_APDU_INTERFACE_PCSC)
|
|||
install(TARGETS apduinterface_pcsc LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}/lpac")
|
||||
endif()
|
||||
|
||||
if(MINGW OR CYGWIN)
|
||||
if(WIN32)
|
||||
target_link_libraries(apduinterface_pcsc winscard)
|
||||
elseif(APPLE)
|
||||
target_link_libraries(apduinterface_pcsc "-framework PCSC")
|
|
@ -1,3 +1,5 @@
|
|||
#include "at.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
@ -5,70 +7,11 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include <euicc/interface.h>
|
||||
#include <euicc/hexutil.h>
|
||||
|
||||
static FILE *fuart;
|
||||
static int logic_channel = 0;
|
||||
|
||||
static int hexutil_hex2bin(uint8_t *output, uint32_t output_len, const char *str, uint32_t str_len)
|
||||
{
|
||||
uint32_t length;
|
||||
|
||||
if (!str || !output || str_len % 2 != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
length = str_len / 2;
|
||||
if (length > output_len)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < length; ++i)
|
||||
{
|
||||
char high = str[2 * i];
|
||||
char low = str[2 * i + 1];
|
||||
|
||||
if (high >= '0' && high <= '9')
|
||||
{
|
||||
high -= '0';
|
||||
}
|
||||
else if (high >= 'a' && high <= 'f')
|
||||
{
|
||||
high = high - 'a' + 10;
|
||||
}
|
||||
else if (high >= 'A' && high <= 'F')
|
||||
{
|
||||
high = high - 'A' + 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (low >= '0' && low <= '9')
|
||||
{
|
||||
low -= '0';
|
||||
}
|
||||
else if (low >= 'a' && low <= 'f')
|
||||
{
|
||||
low = low - 'a' + 10;
|
||||
}
|
||||
else if (low >= 'A' && low <= 'F')
|
||||
{
|
||||
low = low - 'A' + 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
output[i] = (high << 4) + low;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
static int at_expect(char **response, const char *expected)
|
||||
{
|
||||
char buffer[1024];
|
||||
|
@ -195,7 +138,7 @@ static int apdu_interface_transmit(struct euicc_ctx *ctx, uint8_t **rx, uint32_t
|
|||
goto err;
|
||||
}
|
||||
|
||||
ret = hexutil_hex2bin(*rx, *rx_len, hexstr, strlen(hexstr));
|
||||
ret = euicc_hexutil_hex2bin_r(*rx, *rx_len, hexstr, strlen(hexstr));
|
||||
if (ret < 0)
|
||||
{
|
||||
goto err;
|
||||
|
@ -257,7 +200,7 @@ static void apdu_interface_logic_channel_close(struct euicc_ctx *ctx, uint8_t ch
|
|||
at_expect(NULL, NULL);
|
||||
}
|
||||
|
||||
int libapduinterface_init(struct euicc_apdu_interface *ifstruct)
|
||||
static int libapduinterface_init(struct euicc_apdu_interface *ifstruct)
|
||||
{
|
||||
memset(ifstruct, 0, sizeof(struct euicc_apdu_interface));
|
||||
|
||||
|
@ -270,7 +213,19 @@ int libapduinterface_init(struct euicc_apdu_interface *ifstruct)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int libapduinterface_main(int argc, char **argv)
|
||||
static int libapduinterface_main(int argc, char **argv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void libapduinterface_fini(void)
|
||||
{
|
||||
}
|
||||
|
||||
const struct lpac_driver driver_apdu_at = {
|
||||
.type = DRIVER_APDU,
|
||||
.name = "at",
|
||||
.init = (int (*)(void *))libapduinterface_init,
|
||||
.main = libapduinterface_main,
|
||||
.fini = libapduinterface_fini,
|
||||
};
|
4
src/driver/apdu/at.h
Normal file
4
src/driver/apdu/at.h
Normal file
|
@ -0,0 +1,4 @@
|
|||
#pragma once
|
||||
#include <driver.h>
|
||||
|
||||
extern const struct lpac_driver driver_apdu_at;
|
|
@ -1,4 +1,6 @@
|
|||
// vim: expandtab sw=4 ts=4:
|
||||
#include "gbinder_hidl.h"
|
||||
|
||||
#include <euicc/euicc.h>
|
||||
#include <euicc/hexutil.h>
|
||||
#include <euicc/interface.h>
|
||||
|
@ -289,7 +291,7 @@ static int apdu_interface_transmit(struct euicc_ctx *ctx, uint8_t **rx, uint32_t
|
|||
return 0;
|
||||
}
|
||||
|
||||
EUICC_SHARED_EXPORT int libapduinterface_init(struct euicc_apdu_interface *ifstruct)
|
||||
static int libapduinterface_init(struct euicc_apdu_interface *ifstruct)
|
||||
{
|
||||
ifstruct->connect = apdu_interface_connect;
|
||||
ifstruct->disconnect = apdu_interface_disconnect;
|
||||
|
@ -307,7 +309,19 @@ EUICC_SHARED_EXPORT int libapduinterface_init(struct euicc_apdu_interface *ifstr
|
|||
return 0;
|
||||
}
|
||||
|
||||
EUICC_SHARED_EXPORT int libapduinterface_main(int argc, char **argv)
|
||||
static int libapduinterface_main(int argc, char **argv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void libapduinterface_fini(void)
|
||||
{
|
||||
}
|
||||
|
||||
const struct lpac_driver driver_apdu_gbinder_hidl = {
|
||||
.type = DRIVER_APDU,
|
||||
.name = "gbinder_hidl",
|
||||
.init = libapduinterface_init,
|
||||
.main = libapduinterface_main,
|
||||
.fini = libapduinterface_fini,
|
||||
};
|
4
src/driver/apdu/gbinder_hidl.h
Normal file
4
src/driver/apdu/gbinder_hidl.h
Normal file
|
@ -0,0 +1,4 @@
|
|||
#pragma once
|
||||
#include <driver.h>
|
||||
|
||||
extern const struct lpac_driver driver_apdu_gbinder_hidl;
|
|
@ -1,21 +1,19 @@
|
|||
#include "pcsc.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#ifdef _WIN32
|
||||
#include <winscard.h>
|
||||
#elif defined(__CYGWIN__)
|
||||
#include "/usr/include/w32api/winscard.h"
|
||||
#include "/usr/include/w32api/wtypes.h"
|
||||
#else
|
||||
#include <PCSC/wintypes.h>
|
||||
#include <PCSC/winscard.h>
|
||||
#endif
|
||||
|
||||
#include <euicc/interface.h>
|
||||
|
||||
#include <cjson/cJSON_ex.h>
|
||||
#include <euicc/interface.h>
|
||||
|
||||
#define INTERFACE_SELECT_ENV "DRIVER_IFID"
|
||||
|
||||
|
@ -392,7 +390,7 @@ static int pcsc_list_iter(int index, const char *reader, void *userdata)
|
|||
return 0;
|
||||
}
|
||||
|
||||
EUICC_SHARED_EXPORT int libapduinterface_init(struct euicc_apdu_interface *ifstruct)
|
||||
static int libapduinterface_init(struct euicc_apdu_interface *ifstruct)
|
||||
{
|
||||
memset(ifstruct, 0, sizeof(struct euicc_apdu_interface));
|
||||
|
||||
|
@ -410,7 +408,7 @@ EUICC_SHARED_EXPORT int libapduinterface_init(struct euicc_apdu_interface *ifstr
|
|||
return 0;
|
||||
}
|
||||
|
||||
EUICC_SHARED_EXPORT int libapduinterface_main(int argc, char **argv)
|
||||
static int libapduinterface_main(int argc, char **argv)
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
|
@ -454,3 +452,15 @@ EUICC_SHARED_EXPORT int libapduinterface_main(int argc, char **argv)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void libapduinterface_fini(void)
|
||||
{
|
||||
}
|
||||
|
||||
const struct lpac_driver driver_apdu_pcsc = {
|
||||
.type = DRIVER_APDU,
|
||||
.name = "pcsc",
|
||||
.init = (int (*)(void *))libapduinterface_init,
|
||||
.main = libapduinterface_main,
|
||||
.fini = libapduinterface_fini,
|
||||
};
|
4
src/driver/apdu/pcsc.h
Normal file
4
src/driver/apdu/pcsc.h
Normal file
|
@ -0,0 +1,4 @@
|
|||
#pragma once
|
||||
#include <driver.h>
|
||||
|
||||
extern const struct lpac_driver driver_apdu_pcsc;
|
|
@ -1,3 +1,5 @@
|
|||
#include "stdio.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -5,93 +7,8 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include <cjson/cJSON_ex.h>
|
||||
|
||||
#include <euicc/interface.h>
|
||||
|
||||
static int hexutil_bin2hex(char *output, uint32_t output_len, const uint8_t *bin, uint32_t bin_len)
|
||||
{
|
||||
const char hexDigits[] = "0123456789abcdef";
|
||||
|
||||
if (!bin || !output)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (output_len < (2 * bin_len + 1))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < bin_len; ++i)
|
||||
{
|
||||
char byte = bin[i];
|
||||
output[2 * i] = hexDigits[(byte >> 4) & 0x0F];
|
||||
output[2 * i + 1] = hexDigits[byte & 0x0F];
|
||||
}
|
||||
output[2 * bin_len] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hexutil_hex2bin(uint8_t *output, uint32_t output_len, const char *str, uint32_t str_len)
|
||||
{
|
||||
uint32_t length;
|
||||
|
||||
if (!str || !output || str_len % 2 != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
length = str_len / 2;
|
||||
if (length > output_len)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < length; ++i)
|
||||
{
|
||||
char high = str[2 * i];
|
||||
char low = str[2 * i + 1];
|
||||
|
||||
if (high >= '0' && high <= '9')
|
||||
{
|
||||
high -= '0';
|
||||
}
|
||||
else if (high >= 'a' && high <= 'f')
|
||||
{
|
||||
high = high - 'a' + 10;
|
||||
}
|
||||
else if (high >= 'A' && high <= 'F')
|
||||
{
|
||||
high = high - 'A' + 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (low >= '0' && low <= '9')
|
||||
{
|
||||
low -= '0';
|
||||
}
|
||||
else if (low >= 'a' && low <= 'f')
|
||||
{
|
||||
low = low - 'a' + 10;
|
||||
}
|
||||
else if (low >= 'A' && low <= 'F')
|
||||
{
|
||||
low = low - 'A' + 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
output[i] = (high << 4) + low;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
#include <euicc/hexutil.h>
|
||||
|
||||
// getline is a GNU extension, Mingw32 macOS and FreeBSD don't have (a working) one
|
||||
static int afgets(char **obuf, FILE *fp)
|
||||
|
@ -197,7 +114,7 @@ static int json_request(const char *func, const uint8_t *param, unsigned param_l
|
|||
{
|
||||
goto err;
|
||||
}
|
||||
if (hexutil_bin2hex(param_hex, (2 * param_len) + 1, param, param_len) < 0)
|
||||
if (euicc_hexutil_bin2hex(param_hex, (2 * param_len) + 1, param, param_len) < 0)
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
|
@ -306,7 +223,7 @@ static int json_response(int *ecode, uint8_t **data, uint32_t *data_len)
|
|||
{
|
||||
goto err;
|
||||
}
|
||||
if (hexutil_hex2bin(*data, *data_len, jtmp->valuestring, strlen(jtmp->valuestring)) < 0)
|
||||
if (euicc_hexutil_hex2bin_r(*data, *data_len, jtmp->valuestring, strlen(jtmp->valuestring)) < 0)
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
|
@ -407,7 +324,7 @@ static int apdu_interface_transmit(struct euicc_ctx *ctx, uint8_t **rx, uint32_t
|
|||
return ecode;
|
||||
}
|
||||
|
||||
EUICC_SHARED_EXPORT int libapduinterface_init(struct euicc_apdu_interface *ifstruct)
|
||||
static int libapduinterface_init(struct euicc_apdu_interface *ifstruct)
|
||||
{
|
||||
ifstruct->connect = apdu_interface_connect;
|
||||
ifstruct->disconnect = apdu_interface_disconnect;
|
||||
|
@ -418,7 +335,19 @@ EUICC_SHARED_EXPORT int libapduinterface_init(struct euicc_apdu_interface *ifstr
|
|||
return 0;
|
||||
}
|
||||
|
||||
EUICC_SHARED_EXPORT int libapduinterface_main(int argc, char **argv)
|
||||
static int libapduinterface_main(int argc, char **argv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void libapduinterface_fini(void)
|
||||
{
|
||||
}
|
||||
|
||||
const struct lpac_driver driver_apdu_stdio = {
|
||||
.type = DRIVER_APDU,
|
||||
.name = "stdio",
|
||||
.init = (int (*)(void *))libapduinterface_init,
|
||||
.main = libapduinterface_main,
|
||||
.fini = libapduinterface_fini,
|
||||
};
|
4
src/driver/apdu/stdio.h
Normal file
4
src/driver/apdu/stdio.h
Normal file
|
@ -0,0 +1,4 @@
|
|||
#pragma once
|
||||
#include <driver.h>
|
||||
|
||||
extern const struct lpac_driver driver_apdu_stdio;
|
205
src/driver/http/curl.c
Normal file
205
src/driver/http/curl.c
Normal file
|
@ -0,0 +1,205 @@
|
|||
#include "curl.h"
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <euicc/interface.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <curl/curl.h>
|
||||
#else
|
||||
#include <dlfcn-win32/dlfcn.h>
|
||||
#define CURL_GLOBAL_DEFAULT ((1 << 0) | (1 << 1))
|
||||
#define CURLE_OK 0
|
||||
#define CURLOPT_URL 10002
|
||||
#define CURLOPT_WRITEFUNCTION 20011
|
||||
#define CURLOPT_WRITEDATA 10001
|
||||
#define CURLOPT_SSL_VERIFYPEER 64
|
||||
#define CURLOPT_SSL_VERIFYHOST 81
|
||||
#define CURLOPT_HTTPHEADER 10023
|
||||
#define CURLOPT_POSTFIELDS 10015
|
||||
#define CURLOPT_POSTFIELDSIZE 60
|
||||
#define CURLINFO_RESPONSE_CODE 2097154
|
||||
|
||||
typedef void CURL;
|
||||
typedef int CURLcode;
|
||||
typedef int CURLoption;
|
||||
typedef int CURLINFO;
|
||||
|
||||
static void *libcurl_interface_dlhandle = NULL;
|
||||
#endif
|
||||
|
||||
struct http_trans_response_data
|
||||
{
|
||||
uint8_t *data;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
static struct libcurl_interface
|
||||
{
|
||||
CURLcode (*_curl_global_init)(long flags);
|
||||
CURL *(*_curl_easy_init)(void);
|
||||
CURLcode (*_curl_easy_setopt)(CURL *curl, CURLoption option, ...);
|
||||
CURLcode (*_curl_easy_perform)(CURL *curl);
|
||||
CURLcode (*_curl_easy_getinfo)(CURL *curl, CURLINFO info, ...);
|
||||
const char *(*_curl_easy_strerror)(CURLcode);
|
||||
void (*_curl_easy_cleanup)(CURL *curl);
|
||||
|
||||
struct curl_slist *(*_curl_slist_append)(struct curl_slist *list, const char *data);
|
||||
void (*_curl_slist_free_all)(struct curl_slist *list);
|
||||
} libcurl;
|
||||
|
||||
static size_t http_trans_write_callback(void *contents, size_t size, size_t nmemb, void *userp)
|
||||
{
|
||||
size_t realsize = size * nmemb;
|
||||
struct http_trans_response_data *mem = (struct http_trans_response_data *)userp;
|
||||
|
||||
mem->data = realloc(mem->data, mem->size + realsize + 1);
|
||||
if (mem->data == NULL)
|
||||
{
|
||||
/* out of memory! */
|
||||
printf("not enough memory (realloc returned NULL)\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(&(mem->data[mem->size]), contents, realsize);
|
||||
mem->size += realsize;
|
||||
mem->data[mem->size] = 0;
|
||||
|
||||
return realsize;
|
||||
}
|
||||
|
||||
static int http_interface_transmit(struct euicc_ctx *ctx, const char *url, uint32_t *rcode, uint8_t **rx, uint32_t *rx_len, const uint8_t *tx, uint32_t tx_len, const char **h)
|
||||
{
|
||||
int fret = 0;
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
struct http_trans_response_data responseData = {0};
|
||||
struct curl_slist *headers = NULL, *nheaders = NULL;
|
||||
long response_code;
|
||||
|
||||
(*rx) = NULL;
|
||||
(*rcode) = 0;
|
||||
|
||||
curl = libcurl._curl_easy_init();
|
||||
if (!curl)
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
|
||||
libcurl._curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||
libcurl._curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http_trans_write_callback);
|
||||
libcurl._curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&responseData);
|
||||
libcurl._curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
libcurl._curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||
for (int i = 0; h[i] != NULL; i++)
|
||||
{
|
||||
nheaders = libcurl._curl_slist_append(headers, h[i]);
|
||||
if (nheaders == NULL)
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
headers = nheaders;
|
||||
}
|
||||
libcurl._curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
||||
|
||||
if (tx != NULL)
|
||||
{
|
||||
libcurl._curl_easy_setopt(curl, CURLOPT_POSTFIELDS, tx);
|
||||
libcurl._curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, tx_len);
|
||||
}
|
||||
|
||||
res = libcurl._curl_easy_perform(curl);
|
||||
|
||||
if (res != CURLE_OK)
|
||||
{
|
||||
fprintf(stderr, "curl_easy_perform() failed: %s\n", libcurl._curl_easy_strerror(res));
|
||||
goto err;
|
||||
}
|
||||
|
||||
libcurl._curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
|
||||
*rcode = response_code;
|
||||
*rx = responseData.data;
|
||||
*rx_len = responseData.size;
|
||||
|
||||
fret = 0;
|
||||
goto exit;
|
||||
|
||||
err:
|
||||
fret = -1;
|
||||
free(responseData.data);
|
||||
exit:
|
||||
libcurl._curl_easy_cleanup(curl);
|
||||
libcurl._curl_slist_free_all(headers);
|
||||
return fret;
|
||||
}
|
||||
|
||||
static int _init_libcurl(void)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (!(libcurl_interface_dlhandle = dlopen("libcurl.dll", RTLD_LAZY)))
|
||||
{
|
||||
fprintf(stderr, "libcurl init err: %s\n", dlerror());
|
||||
return -1;
|
||||
}
|
||||
|
||||
libcurl._curl_global_init = dlsym(libcurl_interface_dlhandle, "curl_global_init");
|
||||
libcurl._curl_easy_init = dlsym(libcurl_interface_dlhandle, "curl_easy_init");
|
||||
libcurl._curl_easy_setopt = dlsym(libcurl_interface_dlhandle, "curl_easy_setopt");
|
||||
libcurl._curl_easy_perform = dlsym(libcurl_interface_dlhandle, "curl_easy_perform");
|
||||
libcurl._curl_easy_getinfo = dlsym(libcurl_interface_dlhandle, "curl_easy_getinfo");
|
||||
libcurl._curl_easy_strerror = dlsym(libcurl_interface_dlhandle, "curl_easy_strerror");
|
||||
libcurl._curl_easy_cleanup = dlsym(libcurl_interface_dlhandle, "curl_easy_cleanup");
|
||||
libcurl._curl_slist_append = dlsym(libcurl_interface_dlhandle, "curl_slist_append");
|
||||
libcurl._curl_slist_free_all = dlsym(libcurl_interface_dlhandle, "curl_slist_free_all");
|
||||
#else
|
||||
libcurl._curl_global_init = curl_global_init;
|
||||
libcurl._curl_easy_init = curl_easy_init;
|
||||
libcurl._curl_easy_setopt = curl_easy_setopt;
|
||||
libcurl._curl_easy_perform = curl_easy_perform;
|
||||
libcurl._curl_easy_getinfo = curl_easy_getinfo;
|
||||
libcurl._curl_easy_strerror = curl_easy_strerror;
|
||||
libcurl._curl_easy_cleanup = curl_easy_cleanup;
|
||||
libcurl._curl_slist_append = curl_slist_append;
|
||||
libcurl._curl_slist_free_all = curl_slist_free_all;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int libhttpinterface_init(struct euicc_http_interface *ifstruct)
|
||||
{
|
||||
memset(ifstruct, 0, sizeof(struct euicc_http_interface));
|
||||
|
||||
if (_init_libcurl() != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (libcurl._curl_global_init(CURL_GLOBAL_DEFAULT) != CURLE_OK)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
ifstruct->transmit = http_interface_transmit;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int libhttpinterface_main(int argc, char **argv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void libhttpinterface_fini(void)
|
||||
{
|
||||
}
|
||||
|
||||
const struct lpac_driver driver_http_curl = {
|
||||
.type = DRIVER_HTTP,
|
||||
.name = "curl",
|
||||
.init = (int (*)(void *))libhttpinterface_init,
|
||||
.main = libhttpinterface_main,
|
||||
.fini = libhttpinterface_fini,
|
||||
};
|
4
src/driver/http/curl.h
Normal file
4
src/driver/http/curl.h
Normal file
|
@ -0,0 +1,4 @@
|
|||
#pragma once
|
||||
#include <driver.h>
|
||||
|
||||
extern const struct lpac_driver driver_http_curl;
|
|
@ -1,3 +1,5 @@
|
|||
#include "stdio.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -5,93 +7,8 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include <cjson/cJSON_ex.h>
|
||||
|
||||
#include <euicc/interface.h>
|
||||
|
||||
static int hexutil_bin2hex(char *output, uint32_t output_len, const uint8_t *bin, uint32_t bin_len)
|
||||
{
|
||||
const char hexDigits[] = "0123456789abcdef";
|
||||
|
||||
if (!bin || !output)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (output_len < (2 * bin_len + 1))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < bin_len; ++i)
|
||||
{
|
||||
char byte = bin[i];
|
||||
output[2 * i] = hexDigits[(byte >> 4) & 0x0F];
|
||||
output[2 * i + 1] = hexDigits[byte & 0x0F];
|
||||
}
|
||||
output[2 * bin_len] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hexutil_hex2bin(uint8_t *output, uint32_t output_len, const char *str, uint32_t str_len)
|
||||
{
|
||||
uint32_t length;
|
||||
|
||||
if (!str || !output || str_len % 2 != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
length = str_len / 2;
|
||||
if (length > output_len)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < length; ++i)
|
||||
{
|
||||
char high = str[2 * i];
|
||||
char low = str[2 * i + 1];
|
||||
|
||||
if (high >= '0' && high <= '9')
|
||||
{
|
||||
high -= '0';
|
||||
}
|
||||
else if (high >= 'a' && high <= 'f')
|
||||
{
|
||||
high = high - 'a' + 10;
|
||||
}
|
||||
else if (high >= 'A' && high <= 'F')
|
||||
{
|
||||
high = high - 'A' + 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (low >= '0' && low <= '9')
|
||||
{
|
||||
low -= '0';
|
||||
}
|
||||
else if (low >= 'a' && low <= 'f')
|
||||
{
|
||||
low = low - 'a' + 10;
|
||||
}
|
||||
else if (low >= 'A' && low <= 'F')
|
||||
{
|
||||
low = low - 'A' + 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
output[i] = (high << 4) + low;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
#include <euicc/hexutil.h>
|
||||
|
||||
// getline is a GNU extension, Mingw32 macOS and FreeBSD don't have (a working) one
|
||||
static int afgets(char **obuf, FILE *fp)
|
||||
|
@ -196,7 +113,7 @@ static int json_request(const char *url, const uint8_t *tx, uint32_t tx_len, con
|
|||
{
|
||||
goto err;
|
||||
}
|
||||
if (hexutil_bin2hex(tx_hex, (2 * tx_len) + 1, tx, tx_len) < 0)
|
||||
if (euicc_hexutil_bin2hex(tx_hex, (2 * tx_len) + 1, tx, tx_len) < 0)
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
|
@ -321,7 +238,7 @@ static int http_interface_transmit(struct euicc_ctx *ctx, const char *url, uint3
|
|||
{
|
||||
goto err;
|
||||
}
|
||||
if (hexutil_hex2bin(*rx, *rx_len, jtmp->valuestring, strlen(jtmp->valuestring)) < 0)
|
||||
if (euicc_hexutil_hex2bin_r(*rx, *rx_len, jtmp->valuestring, strlen(jtmp->valuestring)) < 0)
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
|
@ -341,7 +258,7 @@ exit:
|
|||
return fret;
|
||||
}
|
||||
|
||||
EUICC_SHARED_EXPORT int libhttpinterface_init(struct euicc_http_interface *ifstruct)
|
||||
static int libhttpinterface_init(struct euicc_http_interface *ifstruct)
|
||||
{
|
||||
memset(ifstruct, 0, sizeof(struct euicc_http_interface));
|
||||
|
||||
|
@ -350,7 +267,19 @@ EUICC_SHARED_EXPORT int libhttpinterface_init(struct euicc_http_interface *ifstr
|
|||
return 0;
|
||||
}
|
||||
|
||||
EUICC_SHARED_EXPORT int libhttpinterface_main(int argc, char **argv)
|
||||
static int libhttpinterface_main(int argc, char **argv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void libhttpinterface_fini(void)
|
||||
{
|
||||
}
|
||||
|
||||
const struct lpac_driver driver_http_stdio = {
|
||||
.type = DRIVER_HTTP,
|
||||
.name = "stdio",
|
||||
.init = (int (*)(void *))libhttpinterface_init,
|
||||
.main = libhttpinterface_main,
|
||||
.fini = libhttpinterface_fini,
|
||||
};
|
4
src/driver/http/stdio.h
Normal file
4
src/driver/http/stdio.h
Normal file
|
@ -0,0 +1,4 @@
|
|||
#pragma once
|
||||
#include <driver.h>
|
||||
|
||||
extern const struct lpac_driver driver_http_stdio;
|
13
src/main.c
13
src/main.c
|
@ -8,8 +8,7 @@
|
|||
#include <euicc/interface.h>
|
||||
#include <euicc/euicc.h>
|
||||
|
||||
#include "dlsym_interface.h"
|
||||
|
||||
#include "driver.h"
|
||||
#include "applet.h"
|
||||
#include "applet/chip.h"
|
||||
#include "applet/profile.h"
|
||||
|
@ -17,7 +16,7 @@
|
|||
#include "applet/version.h"
|
||||
|
||||
static const struct applet_entry *applets[] = {
|
||||
&applet_dlsym_interface,
|
||||
&driver_applet,
|
||||
&applet_chip,
|
||||
&applet_profile,
|
||||
&applet_notification,
|
||||
|
@ -54,17 +53,19 @@ int main(int argc, char **argv)
|
|||
|
||||
memset(&euicc_ctx, 0, sizeof(euicc_ctx));
|
||||
|
||||
if (dlsym_interface_init())
|
||||
if (driver_init())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
euicc_ctx.apdu.interface = &dlsym_apdu_interface;
|
||||
euicc_ctx.http.interface = &dlsym_http_interface;
|
||||
euicc_ctx.apdu.interface = &driver_interface_apdu;
|
||||
euicc_ctx.http.interface = &driver_interface_http;
|
||||
|
||||
ret = applet_entry(argc, argv, applets);
|
||||
|
||||
main_fini_euicc();
|
||||
|
||||
driver_fini();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue