[T106][ZXW-22]7520V3SCV2.01.01.02P42U09_VEC_V0.8_AP_VEC origin source commit
Change-Id: Ic6e05d89ecd62fc34f82b23dcf306c93764aec4b
diff --git a/ap/lib/liblpa/Makefile b/ap/lib/liblpa/Makefile
new file mode 100755
index 0000000..539f889
--- /dev/null
+++ b/ap/lib/liblpa/Makefile
@@ -0,0 +1,53 @@
+#*******************************************************************************
+# include ZTE library makefile
+#*******************************************************************************
+include $(COMMON_MK)
+
+##############USER COMIZE BEGIN################
+
+LIB_STATIC = liblpa.a
+LIB_SHARED = liblpa.so
+
+INTERFACELIB = libes10.a
+
+OBJS = $(patsubst %.c,%.o,$(wildcard *.c))
+
+CFLAGS += -I$(zte_lib_path)/libssl/install/include
+CFLAGS += -I$(LINUX_DIR)/include
+CFLAGS += -g
+
+#CFLAGS += -DWEBS_SSL_SUPPORT -DOPENSSL
+#LDLIBS += -L$(zte_lib_path)/libssl/install/lib -lssl -lcrypto
+#LDLIBS += -ldl
+##############USER COMIZE END##################
+
+CFLAGS += -I$(zte_app_path)/include
+CFLAGS += -fPIC
+LDFLAGS += -shared
+
+
+ifneq ($(MK_SDK_VERSION),yes)
+all: $(INTERFACELIB) $(LIB_STATIC)
+else
+all: $(LIB_STATIC)
+endif
+
+$(INTERFACELIB):
+ ${MAKE} -C ./es10 all
+
+$(LIB_STATIC): $(OBJS)
+ $(AR) rcs $(LIB_STATIC) $(OBJS)
+
+$(LIB_SHARED): $(OBJS)
+ $(CC) $(LDFLAGS) -o $@ $^ $(INTERFACELIB)
+
+romfs:
+ @echo lpa no so
+
+clean:
+ifneq ($(MK_SDK_VERSION),yes)
+ ${MAKE} -C ./es10 clean
+ -$(RM) *.o $(LIB_SHARED) $(LIB_STATIC) $(OBJS)
+else
+ -$(RM) *.o $(LIB_SHARED) $(LIB_STATIC) $(OBJS)
+endif
diff --git a/ap/lib/liblpa/cjson.c b/ap/lib/liblpa/cjson.c
new file mode 100755
index 0000000..21ac10b
--- /dev/null
+++ b/ap/lib/liblpa/cjson.c
@@ -0,0 +1,980 @@
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include <float.h>
+#include <limits.h>
+#include <ctype.h>
+#include "cjson.h"
+
+
+static const char *parse_value(cJSON *item, const char *value);
+static char *print_value(cJSON *item, int depth, int fmt);
+static const char *parse_array(cJSON *item, const char *value);
+static char *print_array(cJSON *item, int depth, int fmt);
+static const char *parse_object(cJSON *item, const char *value);
+static char *print_object(cJSON *item, int depth, int fmt);
+
+static const char *ep;
+
+static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
+
+
+const char *cJSON_GetErrorPtr(void)
+{
+ return ep;
+}
+
+static int cJSON_strcasecmp(const char *s1, const char *s2)
+{
+ if (!s1) return (s1 == s2) ? 0 : 1;
+ if (!s2) return 1;
+ for (; tolower(*s1) == tolower(*s2); ++s1, ++s2) if (*s1 == 0) return 0;
+ return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
+}
+
+static void *(*cJSON_malloc)(size_t sz) = malloc;
+static void (*cJSON_free)(void *ptr) = free;
+
+static const char *skip(const char *in)
+{
+ while (in && *in && (unsigned char)*in <= 32) in++;
+ return in;
+}
+
+static char* cJSON_strdup(const char* str)
+{
+ size_t len;
+ char* str_cpy;
+
+ len = strlen(str) + 1;
+ if (!(str_cpy = (char*)cJSON_malloc(len))) return 0;
+ memcpy(str_cpy, str, len);
+ return str_cpy;
+}
+
+void cJSON_InitHooks(cJSON_Hooks* hooks)
+{
+ if (!hooks) { /*hooks reset*/
+ cJSON_malloc = malloc;
+ cJSON_free = free;
+ return;
+ }
+
+ cJSON_malloc = (hooks->malloc_fn) ? hooks->malloc_fn : malloc;
+ cJSON_free = (hooks->free_fn) ? hooks->free_fn : free;
+}
+
+static cJSON *cJSON_New_Item(void)
+{
+ cJSON* inode = (cJSON*)cJSON_malloc(sizeof(cJSON));
+ if (inode) memset(inode, 0, sizeof(cJSON));
+ return inode;
+}
+
+void cJSON_Delete(cJSON *c)
+{
+ cJSON *next_node;
+ while (c) {
+ next_node = c->next;
+ if (!(c->type & cJSON_IsReference) && c->child) cJSON_Delete(c->child);
+ if (!(c->type & cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);
+ if (c->string) cJSON_free(c->string);
+ cJSON_free(c);
+ c = next_node;
+ }
+}
+
+static const char *parse_number(cJSON *item, const char *num)
+{
+ int subscale = 0, signsubscale = 1;
+
+ double inum = 0, sign = 1, scale = 0;
+
+ if (*num == '-') sign = -1, num++;
+ if (*num == '0') num++;
+ if (*num >= '1' && *num <= '9') do inum = (inum * 10.0) + (*num++ -'0');
+ while (*num >= '0' && *num <= '9');
+ if (*num == '.' && num[1] >= '0' && num[1] <= '9') {
+ num++;
+ do inum = (inum * 10.0) + (*num++ -'0'), scale--;
+ while (*num >= '0' && *num <= '9');
+ }
+ if (*num == 'e' || *num == 'E') {
+ num++;
+ if (*num == '+') num++;
+ else if (*num == '-') signsubscale = -1, num++;
+ while (*num >= '0' && *num <= '9') subscale = (subscale * 10) + (*num++ - '0');
+ }
+
+ inum = sign * inum * pow(10.0, (scale + subscale * signsubscale));
+
+ item->valuedouble = inum;
+ item->valueint = (int)inum;
+ item->type = cJSON_Number;
+ return num;
+}
+
+static char *print_number(cJSON *item)
+{
+ double d = item->valuedouble;
+
+ char *str;
+
+ if (fabs(((double)item->valueint) - d) <= DBL_EPSILON && d <= INT_MAX && d >= INT_MIN) {
+ str = (char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */
+ if (str) sprintf(str, "%d", item->valueint);
+ } else {
+ str = (char*)cJSON_malloc(64);
+ if (str) {
+ if (fabs(floor(d) - d) <= DBL_EPSILON && fabs(d) < 1.0e60)sprintf(str, "%.0f", d);
+ else if (fabs(d) < 1.0e-6 || fabs(d) > 1.0e9) sprintf(str, "%e", d);
+ else sprintf(str, "%f", d);
+ }
+ }
+ return str;
+}
+
+static unsigned parse_hex4(const char *str)
+{
+ unsigned hex = 0;
+ if (*str >= '0' && *str <= '9')
+ hex += (*str) - '0';
+ else if (*str >= 'A' && *str <= 'F')
+ hex += 10 + (*str) - 'A';
+ else if (*str >= 'a' && *str <= 'f')
+ hex += 10 + (*str) - 'a';
+ else
+ return 0;
+ hex = hex << 4;
+ str++;
+ if (*str >= '0' && *str <= '9')
+ hex += (*str) - '0';
+ else if (*str >= 'A' && *str <= 'F')
+ hex += 10 + (*str) - 'A';
+ else if (*str >= 'a' && *str <= 'f')
+ hex += 10 + (*str) - 'a';
+ else
+ return 0;
+ hex = hex << 4;
+ str++;
+ if (*str >= '0' && *str <= '9')
+ hex += (*str) - '0';
+ else if (*str >= 'A' && *str <= 'F')
+ hex += 10 + (*str) - 'A';
+ else if (*str >= 'a' && *str <= 'f')
+ hex += 10 + (*str) - 'a';
+ else
+ return 0;
+ hex = hex << 4;
+ str++;
+ if (*str >= '0' && *str <= '9')
+ hex += (*str) - '0';
+ else if (*str >= 'A' && *str <= 'F')
+ hex += 10 + (*str) - 'A';
+ else if (*str >= 'a' && *str <= 'f')
+ hex += 10 + (*str) - 'a';
+ else
+ return 0;
+ return hex;
+}
+
+static const char *parse_string(cJSON *item, const char *str)
+{
+ const char *pstr = str + 1;
+ char *pstr2;
+ char *out;
+ int len = 0;
+ unsigned uc, uc2;
+ if (*str != '\"') {
+ ep = str; /* not a string! */
+ return 0;
+ }
+
+ while (*pstr != '\"' && *pstr && ++len) if (*pstr++ == '\\') pstr++; /* Skip escaped quotes. */
+
+ out = (char*)cJSON_malloc(len + 1); /* This is how long we need for the string, roughly. */
+ if (!out) return 0;
+
+ pstr = str + 1;
+ pstr2 = out;
+ while (*pstr != '\"' && *pstr) {
+ if (*pstr != '\\') *pstr2++ = *pstr++;
+ else {
+ pstr++;
+ switch (*pstr) {
+ case 'b':
+ *pstr2++ = '\b';
+ break;
+ case 'f':
+ *pstr2++ = '\f';
+ break;
+ case 'n':
+ *pstr2++ = '\n';
+ break;
+ case 'r':
+ *pstr2++ = '\r';
+ break;
+ case 't':
+ *pstr2++ = '\t';
+ break;
+ case 'u':
+ uc = parse_hex4(pstr + 1);
+ pstr += 4;
+
+ if ((uc >= 0xDC00 && uc <= 0xDFFF) || uc == 0)
+ break;
+
+ if (uc >= 0xD800 && uc <= 0xDBFF) {
+ if (pstr[1] != '\\' || pstr[2] != 'u')
+ break;
+ uc2 = parse_hex4(pstr + 3);
+ pstr += 6;
+ if (uc2 < 0xDC00 || uc2 > 0xDFFF)
+ break;
+ uc = 0x10000 + (((uc & 0x3FF) << 10) | (uc2 & 0x3FF));
+ }
+
+ len = 4;
+ if (uc < 0x80) len = 1;
+ else if (uc < 0x800) len = 2;
+ else if (uc < 0x10000) len = 3;
+ pstr2 += len;
+
+ switch (len) {
+ case 4:
+ *--pstr2 = ((uc | 0x80) & 0xBF);
+ uc >>= 6;
+ case 3:
+ *--pstr2 = ((uc | 0x80) & 0xBF);
+ uc >>= 6;
+ case 2:
+ *--pstr2 = ((uc | 0x80) & 0xBF);
+ uc >>= 6;
+ case 1:
+ *--pstr2 = (uc | firstByteMark[len]);
+ }
+ pstr2 += len;
+ break;
+ default:
+ *pstr2++ = *pstr;
+ break;
+ }
+ pstr++;
+ }
+ }
+ *pstr2 = 0;
+ if (*pstr == '\"') pstr++;
+ item->valuestring = out;
+ item->type = cJSON_String;
+ return pstr;
+}
+
+static char *print_string_ptr(const char *str)
+{
+ const char *pstr;
+ char *pstr2, *out;
+ int len = 0;
+ unsigned char token;
+
+ if (!str) return cJSON_strdup("");
+ pstr = str;
+ while ((token = *pstr) && ++len) {
+ if (strchr("\"\\\b\f\n\r\t", token)) len++;
+ else if (token < 32) len += 5;
+ pstr++;
+ }
+
+ out = (char*)cJSON_malloc(len + 3);
+ if (!out) return 0;
+
+ pstr2 = out;
+ pstr = str;
+ *pstr2++ = '\"';
+ while (*pstr) {
+ if ((unsigned char)*pstr > 31 && *pstr != '\"' && *pstr != '\\') *pstr2++ = *pstr++;
+ else {
+ *pstr2++ = '\\';
+ switch (token = *pstr++) {
+ case '\\':
+ *pstr2++ = '\\';
+ break;
+ case '\"':
+ *pstr2++ = '\"';
+ break;
+ case '\b':
+ *pstr2++ = 'b';
+ break;
+ case '\f':
+ *pstr2++ = 'f';
+ break;
+ case '\n':
+ *pstr2++ = 'n';
+ break;
+ case '\r':
+ *pstr2++ = 'r';
+ break;
+ case '\t':
+ *pstr2++ = 't';
+ break;
+ default:
+ sprintf(pstr2, "u%04x", token);
+ pstr2 += 5;
+ break;
+ }
+ }
+ }
+ *pstr2++ = '\"';
+ *pstr2++ = 0;
+ return out;
+}
+
+static char *print_string(cJSON *item)
+{
+ return print_string_ptr(item->valuestring);
+}
+
+cJSON *cJSON_ParseWithOpts(const char *value, const char **return_parse_end, int require_null_terminated)
+{
+ const char *str_end = 0;
+ cJSON *c = cJSON_New_Item();
+ ep = 0;
+ if (!c)
+ return 0;
+
+ str_end = parse_value(c, skip(value));
+ if (!str_end) {
+ cJSON_Delete(c);
+ return 0;
+ }
+
+ if (require_null_terminated) {
+ str_end = skip(str_end);
+ if (*str_end) {
+ cJSON_Delete(c);
+ ep = str_end;
+ return 0;
+ }
+ }
+ if (return_parse_end) *return_parse_end = str_end;
+ return c;
+}
+
+cJSON *cJSON_Parse(const char *value)
+{
+ return cJSON_ParseWithOpts(value, 0, 0);
+}
+char *cJSON_Print(cJSON *item)
+{
+ return print_value(item, 0, 1);
+}
+char *cJSON_PrintUnformatted(cJSON *item)
+{
+ return print_value(item, 0, 0);
+}
+
+static const char *parse_value(cJSON *item, const char *value)
+{
+ if (!value)
+ return 0;
+ if (!strncmp(value, "null", 4)) {
+ item->type = cJSON_NULL;
+ return value + 4;
+ }
+ if (!strncmp(value, "false", 5)) {
+ item->type = cJSON_False;
+ return value + 5;
+ }
+ if (!strncmp(value, "true", 4)) {
+ item->type = cJSON_True;
+ item->valueint = 1;
+ return value + 4;
+ }
+ if (*value == '\"') {
+ return parse_string(item, value);
+ }
+ if (*value == '-' || (*value >= '0' && *value <= '9')) {
+ return parse_number(item, value);
+ }
+ if (*value == '[') {
+ return parse_array(item, value);
+ }
+ if (*value == '{') {
+ return parse_object(item, value);
+ }
+
+ ep = value;
+ return 0;
+}
+
+static char *print_value(cJSON *item, int depth, int fmt)
+{
+ char *item_value = 0;
+ if (!item)
+ return 0;
+ switch ((item->type) & 255) {
+ case cJSON_NULL:
+ item_value = cJSON_strdup("null");
+ break;
+ case cJSON_False:
+ item_value = cJSON_strdup("false");
+ break;
+ case cJSON_True:
+ item_value = cJSON_strdup("true");
+ break;
+ case cJSON_Number:
+ item_value = print_number(item);
+ break;
+ case cJSON_String:
+ item_value = print_string(item);
+ break;
+ case cJSON_Array:
+ item_value = print_array(item, depth, fmt);
+ break;
+ case cJSON_Object:
+ item_value = print_object(item, depth, fmt);
+ break;
+ }
+ return item_value;
+}
+
+
+static const char *parse_array(cJSON *item, const char *value)
+{
+ cJSON *child;
+ if (*value != '[') {
+ ep = value;
+ return 0;
+ }
+
+ item->type = cJSON_Array;
+ value = skip(value + 1);
+ if (*value == ']') return value + 1;
+
+ item->child = child = cJSON_New_Item();
+ if (!item->child) return 0;
+ value = skip(parse_value(child, skip(value)));
+ if (!value) return 0;
+
+ while (*value == ',') {
+ cJSON *new_item;
+ if (!(new_item = cJSON_New_Item()))
+ return 0;
+ child->next = new_item;
+ new_item->prev = child;
+ child = new_item;
+ value = skip(parse_value(child, skip(value + 1)));
+ if (!value)
+ return 0;
+ }
+
+ if (*value == ']')
+ return value + 1;
+ ep = value;
+ return 0;
+}
+
+static char *print_array(cJSON *item, int depth, int fmt)
+{
+ char *oitem = 0, *pstr, *ret;
+ char **entries;
+ int len = 5;
+ int numentries = 0, i = 0, fail = 0;
+ cJSON *child = item->child;
+
+ while (child) numentries++, child = child->next;
+
+ if (!numentries) {
+ oitem = (char*)cJSON_malloc(3);
+ if (oitem)
+ strcpy(oitem, "[]");
+ return oitem;
+ }
+
+ entries = (char**)cJSON_malloc(numentries * sizeof(char*));
+ if (!entries) return 0;
+ memset(entries, 0, numentries * sizeof(char*));
+
+ child = item->child;
+ while (child && !fail) {
+ ret = print_value(child, depth + 1, fmt);
+ entries[i++] = ret;
+ if (ret) len += strlen(ret) + 2 + (fmt ? 1 : 0);
+ else fail = 1;
+ child = child->next;
+ }
+
+
+ if (!fail)
+ oitem = (char*)cJSON_malloc(len);
+
+ if (!oitem)
+ fail = 1;
+
+
+ if (fail) {
+ for (i = 0; i < numentries; i++) if (entries[i]) cJSON_free(entries[i]);
+ cJSON_free(entries);
+ return 0;
+ }
+
+
+ *oitem = '[';
+ pstr = oitem + 1;
+ *pstr = 0;
+ for (i = 0; i < numentries; i++) {
+ strcpy(pstr, entries[i]);
+ pstr += strlen(entries[i]);
+ if (i != numentries - 1) {
+ *pstr++ = ',';
+ if (fmt)*pstr++ = ' ';
+ *pstr = 0;
+ }
+ cJSON_free(entries[i]);
+ }
+ cJSON_free(entries);
+ *pstr++ = ']';
+ *pstr++ = 0;
+ return oitem;
+}
+
+static const char *parse_object(cJSON *item, const char *value)
+{
+ cJSON *child;
+ if (*value != '{') {
+ ep = value;
+ return 0;
+ }
+
+ item->type = cJSON_Object;
+ value = skip(value + 1);
+ if (*value == '}') return value + 1;
+
+ item->child = child = cJSON_New_Item();
+ if (!item->child) return 0;
+ value = skip(parse_string(child, skip(value)));
+ if (!value) return 0;
+ child->string = child->valuestring;
+ child->valuestring = 0;
+ if (*value != ':') {
+ ep = value;
+ return 0;
+ }
+ value = skip(parse_value(child, skip(value + 1)));
+ if (!value) return 0;
+
+ while (*value == ',') {
+ cJSON *new_item;
+ if (!(new_item = cJSON_New_Item())) return 0;
+ child->next = new_item;
+ new_item->prev = child;
+ child = new_item;
+ value = skip(parse_string(child, skip(value + 1)));
+ if (!value) return 0;
+ child->string = child->valuestring;
+ child->valuestring = 0;
+ if (*value != ':') {
+ ep = value;
+ return 0;
+ }
+ value = skip(parse_value(child, skip(value + 1)));
+ if (!value) return 0;
+ }
+
+ if (*value == '}') return value + 1;
+ ep = value;
+ return 0;
+}
+
+static char *print_object(cJSON *item, int depth, int fmt)
+{
+ char *oitem = 0, *pstr, *ret, *str;
+ char **entries = 0, **names = 0;
+ int len = 7, i = 0, j;
+ int numentries = 0, fail = 0;
+ cJSON *child = item->child;
+
+ while (child) numentries++, child = child->next;
+
+ if (!numentries) {
+ oitem = (char*)cJSON_malloc(fmt ? depth + 4 : 3);
+ if (!oitem) return 0;
+ pstr = oitem;
+ *pstr++ = '{';
+ if (fmt) {
+ *pstr++ = '\n';
+ for (i = 0; i < depth - 1; i++) *pstr++ = '\t';
+ }
+ *pstr++ = '}';
+ *pstr++ = 0;
+ return oitem;
+ }
+
+ entries = (char**)cJSON_malloc(numentries * sizeof(char*));
+ if (!entries)
+ return 0;
+ names = (char**)cJSON_malloc(numentries * sizeof(char*));
+ if (!names) {
+ cJSON_free(entries);
+ return 0;
+ }
+ memset(entries, 0, sizeof(char*)*numentries);
+ memset(names, 0, sizeof(char*)*numentries);
+
+
+ child = item->child;
+ depth++;
+ if (fmt) len += depth;
+ while (child) {
+ names[i] = str = print_string_ptr(child->string);
+ entries[i++] = ret = print_value(child, depth, fmt);
+ if (str && ret)
+ len += strlen(ret) + strlen(str) + 2 + (fmt ? 2 + depth : 0);
+ else
+ fail = 1;
+ child = child->next;
+ }
+
+
+ if (!fail) oitem = (char*)cJSON_malloc(len);
+ if (!oitem) fail = 1;
+
+
+ if (fail) {
+ for (i = 0; i < numentries; i++) {
+ if (names[i]) cJSON_free(names[i]);
+ if (entries[i]) cJSON_free(entries[i]);
+ }
+ cJSON_free(names);
+ cJSON_free(entries);
+ return 0;
+ }
+
+
+ *oitem = '{';
+ pstr = oitem + 1;
+ if (fmt)*pstr++ = '\n';
+ *pstr = 0;
+ for (i = 0; i < numentries; i++) {
+ if (fmt) for (j = 0; j < depth; j++) *pstr++ = '\t';
+ strcpy(pstr, names[i]);
+ pstr += strlen(names[i]);
+ *pstr++ = ':';
+ if (fmt) *pstr++ = '\t';
+ strcpy(pstr, entries[i]);
+ pstr += strlen(entries[i]);
+ if (i != numentries - 1) *pstr++ = ',';
+ if (fmt) *pstr++ = '\n';
+ *pstr = 0;
+ cJSON_free(names[i]);
+ cJSON_free(entries[i]);
+ }
+
+ cJSON_free(names);
+ cJSON_free(entries);
+ if (fmt) for (i = 0; i < depth - 1; i++) *pstr++ = '\t';
+ *pstr++ = '}';
+ *pstr++ = 0;
+ return oitem;
+}
+
+int cJSON_GetArraySize(cJSON *array)
+{
+ int i = 0;
+ cJSON *citem = array->child;
+
+ while (citem)i++, citem = citem->next;
+ return i;
+}
+cJSON *cJSON_GetArrayItem(cJSON *array, int item)
+{
+ cJSON *citem = array->child;
+ while (citem && item > 0) item--, citem = citem->next;
+ return citem;
+}
+cJSON *cJSON_GetObjectItem(cJSON *object, const char *string)
+{
+ cJSON *citem = object->child;
+ while (citem && cJSON_strcasecmp(citem->string, string)) citem = citem->next;
+ return citem;
+}
+
+static void suffix_object(cJSON *prev, cJSON *item)
+{
+ prev->next = item;
+ item->prev = prev;
+}
+
+static cJSON *create_reference(cJSON *item)
+{
+ cJSON *refer = cJSON_New_Item();
+ if (!refer)
+ return 0;
+ memcpy(refer, item, sizeof(cJSON));
+ refer->string = 0;
+ refer->type |= cJSON_IsReference;
+ refer->next = refer->prev = 0;
+ return refer;
+}
+
+void cJSON_AddItemToArray(cJSON *array, cJSON *item)
+{
+ cJSON *citem = array->child;
+ if (!item)
+ return;
+ if (!citem) {
+ array->child = item;
+ } else {
+ while (citem && citem->next) citem = citem->next;
+ suffix_object(citem, item);
+ }
+}
+void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
+{
+ if (!item)
+ return;
+ if (item->string) cJSON_free(item->string);
+ item->string = cJSON_strdup(string);
+ cJSON_AddItemToArray(object, item);
+}
+void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
+{
+ cJSON_AddItemToArray(array, create_reference(item));
+}
+void cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
+{
+ cJSON_AddItemToObject(object, string, create_reference(item));
+}
+
+cJSON *cJSON_DetachItemFromArray(cJSON *array, int which)
+{
+ cJSON *citem = array->child;
+ while (citem && which > 0) citem = citem->next, which--;
+ if (!citem)
+ return 0;
+ if (citem->prev) citem->prev->next = citem->next;
+ if (citem->next) citem->next->prev = citem->prev;
+ if (citem == array->child) array->child = citem->next;
+ citem->prev = citem->next = 0;
+ return citem;
+}
+void cJSON_DeleteItemFromArray(cJSON *array, int which)
+{
+ cJSON_Delete(cJSON_DetachItemFromArray(array, which));
+}
+cJSON *cJSON_DetachItemFromObject(cJSON *object, const char *string)
+{
+ int i = 0;
+ cJSON *citem = object->child;
+ while (citem && cJSON_strcasecmp(citem->string, string)) i++, citem = citem->next;
+ if (citem)
+ return cJSON_DetachItemFromArray(object, i);
+ return 0;
+}
+void cJSON_DeleteItemFromObject(cJSON *object, const char *string)
+{
+ cJSON_Delete(cJSON_DetachItemFromObject(object, string));
+}
+
+void cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
+{
+ cJSON *citem = array->child;
+ while (citem && which > 0) citem = citem->next, which--;
+ if (!citem)
+ return;
+ newitem->next = citem->next;
+ newitem->prev = citem->prev;
+ if (newitem->next) newitem->next->prev = newitem;
+ if (citem == array->child) array->child = newitem;
+ else newitem->prev->next = newitem;
+ citem->next = citem->prev = 0;
+ cJSON_Delete(citem);
+}
+void cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
+{
+ int i = 0;
+ cJSON *citem = object->child;
+ while (citem && cJSON_strcasecmp(citem->string, string))i++, citem = citem->next;
+ if (citem) {
+ newitem->string = cJSON_strdup(string);
+ cJSON_ReplaceItemInArray(object, i, newitem);
+ }
+}
+
+cJSON *cJSON_CreateNull(void)
+{
+ cJSON *item = cJSON_New_Item();
+ if (item)item->type = cJSON_NULL;
+ return item;
+}
+cJSON *cJSON_CreateTrue(void)
+{
+ cJSON *item = cJSON_New_Item();
+ if (item)item->type = cJSON_True;
+ return item;
+}
+cJSON *cJSON_CreateFalse(void)
+{
+ cJSON *item = cJSON_New_Item();
+ if (item)item->type = cJSON_False;
+ return item;
+}
+cJSON *cJSON_CreateBool(int b)
+{
+ cJSON *item = cJSON_New_Item();
+ if (item)item->type = b ? cJSON_True : cJSON_False;
+ return item;
+}
+cJSON *cJSON_CreateNumber(double num)
+{
+ cJSON *item = cJSON_New_Item();
+ if (item) {
+ item->type = cJSON_Number;
+ item->valuedouble = num;
+ item->valueint = (int)num;
+ }
+ return item;
+}
+cJSON *cJSON_CreateString(const char *string)
+{
+ cJSON *item = cJSON_New_Item();
+ if (item) {
+ item->type = cJSON_String;
+ item->valuestring = cJSON_strdup(string);
+ }
+ return item;
+}
+cJSON *cJSON_CreateArray(void)
+{
+ cJSON *item = cJSON_New_Item();
+ if (item)item->type = cJSON_Array;
+ return item;
+}
+cJSON *cJSON_CreateObject(void)
+{
+ cJSON *item = cJSON_New_Item();
+ if (item)item->type = cJSON_Object;
+ return item;
+}
+
+cJSON *cJSON_CreateIntArray(const int *numbers, int count)
+{
+ int i;
+ cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
+ for (i = 0; a && i < count; i++) {
+ n = cJSON_CreateNumber(numbers[i]);
+ if (!i)a->child = n;
+ else suffix_object(p, n);
+ p = n;
+ }
+ return a;
+}
+cJSON *cJSON_CreateFloatArray(const float *numbers, int count)
+{
+ int i;
+ cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
+ for (i = 0; a && i < count; i++) {
+ n = cJSON_CreateNumber(numbers[i]);
+ if (!i)a->child = n;
+ else suffix_object(p, n);
+ p = n;
+ }
+ return a;
+}
+cJSON *cJSON_CreateDoubleArray(const double *numbers, int count)
+{
+ int i;
+ cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
+ for (i = 0; a && i < count; i++) {
+ n = cJSON_CreateNumber(numbers[i]);
+ if (!i)a->child = n;
+ else suffix_object(p, n);
+ p = n;
+ }
+ return a;
+}
+cJSON *cJSON_CreateStringArray(const char **strings, int count)
+{
+ int i;
+ cJSON *n = 0, *p = 0, *a = cJSON_CreateArray();
+ for (i = 0; a && i < count; i++) {
+ n = cJSON_CreateString(strings[i]);
+ if (!i)a->child = n;
+ else suffix_object(p, n);
+ p = n;
+ }
+ return a;
+}
+
+cJSON *cJSON_Duplicate(cJSON *item, int recurse)
+{
+ cJSON *newitem, *cptr, *nptr = 0, *newchild;
+
+ if (!item)
+ return 0;
+
+ newitem = cJSON_New_Item();
+ if (!newitem)
+ return 0;
+
+ newitem->type = item->type & (~cJSON_IsReference), newitem->valueint = item->valueint, newitem->valuedouble = item->valuedouble;
+ if (item->valuestring) {
+ newitem->valuestring = cJSON_strdup(item->valuestring);
+ if (!newitem->valuestring) {
+ cJSON_Delete(newitem);
+ return 0;
+ }
+ }
+ if (item->string) {
+ newitem->string = cJSON_strdup(item->string);
+ if (!newitem->string) {
+ cJSON_Delete(newitem);
+ return 0;
+ }
+ }
+
+ if (!recurse)
+ return newitem;
+
+ cptr = item->child;
+ while (cptr) {
+ newchild = cJSON_Duplicate(cptr, 1);
+ if (!newchild) {
+ cJSON_Delete(newitem);
+ return 0;
+ }
+ if (nptr) {
+ nptr->next = newchild, newchild->prev = nptr;
+ nptr = newchild;
+ } else {
+ newitem->child = newchild;
+ nptr = newchild;
+ }
+ cptr = cptr->next;
+ }
+ return newitem;
+}
+
+void cJSON_Minify(char *json)
+{
+ char *cpr_str = json;
+ while (*json) {
+ if (*json == ' ') json++;
+ else if (*json == '\t') json++;
+ else if (*json == '\r') json++;
+ else if (*json == '\n') json++;
+ else if (*json == '/' && json[1] == '/') while (*json && *json != '\n') json++;
+ else if (*json == '/' && json[1] == '*') {
+ while (*json && !(*json == '*' && json[1] == '/')) json++;
+ json += 2;
+ } else if (*json == '\"') {
+ *cpr_str++ = *json++;
+ while (*json && *json != '\"') {
+ if (*json == '\\') *cpr_str++ = *json++;
+ *cpr_str++ = *json++;
+ }
+ *cpr_str++ = *json++;
+ } else *cpr_str++ = *json++;
+ }
+ *cpr_str = 0;
+}
diff --git a/ap/lib/liblpa/cjson.h b/ap/lib/liblpa/cjson.h
new file mode 100755
index 0000000..4a86aba
--- /dev/null
+++ b/ap/lib/liblpa/cjson.h
@@ -0,0 +1,99 @@
+#ifndef cJSON__h
+#define cJSON__h
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+#define cJSON_False 0
+#define cJSON_True 1
+#define cJSON_NULL 2
+#define cJSON_Number 3
+#define cJSON_String 4
+#define cJSON_Array 5
+#define cJSON_Object 6
+
+#define cJSON_IsReference 256
+
+typedef struct cJSON_Hooks {
+ void *(*malloc_fn)(size_t sz);
+ void (*free_fn)(void *ptr);
+} cJSON_Hooks;
+
+typedef struct cJSON {
+ struct cJSON *next, *prev;
+ struct cJSON *child;
+
+ int type;
+
+ char *valuestring;
+ int valueint;
+ double valuedouble;
+
+ char *string;
+} cJSON;
+
+
+extern void cJSON_InitHooks(cJSON_Hooks* hooks);
+
+extern cJSON *cJSON_Parse(const char *value);
+extern char *cJSON_Print(cJSON *item);
+extern char *cJSON_PrintUnformatted(cJSON *item);
+
+extern int cJSON_GetArraySize(cJSON *array);
+extern cJSON *cJSON_GetArrayItem(cJSON *array, int item);
+extern cJSON *cJSON_GetObjectItem(cJSON *object, const char *string);
+
+extern const char *cJSON_GetErrorPtr(void);
+
+extern cJSON *cJSON_CreateNull(void);
+extern cJSON *cJSON_CreateTrue(void);
+extern cJSON *cJSON_CreateFalse(void);
+extern cJSON *cJSON_CreateBool(int b);
+extern cJSON *cJSON_CreateNumber(double num);
+extern cJSON *cJSON_CreateString(const char *string);
+extern cJSON *cJSON_CreateArray(void);
+extern cJSON *cJSON_CreateObject(void);
+
+extern cJSON *cJSON_CreateIntArray(const int *numbers, int count);
+extern cJSON *cJSON_CreateFloatArray(const float *numbers, int count);
+extern cJSON *cJSON_CreateDoubleArray(const double *numbers, int count);
+extern cJSON *cJSON_CreateStringArray(const char **strings, int count);
+
+extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
+extern void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
+extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
+extern void cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
+
+extern void cJSON_Delete(cJSON *c);
+
+extern cJSON *cJSON_DetachItemFromArray(cJSON *array, int which);
+extern void cJSON_DeleteItemFromArray(cJSON *array, int which);
+extern cJSON *cJSON_DetachItemFromObject(cJSON *object, const char *string);
+extern void cJSON_DeleteItemFromObject(cJSON *object, const char *string);
+
+extern void cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
+extern void cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem);
+
+extern cJSON *cJSON_Duplicate(cJSON *item, int recurse);
+extern cJSON *cJSON_ParseWithOpts(const char *value, const char **return_parse_end, int require_null_terminated);
+
+extern void cJSON_Minify(char *json);
+
+#define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val))
+
+#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull())
+#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
+#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
+#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
+#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
+#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ap/lib/liblpa/libes10.a b/ap/lib/liblpa/libes10.a
new file mode 100644
index 0000000..5422bc4
--- /dev/null
+++ b/ap/lib/liblpa/libes10.a
Binary files differ
diff --git a/ap/lib/liblpa/lpa_api.h b/ap/lib/liblpa/lpa_api.h
new file mode 100755
index 0000000..c5adf81
--- /dev/null
+++ b/ap/lib/liblpa/lpa_api.h
@@ -0,0 +1,40 @@
+#ifndef __LPA_API_H__
+#define __LPA_API_H__
+
+
+
+
+
+//
+int lpa_init(void);
+int lpa_uninit(void);
+int lpa_select_aid(void);
+int lpa_check_status(int retry);
+int lpa_exception_process(void);
+
+
+//trigger
+char *lpa_trigger_event(int *next_step);
+int lpa_trigger_updata(void);
+
+
+//api
+int downloadProfileByAc(char *activecode, char *confirmcode);
+int downloadProfileByEid(void);
+int enableProfile(char *iccid);
+int disableProfile(char * iccid);
+int deleteProfile(char * iccid);
+int memoryReset(void);
+int getProfileList(char **info);
+
+int lpa_download_profile(char *activecode, char *confirmcode);
+int lpa_enable_profile(char *iccid);
+int lpa_disable_profile(char *iccid);
+int lpa_delete_profile(char *iccid);
+int lpa_memory_reset(void);
+
+int lpa_open_logical_channel(void);
+int lpa_close_logical_channel(int flag);
+
+
+#endif
diff --git a/ap/lib/liblpa/lpa_es9plus.c b/ap/lib/liblpa/lpa_es9plus.c
new file mode 100755
index 0000000..f30845f
--- /dev/null
+++ b/ap/lib/liblpa/lpa_es9plus.c
@@ -0,0 +1,193 @@
+/***************************************************************/
+//
+//²Î¼û LPA½Ó¿ÚÎĵµV0.1 SGP.22, ·µ»ØJSON
+//
+/***************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/time.h>
+#include <termios.h>
+
+#include "lpa_inner.h"
+
+
+#define LPA_AUTH_DATA_LEN 512
+
+/***************************************************************/
+//
+//euiccChallenge:¿¨·µ»ØµÄAPDU,²»º¬9000
+//euiccInfo1: ¿¨·µ»ØµÄAPDU,²»º¬9000
+//smdpAddress:¼¤»îÂëÖÐsdmpµØÖ·
+//·µ»Øjson
+//
+/***************************************************************/
+char *InitiateAuthentication(char *euiccChallenge, char *euiccInfo1, char *smdpAddress)
+{
+ char *js_data = NULL;
+ unsigned char clg_byte[APDU_BYTE_LEN] = {0};
+ unsigned char info1_byte[APDU_BYTE_LEN] = {0};
+ int clg_len = 0;
+ int info1_len = 0;
+ char *clg_b64 = NULL;
+ char *info1_b64 = NULL;
+
+ clg_len = string2bytes(euiccChallenge, clg_byte, strlen(euiccChallenge));
+ clg_b64 = lpa_base64_encode(clg_byte, clg_len);
+ if (clg_b64 == NULL)
+ return NULL;
+
+ info1_len = string2bytes(euiccInfo1, info1_byte, strlen(euiccInfo1));
+ info1_b64 = lpa_base64_encode(info1_byte, info1_len);
+ if (info1_b64 == NULL) {
+ free(clg_b64);
+ return NULL;
+ }
+
+ js_data = malloc(LPA_AUTH_DATA_LEN);
+ if (js_data != NULL) {
+ memset(js_data, 0, LPA_AUTH_DATA_LEN);
+ snprintf(js_data, LPA_AUTH_DATA_LEN, "{\"euiccChallenge\":\"%s\",\"euiccInfo1\":\"%s\",\"smdpAddress\":\"%s\"}",
+ clg_b64, info1_b64, smdpAddress);
+ //printf("js_data:-%s-\n", js_data);
+ }
+
+ free(clg_b64);
+ free(info1_b64);
+ return js_data;
+}
+
+/***************************************************************/
+//
+//transactionId: smdp InitiateAuthentication½Ó¿Ú·µ»Ø
+//authSerRespHex:¿¨·µ»ØµÄAPDU,²»º¬9000
+//
+/***************************************************************/
+char *AuthenticateClient(
+char *transactionId,
+char *authSerRespHex)
+{
+ char *ac_js = NULL;
+ unsigned char *as_byte = NULL;
+ int as_byte_len = 0;
+ int ashex_len = strlen(authSerRespHex);
+ char *as_b64 = NULL;
+ int as_b64_len = 0;
+
+ as_byte = malloc(ashex_len/2 + 1);
+ if (as_byte == NULL) {
+ return NULL;
+ }
+ memset(as_byte, 0, ashex_len/2 + 1);
+
+ as_byte_len = string2bytes(authSerRespHex, as_byte, ashex_len);
+ as_b64 = lpa_base64_encode(as_byte, as_byte_len);
+ if (as_b64 == NULL) {
+ free(as_byte);
+ return NULL;
+ }
+ as_b64_len = strlen(as_b64);
+
+ ac_js = malloc(as_b64_len + 100);
+ if (ac_js != NULL) {
+ memset(ac_js, 0, as_b64_len + 100);
+ snprintf(ac_js, as_b64_len + 100, "{\"transactionId\":\"%s\",\"authenticateServerResponse\":\"%s\"}",
+ transactionId, as_b64);
+ //printf("js_data:-%s-\n", ac_js);
+ }
+
+ free(as_byte);
+ free(as_b64);
+ return ac_js;
+}
+
+
+/***************************************************************/
+//
+//transactionId: smdp AuthenticateClient½Ó¿Ú·µ»Ø
+//predlRespHex: prepareDownloadResponseHex ¿¨·µ»ØµÄAPDU,²»º¬9000
+//
+/***************************************************************/
+char *GetBoundProfilePackage (
+char *transactionId,
+char *predlRespHex)
+{
+ char *bpp_js = NULL;
+ unsigned char *pdl_byte = NULL;
+ int pdl_byte_len = 0;
+ int pdlhex_len = strlen(predlRespHex);
+ char *pdl_b64 = NULL;
+ int pdl_b64_len = 0;
+
+ pdl_byte = malloc(pdlhex_len/2 + 1);
+ if (pdl_byte == NULL) {
+ return NULL;
+ }
+ memset(pdl_byte, 0, pdlhex_len/2 + 1);
+
+ pdl_byte_len = string2bytes(predlRespHex, pdl_byte, pdlhex_len);
+ pdl_b64 = lpa_base64_encode(pdl_byte, pdl_byte_len);
+ if (pdl_b64 == NULL) {
+ free(pdl_byte);
+ return NULL;
+ }
+ pdl_b64_len = strlen(pdl_b64);
+
+ bpp_js = malloc(pdl_b64_len + 100);
+ if (bpp_js != NULL) {
+ memset(bpp_js, 0, pdl_b64_len + 100);
+ snprintf(bpp_js, pdl_b64_len + 100, "{\"transactionId\":\"%s\",\"prepareDownloadResponse\":\"%s\"}",
+ transactionId, pdl_b64);
+ //printf("js_data:-%s-\n", bpp_js);
+ }
+
+ free(pdl_byte);
+ free(pdl_b64);
+ return bpp_js;
+}
+
+
+/***************************************************************/
+//
+//pnfHex: pendingNotification ¿¨·µ»ØµÄAPDU,²»º¬9000
+//
+/***************************************************************/
+char *HandleNotification(char *pnfHex)
+{
+ char *bpp_js = NULL;
+ unsigned char *pdl_byte = NULL;
+ int pdl_byte_len = 0;
+ int pdlhex_len = strlen(pnfHex);
+ char *pdl_b64 = NULL;
+ int pdl_b64_len = 0;
+
+ pdl_byte = malloc(pdlhex_len/2 + 1);
+ if (pdl_byte == NULL) {
+ return NULL;
+ }
+ memset(pdl_byte, 0, pdlhex_len/2 + 1);
+
+ pdl_byte_len = string2bytes(pnfHex, pdl_byte, pdlhex_len);
+ pdl_b64 = lpa_base64_encode(pdl_byte, pdl_byte_len);
+ if (pdl_b64 == NULL) {
+ free(pdl_byte);
+ return NULL;
+ }
+ pdl_b64_len = strlen(pdl_b64);
+
+ bpp_js = malloc(pdl_b64_len + 100);
+ if (bpp_js != NULL) {
+ memset(bpp_js, 0, pdl_b64_len + 100);
+ snprintf(bpp_js, pdl_b64_len + 100,
+ "{\"header\":{\"functionExecutionStatus\":{\"status\":\"Executed-Success\"}},\"pendingNotification\":\"%s\"}", pdl_b64);
+ //printf("js_data:-%s-\n", bpp_js);
+ }
+
+ free(pdl_byte);
+ free(pdl_b64);
+ return bpp_js;
+}
+
+
diff --git a/ap/lib/liblpa/lpa_esim_api.c b/ap/lib/liblpa/lpa_esim_api.c
new file mode 100755
index 0000000..509d047
--- /dev/null
+++ b/ap/lib/liblpa/lpa_esim_api.c
@@ -0,0 +1,866 @@
+/***************************************************************/
+//
+//²Î¼û ÖйúÁªÍ¨esimÄ£×éÀ©Õ¹Ö¸Áî¼¼Êõ¹æ·¶
+//
+/***************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/time.h>
+#include <termios.h>
+#include <errno.h>
+
+#include "lpa_inner.h"
+
+
+#define SMDP_PORT 443
+#define SMDP_DL_INTERVAL 95//ÏÂÔØ¼ä¸ô>90s
+
+
+//´¥·¢·þÎñÆ÷httpÇëÇó
+static char smdp_https_req[] =
+ "POST /gsma/rsp2/es9plus/%s HTTP/1.1\r\n"
+ "Host: %s\r\n"
+ "User-Agent: gsma-rsp-lpad\r\n"
+ "X-Admin-Protocol: gsma/rsp/v2.2.0\r\n"
+ "Content-Type: application/json\r\n"
+ "Content-Length: %d\r\n"
+ "\r\n%s\r\n";
+
+static https_context_t g_https_ct = {0};
+static char g_transid[MAX_TRANSID_LEN] = {0};
+char curent_iccid[ICCID_LEN+1] = {0};
+
+extern char g_imei[MAX_IMEI_LEN];
+
+//iccid from bpp install result, if null, failed
+//ISD-P AID, tag '4F';ICCID, tag '5A'. if succ, has AID
+static int lpa_parse_iccid_apdu(char *apdu, char *iccid, int size)
+{
+ int apdu_len = strlen(apdu);
+ unsigned char *apdu_byte = malloc(apdu_len/2 + 1);
+ int apdu_byte_len = 0;
+ char *tag_hex = NULL;
+ char has_iccid[ICCID_LEN+1] = {0};
+
+ if (apdu_byte == NULL) {
+ printf("lpa_parse_iccid_apdu no memory\n");
+ return -1;
+ }
+ memset(apdu_byte, 0, apdu_len/2 + 1);
+
+ apdu_byte_len = string2bytes(apdu, apdu_byte, apdu_len);
+
+ tag_hex = lpa_tlv_get_val_by_tag(apdu_byte, apdu_byte_len, 0x4F);
+ if (tag_hex == NULL) {
+ printf("lpa_parse_iccid_apdu not find AID\n");
+ free(apdu_byte);
+ return -1;
+ }
+ printf("lpa aid:%s\n", tag_hex);
+ free(tag_hex);
+ tag_hex = NULL;
+
+ tag_hex = lpa_tlv_get_val_by_tag(apdu_byte, apdu_byte_len, 0x5A);
+ if (tag_hex == NULL) {
+ printf("lpa_parse_iccid_apdu not find iccid\n");
+ free(apdu_byte);
+ return -1;
+
+ }
+
+ snprintf(iccid, size, "%s", tag_hex);
+
+ sc_cfg_get("lpa_bpp_iccid", has_iccid, sizeof(has_iccid));
+ if (strcmp(iccid, has_iccid) != 0) {
+ sc_cfg_set("lpa_bpp_iccid", iccid);
+ sc_cfg_save();
+ printf("lpa iccid not same?\n");
+ }
+
+ printf("lpa iccid:%s\n", iccid);
+
+ free(apdu_byte);
+ free(tag_hex);
+ return 0;
+}
+
+static int lpa_connect_smdp(char *host)
+{
+ SSL_library_init();
+
+ g_https_ct.port=SMDP_PORT;
+ g_https_ct.host=host;
+ g_https_ct.path=NULL;
+ return https_init(&g_https_ct);
+}
+
+static void lpa_disconn_smdp(char *host)
+{
+ https_uninit(&g_https_ct);
+}
+
+static char *lpa_smdp_session(char *path, char *req_data, int *res_len)
+{
+ int ret = -1;
+ int cont_len = 0;
+ char *https_req = NULL;
+ char *https_resp = NULL;
+ int https_req_len = strlen(smdp_https_req)+strlen(path)+strlen(g_https_ct.host)+strlen(req_data)+32;
+
+ *res_len = -1;
+
+ if (https_req_len > SMDP_HTTP_MAX_LEN)
+ return NULL;
+
+ https_req = malloc(https_req_len);
+ if (https_req == NULL)
+ return NULL;
+
+ memset(https_req, 0, https_req_len);
+ g_https_ct.path = path;
+ ret = snprintf(https_req, https_req_len, smdp_https_req,
+ g_https_ct.path, g_https_ct.host, strlen(req_data), req_data);
+
+ printf("[https_smdp]req[%d]:##%s##\n", strlen(https_req), https_req);
+ ret = https_write(&g_https_ct, https_req, ret);
+ if (ret == -1) {
+ //EAGAIN?
+ free(https_req);
+ printf("[https_smdp] https_write err:%d.\n", errno);
+ return NULL;
+ }
+
+ ret = https_get_status_code(&g_https_ct, &cont_len);
+ if(ret == 200) {
+ printf("[https_smdp] https_recv len:%d.\n", cont_len);
+ if (cont_len == HTTP_CHUNKED_FLAG) {
+ ret = https_read_chunked_content(&g_https_ct, &https_resp, SMDP_HTTP_MAX_LEN);
+ if(ret > 0) {
+ *res_len = ret;
+ https_resp[ret] = '\0'; //×Ö·û´®½áÊø±êʶ
+ printf("[https_smdp] https_write https_resp_content##%s##\n",https_resp);
+ }
+ printf("[https_smdp] https_resp chunk %d!!!\n", ret);
+ }
+ else {
+ if (cont_len >= SMDP_HTTP_MAX_LEN) {
+ free(https_req);
+ printf("[https_smdp] https_recv too long = %d.\n", cont_len);
+ return NULL;
+ }
+ https_resp = malloc(cont_len + 1);
+ if (https_resp == NULL) {
+ free(https_req);
+ return NULL;
+ }
+
+ memset(https_resp, 0, cont_len + 1);
+ ret = https_read_content(&g_https_ct, https_resp, cont_len);
+ if(ret > 0) {
+ *res_len = ret;
+ https_resp[ret] = '\0'; //×Ö·û´®½áÊø±êʶ
+ printf("[https_smdp] https_read_content##%s##\n",https_resp);
+ }
+ else {
+ *res_len = -1;
+ free(https_req);
+ free(https_resp);
+ return NULL;
+ }
+ }
+ }
+ else if(ret == 204) {
+ *res_len = 0;
+ }
+ else {
+ printf("[https_smdp] https_resp code = %d.\n", ret);
+ }
+
+ free(https_req);
+ return https_resp;
+}
+/***************************************************************/
+//
+//ÌáÈ¡stringÀàÐÍÊý¾Ý
+//
+/***************************************************************/
+static char *lpa_parse_json_str(char *srcStr, char *key)
+{
+ cJSON *root = NULL;
+ cJSON *object = NULL;
+ char *value_str = NULL;
+ int value_len = 0;
+
+ root = cJSON_Parse(srcStr);
+ if (root == NULL) {
+ printf("root == NULL\n");
+ return NULL;
+ }
+
+ object = cJSON_GetObjectItem(root, key);
+ if (object == NULL) {
+ printf("key: %s not find\n", key);
+ cJSON_Delete(root);
+ return NULL;
+ }
+ //printf("key:%s-value:%s\n", key, object->valuestring);
+ value_len = strlen(object->valuestring);
+
+ value_str = malloc(value_len + 1);
+ if (value_str == NULL) {
+ cJSON_Delete(root);
+ return NULL;
+
+ }
+ memset(value_str, 0, value_len + 1);
+ strncpy(value_str, object->valuestring, value_len);
+
+ cJSON_Delete(root);
+ return value_str;
+}
+
+/***************************************************************/
+//
+//ÌáÈ¡stringÀàÐ͵Äbase64Êý¾Ý->decode->hex string
+//
+/***************************************************************/
+static char *lpa_parse_json_decode(char *srcStr, char *key)
+{
+ cJSON *root = NULL;
+ cJSON *object = NULL;
+ char *value_byte = NULL;
+ char *value_str = NULL;
+ int value_len = 0;
+
+ root = cJSON_Parse(srcStr);
+ if (root == NULL) {
+ printf("root == NULL\n");
+ return NULL;
+ }
+
+ object = cJSON_GetObjectItem(root, key);
+ if (object == NULL) {
+ printf("key: %s not find\n", key);
+ cJSON_Delete(root);
+ return NULL;
+ }
+
+ //printf("key:%s-value:%s\n", key, object->valuestring);
+ value_byte = lpa_base64_decode(object->valuestring, strlen(object->valuestring), &value_len);
+ if (value_byte == NULL) {
+ printf("lpa_base64_decode fail\n");
+ cJSON_Delete(root);
+ return NULL;
+ }
+
+ value_str = malloc(value_len*2 + 1);
+ if (value_str == NULL) {
+ free(value_byte);
+ cJSON_Delete(root);
+ return NULL;
+
+ }
+
+ memset(value_str, 0, value_len*2 + 1);
+ bytes2string(value_byte, value_str, value_len);
+ *(value_str + value_len*2) = '\0';
+ //printf("key:%s(%d)-hex:%s\n", key, value_len*2, value_str);
+ free(value_byte);
+ cJSON_Delete(root);
+ return value_str;
+}
+
+/***************************************************************/
+//
+//char srcStr[] =
+//"{"
+// "\"header\" : {"
+// "\"functionExecutionStatus\" : {"
+// "\"status\" : \"Executed-Success\""
+// "}"
+// "},"
+// "\"serverSigned1\": \"MEKAEAK3+mF5GUrrl+BlIUcujtSBEFK4u91WT/9GbQX+6pX/aoCDCmVzaW0ud28uY26EEEYRuTYzeka9iSyW+gSFF44=\","
+// "\"transactionId\": \"02B7FA6179194AEB97E06521472E8ED4\","
+// "\"serverSignature1\": \"XzdA9J6G6txPTOeOjQThaH/u/Wy/LOcZYec9reC65gjva7waj0XFBs0k551ynos1izFUpXbF8vctFw+/Enqu5aDQTA==\","
+// "\"serverCertificate\": \"MIIC1jCCAn2gAwIBAgIDAYb6MAoGCCqGSM49BAMCMH4xCzAJBgNVBAYTAkNOMQ4wDAYDVQQIDAVKSUxJTjESMBAGA1UEBwwJQ0hBTkdDSFVOMQ0wCwYDVQQLDARDVUNBMQswCQYDVQQKDAJDVTEvMC0GA1UEAwwmQ2hpbmEgVW5pY29tIGVTSU0gUm9vdCBDQSBOSVNUUCBCWlRFU1QwHhcNMTkxMjI1MTUyNzEyWhcNMjAxMjI0MTUyNzEyWjB5MQswCQYDVQQGEwJDTjEnMCUGA1UECwweSW5ub3ZhdGl2ZSBCdXNpbmVzcyBEZXBhcnRtZW50MQ4wDAYDVQQKDAVWc2VuczExMC8GA1UEAwwoVW5pY29tIFZzZW5zIENvbW11bmljYXRpb24gQ28uIEx0ZChUZXN0KTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABC0BAmyq7voWvhezfZnAoQyRb5CgvPjFuGr7c4arFsbBFNYcv7w5C3Tp3wHD03HkIIhPuZrkx9kWNYeBrekfBw6jge4wgeswHwYDVR0jBBgwFoAUfA5UcBQ+qJmO2d8wBXTJLlqayx8wHQYDVR0OBBYEFC2+UJhg5G9/+zlI3mqf7YMrZHPMMA4GA1UdDwEB/wQEAwIHgDAXBgNVHSABAf8EDTALMAkGB2eBEgECAQQwFQYDVR0RBA4wDIgKKwYBBAGC9UYCBDBpBgNVHR8EYjBgMC6gLKAqhihodHRwOi8vY3JsLnVuaS1jYS5jb20uY24vZG93bmxvYWQvbjEuY3JsMC6gLKAqhihodHRwOi8vY3JsLnVuaS1jYS5jb20uY24vZG93bmxvYWQvbjIuY3JsMAoGCCqGSM49BAMCA0cAMEQCIBEAZfg9hJIax/xRpVIAjjmENrPr7q97E0Hv2s+8aOPDAiBaURKuxxzZ8/P0DKE7SmW+AhbxBl1TQd09sM6+Plzu9A==\","
+// "\"euiccCiPKIdToBeUsed\": \"BBR8DlRwFD6omY7Z3zAFdMkuWprLHw==\""
+//"}";
+//
+/***************************************************************/
+static char *lpa_parse_initauth_resp(char *srcStr)
+{
+ char *transid = NULL;
+ char *signed_hex = NULL;
+ char *signature_hex = NULL;
+ char *ciPKId_hex = NULL;
+ char *certificate_hex = NULL;
+
+ char *authser_apdu = NULL;
+ //1 transid
+ //2 get sig...
+ //3 genaner at and send
+
+ transid = lpa_parse_json_str(srcStr, "transactionId");
+ if (transid == NULL)
+ goto parse_END;
+ snprintf(g_transid, sizeof(g_transid), "%s", transid);
+
+
+ signed_hex = lpa_parse_json_decode(srcStr, "serverSigned1");
+ if (signed_hex == NULL)
+ goto parse_END;
+
+ signature_hex = lpa_parse_json_decode(srcStr, "serverSignature1");
+ if (signature_hex == NULL)
+ goto parse_END;
+
+ ciPKId_hex = lpa_parse_json_decode(srcStr, "euiccCiPKIdToBeUsed");
+ if (ciPKId_hex == NULL)
+ goto parse_END;
+
+ certificate_hex = lpa_parse_json_decode(srcStr, "serverCertificate");
+ if (certificate_hex == NULL)
+ goto parse_END;
+
+//×îºóÒ»¶ÎÊÇɶ£¿ctxparams
+//80E29103£¿91±íʾ½öÒ»¶Î»òÕß×îºóÒ»¶Î
+//×î×îºóµÄ00²»ËãÔÚ³¤¶ÈÄÚ
+// 80E21100FFBF38(00 = i, ff =len)
+// ffÖ®ºó×¶àÉÙÏß²»¹Ü
+// ÏÈËãbf38ºó×¶àÉÙ£¬½«bf38ºóÊý¾ÝÏÈ×éºÃ£¬ÔÙ¼Ó
+// 80E2110iLLÀ´·Ö¸îat
+// ²¢ÔÚ×îºóÒ»¶ÎÏ·¢ºó¶ÁÈÏÖ¤·þÎñÆ÷µÄ²ÎÊýat
+
+ //matchingId´Ó¼¤»îÂëÖÐÈ¡£¬Ä¿Ç°Ã»ÓÃ
+ authser_apdu = AuthenticateServer(signed_hex, signature_hex, ciPKId_hex, certificate_hex, "", g_imei);
+
+
+parse_END:
+ if (transid != NULL)
+ free(transid);
+ if (signed_hex != NULL)
+ free(signed_hex);
+ if (signature_hex != NULL)
+ free(signature_hex);
+ if (ciPKId_hex != NULL)
+ free(ciPKId_hex);
+ if (certificate_hex != NULL)
+ free(certificate_hex);
+
+ return authser_apdu;
+}
+
+static char *lpa_parse_authcli_resp(char *srcStr)
+{
+ char *transid = NULL;
+ char *signed2_hex = NULL;
+ char *signature2_hex = NULL;
+ char *certi_hex = NULL;
+ //char *meta_hex = NULL;
+
+ char *predl_apdu = NULL;
+
+ transid = lpa_parse_json_str(srcStr, "transactionId");
+ if (transid == NULL)
+ goto parse_END;
+ snprintf(g_transid, sizeof(g_transid), "%s", transid);
+
+
+ signed2_hex = lpa_parse_json_decode(srcStr, "smdpSigned2");
+ if (signed2_hex == NULL)
+ goto parse_END;
+
+ signature2_hex = lpa_parse_json_decode(srcStr, "smdpSignature2");
+ if (signature2_hex == NULL)
+ goto parse_END;
+
+ certi_hex = lpa_parse_json_decode(srcStr, "smdpCertificate");
+ if (certi_hex == NULL)
+ goto parse_END;
+
+ //meta_hex = lpa_parse_json_decode(srcStr, "profileMetadata");
+ //if (meta_hex == NULL)
+ // goto parse_END;
+
+ predl_apdu = PrepareDownload(transid, signed2_hex, signature2_hex, certi_hex, "");
+
+parse_END:
+ if (transid != NULL)
+ free(transid);
+ if (signed2_hex != NULL)
+ free(signed2_hex);
+ if (signature2_hex != NULL)
+ free(signature2_hex);
+ if (certi_hex != NULL)
+ free(certi_hex);
+ //if (meta_hex != NULL)
+ // free(meta_hex);
+
+ return predl_apdu;
+}
+
+static char *lpa_parse_getbpp_resp(char *srcStr)
+{
+ char *transid = NULL;
+ char *bpp_b64 = NULL;
+
+ char *notify_apdu = NULL;
+
+ transid = lpa_parse_json_str(srcStr, "transactionId");
+ if (transid == NULL)
+ goto parse_END;
+ snprintf(g_transid, sizeof(g_transid), "%s", transid);
+
+
+ bpp_b64 = lpa_parse_json_str(srcStr, "boundProfilePackage");
+ if (bpp_b64 == NULL)
+ goto parse_END;
+
+ notify_apdu = LoadBoundProfilePackage(bpp_b64);
+
+parse_END:
+ if (transid != NULL)
+ free(transid);
+ if (bpp_b64 != NULL)
+ free(bpp_b64);
+
+ return notify_apdu;
+}
+
+
+//·µ»ØjsonÊý¾Ý¸øÏÂÒ»²½µ÷ÓÃ
+static char *lpa_initauth(void)
+{
+ int ret = -1;
+ char *euiccChallenge = NULL;
+ char *euiccInfo1 = NULL;
+ char *ia_json = NULL;
+ char *https_resp = NULL;
+ char *resp_apdu = NULL;
+
+ euiccChallenge = GetEUICCChallenge();
+ if (euiccChallenge == NULL) {
+ return NULL;
+ }
+
+ euiccInfo1 = GetEUICCInfo(TRUE);
+ if (euiccInfo1 == NULL) {
+ free(euiccChallenge);
+ return NULL;
+ }
+
+ ia_json = InitiateAuthentication(euiccChallenge, euiccInfo1, g_https_ct.host);
+ if (ia_json == NULL) {
+ free(euiccChallenge);
+ free(euiccInfo1);
+ return NULL;
+ }
+
+ https_resp = lpa_smdp_session("initiateAuthentication", ia_json, &ret);
+ if (https_resp != NULL) {
+ resp_apdu = lpa_parse_initauth_resp(https_resp);
+ free(https_resp);
+ }
+
+ free(euiccChallenge);
+ free(euiccInfo1);
+ free(ia_json);
+ return resp_apdu;
+}
+
+static char *lpa_authclient(char *as_apdu)
+{
+ int ret = -1;
+
+ char *ac_json = NULL;
+ char *https_resp = NULL;
+ char *resp_apdu = NULL;
+
+ ac_json = AuthenticateClient(g_transid, as_apdu);
+ if (ac_json == NULL) {
+ return NULL;
+ }
+
+ https_resp = lpa_smdp_session("authenticateClient", ac_json, &ret);
+ if (https_resp != NULL) {
+ resp_apdu = lpa_parse_authcli_resp(https_resp);
+ free(https_resp);
+ }
+
+ free(ac_json);
+ return resp_apdu;
+}
+
+static char *lpa_getbpp(char *pdl_apdu)
+{
+ int ret = -1;
+
+ char *bpp_json = NULL;
+ char *https_resp = NULL;
+ char *resp_apdu = NULL;
+
+ bpp_json = GetBoundProfilePackage(g_transid, pdl_apdu);
+ if (bpp_json == NULL) {
+ return NULL;
+ }
+
+ https_resp = lpa_smdp_session("getBoundProfilePackage", bpp_json, &ret);
+ if (ret > 0) {
+ resp_apdu = lpa_parse_getbpp_resp(https_resp);
+ free(https_resp);
+ }
+
+ free(bpp_json);
+ return resp_apdu;
+}
+
+static int lpa_notification(char *notify_apdu)
+{
+ int ret = -1;
+
+ char *notify_json = NULL;
+ char *https_resp = NULL;
+
+ notify_json = HandleNotification(notify_apdu);
+ if (notify_json == NULL) {
+ return ret;
+ }
+ https_resp = lpa_smdp_session("handleNotification", notify_json, &ret);
+ if (https_resp != NULL)
+ free(https_resp);
+ //no resp?
+
+ free(notify_json);
+ return ret;
+}
+
+/***************************************************************/
+//
+//"1$esim.wo.cn$$1.3.6.1.4.1.47814.2.4"
+//
+/***************************************************************/
+static char *parse_accode(char *activecode)
+{
+ char *save = NULL;
+ char *host = NULL;
+ char *tmp = NULL;
+ tmp = strtok_r(activecode, "$", &save);
+ if (tmp == NULL)
+ return NULL;
+ tmp = strtok_r(NULL, "$", &save);
+ if (tmp == NULL)
+ return NULL;
+
+ host = malloc(APDU_RESP_LEN);
+ if (host == NULL)
+ return NULL;
+ memset(host, 0, APDU_RESP_LEN);
+ strncpy(host, tmp, APDU_RESP_LEN-1);
+
+ printf("server:%s\n", host);
+ return host;
+}
+
+static int downloadProfile(char *smdpAddress)
+{
+ int res = -1;
+ char *authser_apdu = NULL;//auth server apdu
+ char *predl_apdu = NULL;//prepare download apdu
+ char *notify_apdu = NULL;//Notification apdu
+ int notify_res = -1;
+ int notify_check = -1;
+ //1 creat https
+ //2 get auth, send
+
+ res = lpa_connect_smdp(smdpAddress);
+ if (res != 0) {
+ res = -2;
+ goto download_END;
+ }
+
+ authser_apdu = lpa_initauth();
+ if (authser_apdu == NULL || strlen(authser_apdu) == 0) {
+ res = -2;
+ goto download_END;
+ }
+
+ predl_apdu = lpa_authclient(authser_apdu);
+ if (predl_apdu == NULL || strlen(predl_apdu) == 0) {
+ res = -2;
+ goto download_END;
+ }
+
+ notify_apdu = lpa_getbpp(predl_apdu);
+ if (notify_apdu == NULL || strlen(notify_apdu) == 0) {
+ res = -2;
+ goto download_END;
+ }
+//dtest
+#if 1
+ notify_res = lpa_notification(notify_apdu);
+ if (notify_res == -1) {
+ printf("lpa_notification fail\n");
+ //goto download_END;//skip, use updata result
+ }
+#endif
+
+ notify_check = lpa_parse_iccid_apdu(notify_apdu, curent_iccid, sizeof(curent_iccid));
+ if (notify_check == -1)
+ goto download_END;
+
+
+ res = 0;
+download_END:
+ if (authser_apdu != NULL)
+ free(authser_apdu);
+ if (predl_apdu != NULL)
+ free(predl_apdu);
+ if (notify_apdu != NULL)
+ free(notify_apdu);
+
+ lpa_disconn_smdp(smdpAddress);
+ return res;
+}
+
+/***************************************************************/
+//
+//ÊäÈ뼤»îÂ뷽ʽÏÂÔØprofile
+//È·ÈÏÂëδÓà confirmcode = NULL
+//
+/***************************************************************/
+int downloadProfileByAc(char *activecode, char *confirmcode)
+{
+ int res = -1;
+ char *smdpAddress = NULL;
+
+ char dl_retry[6] = {0};
+ int count = 0;
+ int i = 0;
+
+ sc_cfg_get("lpa_dl_retry", dl_retry, sizeof(dl_retry));
+ count = atoi(dl_retry);
+ printf("lpa_updata_retry:%s,%d\n", dl_retry, count);
+ if (count <= 0 || count > 10) { //kw 3
+ count = 1;
+ }
+
+ smdpAddress = parse_accode(activecode);
+ if (smdpAddress == NULL)
+ return -1;
+
+ for (i = 0; i < count; i++) {
+ res = downloadProfile(smdpAddress);
+ if (res == -2 && i < count-1) {
+ //retry
+ sleep(SMDP_DL_INTERVAL);
+ continue;
+ }
+ break;
+ }
+
+ free(smdpAddress);
+ return res;
+}
+
+#if 0
+int downloadProfileByEid(void)
+{
+ int res = -1;
+ char *smdpAddress = "esim.wo.cn";//get from default
+
+ res = downloadProfile(smdpAddress);
+
+ return res;
+}
+#endif
+
+/***************************************************************/
+//
+//ÆôÓÃprofile
+//in: iccid 20
+//
+//parse 8001xx return xx:
+//0£ºOK
+//1£ºiccidOrAidNotFound£»
+//2£ºprofileNotInDisabledState£»
+//3£ºdisallowedByPolicy£»
+//4£ºwrongProfileReenabling£»
+//5£ºcatBusy£»
+//127£ºundefinedError
+//ÆäÓà·µ»ØÖµ²Î¿¼6.10½Ú
+//
+/***************************************************************/
+int enableProfile(char *iccid)
+{
+ char *apdu = NULL;
+ int res = 127;
+ apdu = EnableProfile(iccid);
+ if (apdu == NULL)
+ return 127;
+ errno = 0;
+ res = strtol(apdu, NULL, 16);
+ if (errno == ERANGE)// kw ERRNO.NOT_CHECKED
+ {
+ printf("strtol errno %d: %s\n", errno, strerror(errno));
+ }
+ free(apdu);
+ return res;
+}
+
+/***************************************************************/
+//
+//½ûÓÃprofile
+//
+/***************************************************************/
+int disableProfile(char * iccid)
+{
+ char *apdu = NULL;
+ int res = 127;
+ apdu = DisableProfile(iccid);
+ if (apdu == NULL)
+ return 127;
+ errno = 0;
+ res = strtol(apdu, NULL, 16);
+ if (errno == ERANGE)// kw ERRNO.NOT_CHECKED
+ {
+ printf("strtol errno %d: %s\n", errno, strerror(errno));
+ }
+ free(apdu);
+ return res;
+}
+
+
+/***************************************************************/
+//
+//ɾ³ýprofile
+//
+/***************************************************************/
+int deleteProfile(char * iccid)
+{
+ char *apdu = NULL;
+ int res = 127;
+ apdu = DeleteProfile(iccid);
+ if (apdu == NULL)
+ return 127;
+ errno = 0;
+ res = strtol(apdu, NULL, 16);
+ if (errno == ERANGE)// kw ERRNO.NOT_CHECKED
+ {
+ printf("strtol errno %d: %s\n", errno, strerror(errno));
+ }
+ free(apdu);
+ return res;
+}
+
+
+int memoryReset(void)
+{
+ char *apdu = NULL;
+ int res = 127;
+ apdu = EUICCMemoryReset();
+ if (apdu == NULL)
+ return 127;
+ errno = 0;
+ res = strtol(apdu, NULL, 16);
+ if (errno == ERANGE)// kw ERRNO.NOT_CHECKED
+ {
+ printf("strtol errno %d: %s\n", errno, strerror(errno));
+ }
+ free(apdu);
+ return res;
+}
+
+//limit 10
+static char *lap_parse_profile_list(char *pdu, int *list_n)
+{
+ char *js_list = NULL;
+
+ char *profile = NULL;
+ char *iccid = NULL;
+ char *state = NULL;
+ int status = 0;
+ int i = 0;
+ char *tmp_pdu = pdu;
+ char *offset = NULL;
+
+ js_list = malloc(APDU_RESP_LEN);
+ if (js_list == NULL)
+ return NULL;
+ memset(js_list, 0, APDU_RESP_LEN);
+
+ while(i < 10 && strlen(tmp_pdu) > 0) {
+ profile = lpa_tag_apdu_from_atresp(tmp_pdu, 0xE3);
+ if (profile == NULL)
+ break;
+
+ iccid = lpa_tag_apdu_from_atresp(tmp_pdu, 0x5A);
+ if (iccid == NULL) {
+ free(profile);
+ break;
+ }
+ lpa_trans_iccid(iccid, strlen(iccid));
+
+ state = lpa_tag_apdu_from_atresp(tmp_pdu, 0x9F70);
+ if (state == NULL) {
+ free(profile);
+ free(iccid);
+ break;
+ }
+ errno = 0;
+ status = strtol(state, NULL, 16);
+ if (errno == ERANGE)// kw ERRNO.NOT_CHECKED
+ {
+ printf("strtol errno %d: %s\n", errno, strerror(errno));
+ }
+ if (i == 0) {
+ snprintf(js_list, APDU_RESP_LEN,
+ "{\"ICCID\":\"%s\",\"STATUS\":%d}", iccid, status);
+ }
+ else {
+ snprintf(js_list + strlen(js_list), APDU_RESP_LEN - strlen(js_list),
+ ",{\"ICCID\":\"%s\",\"STATUS\":%d}", iccid, status);
+ }
+
+ offset = strstr(tmp_pdu, profile);
+ if (offset == NULL) {
+ free(profile);
+ free(iccid);
+ free(state);
+ break;
+ }
+ tmp_pdu = offset + strlen(profile);
+ free(profile);
+ free(iccid);
+ free(state);
+ i++;
+
+ }
+ *list_n = i;
+ return js_list;
+}
+
+/***************************************************************/
+//
+//·µ»Ø¸öÊý£¬ºÍjson array[iccid, state]
+//
+/***************************************************************/
+int getProfileList(char **info)
+{
+ char *apdu = NULL;
+ int prof_num = 0;
+
+ apdu = GetProfilesInfo(NULL);
+ if (apdu == NULL)
+ return prof_num;
+
+
+ *info = lap_parse_profile_list(apdu, &prof_num);
+
+
+ free(apdu);
+ return prof_num;
+}
+
diff --git a/ap/lib/liblpa/lpa_https.c b/ap/lib/liblpa/lpa_https.c
new file mode 100755
index 0000000..54b549b
--- /dev/null
+++ b/ap/lib/liblpa/lpa_https.c
@@ -0,0 +1,464 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <openssl/ssl.h>
+#include <openssl/bio.h>
+
+#include "lpa_inner.h"
+
+
+
+// http ÇëÇóÍ·ÐÅÏ¢
+static char https_header[] =
+ "GET %s HTTP/1.1\r\n"
+ "Host: %s:%d\r\n"
+ "Connection: Close\r\n"
+ "Accept: */*\r\n"
+ "\r\n";
+ /*
+ HTTP POST /gsma/rsp2/es9plus/initiateAuthentication HTTP/1.1
+ Host: smdp.gsma.com
+ User-Agent: gsma-rsp-lpad
+ X-Admin-Protocol: gsma/rsp/v2.2.0
+ Content-Type: application/json
+ Content-Length: XXX
+
+ {
+ "euiccChallenge" : "ZVVpY2NDaGFsbGVuZ2VFeGFtcGxlQmFzZTY0oUFZuQnNZVE5D",
+ "euiccInfo1" : "RmVHRnRjR3hsUW1GelpUWTBvVUZadVFuTlpWRTU",
+ "smdpAddress" : "smdp.gsma.com"
+ }
+ */
+
+static int create_request_socket(const char* host,const int port)
+{
+ int sockfd;
+ struct hostent *server;
+ struct sockaddr_in serv_addr;
+ struct timeval tv;
+
+ sockfd = socket(AF_INET, SOCK_STREAM, 0);
+ if (sockfd < 0)
+ {
+ printf("[http] create_request_socket create socket fail.\n");
+ return -1;
+ }
+
+ tv.tv_sec = 90;
+ tv.tv_usec = 0;
+ if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
+ printf("[http] socket option SO_RCVTIMEO fail\n");
+ close(sockfd);
+ return -1;
+ }
+
+ /* lookup the ip address */
+ server = gethostbyname(host);
+ if(server == NULL)
+ {
+ printf("[http] create_request_socket gethostbyname--%s--fail.\n", host);
+ close(sockfd);
+ return -1;
+ }
+
+ memset(&serv_addr,0,sizeof(serv_addr));
+ serv_addr.sin_family = AF_INET;
+ serv_addr.sin_port = htons(port);
+ memcpy(&serv_addr.sin_addr.s_addr,server->h_addr,server->h_length);
+
+ if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
+ {
+ printf("[http] create_request_socket connect fail.\n");
+ close(sockfd);
+ return -1;
+ }
+ return sockfd;
+}
+
+/**
+ * @brief https_parser_url ½âÎö³öhttps ÖеÄÓòÃû¡¢¶Ë¿ÚºÍ·¾¶
+ * @param url ÐèÒª½âÎöµÄurl
+ * @param host ½âÎö³öÀ´µÄÓòÃû»òÕßip
+ * @param port ¶Ë¿Ú£¬Ã»ÓÐʱĬÈÏ·µ»Ø443
+ * @param path ·¾¶£¬Ö¸µÄÊÇÓòÃûºóÃæµÄλÖÃ
+ * @return
+ */
+int https_parser_url(const char* url,char **host,int *port,char **path)
+{
+ if(url == NULL || strlen(url) < 9 || host == NULL || path == NULL)
+ {
+ printf("url or host or path is null.\n");
+ return -1;
+ }
+
+ //ÅжÏÊDz»ÊÇ https://
+ int i = 0;
+ char https_prefix[] = "https://";
+ for(i=0;i<8;i++)
+ {
+ if(url[i] != https_prefix[i])
+ {
+ printf("illegal url = %s.\n",url);
+ return -1;
+ }
+ }
+
+ const char *temp = url+i;
+ while(*temp != '/') //next /
+ {
+ if(*temp == '\0') //
+ {
+ printf("illegal url = %s.\n",url);
+ return -1;
+ }
+ temp++;
+ }
+
+ const char *host_port = url+i;
+ while(*host_port != ':' && *host_port != '/') //ÕÒµ½ :»òÕß / ½áÊø
+ {
+ host_port ++;
+ }
+
+ int host_len = host_port-url-i; //¼õµôhttps://
+ int path_len = strlen(temp);
+ char *host_temp = (char *)malloc(host_len + 1); //¶àÒ»¸ö×Ö·û´®½áÊø±êʶ \0
+ if(host_temp == NULL)
+ {
+ printf("malloc host fail.\n");
+ return -1;
+ }
+ if(*host_port++ == ':') //url ÖÐÓж˿Ú
+ {
+ *port = 0;
+ while(*host_port !='/' && *host_port !='\0') //Ê®½øÖÆ×Ö·û´®×ª³ÉÊý×Ö
+ {
+ *port *= 10;
+ *port += (*host_port - '0');
+ host_port ++;
+ }
+ }
+ else
+ {
+ *port = 443;
+ }
+
+ char *path_temp = (char *)malloc(path_len + 1); //¶àÒ»¸ö×Ö·û´®½áÊø±êʶ \0
+ if(path_temp == NULL)
+ {
+ printf("malloc path fail.\n");
+ free(host_temp);
+ return -1;
+ }
+ memcpy(host_temp,url+i,host_len);
+ memcpy(path_temp,temp,path_len);
+ host_temp[host_len] = '\0';
+ path_temp[path_len] = '\0';
+ *host = host_temp;
+ *path = path_temp;
+ return 0;
+}
+
+int https_init(https_context_t *context)
+{
+ int ret = 0;
+ if(context == NULL)
+ {
+ printf("init https_context_t is null.\n");
+ return -1;
+ }
+ /*
+ if(https_parser_url(url,&(context->host),&(context->port),&(context->path)))
+ {
+ printf("https_parser_url fail.\n");
+ return -1;
+ }
+ */
+ context->sock_fd = create_request_socket(context->host,context->port);
+ printf("create_request_socket %d.\n",context->sock_fd);
+ if(context->sock_fd < 0)
+ {
+ goto https_init_fail;
+ }
+
+ context->ssl_ct = SSL_CTX_new(SSLv23_method());
+ printf("SSL_CTX_new %p.\n",context->ssl_ct); //cov m
+ if(context->ssl_ct == NULL)
+ {
+ goto https_init_fail;
+ }
+
+ context->ssl = SSL_new(context->ssl_ct);
+ printf("SSL_new %p.\n",context->ssl); //cov m
+ if(context->ssl == NULL)
+ {
+ goto https_init_fail;
+ }
+ ret = SSL_set_fd(context->ssl,context->sock_fd);
+ printf("SSL_set_fd ret %d \n",ret);
+ ret = SSL_connect(context->ssl);
+ printf("SSL_connect ret %d \n",ret);
+ if(ret == -1)
+ {
+ goto https_init_fail;
+ }
+ return 0;
+https_init_fail:
+ https_uninit(context);
+ return -1;
+}
+
+int https_read(https_context_t *context,void* buff,int len)
+{
+ if(context == NULL || context->ssl == NULL)
+ {
+ printf("read https_context_t or ssl is null.\n");
+ return -1;
+ }
+ return SSL_read(context->ssl,buff,len);
+}
+
+int https_write(https_context_t *context,const void* buff,int len)
+{
+ if(context == NULL || context->ssl == NULL)
+ {
+ printf("write https_context_t or ssl is null.\n");
+ return -1;
+ }
+ return SSL_write(context->ssl,buff,len);
+}
+
+int https_get_status_code(https_context_t *context, int *content_len)
+{
+ int ret;
+ int flag =0;
+ int recv_len = 0;
+ char res_header[1024] = {0};
+
+ if(context == NULL || context->ssl == NULL)
+ {
+ printf("get status https_context_t or ssl is null.\n");
+ return -1;
+ }
+
+ while(recv_len < (sizeof(res_header)-1))
+ {
+ ret = SSL_read(context->ssl, res_header+recv_len, 1);
+ if(ret<1) // recv fail
+ {
+ break;
+ }
+ //ÕÒµ½ÏìӦͷµÄÍ·²¿ÐÅÏ¢, Á½¸ö"\r\n"Ϊ·Ö¸îµã
+ if((res_header[recv_len]=='\r'&&(flag==0||flag==2))||(res_header[recv_len]=='\n'&&(flag==1||flag==3)))
+ {
+ flag++;
+ }
+ else
+ {
+ flag = 0;
+ }
+ recv_len+=ret;
+ if(flag==4)
+ {
+ break;
+ }
+ }
+ //printf("[http] recv_len=%d res_header = %s.\n",recv_len,res_header);
+ /*»ñÈ¡ÏìӦͷµÄÐÅÏ¢*/
+ int status_code = -1;
+ char *pos = strstr(res_header, "HTTP/");
+ if(pos)
+ {
+ sscanf(pos, "%*s %d", &status_code);//·µ»Ø×´Ì¬Âë
+ }
+
+ int cont_len = 0;
+ pos = strstr(res_header, "Content-Length:");
+ if(pos)
+ {
+ sscanf(pos, "%*s %d", &cont_len);//·µ»Ø×´Ì¬Âë
+ }
+ pos = strstr(res_header, "chunked");
+ if(pos)//Transfer-Encoding: chunked
+ {
+ cont_len = HTTP_CHUNKED_FLAG;
+ }
+ *content_len = cont_len;
+
+ printf("res_head##%s##\n", res_header);
+ printf("status_code:%d, Content-Length:%d\n", status_code, cont_len);
+
+ return status_code;
+}
+
+int https_read_content(https_context_t *context,char *resp_contet,int max_len)
+{
+ if(context == NULL || context->ssl == NULL)
+ {
+ printf("read content https_context_t or ssl is null.\n");
+ return -1;
+ }
+ int ret ;
+ int recv_size = 0;
+ while(recv_size < max_len)
+ {
+ ret = SSL_read(context->ssl,resp_contet + recv_size,max_len-recv_size);
+ if(ret < 1)
+ {
+ break;
+ }
+ recv_size += ret;
+ }
+ return recv_size;
+}
+//[Chunk´óС][»Ø³µ][ChunkÊý¾ÝÌå][»Ø³µ][Chunk´óС][»Ø³µ][ChunkÊý¾ÝÌå][»Ø³µ][0][»Ø³µ][footerÄÚÈÝ£¨Óеϰ£©][»Ø³µ]
+//×¢Òâchunk-sizeÊÇÒÔÊ®Áù½øÖƵÄASCIIÂë±íʾµÄ£¬±ÈÈç86AE£¨Êµ¼ÊµÄÊ®Áù½øÖÆÓ¦¸ÃÊÇ£º38366165£©£¬¼ÆËã³É³¤¶ÈÓ¦¸ÃÊÇ£º34478£¬±íʾ´Ó»Ø³µÖ®ºóÓÐÁ¬ÐøµÄ34478×Ö½ÚµÄÊý¾Ý
+int https_read_chunked_content(https_context_t *context,char **resp_contet,int max_len)
+{
+ int ret = 0;
+ int flag = 0;
+ int recv_size = 0;
+
+ int recv_len = 0;
+ char chunk_header[1024] = {0};
+
+ int read_flag = 0;
+ int read_len = 1;
+
+ if(context == NULL || context->ssl == NULL)
+ {
+ printf("read content https_context_t or ssl is null.\n");
+ return -1;
+ }
+
+ while(recv_size < max_len)
+ {
+ if (read_flag == 0) {
+ ret = SSL_read(context->ssl, chunk_header+recv_len, read_len);
+ if(ret < 1) // recv fail
+ {
+ break;
+ }
+ printf("chunk_header##%s##\n", chunk_header+recv_len);
+ //Ò»¸ö"\r\n"Ϊ·Ö¸îµã
+ if((chunk_header[recv_len]=='\r'&&flag==0)||(chunk_header[recv_len]=='\n'&&flag==1))
+ {
+ flag++;
+ }
+ else
+ {
+ flag = 0;
+ }
+ recv_len += ret;
+ if(flag == 2)
+ {
+ if (strlen(chunk_header) > 2) {
+ //Ìø¹ý·Ç0~9£¬A~F???
+ errno = 0;
+ int size =strtol(chunk_header, NULL, 16);
+ if (errno == ERANGE)// kw ERRNO.NOT_CHECKED
+ {
+ printf("strtol errno %d: %s\n", errno, strerror(errno));
+ }
+ //sscanf(pos, "%X", &cont_len);//X???
+ if (size <= 0 || size >= max_len) {
+ read_flag = 2;
+ read_len = sizeof(chunk_header)-1;
+ }
+ else {
+ read_flag = 1;
+ read_len = size;
+ }
+ }
+ memset(chunk_header, 0, sizeof(chunk_header));
+ recv_len = 0;
+ }
+ if (recv_len >= (sizeof(chunk_header)-1))
+ break;
+ }
+ else if(read_flag == 1) {
+ if(recv_size == 0) {
+ char *resp_tmp = malloc(read_len + 1);;
+ if (resp_tmp == NULL) {
+ printf("resp_tmp is null\n");
+ return -1;
+ }
+ memset(resp_tmp, 0, read_len + 1);
+ *resp_contet = resp_tmp;
+ }
+ else {
+ char *resp_tmp = NULL;
+ resp_tmp = realloc(*resp_contet, recv_size + read_len + 1);
+ if (resp_tmp == NULL) {
+ free(*resp_contet);
+ printf("resp_tmp realloc null\n");
+ return -1;
+ }
+ *resp_contet = resp_tmp;
+ }
+ //read Ö±µ½³¤¶È
+ ret = https_read_content(context, (*resp_contet)+recv_size, read_len);
+ if(ret<1) // recv fail
+ {
+ break;
+ }
+ read_len = 1;
+ read_flag = 0;
+ recv_size += ret;
+ }
+ else {
+ ret = SSL_read(context->ssl, chunk_header, read_len);
+ printf("chunk_header##%s##\n", chunk_header);
+ break;
+ }
+
+ }
+ return recv_size;
+}
+
+
+int https_uninit(https_context_t *context)
+{
+ if(context == NULL)
+ {
+ printf("uninit https_context_t is null.\n");
+ return -1;
+ }
+
+ if(context->host != NULL)
+ {
+ //free(context->host);
+ context->host = NULL;
+ }
+
+ if(context->path != NULL)
+ {
+ //free(context->path);
+ context->path = NULL;
+ }
+
+ if(context->ssl != NULL)
+ {
+ SSL_shutdown(context->ssl);
+ //SSl_free(context->ssl);
+ context->ssl = NULL;
+ }
+ if(context->ssl_ct != NULL)
+ {
+ SSL_CTX_free(context->ssl_ct);
+ context->ssl_ct = NULL;
+ }
+ if(context->sock_fd > 0)
+ {
+ close(context->sock_fd);
+ context->sock_fd = -1;
+ }
+ return 0;
+}
+
diff --git a/ap/lib/liblpa/lpa_inner.h b/ap/lib/liblpa/lpa_inner.h
new file mode 100755
index 0000000..d77bd68
--- /dev/null
+++ b/ap/lib/liblpa/lpa_inner.h
@@ -0,0 +1,107 @@
+#ifndef __LPA_INNER_H__
+#define __LPA_INNER_H__
+
+#include <openssl/ssl.h>
+#include <openssl/bio.h>
+
+#include "lpa_api.h"
+
+#include "cjson.h"
+#include "md5.h"
+#include "errno.h"
+
+#define MAX_IMEI_LEN 17
+#define MAX_TRANSID_LEN 41
+
+#define CSIM_REQ_LEN 600
+#define CSIM_RESP_LEN 600
+#define APDU_REQ_LEN 520 //tag10+255*2+00
+#define APDU_RESP_LEN 520 //0xFF*2+sw1+sw2=514
+#define APDU_BYTE_LEN 261 //csimÐÒéÕ»·µ»Ø×î´ó³¤¶È255 APDU_RESP_LEN/2+1
+#define MIN_APDU_LEN 16 //80E2910004TG01XX
+
+#define SMDP_HTTP_MAX_LEN 0x20000 //128K
+#define TRIG_HTTP_MAX_LEN 0x2000 //8K
+#define HTTP_CHUNKED_FLAG 0x7FFFFFFF
+
+
+
+
+#define ICCID_LEN 20
+
+//#define CSIM_APDU_LEN 511 //csimÐÒéÕ»·µ»Ø×î´ó³¤¶È255
+
+#ifndef BOOL
+#define BOOL unsigned char
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+
+typedef struct
+{
+ int sock_fd;
+ SSL_CTX *ssl_ct;
+ SSL *ssl;
+
+ //url ½âÎö³öÀ´µÄÐÅÏ¢
+ char *host;
+ char *path;
+ int port;
+} https_context_t;
+
+//https
+int https_init(https_context_t *context);
+int https_uninit(https_context_t *context);
+int https_read(https_context_t *context,void* buff,int len);
+int https_write(https_context_t *context,const void* buff,int len);
+int https_get_status_code(https_context_t *context, int *content_len);
+int https_read_content(https_context_t *context,char *resp_contet,int max_len);
+
+//es10b
+char *GetEUICCChallenge(void);
+char *GetEUICCInfo(BOOL flag);
+char *AuthenticateServer(char *signd1Hex, char *signature1Hex, char *ciPKIdHex, char *certificateHex, char *matchingId, char *imeiHex);
+char *PrepareDownload(char *transId ,char *signed2Hex,char *signature2Hex,char *certiHex,char *confirmCode);
+char *LoadBoundProfilePackage(char * bppHex);
+
+
+//es10c
+char *EnableProfile(char *iccidHex);
+char *EUICCMemoryReset(void);
+char *GetProfilesInfo(char *iccidHex);
+char *DisableProfile(char *iccidHex);
+char *DeleteProfile (char *iccidHex);
+char *GetEID(void);
+
+//es9+
+char *InitiateAuthentication(char *euiccChallenge, char *euiccInfo1, char *smdpAddress);
+char *AuthenticateClient(char *transactionId,char *authSerRespHex);
+char *GetBoundProfilePackage (char *transactionId, char *predlRespHex);
+char *HandleNotification(char *pnfHex);
+
+//channel
+char *OpenLogicalChannel(void);
+int CloseLogicalChannel(int chan_id);
+
+
+//edcode
+char *lpa_tlv_get_val_by_tag(unsigned char *apdu_byte, int apdu_len, unsigned int tag);
+char *lpa_tag_apdu_from_atresp(char *atres_apdu, unsigned int tag);
+char *lpa_get_apdu_from_atresp(char *atres_apdu);
+int lpa_csim_resp_code(char *atres_apdu, int *second_len);
+int lpa_csim_resp_normal(char *atres_apdu);
+
+int string2bytes(const char* pSrc, unsigned char* pDst, int nSrcLength);
+int bytes2string(const unsigned char* pSrc, char* pDst, int nSrcLength);
+
+char *lpa_base64_encode(const char*data, int data_len);
+unsigned char *lpa_base64_decode(const unsigned char *src, int len, int *out_len);
+
+void lpa_trans_iccid(char *iccid, int len);
+
+#endif
diff --git a/ap/lib/liblpa/lpa_tool.c b/ap/lib/liblpa/lpa_tool.c
new file mode 100755
index 0000000..a13fbe9
--- /dev/null
+++ b/ap/lib/liblpa/lpa_tool.c
@@ -0,0 +1,424 @@
+/***************************************************************/
+//
+//²Î¼û LPA½Ó¿ÚÎĵµV0.1 SGP.22, ·µ»ØAPDU
+//
+/***************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/time.h>
+#include <termios.h>
+
+#include "lpa_inner.h"
+
+
+static const unsigned char base64_table[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+/**
+ * @brief ¿É´òÓ¡×Ö·û´®×ª»»Îª×Ö½ÚÊý¾Ý £¬È磺
+ "C8329BFD0E01" --> {0xC8, 0x32, 0x9B, 0xFD, 0x0E, 0x01}
+ * @param pSrc Ô´×Ö·û´®Ö¸Õë
+ * @param pDst Ä¿±êÊý¾ÝÖ¸Õë
+ * @param nSrcLength Ô´×Ö·û´®³¤¶È
+ * @return Ä¿±êÊý¾Ý³¤¶È
+ * @note
+ * @warning
+ */
+int string2bytes(const char* pSrc, unsigned char* pDst, int nSrcLength)
+{
+ int i=0;
+
+ //УÑé²ÎÊý
+ if(pSrc == NULL || pDst == NULL || nSrcLength < 0)
+ {
+ return -1;
+ }
+
+ for(i = 0; i < nSrcLength; i += 2)
+ {
+ // Êä³ö¸ß4λ
+ if(*pSrc >= '0' && *pSrc <= '9')
+ {
+ *pDst = (*pSrc - '0') << 4;
+ }
+ else
+ {
+ *pDst = ((toupper(*pSrc) - 'A') + 10) << 4;
+ }
+
+ pSrc++;
+
+ // Êä³öµÍ4λ
+ if(*pSrc >= '0' && *pSrc <= '9')
+ {
+ *pDst |= *pSrc - '0';
+ }
+ else
+ {
+ *pDst |= (toupper(*pSrc) - 'A') + 10;
+ }
+
+ pSrc++;
+ pDst++;
+ }
+
+ // ·µ»ØÄ¿±êÊý¾Ý³¤¶È
+ return nSrcLength / 2;
+}
+
+/**
+ * @brief ×Ö½ÚÊý¾Ýת»»Îª¿É´òÓ¡×Ö·û´® £¬È磺
+ {0xC8, 0x32, 0x9B, 0xFD, 0x0E, 0x01} --> "C8329BFD0E01"
+ * @param pSrc Ô´Êý¾ÝÖ¸Õë
+ * @param pDst Ä¿±ê×Ö·û´®Ö¸Õë
+ * @param nSrcLength Ô´Êý¾Ý³¤¶È
+ * @return Ä¿±êÊý¾Ý³¤¶È£»
+ * @note
+ * @warning
+ */
+int bytes2string(const unsigned char* pSrc, char* pDst, int nSrcLength)
+{
+ const char tab[]="0123456789ABCDEF"; // 0x0-0xfµÄ×Ö·û²éÕÒ±í
+ int i = 0;
+
+ //УÑé²ÎÊý
+ if(pSrc == NULL || pDst == NULL || nSrcLength < 0)
+ {
+ return -1;
+ }
+
+ for(i=0; i<nSrcLength; i++)
+ {
+ *pDst++ = tab[*pSrc >> 4]; // Êä³öµÍ4λ
+ *pDst++ = tab[*pSrc & 0x0f]; // Êä³ö¸ß4λ
+ pSrc++;
+ }
+
+ // ·µ»ØÄ¿±ê×Ö·û´®³¤¶È
+ return nSrcLength * 2;
+}
+
+//lower case
+int bytes2string_lower(const unsigned char* pSrc, char* pDst, int nSrcLength)
+{
+ const char tab[]="0123456789abcdef"; // 0x0-0xfµÄ×Ö·û²éÕÒ±í
+ int i = 0;
+
+ //УÑé²ÎÊý
+ if(pSrc == NULL || pDst == NULL || nSrcLength < 0)
+ {
+ return -1;
+ }
+
+ for(i=0; i<nSrcLength; i++)
+ {
+ *pDst++ = tab[*pSrc >> 4]; // Êä³öµÍ4λ
+ *pDst++ = tab[*pSrc & 0x0f]; // Êä³ö¸ß4λ
+ pSrc++;
+ }
+
+ // ·µ»ØÄ¿±ê×Ö·û´®³¤¶È
+ return nSrcLength * 2;
+}
+
+
+char *lpa_base64_encode(const char*data, int data_len)
+{
+ //int data_len = strlen(data);
+ int prepare = 0;
+ int ret_len;
+ int temp = 0;
+ char *ret = NULL;
+ char *f = NULL;
+ int tmp = 0;
+ char changed[4];
+ int i = 0;
+ const char base[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+
+ if(data == NULL)
+ {
+ return NULL;
+ }
+ if(data_len == 0)
+ {
+ return NULL;
+ }
+ ret_len = data_len / 3;
+ temp = data_len % 3;
+ if (temp > 0)
+ {
+ ret_len += 1;
+ }
+ ret_len = ret_len*4 + 1;
+ ret = (char *)malloc(ret_len);
+
+ if (ret == NULL)
+ {
+ printf("No enough memory.\n");
+ return NULL;
+ }
+ memset(ret, 0, ret_len);
+ f = ret;
+ while (tmp < data_len)
+ {
+ temp = 0;
+ prepare = 0;
+ memset(changed, '\0', 4);
+ while (temp < 3)
+ {
+ //printf("tmp = %d\n", tmp);
+ if (tmp >= data_len)
+ {
+ break;
+ }
+ prepare = ((prepare << 8) | (data[tmp] & 0xFF));
+ tmp++;
+ temp++;
+ }
+ prepare = (prepare<<((3-temp)*8));
+ //printf("before for : temp = %d, prepare = %d\n", temp, prepare);
+ for (i = 0; i < 4 ;i++ )
+ {
+ if (temp < i)
+ {
+ changed[i] = 0x40;
+ }
+ else
+ {
+ changed[i] = (prepare>>((3-i)*6)) & 0x3F;
+ }
+ *f = base[changed[i]];
+ //printf("%.2X", changed[i]);
+ f++;
+ }
+ }
+ *f = '\0';
+ return ret;
+}
+
+unsigned char *lpa_base64_decode(const unsigned char *src, int len, int *out_len)
+{
+ unsigned char dtable[256] = {0};//kw
+ unsigned char *out = NULL;
+ unsigned char *pos = NULL;
+ unsigned char in[4] = {0};
+ unsigned char block[4] = {0};
+ unsigned char tmp = 0;
+ int i = 0;
+ int count = 0;
+ int olen = 0;
+
+ memset(dtable, 0x80, 256);
+ for (i = 0; i < sizeof(base64_table) - 1; i++)
+ dtable[base64_table[i]] = (unsigned char) i;
+ dtable['='] = 0;
+
+ count = 0;
+ for (i = 0; i < len; i++) {
+ if (dtable[src[i]] != 0x80)
+ count++;
+ }
+
+ if (count == 0 || count % 4)
+ return NULL;
+
+ olen = count / 4 * 3;
+ pos = out = malloc(olen);
+ if (out == NULL)
+ return NULL;
+ memset(pos, 0, olen);
+
+ count = 0;
+ for (i = 0; i < len; i++) {
+ tmp = dtable[src[i]];
+ if (tmp == 0x80)
+ continue;
+
+ in[count] = src[i];
+ block[count] = tmp;
+ count++;
+ if (count == 4) {
+ *pos++ = (block[0] << 2) | (block[1] >> 4);
+ *pos++ = (block[1] << 4) | (block[2] >> 2);
+ *pos++ = (block[2] << 6) | block[3];
+ count = 0;
+ }
+ }
+
+ if (pos > out) {
+ if (in[2] == '=')
+ pos -= 2;
+ else if (in[3] == '=')
+ pos--;
+ }
+
+ *out_len = pos - out;
+ return out;
+}
+
+//lpa code
+//0 ok, -1 error, 9000 91XX 92XX and 61XX
+int lpa_csim_resp_code(char *atres_apdu, int *second_len)
+{
+ int pdu_len = 0;
+ char sw1_s[3] = {0};
+ char sw2_s[3] = {0};
+ int sw1 = 0;
+ int sw2 = 0;
+ int res = -1;
+
+ pdu_len = strlen(atres_apdu);//kw 1
+ if (pdu_len < 4) {
+ printf("lpa_csim_resp_code len err:%d\n", pdu_len);
+ return res;
+ }
+
+ strncpy(sw1_s, atres_apdu + pdu_len - 4, sizeof(sw1_s) - 1);
+ strncpy(sw2_s, atres_apdu + pdu_len - 2, sizeof(sw2_s) - 1);
+ errno = 0;
+ sw1 =strtol(sw1_s, NULL, 16);
+ if (errno == ERANGE)// kw ERRNO.NOT_CHECKED
+ {
+ printf("strtol errno %d: %s\n", errno, strerror(errno));
+ }
+ errno = 0;
+ sw2 =strtol(sw2_s, NULL, 16);
+ if (errno == ERANGE)// kw ERRNO.NOT_CHECKED
+ {
+ printf("strtol errno %d: %s\n", errno, strerror(errno));
+ }
+ if ((sw1 == 0x90 && sw2 == 0x00) || (sw1 == 0x91) || (sw1 == 0x92)) {
+ *second_len = 0;
+ res = 0;
+ }
+ else if(sw1 == 0x61) {
+ *second_len = sw2;
+ if (sw2 == 0x00) {//tianyu: bigger than 256, use 00c0000000
+ *second_len = 0xFF;
+ }
+ res = 0;
+ }
+
+ return res;
+}
+
+
+//0 ok, -1 error, 9000 91XX 92XX
+int lpa_csim_resp_normal(char *atres_apdu)
+{
+ int pdu_len = 0;
+ char sw1_s[3] = {0};
+ char sw2_s[3] = {0};
+ int sw1 = 0;
+ int sw2 = 0;
+
+ pdu_len = strlen(atres_apdu);//kw 1
+ if (pdu_len < 4) {
+ printf("lpa_csim_resp_normal len err:%d\n", pdu_len);
+ return -1;
+ }
+
+ strncpy(sw1_s, atres_apdu + pdu_len - 4, sizeof(sw1_s) - 1);
+ strncpy(sw2_s, atres_apdu + pdu_len - 2, sizeof(sw2_s) - 1);
+ errno = 0;
+ sw1 =strtol(sw1_s, NULL, 16);
+ if (errno == ERANGE)// kw ERRNO.NOT_CHECKED
+ {
+ printf("strtol errno %d: %s\n", errno, strerror(errno));
+ }
+ errno = 0;
+ sw2 =strtol(sw2_s, NULL, 16);
+ if (errno == ERANGE)// kw ERRNO.NOT_CHECKED
+ {
+ printf("strtol errno %d: %s\n", errno, strerror(errno));
+ }
+ //normal processing: 9000 91XX 92XX
+ if ((sw1 == 0x90 && sw2 == 0x00) || (sw1 == 0x91) || (sw1 == 0x92)) {
+ return 0;
+ }
+
+ return -1;
+}
+
+//delete sw1 sw2
+char *lpa_get_apdu_from_atresp(char *atres_apdu)
+{
+ int pdu_len = 0;
+ char *apdu = NULL;
+
+ pdu_len = strlen(atres_apdu);//kw
+ if (pdu_len < 4 || pdu_len >= APDU_RESP_LEN)
+ return NULL;
+
+ apdu = malloc(APDU_RESP_LEN);
+ if (apdu == NULL)
+ return NULL;
+ memset(apdu, 0, APDU_RESP_LEN);
+ strncpy(apdu, atres_apdu, pdu_len - 4);//len = 4 -> "\0"
+ printf("get apdu: %s\n", apdu);
+ return apdu;
+}
+
+
+//´ÓcsimµÄapduÖнâ³öÖ¸¶¨µÄtagµÄvalue(hexstring)
+//Èç¹ûÓжà×éͬÃûtag£¬Ö»Äܽâ³öµÚÒ»×é
+char *lpa_tag_apdu_from_atresp(char *atres_apdu, unsigned int tag)
+{
+ int pdu_len = 0;
+ char *apdu = NULL;
+ unsigned char *pdu_byte = NULL;
+ int nt_byte_len = 0;
+
+ pdu_len = strlen(atres_apdu);//kw
+ if (pdu_len <= 0) {
+ printf("atres_apdu len err:%d\n", pdu_len);
+ return NULL;
+ }
+
+ pdu_byte = malloc(pdu_len/2 + 1);
+ if (pdu_byte == NULL) {
+ printf("atres_apdu malloc fail\n");
+ return NULL;
+ }
+
+ memset(pdu_byte, 0, pdu_len/2 + 1);
+ nt_byte_len = string2bytes(atres_apdu, pdu_byte, pdu_len);
+ if (nt_byte_len < 2) {
+ free(pdu_byte);
+ printf("atres_apdu to byte err\n");
+ return NULL;
+ }
+
+ apdu = lpa_tlv_get_val_by_tag(pdu_byte, nt_byte_len, tag);
+
+ free(pdu_byte);
+
+ return apdu;
+}
+
+
+//9812.... to 8921
+void lpa_trans_iccid(char *iccid, int len)
+{
+ char low = 0;
+ char high = 0;
+ int i = 0;
+
+ if (iccid == NULL || len != ICCID_LEN) {
+ printf("iccid check fail\n");
+ return;
+ }
+
+ for(i = 0; i < len; i += 2)
+ {
+ low = *(iccid);
+ high = *(iccid + 1);
+ *(iccid) = high;
+ *(iccid + 1) = low;
+
+ iccid = iccid + 2;
+ }
+}
+
diff --git a/ap/lib/liblpa/lpa_user.c b/ap/lib/liblpa/lpa_user.c
new file mode 100755
index 0000000..da2f16f
--- /dev/null
+++ b/ap/lib/liblpa/lpa_user.c
@@ -0,0 +1,935 @@
+/***************************************************************/
+//
+//²Î¼û LPA½Ó¿ÚÎĵµV0.1 SGP.22, ·µ»ØAPDU
+//
+/***************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/time.h>
+#include <time.h>
+#include <termios.h>
+
+#include "lpa_inner.h"
+
+#define LPA_TRIGGER_DATA_LEN 512
+#define TRIGGER_HTTP_REQ_LEN 512
+#define TRIGGER_HTTP_RESP_LEN 512
+
+#define HASH_SIZE 16
+#define HASH_HEX_SIZE 33
+
+#define MAX_TIME_LEN 24
+
+#define MAX_APPID_LEN 65
+#define MAX_URL_LEN 129
+
+int g_chan_id = 0; //logical channel
+static int g_open_channel_flag = 0;
+
+extern char curent_iccid[ICCID_LEN+1];
+
+//use nv
+//#define APPID "O8XTcVkZ8L4RDv1V"
+//#define APPSECRET "WNbHQlRV9JKeqpVWSurQWZLXwDs5T9Dl"
+//#define TRIGGER_PORT 61622
+//#define TRIGGER_HOST "serviceplatformt.esim.chinaunicom.cn"
+//#define TRIGGER_EVENT_URL "/esim_uni_plus_server/api/event"
+//#define TRIGGER_UPDATA_URL "/esim_uni_plus_server/api/updata"
+
+
+//´¥·¢·þÎñÆ÷httpÇëÇó
+static char trigger_https_req[] =
+ "POST %s HTTP/1.1\r\n"
+ "Host: %s\r\n"
+ "Content-Type: application/json\r\n"
+ "Content-Length: %d\r\n"
+ "Accept: */*\r\n"
+ "\r\n%s\r\n";
+
+static char trigger_https_event[] =
+"{"
+ "\"HEAD\": {"
+ "\"APPID\": \"%s\","
+ "\"TIME\": \"%s\","
+ "\"TRANSID\": \"%s\","
+ "\"TOKEN\": \"%s\""
+ "},"
+ "\"BODY\": {"
+ "\"EID\": \"%s\","
+ "\"IMEI\": \"%s\""
+ "}"
+"}";
+
+static char trigger_https_updata[] =
+"{"
+ "\"HEAD\": {"
+ "\"APPID\": \"%s\","
+ "\"TIME\": \"%s\","
+ "\"TRANSID\": \"%s\","
+ "\"TOKEN\": \"%s\""
+ "},"
+ "\"BODY\": {"
+ "\"EID\": \"%s\","
+ "\"IMEI\": \"%s\","
+ "\"EXEC_RESULT\": %d,"
+ "\"EXEC_REASON\": \"%s\","
+ "\"DATA_INFO\": [%s]"
+ "}"
+"}";
+
+
+char g_imei[MAX_IMEI_LEN] = {0};
+
+/***************************************************************/
+//
+//imei
+//
+/***************************************************************/
+static int lpa_get_imei(char *imei, int size)
+{
+ int ret = -1;
+ char t_imei[MAX_IMEI_LEN] = {0};
+ void *p2[] = {t_imei};
+
+ sc_cfg_get ("imei", imei, size);
+ if (strlen(imei) < 15) {
+ ret = get_modem_info("AT+CGSN\r\n", "%s", p2);
+ if(ret == 0) {
+ snprintf(imei, size, "%s", t_imei);
+ }
+ return ret;
+ }
+
+ return 0;
+}
+
+static int lpa_get_iccid(char *iccid, int size)
+{
+ int ret = -1;
+ char t_iccid[ICCID_LEN+1] = {0};
+ void *p2[] = {t_iccid};
+
+
+ ret = get_modem_info("AT+ZICCID?\r\n", "%s", p2);
+ if(ret == 0) {
+ snprintf(iccid, size, "%s", t_iccid);
+ }
+ return ret;
+
+}
+
+/***************************************************************/
+//
+//time
+//
+/***************************************************************/
+static int lpa_get_time(char *time, int size)
+{
+ struct tm ptm = {0};
+ struct timeval now_time = {0};
+
+ gettimeofday(&now_time, NULL);
+ localtime_r(&now_time.tv_sec, &ptm);
+
+ snprintf(time, size, "%d-%02d-%02d %02d:%02d:%02d %03d",
+ ptm.tm_year + 1900, ptm.tm_mon + 1, ptm.tm_mday, ptm.tm_hour, ptm.tm_min, ptm.tm_sec, now_time.tv_usec/1000);
+
+ //printf("lpa_get_time: %s\n", time);
+ return 0;
+}
+
+static int lpa_get_transid(char *transid, int size, char *imei)
+{
+ struct tm ptm = {0};
+ struct timeval now_time = {0};
+
+ gettimeofday(&now_time, NULL);
+ localtime_r(&now_time.tv_sec, &ptm);
+
+ snprintf(transid, size, "%s%04d%02d%02d%02d%02d%02d%03d",
+ imei, ptm.tm_year + 1900, ptm.tm_mon + 1, ptm.tm_mday, ptm.tm_hour, ptm.tm_min, ptm.tm_sec, now_time.tv_usec/1000);
+
+ //printf("lpa_get_transid: %s\n", transid);
+ return 0;
+}
+
+//0 fail 1 succ
+static int lpa_get_exeres(char *exe_reason, int len)
+{
+ sc_cfg_get("lpa_last_res", exe_reason, len);
+ if (0 == strcmp(exe_reason,"success"))
+ return 1;
+
+ return 0;
+}
+
+/***************************************************************/
+//
+//
+//
+/***************************************************************/
+static char *lpa_get_trigger_data(void)
+{
+ int ret = -1;
+ //char imei[MAX_IMEI_LEN] = {0};
+ char time[MAX_TIME_LEN] = {0};
+ char transid[MAX_TRANSID_LEN] = {0};
+ char *eid = NULL;
+ lpa_MD5_CTX md5ctx = {0};
+ unsigned char hash[HASH_SIZE] = {0};
+ char token[HASH_HEX_SIZE] = {0};
+ char *js_data = NULL;
+ char appid[MAX_APPID_LEN] = {0};
+ char appsecret[MAX_APPID_LEN] = {0};
+
+ sc_cfg_get("lpa_appid", appid, sizeof(appid));
+ sc_cfg_get("lpa_appsecret", appsecret, sizeof(appsecret));
+
+ lpa_get_time(time, sizeof(time));
+ lpa_get_transid(transid, sizeof(transid), g_imei);
+
+ lpa_MD5_Init(&md5ctx);
+ lpa_MD5_Update(&md5ctx, appid, strlen(appid));
+ lpa_MD5_Update(&md5ctx, transid, strlen(transid));
+ lpa_MD5_Update(&md5ctx, time, strlen(time));
+ lpa_MD5_Update(&md5ctx, appsecret, strlen(appsecret));
+ lpa_MD5_Final(hash, &md5ctx);
+ //token lower case
+ bytes2string_lower(hash, token, sizeof(hash));
+
+ eid = GetEID();
+ if (eid == NULL) {
+ return NULL;
+ }
+ js_data = malloc(LPA_TRIGGER_DATA_LEN);
+ if (js_data != NULL) {
+ memset(js_data, 0, LPA_TRIGGER_DATA_LEN);
+ snprintf(js_data, LPA_TRIGGER_DATA_LEN, trigger_https_event,
+ appid, time, transid, token, eid, g_imei);
+ //printf("trigger json:-%s-\n", js_data);
+ }
+
+ free(eid);
+ return js_data;
+}
+
+static char *lpa_get_updata_data(void)
+{
+ int ret = -1;
+ //char imei[MAX_IMEI_LEN] = {0};
+ char time[MAX_TIME_LEN] = {0};
+ char transid[MAX_TRANSID_LEN] = {0};
+ char *eid = NULL;
+ lpa_MD5_CTX md5ctx = {0};
+ unsigned char hash[HASH_SIZE] = {0};
+ char token[HASH_HEX_SIZE] = {0};
+ char *js_data = NULL;
+ char exe_reason[200] = {0};
+ int exe_res = 0;
+ char *pro_list = NULL;
+ char appid[MAX_APPID_LEN] = {0};
+ char appsecret[MAX_APPID_LEN] = {0};
+
+ sc_cfg_get("lpa_appid", appid, sizeof(appid));
+ sc_cfg_get("lpa_appsecret", appsecret, sizeof(appsecret));
+
+ lpa_get_time(time, sizeof(time));
+ lpa_get_transid(transid, sizeof(transid), g_imei);
+
+ lpa_MD5_Init(&md5ctx);
+ lpa_MD5_Update(&md5ctx, appid, strlen(appid));
+ lpa_MD5_Update(&md5ctx, transid, strlen(transid));
+ lpa_MD5_Update(&md5ctx, time, strlen(time));
+ lpa_MD5_Update(&md5ctx, appsecret, strlen(appsecret));
+ lpa_MD5_Final(hash, &md5ctx);
+ //token lower case
+ bytes2string_lower(hash, token, sizeof(hash));
+
+ eid = GetEID();
+ if (eid == NULL) {
+ return NULL;
+ }
+
+ exe_res = lpa_get_exeres(exe_reason, sizeof(exe_reason));
+
+ getProfileList(&pro_list);
+
+ js_data = malloc(LPA_TRIGGER_DATA_LEN);
+ if (js_data != NULL) {
+ memset(js_data, 0, LPA_TRIGGER_DATA_LEN);
+ if (pro_list != NULL) {
+ snprintf(js_data, LPA_TRIGGER_DATA_LEN, trigger_https_updata,
+ appid, time, transid, token, eid, g_imei, exe_res, exe_reason, pro_list);
+ }
+ else {
+ snprintf(js_data, LPA_TRIGGER_DATA_LEN, trigger_https_updata,
+ appid, time, transid, token, eid, g_imei, exe_res, exe_reason, "");
+ }
+ //printf("trigger json:-%s-\n", js_data);
+ }
+
+ if (pro_list != NULL)
+ free(pro_list);
+ free(eid);
+ return js_data;
+}
+
+static int lpa_get_profile_state(char *iccid)
+{
+ char *apdu = NULL;
+ char *state = NULL;
+ int status = 0;
+
+ apdu = GetProfilesInfo(iccid);
+ if (apdu == NULL)
+ return -1;
+
+
+ state = lpa_tag_apdu_from_atresp(apdu, 0x9F70);
+ if (state == NULL) {
+ free(apdu);
+ return -1;
+ }
+ errno = 0;
+ status = strtol(state, NULL, 16);
+ if (errno == ERANGE)// kw ERRNO.NOT_CHECKED
+ {
+ printf("strtol errno %d: %s\n", errno, strerror(errno));
+ }
+ free(state);
+ free(apdu);
+ return status;
+}
+
+//µ±Ç°iccidÊÇ·ñΪ¼¤»î״̬µÄprofile
+static int lpa_get_cur_iccid_state(void)
+{
+ char cur_iccid[ICCID_LEN+1] = {0};
+
+ lpa_get_iccid(cur_iccid, sizeof(cur_iccid));
+ lpa_trans_iccid(cur_iccid, strlen(cur_iccid));
+ if (strlen(cur_iccid) == ICCID_LEN) {
+ return lpa_get_profile_state(cur_iccid);
+ }
+
+ return -1;
+}
+
+/***************************************************************/
+//
+//
+//
+/***************************************************************/
+static char *lpa_parse_trigger_resp(char *srcStr, int *next_step)
+{
+ cJSON *root = NULL;
+ cJSON *object = NULL;
+ cJSON *object2 = NULL;
+ cJSON *array = NULL;
+ char *accode_apdu = NULL;
+
+ root = cJSON_Parse(srcStr);
+ if (root == NULL) {
+ printf("root == NULL\n");
+ return NULL;
+ }
+
+ object = cJSON_GetObjectItem(root, "BODY");
+ if (object == NULL) {
+ printf("BODY not find\n");
+ cJSON_Delete(root);
+ return NULL;
+ }
+
+ object2 = cJSON_GetObjectItem(object, "NEXT_STEP");
+ if (object2 == NULL) {
+ printf("NEXT_STEP not find\n");
+ cJSON_Delete(root);
+ return NULL;
+ }
+ printf("NEXT_STEP:%d\n", object2->valueint);
+ *next_step = object2->valueint;
+ if (object2->valueint == 2 || object2->valueint == 3
+ || object2->valueint == 4) {
+ object2 = cJSON_GetObjectItem(object, "ICCID");
+ if (object2 == NULL) {
+ printf("ICCID not find\n");
+ cJSON_Delete(root);
+ return NULL;
+ }
+ printf("ICCID:%s\n", object2->valuestring);
+
+ accode_apdu = malloc(APDU_RESP_LEN);
+ if (accode_apdu != NULL) {
+ memset(accode_apdu, 0, APDU_RESP_LEN);
+ strncpy(accode_apdu, object2->valuestring, APDU_RESP_LEN-1);
+ lpa_trans_iccid(accode_apdu, strlen(accode_apdu));
+ printf("ICCID-Trans:-%s-\n", accode_apdu);
+ }
+ }
+ else if (object2->valueint == 1) {
+ object2 = cJSON_GetObjectItem(object, "COMMAND");
+ if (object2 == NULL) {
+ printf("COMMAND not find\n");
+ cJSON_Delete(root);
+ return NULL;
+ }
+ array = cJSON_GetArrayItem(object2, 0);
+ if (array == NULL) {
+ printf("COMMAND no item\n");
+ cJSON_Delete(root);
+ return NULL;
+ }
+ printf("COMMAND:%s\n", array->valuestring);
+
+ accode_apdu = malloc(APDU_RESP_LEN);
+ if (accode_apdu != NULL) {
+ memset(accode_apdu, 0, APDU_RESP_LEN);
+ strncpy(accode_apdu, array->valuestring, APDU_RESP_LEN-1);
+ printf("accode or apdu:-%s-\n", accode_apdu);
+ }
+ }
+ cJSON_Delete(root);
+ return accode_apdu;
+}
+
+static char *lpa_parse_updata_resp(char *srcStr)
+{
+ cJSON *root = NULL;
+ cJSON *object = NULL;
+ cJSON *object2 = NULL;
+ cJSON *array = NULL;
+ char *code = NULL;
+
+ root = cJSON_Parse(srcStr);
+ if (root == NULL) {
+ printf("root == NULL\n");
+ return NULL;
+ }
+
+ object = cJSON_GetObjectItem(root, "HEAD");
+ if (object == NULL) {
+ printf("HEAD not find\n");
+ cJSON_Delete(root);
+ return NULL;
+ }
+
+ object2 = cJSON_GetObjectItem(object, "CODE");
+ if (object2 == NULL) {
+ printf("CODE not find\n");
+ cJSON_Delete(root);
+ return NULL;
+ }
+ printf("CODE:%s\n", object2->valuestring);
+
+ code = malloc(APDU_RESP_LEN);
+ if (code != NULL) {
+ memset(code, 0, APDU_RESP_LEN);
+ strncpy(code, object2->valuestring, APDU_RESP_LEN-1);
+ }
+ cJSON_Delete(root);
+ return code;
+}
+
+static void lpa_open_cfun(void)
+{
+ int cfun_stat = -1;
+ void *p2[] = {&cfun_stat};
+
+ get_modem_info("AT+CFUN?\r\n", "%d", p2);
+ if (cfun_stat != 1) {
+ get_modem_info("AT+CFUN=0\r\n", NULL, NULL);
+ get_modem_info("AT+CFUN=1\r\n", NULL, NULL);
+ lpa_close_logical_channel(0);
+ }
+}
+
+//wifiʱ·ÀÖ¹ËÑÍøµÄsim¿¨²Ù×÷´ò¶Ïesim·Ö¶Îд¿¨
+static void lpa_close_cfun(void)
+{
+ char ps_wan[20] = {0};
+ char def_wan[20] = {0};
+ int cfun_stat = -1;
+ void *p2[] = {&cfun_stat};
+
+ sc_cfg_get("pswan", ps_wan, sizeof(ps_wan));
+ sc_cfg_get("default_wan_name", def_wan, sizeof(def_wan));
+ if (strncmp(def_wan, ps_wan, strlen(ps_wan)) != 0) {
+ get_modem_info("AT+CFUN?\r\n", "%d", p2);
+ if (cfun_stat == 1) {
+ get_modem_info("AT+CFUN=4\r\n", NULL, NULL);
+ }
+ }
+}
+
+static int lpa_exe_updata(void)
+{
+ int code = -1;
+ int i = 0;
+ char updata_retry[6] = {0};
+ int count = 0;
+//dtest
+#if 1
+ sc_cfg_get("lpa_updata_retry", updata_retry, sizeof(updata_retry));
+ count = atoi(updata_retry);
+ if (count <= 0 || count > 10) { //kw 3
+ count = 1;
+ }
+
+ if (0 == lpa_check_status(60)) {
+ printf("lpa_exe_updata not ready\n");
+ return -1;
+ }
+
+ for (i = 0; i < count; i++) {
+ code = lpa_trigger_updata();
+ if (code == 0 || i == count-1)
+ break;
+ //retry
+ sleep(30);
+ }
+
+ if (code != 0) {
+ printf("lpa_exe_updata updata fail\n");
+ return -1;
+ }
+#endif
+ return 0;
+}
+//check sim && net && sntp ready
+int lpa_check_status(int retry)
+{
+ int i = 0;
+ int res = -1;
+
+ //+ZPBIC
+ for(i = 0; i < retry; i++) {
+ char sntp_res[20] = {0};
+ sc_cfg_get("zpbic_pb", sntp_res, sizeof(sntp_res));
+ if (strcmp(sntp_res, "ready") == 0) {
+ res = 1;
+ break;
+ }
+ printf("lpa zpbic_pb: %s\n", sntp_res);
+ sleep(6);
+ }
+ if (res != 1) {
+ printf("lpa sim not ready\n");
+ return 0;
+ }
+
+ //net
+ res = -1;
+ for(i = 0; i < retry; i++) {
+ res = default_route_check();
+ if (res == 1)
+ break;
+ printf("lpa default_route_check: %d\n", res);
+ sleep(6);
+ }
+ if (res != 1) {
+ printf("lpa check net timeout\n");
+ return 0;
+ }
+
+ //sntp, no +zmmi
+ res = -1;
+ for(i = 0; i < retry; i++) {
+ char sntp_res[20] = {0};
+ sc_cfg_get("sntp_process_result", sntp_res, sizeof(sntp_res));
+ if (strcmp(sntp_res, "success") == 0) {
+ res = 1;
+ break;
+ }
+ printf("lpa sntp_process_result: %s\n", sntp_res);
+ sleep(6);
+ }
+ if (res != 1) {
+ printf("lpa check sntp timeout\n");
+ return 0;
+ }
+
+ //open channel
+ res = -1;
+ for(i = 0; i < 4; i++) {
+ res = lpa_open_logical_channel();
+ if (res == 0)
+ break;
+ printf("lpa lpa_open_logical_channel: %d\n", res);
+ sleep(2);
+ }
+ if (res != 0) {
+ printf("lpa open channel fail\n");
+ return 0;
+ }
+
+ ////select app id
+ res = -1;
+ for(i = 0; i < 4; i++) {
+ res = lpa_select_aid();
+ if (res == 0)
+ break;
+ printf("lpa lpa_select_aid: %d\n", res);
+ sleep(2);
+ }
+ if (res != 0) {
+ printf("lpa select fail\n");
+ return 0;
+ }
+ return 1;
+}
+
+//²éѯһЩ¹Ì¶¨²ÎÊý
+int lpa_init(void)
+{
+ //zpbic && sntp && net ok, if use wlan close modem, open channel select isdr
+ if (0 == lpa_check_status(60)) {
+ printf("lpa not ready\n");
+ return -1;
+ }
+
+ if(0 != lpa_get_imei(g_imei, sizeof(g_imei))) {
+ printf("lpa no imei\n");
+ return -1;
+ }
+
+ return 0;
+}
+int lpa_uninit(void)
+{
+ lpa_close_logical_channel(1);
+
+ return 0;
+}
+
+static char *lpa_tigger_session(char *path, char *req_data)
+{
+ int ret = -1;
+ int cont_len = 0;
+ https_context_t https_ct = {0};
+ char trigger_port[6] = {0};
+ char trigger_host[MAX_URL_LEN] = {0};
+ char *https_req = NULL;
+ char *https_resp = NULL;
+ int https_req_len = 0;
+ //kw 3
+ //if (https_req_len > TRIG_HTTP_MAX_LEN)
+ // return NULL;
+
+ sc_cfg_get("lpa_trigger_port", trigger_port, sizeof(trigger_port));
+ sc_cfg_get("lpa_trigger_host", trigger_host, sizeof(trigger_host));
+
+ SSL_library_init();
+ https_ct.port = atoi(trigger_port);
+ https_ct.host = trigger_host;
+ https_ct.path = path;
+ ret = https_init(&https_ct);
+ if (ret != 0) {
+ printf("[trigger] https_init fail\n");
+ return NULL;
+ }
+
+ https_req_len = strlen(trigger_https_req)+strlen(https_ct.path)+strlen(https_ct.host)+strlen(req_data)+32;
+ https_req = malloc(https_req_len);
+ if (https_req == NULL) {
+ https_uninit(&https_ct);
+ return NULL;
+ }
+ memset(https_req, 0, https_req_len);
+ ret = snprintf(https_req, https_req_len, trigger_https_req,
+ https_ct.path, https_ct.host, strlen(req_data), req_data);
+
+ printf("[trigger] request##%s##\n", https_req);
+ ret = https_write(&https_ct, https_req, ret);
+ printf("[trigger] https_write ret = %d.\n", ret);
+
+ ret = https_get_status_code(&https_ct, &cont_len);
+ printf("[trigger] https_recv code = %d.\n", ret);
+ if(ret == 200 && (cont_len > 0 && cont_len < TRIG_HTTP_MAX_LEN))
+ {
+ https_resp = malloc(cont_len + 1);
+ if (https_resp == NULL) {
+ https_uninit(&https_ct);
+ free(https_req);
+ printf("[trigger] https_resp_cont NULL.\n");
+ return NULL;
+ }
+
+ memset(https_resp, 0, cont_len + 1);
+ ret = https_read_content(&https_ct, https_resp, cont_len);
+ if(cont_len == ret)
+ {
+ https_resp[ret] = '\0'; //×Ö·û´®½áÊø±êʶ
+ printf("[trigger] https_write https_resp_content = \n %s.\n", https_resp);
+ }
+ }
+
+ https_uninit(&https_ct);
+ free(https_req);
+ return https_resp;
+}
+
+/***************************************************************/
+//
+//´Ó´¥·¢·þÎñÆ÷²éѯָÁî
+//
+/***************************************************************/
+char *lpa_trigger_event(int *next_step)
+{
+ char *trigger_data = NULL;
+ char *https_resp_cont = NULL;
+ char *command = NULL;
+ char trigger_event[MAX_URL_LEN] = {0};
+
+ trigger_data = lpa_get_trigger_data();
+ if (trigger_data == NULL) {
+ printf("[trigger] request data NULL.\n");
+ return NULL;
+ }
+
+ sc_cfg_get("lpa_trigger_event_url", trigger_event, sizeof(trigger_event));
+ https_resp_cont = lpa_tigger_session(trigger_event, trigger_data);
+ if (https_resp_cont != NULL) {
+ command = lpa_parse_trigger_resp(https_resp_cont, next_step);
+ free(https_resp_cont);
+ }
+
+ free(trigger_data);
+ return command;
+}
+
+/***************************************************************/
+//
+//Ïò´¥·¢·þÎñÆ÷Éϱ¨Êý¾Ý
+//
+/***************************************************************/
+int lpa_trigger_updata(void)
+{
+ char *trigger_data = NULL;
+ char *https_resp_cont = NULL;
+ char *code = NULL;
+ int res_code = -1;
+ char trigger_updata[MAX_URL_LEN] = {0};
+
+ trigger_data = lpa_get_updata_data();
+ if (trigger_data == NULL) {
+ printf("[trigger] request data NULL.\n");
+ return NULL;
+ }
+
+ sc_cfg_get("lpa_trigger_updata_url", trigger_updata, sizeof(trigger_updata));
+ https_resp_cont = lpa_tigger_session(trigger_updata, trigger_data);
+ if (https_resp_cont != NULL) {
+ code = lpa_parse_updata_resp(https_resp_cont);
+ if (code != NULL) {
+ errno = 0;
+ res_code = strtol(code, NULL, 10);
+ if (errno == ERANGE)// kw ERRNO.NOT_CHECKED
+ {
+ printf("strtol errno %d: %s\n", errno, strerror(errno));
+ }
+ free(code);
+ }
+ free(https_resp_cont);
+ }
+
+ free(trigger_data);
+ return res_code;
+}
+
+//µôµçµÈ³¡¾°£¬Èç´æÔÚiccid¼¤»î²¢Éϱ¨£¬²»´æÔÚÖ±½Ó×ßevent£¬ÖØÐ´¥·¢ÏÂÔØµÈ²Ù×÷
+int lpa_exception_process(void)
+{
+ char has_iccid[ICCID_LEN+1] = {0};
+ int status = 0;
+ int res = 0;
+
+ sc_cfg_get("lpa_bpp_iccid", has_iccid, sizeof(has_iccid));
+ if (strlen(has_iccid) == ICCID_LEN) {
+ status = lpa_get_profile_state(has_iccid);
+ if (status == 1 || status == 0) {
+ res = lpa_enable_profile(has_iccid);
+ if (res == 0) {
+ sc_cfg_set("lpa_bpp_iccid", "");
+ sc_cfg_save();
+ return 0;
+ }
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int lpa_download_profile(char *activecode, char *confirmcode)
+{
+ int res = -1;
+
+ lpa_close_cfun();
+
+ memset(curent_iccid, 0, sizeof(curent_iccid));
+ res = downloadProfileByAc(activecode, confirmcode);
+
+ //²»¹Ü³É¹¦Óë·ñ£¬¶¼ÒªÉϱ¨
+ res = lpa_enable_profile(curent_iccid);
+ if (res == 0) {
+ sc_cfg_set("lpa_bpp_iccid", "");
+ sc_cfg_save();
+ }
+
+ lpa_open_cfun();
+
+ return res;
+}
+
+int lpa_enable_profile(char *iccid)
+{
+ int res = 0;
+ int code = 0;
+
+ res = enableProfile(iccid);
+ if (res == 0) {
+ sc_cfg_set("zpbic_pb", "");//wait sim ready
+ sc_cfg_set("lpa_last_res", "success");
+ lpa_close_logical_channel(0);
+ sleep(2);
+ }
+ else if (res == 2) {
+ sc_cfg_set("lpa_last_res", "success");
+ }
+ else {
+ sc_cfg_set("lpa_last_res", "fail");
+ }
+
+ code = lpa_exe_updata();
+ if (code != 0) {
+ printf("lpa_enable_profile updata fail\n");
+ return -1;
+ }
+ return 0;
+}
+
+int lpa_disable_profile(char *iccid)
+{
+ int res = 0;
+ int code = 0;
+
+ res = disableProfile(iccid);
+ if (res == 0) {
+ sc_cfg_set("zpbic_pb", "");//wait sim ready
+ sc_cfg_set("lpa_last_res", "success");
+ lpa_close_logical_channel(0);
+ sleep(2);
+ }
+ else if (res == 2) {
+ sc_cfg_set("lpa_last_res", "success");
+ }
+ else {
+ sc_cfg_set("lpa_last_res", "fail");
+ }
+
+ code = lpa_exe_updata();
+ if (code != 0) {
+ printf("lpa_disable_profile updata fail\n");
+ return -1;
+ }
+ return 0;
+}
+
+int lpa_delete_profile(char *iccid)
+{
+ int res = 0;
+ int code = 0;
+
+ res = deleteProfile(iccid);
+ if (res == 0) {
+ sc_cfg_set("lpa_last_res", "success");
+ sleep(2);
+ }
+ else if (res == 1) {
+ sc_cfg_set("lpa_last_res", "success");
+ }
+ else {
+ sc_cfg_set("lpa_last_res", "fail");
+ }
+
+ code = lpa_exe_updata();
+ if (code != 0) {
+ printf("lpa_disable_profile updata fail\n");
+ return -1;
+ }
+ return 0;
+}
+
+int lpa_memory_reset(void)
+{
+ int res = 0;
+ int state = 0;
+ int code = 0;
+
+ state = lpa_get_cur_iccid_state();
+ res = memoryReset();
+ if (res == 0) {
+ if(state == 1) {
+ sc_cfg_set("zpbic_pb", "");//wait sim ready
+ lpa_close_logical_channel(0);
+ printf("lpa zpbic_pb reset\n");
+ }
+ sc_cfg_set("lpa_last_res", "success");
+ sleep(2);//wait sim ready
+ }
+ else if (res == 1) {
+ sc_cfg_set("lpa_last_res", "success");
+ }
+ else {
+ sc_cfg_set("lpa_last_res", "fail");
+ }
+
+ code = lpa_exe_updata();
+ if (code != 0) {
+ printf("lpa_disable_profile updata fail\n");
+ return -1;
+ }
+ return 0;
+}
+
+int lpa_open_logical_channel(void)
+{
+ char *apdu = NULL;
+ int chan = 0;
+ if (g_open_channel_flag == 0) {
+ apdu = OpenLogicalChannel();
+ if (apdu == NULL)
+ return -1;
+ errno = 0;
+ chan = strtol(apdu, NULL, 16);
+ if (errno == ERANGE)// kw ERRNO.NOT_CHECKED
+ {
+ printf("strtol errno %d: %s\n", errno, strerror(errno));
+ }
+ free(apdu);
+ if (chan < 0 || chan > 3)
+ return -1;
+ g_open_channel_flag = 1;
+ g_chan_id = chan;
+ }
+ return 0;
+}
+//flag = 0, when refresh not need close
+int lpa_close_logical_channel(int flag)
+{
+ char *apdu = NULL;
+ int res = 0;
+ if (flag == 1 && g_open_channel_flag == 1) {
+ res = CloseLogicalChannel(g_chan_id);
+ printf("lpa_close_logical_channel:%d, res:%d\n", g_chan_id, res);
+ }
+ g_chan_id = 0;
+ g_open_channel_flag = 0;
+
+ return res;
+}
+
diff --git a/ap/lib/liblpa/md5.c b/ap/lib/liblpa/md5.c
new file mode 100755
index 0000000..da96c3a
--- /dev/null
+++ b/ap/lib/liblpa/md5.c
@@ -0,0 +1,307 @@
+
+
+/*
+ ***********************************************************************
+ ** md5.c -- the source code for MD5 routines **
+ ** RSA Data Security, Inc. MD5 Message-Digest Algorithm **
+ ** Created: 2/17/90 RLR **
+ ** Revised: 1/91 SRD,AJ,BSK,JT Reference C ver., 7/10 constant corr. **
+ ***********************************************************************
+ */
+
+/*
+ ***********************************************************************
+ ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
+ ** **
+ ** License to copy and use this software is granted provided that **
+ ** it is identified as the "RSA Data Security, Inc. MD5 Message- **
+ ** Digest Algorithm" in all material mentioning or referencing this **
+ ** software or this function. **
+ ** **
+ ** License is also granted to make and use derivative works **
+ ** provided that such works are identified as "derived from the RSA **
+ ** Data Security, Inc. MD5 Message-Digest Algorithm" in all **
+ ** material mentioning or referencing the derived work. **
+ ** **
+ ** RSA Data Security, Inc. makes no representations concerning **
+ ** either the merchantability of this software or the suitability **
+ ** of this software for any particular purpose. It is provided "as **
+ ** is" without express or implied warranty of any kind. **
+ ** **
+ ** These notices must be retained in any copies of any part of this **
+ ** documentation and/or software. **
+ ***********************************************************************
+ */
+
+#include <string.h>
+#include "md5.h"
+
+/*
+ ***********************************************************************
+ ** Message-digest routines: **
+ ** To form the message digest for a message M **
+ ** (1) Initialize a context buffer mdContext using MD5_Init **
+ ** (2) Call MD5_Update on mdContext and M **
+ ** (3) Call MD5_Final on mdContext **
+ ** The message digest is now in mdContext->digest[0...15] **
+ ***********************************************************************
+ */
+
+/* forward declaration */
+static void Transform (UINT4 *buf, UINT4 *in);
+
+static unsigned char PADDING[64] = {
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/* F, G, H and I are basic MD5 functions */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */
+/* Rotation is separate from addition to prevent recomputation */
+#define FF(a, b, c, d, x, s, ac) \
+ {(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define GG(a, b, c, d, x, s, ac) \
+ {(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define HH(a, b, c, d, x, s, ac) \
+ {(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define II(a, b, c, d, x, s, ac) \
+ {(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+
+#ifdef __STDC__
+#define UL(x) x##U
+#else
+#define UL(x) x
+#endif
+
+/* The routine MD5_Init initializes the message-digest context
+ mdContext. All fields are set to zero.
+ */
+void lpa_MD5_Init (mdContext)
+lpa_MD5_CTX *mdContext;
+{
+ mdContext->i[0] = mdContext->i[1] = (UINT4)0;
+
+ /* Load magic initialization constants.
+ */
+ mdContext->buf[0] = (UINT4)0x67452301;
+ mdContext->buf[1] = (UINT4)0xefcdab89;
+ mdContext->buf[2] = (UINT4)0x98badcfe;
+ mdContext->buf[3] = (UINT4)0x10325476;
+}
+
+/* The routine MD5Update updates the message-digest context to
+ account for the presence of each of the characters inBuf[0..inLen-1]
+ in the message whose digest is being computed.
+ */
+void lpa_MD5_Update (mdContext, inBuf, inLen)
+lpa_MD5_CTX *mdContext;
+unsigned char *inBuf;
+unsigned int inLen;
+{
+ UINT4 in[16];
+ int mdi;
+ unsigned int i, ii;
+
+ /* compute number of bytes mod 64 */
+ mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
+
+ /* update number of bits */
+ if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0])
+ mdContext->i[1]++;
+ mdContext->i[0] += ((UINT4)inLen << 3);
+ mdContext->i[1] += ((UINT4)inLen >> 29);
+
+ while (inLen--) {
+ /* add new character to buffer, increment mdi */
+ mdContext->in[mdi++] = *inBuf++;
+
+ /* transform if necessary */
+ if (mdi == 0x40) {
+ for (i = 0, ii = 0; i < 16; i++, ii += 4)
+ in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
+ (((UINT4)mdContext->in[ii+2]) << 16) |
+ (((UINT4)mdContext->in[ii+1]) << 8) |
+ ((UINT4)mdContext->in[ii]);
+ Transform (mdContext->buf, in);
+ mdi = 0;
+ }
+ }
+}
+
+/* The routine MD5Final terminates the message-digest computation and
+ ends with the desired message digest in mdContext->digest[0...15].
+ */
+void lpa_MD5_Final (hash, mdContext)
+unsigned char hash[];
+lpa_MD5_CTX *mdContext;
+{
+ UINT4 in[16];
+ int mdi;
+ unsigned int i, ii;
+ unsigned int padLen;
+
+ /* save number of bits */
+ in[14] = mdContext->i[0];
+ in[15] = mdContext->i[1];
+
+ /* compute number of bytes mod 64 */
+ mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
+
+ /* pad out to 56 mod 64 */
+ padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);
+ lpa_MD5_Update (mdContext, PADDING, padLen);
+
+ /* append length in bits and transform */
+ for (i = 0, ii = 0; i < 14; i++, ii += 4)
+ in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
+ (((UINT4)mdContext->in[ii+2]) << 16) |
+ (((UINT4)mdContext->in[ii+1]) << 8) |
+ ((UINT4)mdContext->in[ii]);
+ Transform (mdContext->buf, in);
+
+ /* store buffer in digest */
+ for (i = 0, ii = 0; i < 4; i++, ii += 4) {
+ mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF);
+ mdContext->digest[ii+1] =
+ (unsigned char)((mdContext->buf[i] >> 8) & 0xFF);
+ mdContext->digest[ii+2] =
+ (unsigned char)((mdContext->buf[i] >> 16) & 0xFF);
+ mdContext->digest[ii+3] =
+ (unsigned char)((mdContext->buf[i] >> 24) & 0xFF);
+ }
+ memcpy(hash, mdContext->digest, 16);
+}
+
+/* Basic MD5 step. Transforms buf based on in.
+ */
+static void Transform (buf, in)
+UINT4 *buf;
+UINT4 *in;
+{
+ UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
+
+ /* Round 1 */
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+ FF ( a, b, c, d, in[ 0], S11, UL(3614090360)); /* 1 */
+ FF ( d, a, b, c, in[ 1], S12, UL(3905402710)); /* 2 */
+ FF ( c, d, a, b, in[ 2], S13, UL( 606105819)); /* 3 */
+ FF ( b, c, d, a, in[ 3], S14, UL(3250441966)); /* 4 */
+ FF ( a, b, c, d, in[ 4], S11, UL(4118548399)); /* 5 */
+ FF ( d, a, b, c, in[ 5], S12, UL(1200080426)); /* 6 */
+ FF ( c, d, a, b, in[ 6], S13, UL(2821735955)); /* 7 */
+ FF ( b, c, d, a, in[ 7], S14, UL(4249261313)); /* 8 */
+ FF ( a, b, c, d, in[ 8], S11, UL(1770035416)); /* 9 */
+ FF ( d, a, b, c, in[ 9], S12, UL(2336552879)); /* 10 */
+ FF ( c, d, a, b, in[10], S13, UL(4294925233)); /* 11 */
+ FF ( b, c, d, a, in[11], S14, UL(2304563134)); /* 12 */
+ FF ( a, b, c, d, in[12], S11, UL(1804603682)); /* 13 */
+ FF ( d, a, b, c, in[13], S12, UL(4254626195)); /* 14 */
+ FF ( c, d, a, b, in[14], S13, UL(2792965006)); /* 15 */
+ FF ( b, c, d, a, in[15], S14, UL(1236535329)); /* 16 */
+
+ /* Round 2 */
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+ GG ( a, b, c, d, in[ 1], S21, UL(4129170786)); /* 17 */
+ GG ( d, a, b, c, in[ 6], S22, UL(3225465664)); /* 18 */
+ GG ( c, d, a, b, in[11], S23, UL( 643717713)); /* 19 */
+ GG ( b, c, d, a, in[ 0], S24, UL(3921069994)); /* 20 */
+ GG ( a, b, c, d, in[ 5], S21, UL(3593408605)); /* 21 */
+ GG ( d, a, b, c, in[10], S22, UL( 38016083)); /* 22 */
+ GG ( c, d, a, b, in[15], S23, UL(3634488961)); /* 23 */
+ GG ( b, c, d, a, in[ 4], S24, UL(3889429448)); /* 24 */
+ GG ( a, b, c, d, in[ 9], S21, UL( 568446438)); /* 25 */
+ GG ( d, a, b, c, in[14], S22, UL(3275163606)); /* 26 */
+ GG ( c, d, a, b, in[ 3], S23, UL(4107603335)); /* 27 */
+ GG ( b, c, d, a, in[ 8], S24, UL(1163531501)); /* 28 */
+ GG ( a, b, c, d, in[13], S21, UL(2850285829)); /* 29 */
+ GG ( d, a, b, c, in[ 2], S22, UL(4243563512)); /* 30 */
+ GG ( c, d, a, b, in[ 7], S23, UL(1735328473)); /* 31 */
+ GG ( b, c, d, a, in[12], S24, UL(2368359562)); /* 32 */
+
+ /* Round 3 */
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+ HH ( a, b, c, d, in[ 5], S31, UL(4294588738)); /* 33 */
+ HH ( d, a, b, c, in[ 8], S32, UL(2272392833)); /* 34 */
+ HH ( c, d, a, b, in[11], S33, UL(1839030562)); /* 35 */
+ HH ( b, c, d, a, in[14], S34, UL(4259657740)); /* 36 */
+ HH ( a, b, c, d, in[ 1], S31, UL(2763975236)); /* 37 */
+ HH ( d, a, b, c, in[ 4], S32, UL(1272893353)); /* 38 */
+ HH ( c, d, a, b, in[ 7], S33, UL(4139469664)); /* 39 */
+ HH ( b, c, d, a, in[10], S34, UL(3200236656)); /* 40 */
+ HH ( a, b, c, d, in[13], S31, UL( 681279174)); /* 41 */
+ HH ( d, a, b, c, in[ 0], S32, UL(3936430074)); /* 42 */
+ HH ( c, d, a, b, in[ 3], S33, UL(3572445317)); /* 43 */
+ HH ( b, c, d, a, in[ 6], S34, UL( 76029189)); /* 44 */
+ HH ( a, b, c, d, in[ 9], S31, UL(3654602809)); /* 45 */
+ HH ( d, a, b, c, in[12], S32, UL(3873151461)); /* 46 */
+ HH ( c, d, a, b, in[15], S33, UL( 530742520)); /* 47 */
+ HH ( b, c, d, a, in[ 2], S34, UL(3299628645)); /* 48 */
+
+ /* Round 4 */
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+ II ( a, b, c, d, in[ 0], S41, UL(4096336452)); /* 49 */
+ II ( d, a, b, c, in[ 7], S42, UL(1126891415)); /* 50 */
+ II ( c, d, a, b, in[14], S43, UL(2878612391)); /* 51 */
+ II ( b, c, d, a, in[ 5], S44, UL(4237533241)); /* 52 */
+ II ( a, b, c, d, in[12], S41, UL(1700485571)); /* 53 */
+ II ( d, a, b, c, in[ 3], S42, UL(2399980690)); /* 54 */
+ II ( c, d, a, b, in[10], S43, UL(4293915773)); /* 55 */
+ II ( b, c, d, a, in[ 1], S44, UL(2240044497)); /* 56 */
+ II ( a, b, c, d, in[ 8], S41, UL(1873313359)); /* 57 */
+ II ( d, a, b, c, in[15], S42, UL(4264355552)); /* 58 */
+ II ( c, d, a, b, in[ 6], S43, UL(2734768916)); /* 59 */
+ II ( b, c, d, a, in[13], S44, UL(1309151649)); /* 60 */
+ II ( a, b, c, d, in[ 4], S41, UL(4149444226)); /* 61 */
+ II ( d, a, b, c, in[11], S42, UL(3174756917)); /* 62 */
+ II ( c, d, a, b, in[ 2], S43, UL( 718787259)); /* 63 */
+ II ( b, c, d, a, in[ 9], S44, UL(3951481745)); /* 64 */
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+}
+
+/*
+ ***********************************************************************
+ ** End of md5.c **
+ ******************************** (cut) ********************************
+ */
diff --git a/ap/lib/liblpa/md5.h b/ap/lib/liblpa/md5.h
new file mode 100755
index 0000000..b231d34
--- /dev/null
+++ b/ap/lib/liblpa/md5.h
@@ -0,0 +1,65 @@
+/*
+ ***********************************************************************
+ ** md5.h -- header file for implementation of MD5 **
+ ** RSA Data Security, Inc. MD5 Message-Digest Algorithm **
+ ** Created: 2/17/90 RLR **
+ ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version **
+ ** Revised (for MD5): RLR 4/27/91 **
+ ** -- G modified to have y&~z instead of y&z **
+ ** -- FF, GG, HH modified to add in last register done **
+ ** -- Access pattern: round 2 works mod 5, round 3 works mod 3 **
+ ** -- distinct additive constant for each step **
+ ** -- round 4 added, working mod 7 **
+ ***********************************************************************
+ */
+
+/*
+ ***********************************************************************
+ ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
+ ** **
+ ** License to copy and use this software is granted provided that **
+ ** it is identified as the "RSA Data Security, Inc. MD5 Message- **
+ ** Digest Algorithm" in all material mentioning or referencing this **
+ ** software or this function. **
+ ** **
+ ** License is also granted to make and use derivative works **
+ ** provided that such works are identified as "derived from the RSA **
+ ** Data Security, Inc. MD5 Message-Digest Algorithm" in all **
+ ** material mentioning or referencing the derived work. **
+ ** **
+ ** RSA Data Security, Inc. makes no representations concerning **
+ ** either the merchantability of this software or the suitability **
+ ** of this software for any particular purpose. It is provided "as **
+ ** is" without express or implied warranty of any kind. **
+ ** **
+ ** These notices must be retained in any copies of any part of this **
+ ** documentation and/or software. **
+ ***********************************************************************
+ */
+
+#ifndef __MD5_INCLUDE__
+
+/* typedef a 32-bit type */
+#ifdef _LP64
+typedef unsigned int UINT4;
+typedef int INT4;
+#else
+typedef unsigned long UINT4;
+typedef long INT4;
+#endif
+#define _UINT4_T
+
+/* Data structure for MD5 (Message-Digest) computation */
+typedef struct {
+ UINT4 i[2]; /* number of _bits_ handled mod 2^64 */
+ UINT4 buf[4]; /* scratch buffer */
+ unsigned char in[64]; /* input buffer */
+ unsigned char digest[16]; /* actual digest after MD5Final call */
+} lpa_MD5_CTX;
+
+void lpa_MD5_Init (lpa_MD5_CTX *mdContext);
+void lpa_MD5_Update (lpa_MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen);
+void lpa_MD5_Final (unsigned char hash[], lpa_MD5_CTX *mdContext);
+
+#define __MD5_INCLUDE__
+#endif /* __MD5_INCLUDE__ */