[T106][ZXW-22]7520V3SCV2.01.01.02P42U09_VEC_V0.8_AP_VEC origin source commit

Change-Id: Ic6e05d89ecd62fc34f82b23dcf306c93764aec4b
diff --git a/ap/app/zte_comm/zte_locknet/Makefile b/ap/app/zte_comm/zte_locknet/Makefile
new file mode 100755
index 0000000..1372932
--- /dev/null
+++ b/ap/app/zte_comm/zte_locknet/Makefile
@@ -0,0 +1,43 @@
+#*******************************************************************************
+# include ZTE application makefile
+#*******************************************************************************	
+include $(COMMON_MK)
+
+##############USER COMIZE BEGIN################
+EXEC1 = zte_locknet 
+
+CPU_PUB_ROOT=$(TOPDIR_AP)/../pub
+
+OBJS1 = $(patsubst %.c,%.o,$(wildcard ./src/*.c ))
+                                   
+CFLAGS += -I.
+CFLAGS += -I./inc
+CFLAGS += -I$(zte_app_path)/include
+CFLAGS += -I$(zte_app_path)/zte_comm/at_ctl/inc
+CFLAGS += -I$(zte_lib_path)/libsqlite
+CFLAGS += -I$(LINUX_DIR)
+
+CFLAGS += -I$(CPU_PUB_ROOT)/project/zx297520v3/include/nv
+CFLAGS += -O -Dlinux=1 -DHIGH_SPEED=1
+CFLAGS += -g
+CFLAGS += -g -Werror=implicit-function-declaration
+ 
+LDLIBS  += -lnvram_sc -L$(zte_lib_path)/libnvram
+LDLIBS  += -lsoftap -L$(zte_lib_path)/libsoftap
+LDLIBS  += -latutils -L$(zte_lib_path)/libatutils
+LDLIBS  += -lsqlite -L$(zte_lib_path)/libsqlite
+LDLIBS  += -lsoft_timer_sc -L$(zte_lib_path)/libsoft_timer
+
+LDLIBS  += -lm
+LDLIBS  += -lpthread -L$(zte_lib_path)/libpthread
+LDLIBS  += -lcpnv -L$(zte_lib_path)/libcpnv
+##############USER COMIZE END##################
+
+#*******************************************************************************
+# targets
+#*******************************************************************************
+lib: $(OBJS1)
+	@echo Compiling zte_locknet libraries.
+	
+clean:
+	-rm -f $(OBJS1)
diff --git a/ap/app/zte_comm/zte_locknet/inc/zctrm_ln_bignum.h b/ap/app/zte_comm/zte_locknet/inc/zctrm_ln_bignum.h
new file mode 100755
index 0000000..01a09c3
--- /dev/null
+++ b/ap/app/zte_comm/zte_locknet/inc/zctrm_ln_bignum.h
@@ -0,0 +1,533 @@
+/**
+ * \file bignum.h
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_BIGNUM_H
+#define POLARSSL_BIGNUM_H
+
+#include <stdio.h>
+
+#define POLARSSL_ERR_MPI_FILE_IO_ERROR                     0x0002
+#define POLARSSL_ERR_MPI_BAD_INPUT_DATA                    0x0004
+#define POLARSSL_ERR_MPI_INVALID_CHARACTER                 0x0006
+#define POLARSSL_ERR_MPI_BUFFER_TOO_SMALL                  0x0008
+#define POLARSSL_ERR_MPI_NEGATIVE_VALUE                    0x000A
+#define POLARSSL_ERR_MPI_DIVISION_BY_ZERO                  0x000C
+#define POLARSSL_ERR_MPI_NOT_ACCEPTABLE                    0x000E
+
+#define MPI_CHK(f) {if( ( ret = f ) != 0 ) goto cleanup;}
+
+/*
+ * Define the base integer type, architecture-wise
+ */
+#if defined(POLARSSL_HAVE_INT8)
+typedef unsigned char  t_int;
+typedef unsigned short t_dbl;
+#else
+#if defined(POLARSSL_HAVE_INT16)
+typedef unsigned short t_int;
+typedef unsigned long  t_dbl;
+#else
+  typedef unsigned long t_int;
+  #if defined(_MSC_VER) && defined(_M_IX86)
+  typedef unsigned __int64 t_dbl;
+  #else
+    #if defined(__amd64__) || defined(__x86_64__)    || \
+        defined(__ppc64__) || defined(__powerpc64__) || \
+        defined(__ia64__)  || defined(__alpha__)
+    typedef unsigned int t_dbl __attribute__((mode(TI)));
+    #else
+      #if defined(POLARSSL_HAVE_LONGLONG)
+      typedef unsigned long long t_dbl;
+      #endif
+    #endif
+  #endif
+#endif
+#endif
+
+/**
+ * \brief          MPI structure
+ */
+typedef struct
+{
+    int s;              /*!<  integer sign      */
+    int n;              /*!<  total # of limbs  */
+    t_int *p;           /*!<  pointer to limbs  */
+}
+mpi;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          Initialize one or more mpi
+ */
+void mpi_init( mpi *X, ... );
+
+/**
+ * \brief          Unallocate one or more mpi
+ */
+void mpi_free( mpi *X, ... );
+
+/**
+ * \brief          Enlarge to the specified number of limbs
+ *
+ * \param X        MPI to grow
+ * \param nblimbs  The target number of limbs
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed
+ */
+int mpi_grow( mpi *X, int nblimbs );
+
+/**
+ * \brief          Copy the contents of Y into X
+ *
+ * \param X        Destination MPI
+ * \param Y        Source MPI
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed
+ */
+int mpi_copy( mpi *X, const mpi *Y );
+
+/**
+ * \brief          Swap the contents of X and Y
+ *
+ * \param X        First MPI value
+ * \param Y        Second MPI value
+ */
+void mpi_swap( mpi *X, mpi *Y );
+
+/**
+ * \brief          Set value from integer
+ *
+ * \param X        MPI to set
+ * \param z        Value to use
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed
+ */
+int mpi_lset( mpi *X, int z );
+
+/**
+ * \brief          Return the number of least significant bits
+ *
+ * \param X        MPI to use
+ */
+int mpi_lsb( const mpi *X );
+
+/**
+ * \brief          Return the number of most significant bits
+ *
+ * \param X        MPI to use
+ */
+int mpi_msb( const mpi *X );
+
+/**
+ * \brief          Return the total size in bytes
+ *
+ * \param X        MPI to use
+ */
+int mpi_size( const mpi *X );
+
+/**
+ * \brief          Import from an ASCII string
+ *
+ * \param X        Destination MPI
+ * \param radix    Input numeric base
+ * \param s        Null-terminated string buffer
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_MPI_XXX error code
+ */
+int mpi_read_string( mpi *X, int radix, const char *s );
+
+/**
+ * \brief          Export into an ASCII string
+ *
+ * \param X        Source MPI
+ * \param radix    Output numeric base
+ * \param s        String buffer
+ * \param slen     String buffer size
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_MPI_XXX error code.
+ *                 *slen is always updated to reflect the amount
+ *                 of data that has (or would have) been written.
+ *
+ * \note           Call this function with *slen = 0 to obtain the
+ *                 minimum required buffer size in *slen.
+ */
+int mpi_write_string( const mpi *X, int radix, char *s, int *slen );
+
+/**
+ * \brief          Read X from an opened file
+ *
+ * \param X        Destination MPI
+ * \param radix    Input numeric base
+ * \param fin      Input file handle
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_MPI_XXX error code
+ */
+//int mpi_read_file( mpi *X, int radix, FILE *fin );
+
+/**
+ * \brief          Write X into an opened file, or stdout if fout is NULL
+ *
+ * \param p        Prefix, can be NULL
+ * \param X        Source MPI
+ * \param radix    Output numeric base
+ * \param fout     Output file handle (can be NULL)
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_MPI_XXX error code
+ *
+ * \note           Set fout == NULL to print X on the console.
+ */
+//int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout );
+
+/**
+ * \brief          Import X from unsigned binary data, big endian
+ *
+ * \param X        Destination MPI
+ * \param buf      Input buffer
+ * \param buflen   Input buffer size
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed
+ */
+int mpi_read_binary( mpi *X, const unsigned char *buf, int buflen );
+
+/**
+ * \brief          Export X into unsigned binary data, big endian
+ *
+ * \param X        Source MPI
+ * \param buf      Output buffer
+ * \param buflen   Output buffer size
+ *
+ * \return         0 if successful,
+ *                 POLARSSL_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough
+ */
+int mpi_write_binary( const mpi *X, unsigned char *buf, int buflen );
+
+/**
+ * \brief          Left-shift: X <<= count
+ *
+ * \param X        MPI to shift
+ * \param count    Amount to shift
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed
+ */
+int mpi_shift_l( mpi *X, int count );
+
+/**
+ * \brief          Right-shift: X >>= count
+ *
+ * \param X        MPI to shift
+ * \param count    Amount to shift
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed
+ */
+int mpi_shift_r( mpi *X, int count );
+
+/**
+ * \brief          Compare unsigned values
+ *
+ * \param X        Left-hand MPI
+ * \param Y        Right-hand MPI
+ *
+ * \return         1 if |X| is greater than |Y|,
+ *                -1 if |X| is lesser  than |Y| or
+ *                 0 if |X| is equal to |Y|
+ */
+int mpi_cmp_abs( const mpi *X, const mpi *Y );
+
+/**
+ * \brief          Compare signed values
+ *
+ * \param X        Left-hand MPI
+ * \param Y        Right-hand MPI
+ *
+ * \return         1 if X is greater than Y,
+ *                -1 if X is lesser  than Y or
+ *                 0 if X is equal to Y
+ */
+int mpi_cmp_mpi( const mpi *X, const mpi *Y );
+
+/**
+ * \brief          Compare signed values
+ *
+ * \param X        Left-hand MPI
+ * \param z        The integer value to compare to
+ *
+ * \return         1 if X is greater than z,
+ *                -1 if X is lesser  than z or
+ *                 0 if X is equal to z
+ */
+int mpi_cmp_int( const mpi *X, int z );
+
+/**
+ * \brief          Unsigned addition: X = |A| + |B|
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param B        Right-hand MPI
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed
+ */
+int mpi_add_abs( mpi *X, const mpi *A, const mpi *B );
+
+/**
+ * \brief          Unsigned substraction: X = |A| - |B|
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param B        Right-hand MPI
+ *
+ * \return         0 if successful,
+ *                 POLARSSL_ERR_MPI_NEGATIVE_VALUE if B is greater than A
+ */
+int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B );
+
+/**
+ * \brief          Signed addition: X = A + B
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param B        Right-hand MPI
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed
+ */
+int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B );
+
+/**
+ * \brief          Signed substraction: X = A - B
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param B        Right-hand MPI
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed
+ */
+int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B );
+
+/**
+ * \brief          Signed addition: X = A + b
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param b        The integer value to add
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed
+ */
+int mpi_add_int( mpi *X, const mpi *A, int b );
+
+/**
+ * \brief          Signed substraction: X = A - b
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param b        The integer value to subtract
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed
+ */
+int mpi_sub_int( mpi *X, const mpi *A, int b );
+
+/**
+ * \brief          Baseline multiplication: X = A * B
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param B        Right-hand MPI
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed
+ */
+int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B );
+
+/**
+ * \brief          Baseline multiplication: X = A * b
+ *                 Note: b is an unsigned integer type, thus
+ *                 Negative values of b are ignored.
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param b        The integer value to multiply with
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed
+ */
+int mpi_mul_int( mpi *X, const mpi *A, t_int b );
+
+/**
+ * \brief          Division by mpi: A = Q * B + R
+ *
+ * \param Q        Destination MPI for the quotient
+ * \param R        Destination MPI for the rest value
+ * \param A        Left-hand MPI
+ * \param B        Right-hand MPI
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed,
+ *                 POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0
+ *
+ * \note           Either Q or R can be NULL.
+ */
+int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B );
+
+/**
+ * \brief          Division by int: A = Q * b + R
+ *
+ * \param Q        Destination MPI for the quotient
+ * \param R        Destination MPI for the rest value
+ * \param A        Left-hand MPI
+ * \param b        Integer to divide by
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed,
+ *                 POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0
+ *
+ * \note           Either Q or R can be NULL.
+ */
+int mpi_div_int( mpi *Q, mpi *R, const mpi *A, int b );
+
+/**
+ * \brief          Modulo: R = A mod B
+ *
+ * \param R        Destination MPI for the rest value
+ * \param A        Left-hand MPI
+ * \param B        Right-hand MPI
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed,
+ *                 POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0,
+ *                 POLARSSL_ERR_MPI_NEGATIVE_VALUE if B < 0
+ */
+int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B );
+
+/**
+ * \brief          Modulo: r = A mod b
+ *
+ * \param r        Destination t_int
+ * \param A        Left-hand MPI
+ * \param b        Integer to divide by
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed,
+ *                 POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0,
+ *                 POLARSSL_ERR_MPI_NEGATIVE_VALUE if b < 0
+ */
+int mpi_mod_int( t_int *r, const mpi *A, int b );
+
+/**
+ * \brief          Sliding-window exponentiation: X = A^E mod N
+ *
+ * \param X        Destination MPI 
+ * \param A        Left-hand MPI
+ * \param E        Exponent MPI
+ * \param N        Modular MPI
+ * \param _RR      Speed-up MPI used for recalculations
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed,
+ *                 POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or even
+ *
+ * \note           _RR is used to avoid re-computing R*R mod N across
+ *                 multiple calls, which speeds up things a bit. It can
+ *                 be set to NULL if the extra performance is unneeded.
+ */
+int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR );
+
+/**
+ * \brief          Greatest common divisor: G = gcd(A, B)
+ *
+ * \param G        Destination MPI
+ * \param A        Left-hand MPI
+ * \param B        Right-hand MPI
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed
+ */
+int mpi_gcd( mpi *G, const mpi *A, const mpi *B );
+
+/**
+ * \brief          Modular inverse: X = A^-1 mod N
+ *
+ * \param X        Destination MPI
+ * \param A        Left-hand MPI
+ * \param N        Right-hand MPI
+ *
+ * \return         0 if successful,
+ *                 1 if memory allocation failed,
+ *                 POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or nil
+                   POLARSSL_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N
+ */
+int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N );
+
+/**
+ * \brief          Miller-Rabin primality test
+ *
+ * \param X        MPI to check
+ * \param f_rng    RNG function
+ * \param p_rng    RNG parameter
+ *
+ * \return         0 if successful (probably prime),
+ *                 1 if memory allocation failed,
+ *                 POLARSSL_ERR_MPI_NOT_ACCEPTABLE if X is not prime
+ */
+int mpi_is_prime( mpi *X, int (*f_rng)(void *), void *p_rng );
+
+/**
+ * \brief          Prime number generation
+ *
+ * \param X        Destination MPI
+ * \param nbits    Required size of X in bits
+ * \param dh_flag  If 1, then (X-1)/2 will be prime too
+ * \param f_rng    RNG function
+ * \param p_rng    RNG parameter
+ *
+ * \return         0 if successful (probably prime),
+ *                 1 if memory allocation failed,
+ *                 POLARSSL_ERR_MPI_BAD_INPUT_DATA if nbits is < 3
+ */
+int mpi_gen_prime( mpi *X, int nbits, int dh_flag,
+                   int (*f_rng)(void *), void *p_rng );
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int mpi_self_test( int verbose );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* bignum.h */
diff --git a/ap/app/zte_comm/zte_locknet/inc/zctrm_ln_bnmul.h b/ap/app/zte_comm/zte_locknet/inc/zctrm_ln_bnmul.h
new file mode 100755
index 0000000..b4a60c5
--- /dev/null
+++ b/ap/app/zte_comm/zte_locknet/inc/zctrm_ln_bnmul.h
@@ -0,0 +1,736 @@
+/**
+ * \file bn_mul.h
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *      Multiply source vector [s] with b, add result
+ *       to destination vector [d] and set carry c.
+ *
+ *      Currently supports:
+ *
+ *         . IA-32 (386+)         . AMD64 / EM64T
+ *         . IA-32 (SSE2)         . Motorola 68000
+ *         . PowerPC, 32-bit      . MicroBlaze
+ *         . PowerPC, 64-bit      . TriCore
+ *         . SPARC v8             . ARM v3+
+ *         . Alpha                . MIPS32
+ *         . C, longlong          . C, generic
+ */
+#ifndef POLARSSL_BN_MUL_H
+#define POLARSSL_BN_MUL_H
+
+#include "zctrm_ln_config.h"
+
+#if defined(POLARSSL_HAVE_ASM)
+
+#if defined(__GNUC__)
+#if defined(__i386__)
+
+#define MULADDC_INIT                \
+    asm( "                          \
+        movl   %%ebx, %0;           \
+        movl   %5, %%esi;           \
+        movl   %6, %%edi;           \
+        movl   %7, %%ecx;           \
+        movl   %8, %%ebx;           \
+        "
+
+#define MULADDC_CORE                \
+        "                           \
+        lodsl;                      \
+        mull   %%ebx;               \
+        addl   %%ecx,   %%eax;      \
+        adcl   $0,      %%edx;      \
+        addl   (%%edi), %%eax;      \
+        adcl   $0,      %%edx;      \
+        movl   %%edx,   %%ecx;      \
+        stosl;                      \
+        "
+
+#if defined(POLARSSL_HAVE_SSE2)
+
+#define MULADDC_HUIT                    \
+        "                               \
+        movd     %%ecx,     %%mm1;      \
+        movd     %%ebx,     %%mm0;      \
+        movd     (%%edi),   %%mm3;      \
+        paddq    %%mm3,     %%mm1;      \
+        movd     (%%esi),   %%mm2;      \
+        pmuludq  %%mm0,     %%mm2;      \
+        movd     4(%%esi),  %%mm4;      \
+        pmuludq  %%mm0,     %%mm4;      \
+        movd     8(%%esi),  %%mm6;      \
+        pmuludq  %%mm0,     %%mm6;      \
+        movd     12(%%esi), %%mm7;      \
+        pmuludq  %%mm0,     %%mm7;      \
+        paddq    %%mm2,     %%mm1;      \
+        movd     4(%%edi),  %%mm3;      \
+        paddq    %%mm4,     %%mm3;      \
+        movd     8(%%edi),  %%mm5;      \
+        paddq    %%mm6,     %%mm5;      \
+        movd     12(%%edi), %%mm4;      \
+        paddq    %%mm4,     %%mm7;      \
+        movd     %%mm1,     (%%edi);    \
+        movd     16(%%esi), %%mm2;      \
+        pmuludq  %%mm0,     %%mm2;      \
+        psrlq    $32,       %%mm1;      \
+        movd     20(%%esi), %%mm4;      \
+        pmuludq  %%mm0,     %%mm4;      \
+        paddq    %%mm3,     %%mm1;      \
+        movd     24(%%esi), %%mm6;      \
+        pmuludq  %%mm0,     %%mm6;      \
+        movd     %%mm1,     4(%%edi);   \
+        psrlq    $32,       %%mm1;      \
+        movd     28(%%esi), %%mm3;      \
+        pmuludq  %%mm0,     %%mm3;      \
+        paddq    %%mm5,     %%mm1;      \
+        movd     16(%%edi), %%mm5;      \
+        paddq    %%mm5,     %%mm2;      \
+        movd     %%mm1,     8(%%edi);   \
+        psrlq    $32,       %%mm1;      \
+        paddq    %%mm7,     %%mm1;      \
+        movd     20(%%edi), %%mm5;      \
+        paddq    %%mm5,     %%mm4;      \
+        movd     %%mm1,     12(%%edi);  \
+        psrlq    $32,       %%mm1;      \
+        paddq    %%mm2,     %%mm1;      \
+        movd     24(%%edi), %%mm5;      \
+        paddq    %%mm5,     %%mm6;      \
+        movd     %%mm1,     16(%%edi);  \
+        psrlq    $32,       %%mm1;      \
+        paddq    %%mm4,     %%mm1;      \
+        movd     28(%%edi), %%mm5;      \
+        paddq    %%mm5,     %%mm3;      \
+        movd     %%mm1,     20(%%edi);  \
+        psrlq    $32,       %%mm1;      \
+        paddq    %%mm6,     %%mm1;      \
+        movd     %%mm1,     24(%%edi);  \
+        psrlq    $32,       %%mm1;      \
+        paddq    %%mm3,     %%mm1;      \
+        movd     %%mm1,     28(%%edi);  \
+        addl     $32,       %%edi;      \
+        addl     $32,       %%esi;      \
+        psrlq    $32,       %%mm1;      \
+        movd     %%mm1,     %%ecx;      \
+        "
+
+#define MULADDC_STOP            \
+        "                       \
+        emms;                   \
+        movl   %4, %%ebx;       \
+        movl   %%ecx, %1;       \
+        movl   %%edi, %2;       \
+        movl   %%esi, %3;       \
+        "                       \
+        : "=m" (t), "=m" (c), "=m" (d), "=m" (s)        \
+        : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b)   \
+        : "eax", "ecx", "edx", "esi", "edi"             \
+    );
+
+#else
+
+#define MULADDC_STOP            \
+        "                       \
+        movl   %4, %%ebx;       \
+        movl   %%ecx, %1;       \
+        movl   %%edi, %2;       \
+        movl   %%esi, %3;       \
+        "                       \
+        : "=m" (t), "=m" (c), "=m" (d), "=m" (s)        \
+        : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b)   \
+        : "eax", "ecx", "edx", "esi", "edi"             \
+    );
+#endif /* SSE2 */
+#endif /* i386 */
+
+#if defined(__amd64__) || defined (__x86_64__)
+
+#define MULADDC_INIT                            \
+    asm( "movq   %0, %%rsi      " :: "m" (s));  \
+    asm( "movq   %0, %%rdi      " :: "m" (d));  \
+    asm( "movq   %0, %%rcx      " :: "m" (c));  \
+    asm( "movq   %0, %%rbx      " :: "m" (b));  \
+    asm( "xorq   %r8, %r8       " );
+
+#define MULADDC_CORE                            \
+    asm( "movq  (%rsi),%rax     " );            \
+    asm( "mulq   %rbx           " );            \
+    asm( "addq   $8,   %rsi     " );            \
+    asm( "addq   %rcx, %rax     " );            \
+    asm( "movq   %r8,  %rcx     " );            \
+    asm( "adcq   $0,   %rdx     " );            \
+    asm( "nop                   " );            \
+    asm( "addq   %rax, (%rdi)   " );            \
+    asm( "adcq   %rdx, %rcx     " );            \
+    asm( "addq   $8,   %rdi     " );
+
+#define MULADDC_STOP                            \
+    asm( "movq   %%rcx, %0      " : "=m" (c));  \
+    asm( "movq   %%rdi, %0      " : "=m" (d));  \
+    asm( "movq   %%rsi, %0      " : "=m" (s) :: \
+    "rax", "rcx", "rdx", "rbx", "rsi", "rdi", "r8" );
+
+#endif /* AMD64 */
+
+#if defined(__mc68020__) || defined(__mcpu32__)
+
+#define MULADDC_INIT                            \
+    asm( "movl   %0, %%a2       " :: "m" (s));  \
+    asm( "movl   %0, %%a3       " :: "m" (d));  \
+    asm( "movl   %0, %%d3       " :: "m" (c));  \
+    asm( "movl   %0, %%d2       " :: "m" (b));  \
+    asm( "moveq  #0, %d0        " );
+
+#define MULADDC_CORE                            \
+    asm( "movel  %a2@+, %d1     " );            \
+    asm( "mulul  %d2, %d4:%d1   " );            \
+    asm( "addl   %d3, %d1       " );            \
+    asm( "addxl  %d0, %d4       " );            \
+    asm( "moveq  #0,  %d3       " );            \
+    asm( "addl   %d1, %a3@+     " );            \
+    asm( "addxl  %d4, %d3       " );
+
+#define MULADDC_STOP                            \
+    asm( "movl   %%d3, %0       " : "=m" (c));  \
+    asm( "movl   %%a3, %0       " : "=m" (d));  \
+    asm( "movl   %%a2, %0       " : "=m" (s) :: \
+    "d0", "d1", "d2", "d3", "d4", "a2", "a3" );
+
+#define MULADDC_HUIT                            \
+    asm( "movel  %a2@+, %d1     " );            \
+    asm( "mulul  %d2, %d4:%d1   " );            \
+    asm( "addxl  %d3, %d1       " );            \
+    asm( "addxl  %d0, %d4       " );            \
+    asm( "addl   %d1, %a3@+     " );            \
+    asm( "movel  %a2@+, %d1     " );            \
+    asm( "mulul  %d2, %d3:%d1   " );            \
+    asm( "addxl  %d4, %d1       " );            \
+    asm( "addxl  %d0, %d3       " );            \
+    asm( "addl   %d1, %a3@+     " );            \
+    asm( "movel  %a2@+, %d1     " );            \
+    asm( "mulul  %d2, %d4:%d1   " );            \
+    asm( "addxl  %d3, %d1       " );            \
+    asm( "addxl  %d0, %d4       " );            \
+    asm( "addl   %d1, %a3@+     " );            \
+    asm( "movel  %a2@+, %d1     " );            \
+    asm( "mulul  %d2, %d3:%d1   " );            \
+    asm( "addxl  %d4, %d1       " );            \
+    asm( "addxl  %d0, %d3       " );            \
+    asm( "addl   %d1, %a3@+     " );            \
+    asm( "movel  %a2@+, %d1     " );            \
+    asm( "mulul  %d2, %d4:%d1   " );            \
+    asm( "addxl  %d3, %d1       " );            \
+    asm( "addxl  %d0, %d4       " );            \
+    asm( "addl   %d1, %a3@+     " );            \
+    asm( "movel  %a2@+, %d1     " );            \
+    asm( "mulul  %d2, %d3:%d1   " );            \
+    asm( "addxl  %d4, %d1       " );            \
+    asm( "addxl  %d0, %d3       " );            \
+    asm( "addl   %d1, %a3@+     " );            \
+    asm( "movel  %a2@+, %d1     " );            \
+    asm( "mulul  %d2, %d4:%d1   " );            \
+    asm( "addxl  %d3, %d1       " );            \
+    asm( "addxl  %d0, %d4       " );            \
+    asm( "addl   %d1, %a3@+     " );            \
+    asm( "movel  %a2@+, %d1     " );            \
+    asm( "mulul  %d2, %d3:%d1   " );            \
+    asm( "addxl  %d4, %d1       " );            \
+    asm( "addxl  %d0, %d3       " );            \
+    asm( "addl   %d1, %a3@+     " );            \
+    asm( "addxl  %d0, %d3       " );
+
+#endif /* MC68000 */
+
+#if defined(__powerpc__)   || defined(__ppc__)
+#if defined(__powerpc64__) || defined(__ppc64__)
+
+#if defined(__MACH__) && defined(__APPLE__)
+
+#define MULADDC_INIT                            \
+    asm( "ld     r3, %0         " :: "m" (s));  \
+    asm( "ld     r4, %0         " :: "m" (d));  \
+    asm( "ld     r5, %0         " :: "m" (c));  \
+    asm( "ld     r6, %0         " :: "m" (b));  \
+    asm( "addi   r3, r3, -8     " );            \
+    asm( "addi   r4, r4, -8     " );            \
+    asm( "addic  r5, r5,  0     " );
+
+#define MULADDC_CORE                            \
+    asm( "ldu    r7, 8(r3)      " );            \
+    asm( "mulld  r8, r7, r6     " );            \
+    asm( "mulhdu r9, r7, r6     " );            \
+    asm( "adde   r8, r8, r5     " );            \
+    asm( "ld     r7, 8(r4)      " );            \
+    asm( "addze  r5, r9         " );            \
+    asm( "addc   r8, r8, r7     " );            \
+    asm( "stdu   r8, 8(r4)      " );
+
+#define MULADDC_STOP                            \
+    asm( "addze  r5, r5         " );            \
+    asm( "addi   r4, r4, 8      " );            \
+    asm( "addi   r3, r3, 8      " );            \
+    asm( "std    r5, %0         " : "=m" (c));  \
+    asm( "std    r4, %0         " : "=m" (d));  \
+    asm( "std    r3, %0         " : "=m" (s) :: \
+    "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
+
+#else
+
+#define MULADDC_INIT                            \
+    asm( "ld     %%r3, %0       " :: "m" (s));  \
+    asm( "ld     %%r4, %0       " :: "m" (d));  \
+    asm( "ld     %%r5, %0       " :: "m" (c));  \
+    asm( "ld     %%r6, %0       " :: "m" (b));  \
+    asm( "addi   %r3, %r3, -8   " );            \
+    asm( "addi   %r4, %r4, -8   " );            \
+    asm( "addic  %r5, %r5,  0   " );
+
+#define MULADDC_CORE                            \
+    asm( "ldu    %r7, 8(%r3)    " );            \
+    asm( "mulld  %r8, %r7, %r6  " );            \
+    asm( "mulhdu %r9, %r7, %r6  " );            \
+    asm( "adde   %r8, %r8, %r5  " );            \
+    asm( "ld     %r7, 8(%r4)    " );            \
+    asm( "addze  %r5, %r9       " );            \
+    asm( "addc   %r8, %r8, %r7  " );            \
+    asm( "stdu   %r8, 8(%r4)    " );
+
+#define MULADDC_STOP                            \
+    asm( "addze  %r5, %r5       " );            \
+    asm( "addi   %r4, %r4, 8    " );            \
+    asm( "addi   %r3, %r3, 8    " );            \
+    asm( "std    %%r5, %0       " : "=m" (c));  \
+    asm( "std    %%r4, %0       " : "=m" (d));  \
+    asm( "std    %%r3, %0       " : "=m" (s) :: \
+    "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
+
+#endif
+
+#else /* PPC32 */
+
+#if defined(__MACH__) && defined(__APPLE__)
+
+#define MULADDC_INIT                            \
+    asm( "lwz    r3, %0         " :: "m" (s));  \
+    asm( "lwz    r4, %0         " :: "m" (d));  \
+    asm( "lwz    r5, %0         " :: "m" (c));  \
+    asm( "lwz    r6, %0         " :: "m" (b));  \
+    asm( "addi   r3, r3, -4     " );            \
+    asm( "addi   r4, r4, -4     " );            \
+    asm( "addic  r5, r5,  0     " );
+
+#define MULADDC_CORE                            \
+    asm( "lwzu   r7, 4(r3)      " );            \
+    asm( "mullw  r8, r7, r6     " );            \
+    asm( "mulhwu r9, r7, r6     " );            \
+    asm( "adde   r8, r8, r5     " );            \
+    asm( "lwz    r7, 4(r4)      " );            \
+    asm( "addze  r5, r9         " );            \
+    asm( "addc   r8, r8, r7     " );            \
+    asm( "stwu   r8, 4(r4)      " );
+
+#define MULADDC_STOP                            \
+    asm( "addze  r5, r5         " );            \
+    asm( "addi   r4, r4, 4      " );            \
+    asm( "addi   r3, r3, 4      " );            \
+    asm( "stw    r5, %0         " : "=m" (c));  \
+    asm( "stw    r4, %0         " : "=m" (d));  \
+    asm( "stw    r3, %0         " : "=m" (s) :: \
+    "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
+
+#else
+
+#define MULADDC_INIT                            \
+    asm( "lwz    %%r3, %0       " :: "m" (s));  \
+    asm( "lwz    %%r4, %0       " :: "m" (d));  \
+    asm( "lwz    %%r5, %0       " :: "m" (c));  \
+    asm( "lwz    %%r6, %0       " :: "m" (b));  \
+    asm( "addi   %r3, %r3, -4   " );            \
+    asm( "addi   %r4, %r4, -4   " );            \
+    asm( "addic  %r5, %r5,  0   " );
+
+#define MULADDC_CORE                            \
+    asm( "lwzu   %r7, 4(%r3)    " );            \
+    asm( "mullw  %r8, %r7, %r6  " );            \
+    asm( "mulhwu %r9, %r7, %r6  " );            \
+    asm( "adde   %r8, %r8, %r5  " );            \
+    asm( "lwz    %r7, 4(%r4)    " );            \
+    asm( "addze  %r5, %r9       " );            \
+    asm( "addc   %r8, %r8, %r7  " );            \
+    asm( "stwu   %r8, 4(%r4)    " );
+
+#define MULADDC_STOP                            \
+    asm( "addze  %r5, %r5       " );            \
+    asm( "addi   %r4, %r4, 4    " );            \
+    asm( "addi   %r3, %r3, 4    " );            \
+    asm( "stw    %%r5, %0       " : "=m" (c));  \
+    asm( "stw    %%r4, %0       " : "=m" (d));  \
+    asm( "stw    %%r3, %0       " : "=m" (s) :: \
+    "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
+
+#endif
+
+#endif /* PPC32 */
+#endif /* PPC64 */
+
+#if defined(__sparc__)
+
+#define MULADDC_INIT                            \
+    asm( "ld     %0, %%o0       " :: "m" (s));  \
+    asm( "ld     %0, %%o1       " :: "m" (d));  \
+    asm( "ld     %0, %%o2       " :: "m" (c));  \
+    asm( "ld     %0, %%o3       " :: "m" (b));
+
+#define MULADDC_CORE                            \
+    asm( "ld    [%o0], %o4      " );            \
+    asm( "inc      4,  %o0      " );            \
+    asm( "ld    [%o1], %o5      " );            \
+    asm( "umul   %o3,  %o4, %o4 " );            \
+    asm( "addcc  %o4,  %o2, %o4 " );            \
+    asm( "rd      %y,  %g1      " );            \
+    asm( "addx   %g1,    0, %g1 " );            \
+    asm( "addcc  %o4,  %o5, %o4 " );            \
+    asm( "st     %o4, [%o1]     " );            \
+    asm( "addx   %g1,    0, %o2 " );            \
+    asm( "inc      4,  %o1      " );
+
+#define MULADDC_STOP                            \
+    asm( "st     %%o2, %0       " : "=m" (c));  \
+    asm( "st     %%o1, %0       " : "=m" (d));  \
+    asm( "st     %%o0, %0       " : "=m" (s) :: \
+    "g1", "o0", "o1", "o2", "o3", "o4", "o5" );
+
+#endif /* SPARCv8 */
+
+#if defined(__microblaze__) || defined(microblaze)
+
+#define MULADDC_INIT                            \
+    asm( "lwi   r3,   %0        " :: "m" (s));  \
+    asm( "lwi   r4,   %0        " :: "m" (d));  \
+    asm( "lwi   r5,   %0        " :: "m" (c));  \
+    asm( "lwi   r6,   %0        " :: "m" (b));  \
+    asm( "andi  r7,   r6, 0xffff" );            \
+    asm( "bsrli r6,   r6, 16    " );
+
+#define MULADDC_CORE                            \
+    asm( "lhui  r8,   r3,   0   " );            \
+    asm( "addi  r3,   r3,   2   " );            \
+    asm( "lhui  r9,   r3,   0   " );            \
+    asm( "addi  r3,   r3,   2   " );            \
+    asm( "mul   r10,  r9,  r6   " );            \
+    asm( "mul   r11,  r8,  r7   " );            \
+    asm( "mul   r12,  r9,  r7   " );            \
+    asm( "mul   r13,  r8,  r6   " );            \
+    asm( "bsrli  r8, r10,  16   " );            \
+    asm( "bsrli  r9, r11,  16   " );            \
+    asm( "add   r13, r13,  r8   " );            \
+    asm( "add   r13, r13,  r9   " );            \
+    asm( "bslli r10, r10,  16   " );            \
+    asm( "bslli r11, r11,  16   " );            \
+    asm( "add   r12, r12, r10   " );            \
+    asm( "addc  r13, r13,  r0   " );            \
+    asm( "add   r12, r12, r11   " );            \
+    asm( "addc  r13, r13,  r0   " );            \
+    asm( "lwi   r10,  r4,   0   " );            \
+    asm( "add   r12, r12, r10   " );            \
+    asm( "addc  r13, r13,  r0   " );            \
+    asm( "add   r12, r12,  r5   " );            \
+    asm( "addc   r5, r13,  r0   " );            \
+    asm( "swi   r12,  r4,   0   " );            \
+    asm( "addi   r4,  r4,   4   " );
+
+#define MULADDC_STOP                            \
+    asm( "swi   r5,   %0        " : "=m" (c));  \
+    asm( "swi   r4,   %0        " : "=m" (d));  \
+    asm( "swi   r3,   %0        " : "=m" (s) :: \
+     "r3", "r4" , "r5" , "r6" , "r7" , "r8" ,   \
+     "r9", "r10", "r11", "r12", "r13" );
+
+#endif /* MicroBlaze */
+
+#if defined(__tricore__)
+
+#define MULADDC_INIT                            \
+    asm( "ld.a   %%a2, %0       " :: "m" (s));  \
+    asm( "ld.a   %%a3, %0       " :: "m" (d));  \
+    asm( "ld.w   %%d4, %0       " :: "m" (c));  \
+    asm( "ld.w   %%d1, %0       " :: "m" (b));  \
+    asm( "xor    %d5, %d5       " );
+
+#define MULADDC_CORE                            \
+    asm( "ld.w   %d0,   [%a2+]      " );        \
+    asm( "madd.u %e2, %e4, %d0, %d1 " );        \
+    asm( "ld.w   %d0,   [%a3]       " );        \
+    asm( "addx   %d2,    %d2,  %d0  " );        \
+    asm( "addc   %d3,    %d3,    0  " );        \
+    asm( "mov    %d4,    %d3        " );        \
+    asm( "st.w  [%a3+],  %d2        " );
+
+#define MULADDC_STOP                            \
+    asm( "st.w   %0, %%d4       " : "=m" (c));  \
+    asm( "st.a   %0, %%a3       " : "=m" (d));  \
+    asm( "st.a   %0, %%a2       " : "=m" (s) :: \
+    "d0", "d1", "e2", "d4", "a2", "a3" );
+
+#endif /* TriCore */
+
+#if defined(__arm__)
+
+#define MULADDC_INIT                            \
+    asm( "ldr    r0, %0         " :: "m" (s));  \
+    asm( "ldr    r1, %0         " :: "m" (d));  \
+    asm( "ldr    r2, %0         " :: "m" (c));  \
+    asm( "ldr    r3, %0         " :: "m" (b));
+
+#define MULADDC_CORE                            \
+    asm( "ldr    r4, [r0], #4   " );            \
+    asm( "mov    r5, #0         " );            \
+    asm( "ldr    r6, [r1]       " );            \
+    asm( "umlal  r2, r5, r3, r4 " );            \
+    asm( "adds   r7, r6, r2     " );            \
+    asm( "adc    r2, r5, #0     " );            \
+    asm( "str    r7, [r1], #4   " );
+
+#define MULADDC_STOP                            \
+    asm( "str    r2, %0         " : "=m" (c));  \
+    asm( "str    r1, %0         " : "=m" (d));  \
+    asm( "str    r0, %0         " : "=m" (s) :: \
+    "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7" );
+
+#endif /* ARMv3 */
+
+#if defined(__alpha__)
+
+#define MULADDC_INIT                            \
+    asm( "ldq    $1, %0         " :: "m" (s));  \
+    asm( "ldq    $2, %0         " :: "m" (d));  \
+    asm( "ldq    $3, %0         " :: "m" (c));  \
+    asm( "ldq    $4, %0         " :: "m" (b));
+
+#define MULADDC_CORE                            \
+    asm( "ldq    $6,  0($1)     " );            \
+    asm( "addq   $1,  8, $1     " );            \
+    asm( "mulq   $6, $4, $7     " );            \
+    asm( "umulh  $6, $4, $6     " );            \
+    asm( "addq   $7, $3, $7     " );            \
+    asm( "cmpult $7, $3, $3     " );            \
+    asm( "ldq    $5,  0($2)     " );            \
+    asm( "addq   $7, $5, $7     " );            \
+    asm( "cmpult $7, $5, $5     " );            \
+    asm( "stq    $7,  0($2)     " );            \
+    asm( "addq   $2,  8, $2     " );            \
+    asm( "addq   $6, $3, $3     " );            \
+    asm( "addq   $5, $3, $3     " );
+
+#define MULADDC_STOP                            \
+    asm( "stq    $3, %0         " : "=m" (c));  \
+    asm( "stq    $2, %0         " : "=m" (d));  \
+    asm( "stq    $1, %0         " : "=m" (s) :: \
+    "$1", "$2", "$3", "$4", "$5", "$6", "$7" );
+
+#endif /* Alpha */
+
+#if defined(__mips__)
+
+#define MULADDC_INIT                            \
+    asm( "lw     $10, %0        " :: "m" (s));  \
+    asm( "lw     $11, %0        " :: "m" (d));  \
+    asm( "lw     $12, %0        " :: "m" (c));  \
+    asm( "lw     $13, %0        " :: "m" (b));
+
+#define MULADDC_CORE                            \
+    asm( "lw     $14, 0($10)    " );            \
+    asm( "multu  $13, $14       " );            \
+    asm( "addi   $10, $10, 4    " );            \
+    asm( "mflo   $14            " );            \
+    asm( "mfhi   $9             " );            \
+    asm( "addu   $14, $12, $14  " );            \
+    asm( "lw     $15, 0($11)    " );            \
+    asm( "sltu   $12, $14, $12  " );            \
+    asm( "addu   $15, $14, $15  " );            \
+    asm( "sltu   $14, $15, $14  " );            \
+    asm( "addu   $12, $12, $9   " );            \
+    asm( "sw     $15, 0($11)    " );            \
+    asm( "addu   $12, $12, $14  " );            \
+    asm( "addi   $11, $11, 4    " );
+
+#define MULADDC_STOP                            \
+    asm( "sw     $12, %0        " : "=m" (c));  \
+    asm( "sw     $11, %0        " : "=m" (d));  \
+    asm( "sw     $10, %0        " : "=m" (s) :: \
+    "$9", "$10", "$11", "$12", "$13", "$14", "$15" );
+
+#endif /* MIPS */
+#endif /* GNUC */
+
+#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
+
+#define MULADDC_INIT                            \
+    __asm   mov     esi, s                      \
+    __asm   mov     edi, d                      \
+    __asm   mov     ecx, c                      \
+    __asm   mov     ebx, b
+
+#define MULADDC_CORE                            \
+    __asm   lodsd                               \
+    __asm   mul     ebx                         \
+    __asm   add     eax, ecx                    \
+    __asm   adc     edx, 0                      \
+    __asm   add     eax, [edi]                  \
+    __asm   adc     edx, 0                      \
+    __asm   mov     ecx, edx                    \
+    __asm   stosd
+
+#if defined(POLARSSL_HAVE_SSE2)
+
+#define EMIT __asm _emit
+
+#define MULADDC_HUIT                            \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0xC9             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0xC3             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x1F             \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCB             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x16             \
+    EMIT 0x0F  EMIT 0xF4  EMIT 0xD0             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x66  EMIT 0x04  \
+    EMIT 0x0F  EMIT 0xF4  EMIT 0xE0             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x76  EMIT 0x08  \
+    EMIT 0x0F  EMIT 0xF4  EMIT 0xF0             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x7E  EMIT 0x0C  \
+    EMIT 0x0F  EMIT 0xF4  EMIT 0xF8             \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCA             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x5F  EMIT 0x04  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xDC             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x08  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xEE             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x67  EMIT 0x0C  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xFC             \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0x0F             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x56  EMIT 0x10  \
+    EMIT 0x0F  EMIT 0xF4  EMIT 0xD0             \
+    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x66  EMIT 0x14  \
+    EMIT 0x0F  EMIT 0xF4  EMIT 0xE0             \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCB             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x76  EMIT 0x18  \
+    EMIT 0x0F  EMIT 0xF4  EMIT 0xF0             \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x04  \
+    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x5E  EMIT 0x1C  \
+    EMIT 0x0F  EMIT 0xF4  EMIT 0xD8             \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCD             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x10  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xD5             \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x08  \
+    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCF             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x14  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xE5             \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x0C  \
+    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCA             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x18  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xF5             \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x10  \
+    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCC             \
+    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x1C  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xDD             \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x14  \
+    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCE             \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x18  \
+    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
+    EMIT 0x0F  EMIT 0xD4  EMIT 0xCB             \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x1C  \
+    EMIT 0x83  EMIT 0xC7  EMIT 0x20             \
+    EMIT 0x83  EMIT 0xC6  EMIT 0x20             \
+    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
+    EMIT 0x0F  EMIT 0x7E  EMIT 0xC9
+
+#define MULADDC_STOP                            \
+    EMIT 0x0F  EMIT 0x77                        \
+    __asm   mov     c, ecx                      \
+    __asm   mov     d, edi                      \
+    __asm   mov     s, esi                      \
+
+#else
+
+#define MULADDC_STOP                            \
+    __asm   mov     c, ecx                      \
+    __asm   mov     d, edi                      \
+    __asm   mov     s, esi                      \
+
+#endif /* SSE2 */
+#endif /* MSVC */
+
+#endif /* POLARSSL_HAVE_ASM */
+
+#if !defined(MULADDC_CORE)
+#if defined(POLARSSL_HAVE_LONGLONG)
+
+#define MULADDC_INIT                    \
+{                                       \
+    t_dbl r;                            \
+    t_int r0, r1;
+
+#define MULADDC_CORE                    \
+    r   = *(s++) * (t_dbl) b;           \
+    r0  = r;                            \
+    r1  = r >> biL;                     \
+    r0 += c;  r1 += (r0 <  c);          \
+    r0 += *d; r1 += (r0 < *d);          \
+    c = r1; *(d++) = r0;
+
+#define MULADDC_STOP                    \
+}
+
+#else
+#define MULADDC_INIT                    \
+{                                       \
+    t_int s0, s1, b0, b1;               \
+    t_int r0, r1, rx, ry;               \
+    b0 = ( b << biH ) >> biH;           \
+    b1 = ( b >> biH );
+
+#define MULADDC_CORE                    \
+    s0 = ( *s << biH ) >> biH;          \
+    s1 = ( *s >> biH ); s++;            \
+    rx = s0 * b1; r0 = s0 * b0;         \
+    ry = s1 * b0; r1 = s1 * b1;         \
+    r1 += ( rx >> biH );                \
+    r1 += ( ry >> biH );                \
+    rx <<= biH; ry <<= biH;             \
+    r0 += rx; r1 += (r0 < rx);          \
+    r0 += ry; r1 += (r0 < ry);          \
+    r0 +=  c; r1 += (r0 <  c);          \
+    r0 += *d; r1 += (r0 < *d);          \
+    c = r1; *(d++) = r0;
+
+#define MULADDC_STOP                    \
+}
+
+#endif /* C (generic)  */
+#endif /* C (longlong) */
+
+#endif /* bn_mul.h */
diff --git a/ap/app/zte_comm/zte_locknet/inc/zctrm_ln_config.h b/ap/app/zte_comm/zte_locknet/inc/zctrm_ln_config.h
new file mode 100755
index 0000000..b0cb2ae
--- /dev/null
+++ b/ap/app/zte_comm/zte_locknet/inc/zctrm_ln_config.h
@@ -0,0 +1,338 @@
+/**
+ * \file config.h
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * This set of compile-time options may be used to enable
+ * or disable features selectively, and reduce the global
+ * memory footprint.
+ */
+#ifndef POLARSSL_CONFIG_H
+#define POLARSSL_CONFIG_H
+
+//#include "oss_api.h"
+
+#ifndef _CRT_SECURE_NO_DEPRECATE
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+
+/*
+ * Uncomment if native integers are 8-bit wide.
+ *
+#define POLARSSL_HAVE_INT8
+ */
+
+/*
+ * Uncomment if native integers are 16-bit wide.
+ *
+#define POLARSSL_HAVE_INT16
+ */
+
+/*
+ * Uncomment if the compiler supports long long.
+ *
+#define POLARSSL_HAVE_LONGLONG
+ */
+
+/*
+ * Uncomment to enable the use of assembly code.
+ *
+ * Requires support for asm() in compiler.
+ *
+ * Used in:
+ *      library/timing.c
+ *      library/padlock.c
+ *      include/polarssl/bn_mul.h
+ *
+ */
+#define POLARSSL_HAVE_ASM
+
+/*
+ * Uncomment if the CPU supports SSE2 (IA-32 specific).
+ *
+#define POLARSSL_HAVE_SSE2
+ */
+
+/*
+ * Enable all SSL/TLS debugging messages.
+ */
+#define POLARSSL_DEBUG_MSG
+
+/*
+ * Enable the checkup functions (*_self_test).
+ */
+#define POLARSSL_SELF_TEST
+
+/*
+ * Enable run-time version information functions
+ */
+#define POLARSSL_VERSION_C
+
+/*
+ * Enable the prime-number generation code.
+ */
+#define POLARSSL_GENPRIME
+
+/*
+ * Uncomment this macro to store the AES tables in ROM.
+ *
+#define POLARSSL_AES_ROM_TABLES
+ */
+
+/*
+ * Module:  library/aes.c
+ * Caller:  library/ssl_tls.c
+ *
+ * This module enables the following ciphersuites:
+ *      SSL_RSA_AES_128_SHA
+ *      SSL_RSA_AES_256_SHA
+ *      SSL_EDH_RSA_AES_256_SHA
+ */
+#define POLARSSL_AES_C
+
+/*
+ * Module:  library/arc4.c
+ * Caller:  library/ssl_tls.c
+ *
+ * This module enables the following ciphersuites:
+ *      SSL_RSA_RC4_128_MD5
+ *      SSL_RSA_RC4_128_SHA
+ */
+#define POLARSSL_ARC4_C
+
+/*
+ * Module:  library/base64.c
+ * Caller:  library/x509parse.c
+ *
+ * This module is required for X.509 support.
+ */
+#define POLARSSL_BASE64_C
+
+/*
+ * Module:  library/bignum.c
+ * Caller:  library/dhm.c
+ *          library/rsa.c
+ *          library/ssl_tls.c
+ *          library/x509parse.c
+ *
+ * This module is required for RSA and DHM support.
+ */
+#define POLARSSL_BIGNUM_C
+
+/*
+ * Module:  library/camellia.c
+ * Caller:  library/ssl_tls.c
+ *
+ * This module enabled the following cipher suites:
+ *      SSL_RSA_CAMELLIA_128_SHA
+ *      SSL_RSA_CAMELLIA_256_SHA
+ *      SSL_EDH_RSA_CAMELLIA_256_SHA
+ */
+#define POLARSSL_CAMELLIA_C
+
+/*
+ * Module:  library/certs.c
+ * Caller:
+ *
+ * This module is used for testing (ssl_client/server).
+ */
+#define POLARSSL_CERTS_C
+
+/*
+ * Module:  library/debug.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *          library/ssl_tls.c
+ *
+ * This module provides debugging functions.
+ */
+#define POLARSSL_DEBUG_C
+
+/*
+ * Module:  library/des.c
+ * Caller:  library/ssl_tls.c
+ *
+ * This module enables the following ciphersuites:
+ *      SSL_RSA_DES_168_SHA
+ *      SSL_EDH_RSA_DES_168_SHA
+ */
+#define POLARSSL_DES_C
+
+/*
+ * Module:  library/dhm.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *
+ * This module enables the following ciphersuites:
+ *      SSL_EDH_RSA_DES_168_SHA
+ *      SSL_EDH_RSA_AES_256_SHA
+ *      SSL_EDH_RSA_CAMELLIA_256_SHA
+ */
+#define POLARSSL_DHM_C
+
+/*
+ * Module:  library/havege.c
+ * Caller:
+ *
+ * This module enables the HAVEGE random number generator.
+ */
+#define POLARSSL_HAVEGE_C
+
+/*
+ * Module:  library/md2.c
+ * Caller:  library/x509parse.c
+ *
+ * Uncomment to enable support for (rare) MD2-signed X.509 certs.
+ *
+#define POLARSSL_MD2_C
+ */
+
+/*
+ * Module:  library/md4.c
+ * Caller:  library/x509parse.c
+ *
+ * Uncomment to enable support for (rare) MD4-signed X.509 certs.
+ *
+#define POLARSSL_MD4_C
+ */
+
+/*
+ * Module:  library/md5.c
+ * Caller:  library/ssl_tls.c
+ *          library/x509parse.c
+ *
+ * This module is required for SSL/TLS and X.509.
+ */
+#define POLARSSL_MD5_C
+
+/*
+ * Module:  library/net.c
+ * Caller:
+ *
+ * This module provides TCP/IP networking routines.
+ */
+#define POLARSSL_NET_C
+
+/*
+ * Module:  library/padlock.c
+ * Caller:  library/aes.c
+ *
+ * This modules adds support for the VIA PadLock on x86.
+ */
+#define POLARSSL_PADLOCK_C
+
+/*
+ * Module:  library/rsa.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *          library/ssl_tls.c
+ *          library/x509.c
+ *
+ * This module is required for SSL/TLS and MD5-signed certificates.
+ */
+#define POLARSSL_RSA_C
+
+/*
+ * Module:  library/sha1.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *          library/ssl_tls.c
+ *          library/x509parse.c
+ *
+ * This module is required for SSL/TLS and SHA1-signed certificates.
+ */
+#define POLARSSL_SHA1_C
+
+/*
+ * Module:  library/sha2.c
+ * Caller:
+ *
+ * This module adds support for SHA-224 and SHA-256.
+ */
+#define POLARSSL_SHA2_C
+
+/*
+ * Module:  library/sha4.c
+ * Caller:
+ *
+ * This module adds support for SHA-384 and SHA-512.
+ */
+#define POLARSSL_SHA4_C
+
+/*
+ * Module:  library/ssl_cli.c
+ * Caller:
+ *
+ * This module is required for SSL/TLS client support.
+ */
+#define POLARSSL_SSL_CLI_C
+
+/*
+ * Module:  library/ssl_srv.c
+ * Caller:
+ *
+ * This module is required for SSL/TLS server support.
+ */
+#define POLARSSL_SSL_SRV_C
+
+/*
+ * Module:  library/ssl_tls.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *
+ * This module is required for SSL/TLS.
+ */
+#define POLARSSL_SSL_TLS_C
+
+/*
+ * Module:  library/timing.c
+ * Caller:  library/havege.c
+ *
+ * This module is used by the HAVEGE random number generator.
+ */
+#define POLARSSL_TIMING_C
+
+/*
+ * Module:  library/x509parse.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *          library/ssl_tls.c
+ *
+ * This module is required for X.509 certificate parsing.
+ */
+#define POLARSSL_X509_PARSE_C
+
+/*
+ * Module:  library/x509_write.c
+ * Caller:
+ *
+ * This module is required for X.509 certificate writing.
+ */
+#define POLARSSL_X509_WRITE_C
+
+/*
+ * Module:  library/xtea.c
+ * Caller:
+ */
+#define POLARSSL_XTEA_C
+
+#endif /* config.h */
diff --git a/ap/app/zte_comm/zte_locknet/inc/zctrm_ln_md5.h b/ap/app/zte_comm/zte_locknet/inc/zctrm_ln_md5.h
new file mode 100755
index 0000000..249e878
--- /dev/null
+++ b/ap/app/zte_comm/zte_locknet/inc/zctrm_ln_md5.h
@@ -0,0 +1,61 @@
+/*
+ ***********************************************************************
+ ** 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 ZCTRM_LN_MD5_H
+#define ZCTRM_LN_MD5_H
+
+typedef unsigned long u32_t;
+
+#ifndef SMEMCPY
+#define SMEMCPY(dst,src,len)            memcpy(dst,src,len)
+#endif
+
+/* Data structure for MD5 (Message-Digest) computation */
+typedef struct {
+  u32_t i[2];               /* number of _bits_ handled mod 2^64 */
+  u32_t buf[4];             /* scratch buffer */
+  unsigned char in[64];     /* input buffer */
+  unsigned char digest[16]; /* actual digest after md5_final call */
+} md5_ctx;
+
+void md5_init(md5_ctx *ctx);
+void md5_update(md5_ctx *ctx, unsigned char *buf, unsigned int len);
+void md5_final(unsigned char hash[], md5_ctx *ctx);
+
+#endif /* ZCTRM_LN_MD5_H */
diff --git a/ap/app/zte_comm/zte_locknet/inc/zctrm_ln_rsa.h b/ap/app/zte_comm/zte_locknet/inc/zctrm_ln_rsa.h
new file mode 100755
index 0000000..3093f7d
--- /dev/null
+++ b/ap/app/zte_comm/zte_locknet/inc/zctrm_ln_rsa.h
@@ -0,0 +1,355 @@
+/**
+ * \file rsa.h
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef POLARSSL_RSA_H
+#define POLARSSL_RSA_H
+
+#include "zctrm_ln_bignum.h"
+#include "at_netdog.h"
+
+/*
+ * RSA Error codes
+ */
+#define POLARSSL_ERR_RSA_BAD_INPUT_DATA                    -0x0400
+#define POLARSSL_ERR_RSA_INVALID_PADDING                   -0x0410
+#define POLARSSL_ERR_RSA_KEY_GEN_FAILED                    -0x0420
+#define POLARSSL_ERR_RSA_KEY_CHECK_FAILED                  -0x0430
+#define POLARSSL_ERR_RSA_PUBLIC_FAILED                     -0x0440
+#define POLARSSL_ERR_RSA_PRIVATE_FAILED                    -0x0450
+#define POLARSSL_ERR_RSA_VERIFY_FAILED                     -0x0460
+#define POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE                  -0x0470
+#define POLARSSL_ERR_RSA_RNG_FAILED                        -0x0480
+
+/*
+ * PKCS#1 constants
+ */
+#define SIG_RSA_RAW     0
+#define SIG_RSA_MD2     2
+#define SIG_RSA_MD4     3
+#define SIG_RSA_MD5     4
+#define SIG_RSA_SHA1	5
+#define SIG_RSA_SHA224	14
+#define SIG_RSA_SHA256	11
+#define	SIG_RSA_SHA384	12
+#define SIG_RSA_SHA512	13
+
+#define RSA_PUBLIC      0
+#define RSA_PRIVATE     1
+
+#define RSA_PKCS_V15    0
+#define RSA_PKCS_V21    1
+
+#define RSA_SIGN        1
+#define RSA_CRYPT       2
+
+#define ASN1_STR_CONSTRUCTED_SEQUENCE	"\x30"
+#define ASN1_STR_NULL			        "\x05"
+#define ASN1_STR_OID			        "\x06"
+#define ASN1_STR_OCTET_STRING		    "\x04"
+
+#define OID_DIGEST_ALG_MDX	        "\x2A\x86\x48\x86\xF7\x0D\x02\x00"
+#define OID_HASH_ALG_SHA1	        "\x2b\x0e\x03\x02\x1a"
+#define OID_HASH_ALG_SHA2X	        "\x60\x86\x48\x01\x65\x03\x04\x02\x00"
+
+#define OID_ISO_MEMBER_BODIES	    "\x2a"
+#define OID_ISO_IDENTIFIED_ORG	    "\x2b"
+
+/*
+ * ISO Member bodies OID parts
+ */
+#define OID_COUNTRY_US		        "\x86\x48"
+#define OID_RSA_DATA_SECURITY	    "\x86\xf7\x0d"
+
+/*
+ * ISO Identified organization OID parts
+ */
+#define OID_OIW_SECSIG_SHA1	        "\x0e\x03\x02\x1a"
+
+/*
+ * DigestInfo ::= SEQUENCE {
+ *   digestAlgorithm DigestAlgorithmIdentifier,
+ *   digest Digest }
+ *
+ * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
+ *
+ * Digest ::= OCTET STRING
+ */
+#define ASN1_HASH_MDX					        \
+(							                    \
+    ASN1_STR_CONSTRUCTED_SEQUENCE "\x20"		\
+      ASN1_STR_CONSTRUCTED_SEQUENCE "\x0C"		\
+        ASN1_STR_OID "\x08"				        \
+	  OID_DIGEST_ALG_MDX				        \
+	ASN1_STR_NULL "\x00"				        \
+      ASN1_STR_OCTET_STRING "\x10"			    \
+)
+
+#define ASN1_HASH_SHA1					        \
+    ASN1_STR_CONSTRUCTED_SEQUENCE "\x21"		\
+      ASN1_STR_CONSTRUCTED_SEQUENCE "\x09"		\
+        ASN1_STR_OID "\x05"				        \
+	  OID_HASH_ALG_SHA1				            \
+        ASN1_STR_NULL "\x00"				    \
+      ASN1_STR_OCTET_STRING "\x14"
+
+#define ASN1_HASH_SHA2X					        \
+    ASN1_STR_CONSTRUCTED_SEQUENCE "\x11"		\
+      ASN1_STR_CONSTRUCTED_SEQUENCE "\x0d"		\
+        ASN1_STR_OID "\x09"				        \
+	  OID_HASH_ALG_SHA2X				        \
+        ASN1_STR_NULL "\x00"				    \
+      ASN1_STR_OCTET_STRING "\x00"
+
+/**
+ * \brief          RSA context structure
+ */
+typedef struct
+{
+    int ver;                    /*!<  always 0          */
+    int len;                    /*!<  size(N) in chars  */
+
+    mpi N;                      /*!<  public modulus    */
+    mpi E;                      /*!<  public exponent   */
+
+    mpi D;                      /*!<  private exponent  */
+    mpi P;                      /*!<  1st prime factor  */
+    mpi Q;                      /*!<  2nd prime factor  */
+    mpi DP;                     /*!<  D % (P - 1)       */
+    mpi DQ;                     /*!<  D % (Q - 1)       */
+    mpi QP;                     /*!<  1 / (Q % P)       */
+
+    mpi RN;                     /*!<  cached R^2 mod N  */
+    mpi RP;                     /*!<  cached R^2 mod P  */
+    mpi RQ;                     /*!<  cached R^2 mod Q  */
+
+    int padding;                /*!<  1.5 or OAEP/PSS   */
+    int hash_id;                /*!<  hash identifier   */
+}
+rsa_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          Initialize an RSA context
+ *
+ * \param ctx      RSA context to be initialized
+ * \param padding  RSA_PKCS_V15 or RSA_PKCS_V21
+ * \param hash_id  RSA_PKCS_V21 hash identifier
+ *
+ * \note           The hash_id parameter is actually ignored
+ *                 when using RSA_PKCS_V15 padding.
+ *
+ * \note           Currently, RSA_PKCS_V21 padding
+ *                 is not supported.
+ */
+void rsa_init( rsa_context *ctx,
+               int padding,
+               int hash_id);
+
+/**
+ * \brief          Generate an RSA keypair
+ *
+ * \param ctx      RSA context that will hold the key
+ * \param f_rng    RNG function
+ * \param p_rng    RNG parameter
+ * \param nbits    size of the public key in bits
+ * \param exponent public exponent (e.g., 65537)
+ *
+ * \note           rsa_init() must be called beforehand to setup
+ *                 the RSA context.
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ */
+int rsa_gen_key( rsa_context *ctx,
+                 int (*f_rng)(void *),
+                 void *p_rng,
+                 int nbits, int exponent );
+
+/**
+ * \brief          Check a public RSA key
+ *
+ * \param ctx      RSA context to be checked
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ */
+int rsa_check_pubkey( const rsa_context *ctx );
+
+/**
+ * \brief          Check a private RSA key
+ *
+ * \param ctx      RSA context to be checked
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ */
+int rsa_check_privkey( const rsa_context *ctx );
+
+/**
+ * \brief          Do an RSA public key operation
+ *
+ * \param ctx      RSA context
+ * \param input    input buffer
+ * \param output   output buffer
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note           This function does NOT take care of message
+ *                 padding. Also, be sure to set input[0] = 0 or assure that
+ *                 input is smaller than N.
+ *
+ * \note           The input and output buffers must be large
+ *                 enough (eg. 128 bytes if RSA-1024 is used).
+ */
+int rsa_public( rsa_context *ctx,
+                const unsigned char *input,
+                unsigned char *output );
+
+/**
+ * \brief          Do an RSA private key operation
+ *
+ * \param ctx      RSA context
+ * \param input    input buffer
+ * \param output   output buffer
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note           The input and output buffers must be large
+ *                 enough (eg. 128 bytes if RSA-1024 is used).
+ */
+int rsa_private( rsa_context *ctx,
+                 const unsigned char *input,
+                 unsigned char *output );
+
+/**
+ * \brief          Add the message padding, then do an RSA operation
+ *
+ * \param ctx      RSA context
+ * \param f_rng    RNG function
+ * \param p_rng    RNG parameter
+ * \param mode     RSA_PUBLIC or RSA_PRIVATE
+ * \param ilen     contains the plaintext length
+ * \param input    buffer holding the data to be encrypted
+ * \param output   buffer that will hold the ciphertext
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note           The output buffer must be as large as the size
+ *                 of ctx->N (eg. 128 bytes if RSA-1024 is used).
+ */
+int rsa_pkcs1_encrypt( rsa_context *ctx,
+                       int (*f_rng)(void *),
+                       void *p_rng,
+                       int mode, int  ilen,
+                       const unsigned char *input,
+                       unsigned char *output );
+
+/**
+ * \brief          Do an RSA operation, then remove the message padding
+ *
+ * \param ctx      RSA context
+ * \param mode     RSA_PUBLIC or RSA_PRIVATE
+ * \param input    buffer holding the encrypted data
+ * \param output   buffer that will hold the plaintext
+ * \param olen     will contain the plaintext length
+ * \param output_max_len	maximum length of the output buffer
+ *
+ * \return         0 if successful, or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note           The output buffer must be as large as the size
+ *                 of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise
+ *                 an error is thrown.
+ */
+int rsa_pkcs1_decrypt( rsa_context *ctx,
+                       int mode, int *olen,
+                       const unsigned char *input,
+                       unsigned char *output,
+		               int output_max_len );
+
+/**
+ * \brief          Do a private RSA to sign a message digest
+ *
+ * \param ctx      RSA context
+ * \param mode     RSA_PUBLIC or RSA_PRIVATE
+ * \param hash_id  SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512}
+ * \param hashlen  message digest length (for SIG_RSA_RAW only)
+ * \param hash     buffer holding the message digest
+ * \param sig      buffer that will hold the ciphertext
+ *
+ * \return         0 if the signing operation was successful,
+ *                 or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note           The "sig" buffer must be as large as the size
+ *                 of ctx->N (eg. 128 bytes if RSA-1024 is used).
+ */
+int rsa_pkcs1_sign( rsa_context *ctx,
+                    int mode,
+                    int hash_id,
+                    int hashlen,
+                    const unsigned char *hash,
+                    unsigned char *sig );
+
+/**
+ * \brief          Do a public RSA and check the message digest
+ *
+ * \param ctx      points to an RSA public key
+ * \param mode     RSA_PUBLIC or RSA_PRIVATE
+ * \param hash_id  SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512}
+ * \param hashlen  message digest length (for SIG_RSA_RAW only)
+ * \param hash     buffer holding the message digest
+ * \param sig      buffer holding the ciphertext
+ *
+ * \return         0 if the verify operation was successful,
+ *                 or an POLARSSL_ERR_RSA_XXX error code
+ *
+ * \note           The "sig" buffer must be as large as the size
+ *                 of ctx->N (eg. 128 bytes if RSA-1024 is used).
+ */
+int rsa_pkcs1_verify( rsa_context *ctx,
+                      int mode,
+                      int hash_id,
+                      int hashlen,
+                      const unsigned char *hash,
+                      unsigned char *sig );
+
+/**
+ * \brief          Free the components of an RSA key
+ *
+ * \param ctx      RSA Context to free
+ */
+void rsa_free( rsa_context *ctx );
+
+/**
+ * \brief          Checkup routine
+ *
+ * \return         0 if successful, or 1 if the test failed
+ */
+int rsa_self_test( int verbose );
+
+int rsa_private_decrypt(const unsigned char *rsa_ciphertext, unsigned char *rsa_decrypted);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* rsa.h */
diff --git a/ap/app/zte_comm/zte_locknet/inc/zctrm_locknet.h b/ap/app/zte_comm/zte_locknet/inc/zctrm_locknet.h
new file mode 100755
index 0000000..9761bf6
--- /dev/null
+++ b/ap/app/zte_comm/zte_locknet/inc/zctrm_locknet.h
@@ -0,0 +1,177 @@
+#ifndef __ZCTRM_LOCKNET_H__

+#define __ZCTRM_LOCKNET_H__

+

+#include "at_context.h"

+#include <sys/ioctl.h>

+#include "libcpnv.h"

+#include "RONvConfig.h"

+

+#define EFUSE_IOC_MAGIC     'E'

+

+#define EFUSE_GET_DATA			_IOWR(EFUSE_IOC_MAGIC, 1, char *)

+

+

+#define LOCKNET_KEY_LEN 16

+#define ZCTRM_LOCKNET_AT_LEN 64

+#define KEY_LEN 128

+

+#define IDENTIFIER_GID1 28478

+#define IDENTIFIER_GID2 28479

+

+#define LOCKNET_ITEM_NUM 6

+#define LOCKNET_FIRST_NUM 42

+#define LOCKNET_MAX_NUM 50

+#define LOCKNET_MAX_AT_LEN 560

+

+#define EXT_SUCCESS   0

+#define EXT_ERROR   -1

+

+// 2 Bytes

+#define USED_GID_LEN 4

+#define MAX_AMT_AT_LEN 1024

+#define MAX_RETRY_TIMES 10

+#define LIST_MCCMNC_LEN 4

+#define LIST_IMSI_LEN 2

+#define LIST_GID_LEN 256

+#define LIST_LEN (LIST_MCCMNC_LEN*2+LIST_IMSI_LEN*2+LIST_GID_LEN*2)

+#define MAX_IMSI_LEN 32

+#define AT_STR_LEN 64

+//lock state

+#define AMT_LOCKNET_BASE OS_FLASH_ROW_OFFSET_FROM_NV//0x000D0000

+#define AMT_LOCKNET_TIMES (AMT_LOCKNET_BASE + 0x40)

+#define AMT_LOCKNET_KEY (AMT_LOCKNET_BASE + 0x80)

+#define AMT_LOCKNET_USRKEY (AMT_LOCKNET_BASE + 0x100)

+#define AMT_LOCKNET_SIGN (AMT_LOCKNET_BASE + 0x120)

+#define AMT_LOCKNET_LIST (AMT_LOCKNET_BASE + 0x1A0)

+

+/*Êý¾Ý½á¹¹¶¨ÒåÇø*/

+typedef struct

+{

+	unsigned int pubKeyRsaE[32];

+	unsigned int pubKeyRsaN[32];

+	unsigned int secureFlag;

+	unsigned int pubKeyHash[4];

+	unsigned int secureDevId[3];

+}T_ZDrvEfuse_Secure;

+

+

+typedef enum

+{

+    ENCRYPT_INITING = 0,

+    ENCRYPT_ERROR, 

+    ENCRYPT_LOCK,

+    ENCRYPT_UNLOCK_CORRECT,

+}T_zAt_SecStatue;

+

+typedef struct

+{

+    UINT8 mcc[LIST_MCCMNC_LEN]; 

+    UINT8 mnc[LIST_MCCMNC_LEN]; 

+    UINT8 imsi6[LIST_IMSI_LEN]; 

+    UINT8 imsi7[LIST_IMSI_LEN]; 

+    UINT8 gid1[LIST_GID_LEN]; 

+    UINT8 gid2[LIST_GID_LEN]; 

+}T_zCtrm_LockListPara;

+

+typedef struct

+{

+	UINT8  cmd[2];

+    UINT8  code[32];

+} T_zAt_LockListAuthRes;

+

+typedef enum

+{

+    PARA_MCC = 0,    

+	PARA_MNC,

+	PARA_IMSI6,

+	PARA_IMSI7,

+    PARA_GID1,

+    PARA_GID2,

+}T_zCtrm_LockPara;

+

+

+typedef enum

+{

+    LOCKFLAG_ERROR = 0,    

+	ALREADY_UNLOCKED,

+	LOCKED,

+	NEVER_LOCKED = 0xFFFFFFFF,

+}T_zCtrm_LockLevel;

+

+typedef enum

+{

+    NO_ACTION = 0,    

+    NET_LOCK, 

+    SIM_LOCK, 

+    NET_SIM_LOCK, 

+    

+}T_zCtrm_SecItems;

+

+typedef enum

+{

+    RESULT_ERROR = 0,//´íÎó

+    RESULT_LOCKED,//²»ÔÊÐíËÑÍø

+    RESULT_UNLOCKED,//ÔÊÐíËÑÍø

+}T_zCtrm_RESULT;

+

+typedef enum

+{

+    READ_ERROR=0,

+    LOCKKEY_ISNULL,

+    READ_SUCCESS,

+}T_zCtrm_ReadResult;

+

+

+typedef struct

+{

+    UINT16 cardMode;

+    UINT16 mncLen;

+    UINT32 fileLen;

+    UINT8 simImsi[MAX_IMSI_LEN];

+}T_zCtrm_SIMPara;

+

+typedef enum

+{

+    CARDMODE_UNKNOW = 0,

+    CARDMODE_SIM,

+    CARDMODE_USIM,

+}T_zCtrm_SimType;

+

+typedef enum

+{

+    GET_NONE = 0,

+    GET_GID1LEN,

+    GET_GID1,

+    GET_GID2LEN,

+    GET_GID2,

+    GET_MNCLEN

+}T_zCtrm_CrsmReq;

+

+/**

+ * @brief ËøÍøÏìÓ¦ÏûϢͨÓýṹÌ壬¶ÔÓ¦ÏûÏ¢MSG_CMD_LOCKNET_AUTH_RSP/MSG_CMD_LOCKNET_UNLOCK_RSP

+ * @param result ½á¹ûÂë AT_RSP_OK/AT_RSP_ERR

+ * @param errcode Èç¹û¼øÈ¨Ê§°Ü£¬·µ»Ø´íÎóÂë

+ */

+typedef struct

+{

+	int result;

+	char errcode[8];

+}AT_LOCKNET_RSP_INFO;

+

+int zCtrm_LocknetAuthProc(MSG_BUF *msg);

+int zCtrm_LocknetListSet(MSG_BUF *msg);

+int zCtrm_LocknetKeyProc(MSG_BUF *msg);

+int zCtrm_LocknetAmtStatus(MSG_BUF *msg);

+int zCtrm_LocknetDigestGet(MSG_BUF *msg);

+int zCtrm_LocknetSignSet(MSG_BUF *msg);

+int zCtrm_LocknetLevel(MSG_BUF *msg);

+int zCtrm_LocknetListGetProc(MSG_BUF *msg);

+int zCtrm_makeLocknetAuth(MSG_BUF *msg);

+int zCtrm_LocknetUnlockTimes(MSG_BUF *msg);

+int zCtrm_LocknetStatus(MSG_BUF *msg);

+int zCtrm_LocknetUnlock(MSG_BUF *msg);

+int zCtrm_makeLocknetAuth(MSG_BUF *msg);

+/*Íⲿº¯Êý,½Ó¿Ú*/

+extern void zDrvEfuse_GetSecureMsg(T_ZDrvEfuse_Secure *secure);

+

+#endif

diff --git a/ap/app/zte_comm/zte_locknet/src/zctrm_ln_bignum.c b/ap/app/zte_comm/zte_locknet/src/zctrm_ln_bignum.c
new file mode 100755
index 0000000..2cfc932
--- /dev/null
+++ b/ap/app/zte_comm/zte_locknet/src/zctrm_ln_bignum.c
@@ -0,0 +1,2043 @@
+/*
+ *  Multi-precision integer library
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  This MPI implementation is based on:
+ *
+ *  http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
+ *  http://www.stillhq.com/extracted/gnupg-api/mpi/
+ *  http://math.libtomcrypt.com/files/tommath.pdf
+ */
+
+#include "zctrm_ln_config.h"
+
+#if defined(POLARSSL_BIGNUM_C)
+
+#include "zctrm_ln_bignum.h"
+#include "zctrm_ln_bnmul.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#define ciL    ((int) sizeof(t_int))    /* chars in limb  */
+#define biL    (ciL << 3)               /* bits  in limb  */
+#define biH    (ciL << 2)               /* half limb size */
+
+/*
+ * Convert between bits/chars and number of limbs
+ */
+#define BITS_TO_LIMBS(i)  (((i) + biL - 1) / biL)
+#define CHARS_TO_LIMBS(i) (((i) + ciL - 1) / ciL)
+
+/*
+ * Initialize one or more mpi
+ */
+void mpi_init( mpi *X, ... )
+{
+    va_list args;
+
+    va_start( args, X );
+
+    while( X != NULL )
+    {
+        X->s = 1;
+        X->n = 0;
+        X->p = NULL;
+
+        X = va_arg( args, mpi* );
+    }
+
+    va_end( args );
+}
+
+/*
+ * Unallocate one or more mpi
+ */
+void mpi_free( mpi *X, ... )
+{
+    va_list args;
+
+    va_start( args, X );
+
+    while( X != NULL )
+    {
+        if( X->p != NULL )
+        {
+            memset( X->p, 0, X->n * ciL );
+            free( X->p );
+        }
+
+        X->s = 1;
+        X->n = 0;
+        X->p = NULL;
+
+        X = va_arg( args, mpi* );
+    }
+
+    va_end( args );
+}
+
+/*
+ * Enlarge to the specified number of limbs
+ */
+int mpi_grow( mpi *X, int nblimbs )
+{
+    t_int *p;
+
+    if( X->n < nblimbs )
+    {
+        if( ( p = (t_int *) malloc( nblimbs * ciL ) ) == NULL )
+            return( 1 );
+
+        memset( p, 0, nblimbs * ciL );
+
+        if( X->p != NULL )
+        {
+            memcpy( p, X->p, X->n * ciL );
+            memset( X->p, 0, X->n * ciL );
+            free( X->p );
+        }
+
+        X->n = nblimbs;
+        X->p = p;
+    }
+
+    return( 0 );
+}
+
+/*
+ * Copy the contents of Y into X
+ */
+int mpi_copy( mpi *X, const mpi *Y )
+{
+    int ret, i;
+
+    if( X == Y )
+        return( 0 );
+
+    for( i = Y->n - 1; i > 0; i-- )
+        if( Y->p[i] != 0 )
+            break;
+    i++;
+
+    X->s = Y->s;
+
+    MPI_CHK( mpi_grow( X, i ) );
+
+    memset( X->p, 0, X->n * ciL );
+    memcpy( X->p, Y->p, i * ciL );
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Swap the contents of X and Y
+ */
+void mpi_swap( mpi *X, mpi *Y )
+{
+    mpi T;
+
+    memcpy( &T,  X, sizeof( mpi ) );
+    memcpy(  X,  Y, sizeof( mpi ) );
+    memcpy(  Y, &T, sizeof( mpi ) );
+}
+
+/*
+ * Set value from integer
+ */
+int mpi_lset( mpi *X, int z )
+{
+    int ret;
+
+    MPI_CHK( mpi_grow( X, 1 ) );
+    memset( X->p, 0, X->n * ciL );
+
+    X->p[0] = ( z < 0 ) ? -z : z;
+    X->s    = ( z < 0 ) ? -1 : 1;
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Return the number of least significant bits
+ */
+int mpi_lsb( const mpi *X )
+{
+    int i, j, count = 0;
+
+    for( i = 0; i < X->n; i++ )
+        for( j = 0; j < (int) biL; j++, count++ )
+            if( ( ( X->p[i] >> j ) & 1 ) != 0 )
+                return( count );
+
+    return( 0 );
+}
+
+/*
+ * Return the number of most significant bits
+ */
+int mpi_msb( const mpi *X )
+{
+    int i, j;
+
+    for( i = X->n - 1; i > 0; i-- )
+        if( X->p[i] != 0 )
+            break;
+
+    for( j = biL - 1; j >= 0; j-- )
+        if( ( ( X->p[i] >> j ) & 1 ) != 0 )
+            break;
+
+    return( ( i * biL ) + j + 1 );
+}
+
+/*
+ * Return the total size in bytes
+ */
+int mpi_size( const mpi *X )
+{
+    return( ( mpi_msb( X ) + 7 ) >> 3 );
+}
+
+/*
+ * Convert an ASCII character to digit value
+ */
+static int mpi_get_digit( t_int *d, int radix, char c )
+{
+    *d = 255;
+
+    if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
+    if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
+    if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
+
+    if( *d >= (t_int) radix )
+        return( POLARSSL_ERR_MPI_INVALID_CHARACTER );
+
+    return( 0 );
+}
+
+/*
+ * Import from an ASCII string
+ */
+int mpi_read_string( mpi *X, int radix, const char *s )
+{
+    int ret, i, j, n, slen;
+    t_int d;
+    mpi T;
+
+    if( radix < 2 || radix > 16 )
+        return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+    mpi_init( &T, NULL );
+
+    slen = strlen( s );
+
+    if( radix == 16 )
+    {
+        n = BITS_TO_LIMBS( slen << 2 );
+
+        MPI_CHK( mpi_grow( X, n ) );
+        MPI_CHK( mpi_lset( X, 0 ) );
+
+        for( i = slen - 1, j = 0; i >= 0; i--, j++ )
+        {
+            if( i == 0 && s[i] == '-' )
+            {
+                X->s = -1;
+                break;
+            }
+
+            MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
+            X->p[j / (2 * ciL)] |= d << ( (j % (2 * ciL)) << 2 );
+        }
+    }
+    else
+    {
+        MPI_CHK( mpi_lset( X, 0 ) );
+
+        for( i = 0; i < slen; i++ )
+        {
+            if( i == 0 && s[i] == '-' )
+            {
+                X->s = -1;
+                continue;
+            }
+
+            MPI_CHK( mpi_get_digit( &d, radix, s[i] ) );
+            MPI_CHK( mpi_mul_int( &T, X, radix ) );
+
+            if( X->s == 1 )
+            {
+                MPI_CHK( mpi_add_int( X, &T, d ) );
+            }
+            else
+            {
+                MPI_CHK( mpi_sub_int( X, &T, d ) );
+            }
+        }
+    }
+
+cleanup:
+
+    mpi_free( &T, NULL );
+
+    return( ret );
+}
+
+/*
+ * Helper to write the digits high-order first
+ */
+static int mpi_write_hlp( mpi *X, int radix, char **p )
+{
+    int ret;
+    t_int r;
+
+    if( radix < 2 || radix > 16 )
+        return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+    MPI_CHK( mpi_mod_int( &r, X, radix ) );
+    MPI_CHK( mpi_div_int( X, NULL, X, radix ) );
+
+    if( mpi_cmp_int( X, 0 ) != 0 )
+        MPI_CHK( mpi_write_hlp( X, radix, p ) );
+
+    if( r < 10 )
+        *(*p)++ = (char)( r + 0x30 );
+    else
+        *(*p)++ = (char)( r + 0x37 );
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Export into an ASCII string
+ */
+int mpi_write_string( const mpi *X, int radix, char *s, int *slen )
+{
+    int ret = 0, n;
+    char *p;
+    mpi T;
+
+    if( radix < 2 || radix > 16 )
+        return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+    n = mpi_msb( X );
+    if( radix >=  4 ) n >>= 1;
+    if( radix >= 16 ) n >>= 1;
+    n += 3;
+
+    if( *slen < n )
+    {
+        *slen = n;
+        return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
+    }
+
+    p = s;
+    mpi_init( &T, NULL );
+
+    if( X->s == -1 )
+        *p++ = '-';
+
+    if( radix == 16 )
+    {
+        int c, i, j, k;
+
+        for( i = X->n - 1, k = 0; i >= 0; i-- )
+        {
+            for( j = ciL - 1; j >= 0; j-- )
+            {
+                c = ( X->p[i] >> (j << 3) ) & 0xFF;
+
+                if( c == 0 && k == 0 && (i + j) != 0 )
+                    continue;
+
+                p += sprintf( p, "%02X", c );
+                k = 1;
+            }
+        }
+    }
+    else
+    {
+        MPI_CHK( mpi_copy( &T, X ) );
+
+        if( T.s == -1 )
+            T.s = 1;
+
+        MPI_CHK( mpi_write_hlp( &T, radix, &p ) );
+    }
+
+    *p++ = '\0';
+    *slen = p - s;
+
+cleanup:
+
+    mpi_free( &T, NULL );
+
+    return( ret );
+}
+#if 0
+/*
+ * Read X from an opened file
+ */
+int mpi_read_file( mpi *X, int radix, FILE *fin )
+{
+    t_int d;
+    int slen;
+    char *p;
+    char s[1024];
+
+    memset( s, 0, sizeof( s ) );
+    if( fgets( s, sizeof( s ) - 1, fin ) == NULL )
+        return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
+
+    slen = strlen( s );
+    if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
+    if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; }
+
+    p = s + slen;
+    while( --p >= s )
+        if( mpi_get_digit( &d, radix, *p ) != 0 )
+            break;
+
+    return( mpi_read_string( X, radix, p + 1 ) );
+}
+
+/*
+ * Write X into an opened file (or stdout if fout == NULL)
+ */
+int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout )
+{
+    int n, ret;
+    size_t slen;
+    size_t plen;
+    char s[2048];
+
+    n = sizeof( s );
+    memset( s, 0, n );
+    n -= 2;
+
+    MPI_CHK( mpi_write_string( X, radix, s, (int *) &n ) );
+
+    if( p == NULL ) p = "";
+
+    plen = strlen( p );
+    slen = strlen( s );
+    s[slen++] = '\r';
+    s[slen++] = '\n';
+
+    if( fout != NULL )
+    {
+        if( fwrite( p, 1, plen, fout ) != plen ||
+            fwrite( s, 1, slen, fout ) != slen )
+            return( POLARSSL_ERR_MPI_FILE_IO_ERROR );
+    }
+    else
+        printf( "%s%s", p, s );
+
+cleanup:
+
+    return( ret );
+}
+#endif
+/*
+ * Import X from unsigned binary data, big endian
+ */
+int mpi_read_binary( mpi *X, const unsigned char *buf, int buflen )
+{
+    int ret, i, j, n;
+
+    for( n = 0; n < buflen; n++ )
+        if( buf[n] != 0 )
+            break;
+
+    MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) );
+    MPI_CHK( mpi_lset( X, 0 ) );
+
+    for( i = buflen - 1, j = 0; i >= n; i--, j++ )
+        X->p[j / ciL] |= ((t_int) buf[i]) << ((j % ciL) << 3);
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Export X into unsigned binary data, big endian
+ */
+int mpi_write_binary( const mpi *X, unsigned char *buf, int buflen )
+{
+    int i, j, n;
+
+    n = mpi_size( X );
+
+    if( buflen < n )
+        return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL );
+
+    memset( buf, 0, buflen );
+
+    for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
+        buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
+
+    return( 0 );
+}
+
+/*
+ * Left-shift: X <<= count
+ */
+int mpi_shift_l( mpi *X, int count )
+{
+    int ret, i, v0, t1;
+    t_int r0 = 0, r1;
+
+    v0 = count / (biL    );
+    t1 = count & (biL - 1);
+
+    i = mpi_msb( X ) + count;
+
+    if( X->n * (int) biL < i )
+        MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) );
+
+    ret = 0;
+
+    /*
+     * shift by count / limb_size
+     */
+    if( v0 > 0 )
+    {
+        for( i = X->n - 1; i >= v0; i-- )
+            X->p[i] = X->p[i - v0];
+
+        for( ; i >= 0; i-- )
+            X->p[i] = 0;
+    }
+
+    /*
+     * shift by count % limb_size
+     */
+    if( t1 > 0 )
+    {
+        for( i = v0; i < X->n; i++ )
+        {
+            r1 = X->p[i] >> (biL - t1);
+            X->p[i] <<= t1;
+            X->p[i] |= r0;
+            r0 = r1;
+        }
+    }
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Right-shift: X >>= count
+ */
+int mpi_shift_r( mpi *X, int count )
+{
+    int i, v0, v1;
+    t_int r0 = 0, r1;
+
+    v0 = count /  biL;
+    v1 = count & (biL - 1);
+
+    /*
+     * shift by count / limb_size
+     */
+    if( v0 > 0 )
+    {
+        for( i = 0; i < X->n - v0; i++ )
+            X->p[i] = X->p[i + v0];
+
+        for( ; i < X->n; i++ )
+            X->p[i] = 0;
+    }
+
+    /*
+     * shift by count % limb_size
+     */
+    if( v1 > 0 )
+    {
+        for( i = X->n - 1; i >= 0; i-- )
+        {
+            r1 = X->p[i] << (biL - v1);
+            X->p[i] >>= v1;
+            X->p[i] |= r0;
+            r0 = r1;
+        }
+    }
+
+    return( 0 );
+}
+
+/*
+ * Compare unsigned values
+ */
+int mpi_cmp_abs( const mpi *X, const mpi *Y )
+{
+    int i, j;
+
+    for( i = X->n - 1; i >= 0; i-- )
+        if( X->p[i] != 0 )
+            break;
+
+    for( j = Y->n - 1; j >= 0; j-- )
+        if( Y->p[j] != 0 )
+            break;
+
+    if( i < 0 && j < 0 )
+        return( 0 );
+
+    if( i > j ) return(  1 );
+    if( j > i ) return( -1 );
+
+    for( ; i >= 0; i-- )
+    {
+        if( X->p[i] > Y->p[i] ) return(  1 );
+        if( X->p[i] < Y->p[i] ) return( -1 );
+    }
+
+    return( 0 );
+}
+
+/*
+ * Compare signed values
+ */
+int mpi_cmp_mpi( const mpi *X, const mpi *Y )
+{
+    int i, j;
+
+    for( i = X->n - 1; i >= 0; i-- )
+        if( X->p[i] != 0 )
+            break;
+
+    for( j = Y->n - 1; j >= 0; j-- )
+        if( Y->p[j] != 0 )
+            break;
+
+    if( i < 0 && j < 0 )
+        return( 0 );
+
+    if( i > j ) return(  X->s );
+    if( j > i ) return( -X->s );
+
+    if( X->s > 0 && Y->s < 0 ) return(  1 );
+    if( Y->s > 0 && X->s < 0 ) return( -1 );
+
+    for( ; i >= 0; i-- )
+    {
+        if( X->p[i] > Y->p[i] ) return(  X->s );
+        if( X->p[i] < Y->p[i] ) return( -X->s );
+    }
+
+    return( 0 );
+}
+
+/*
+ * Compare signed values
+ */
+int mpi_cmp_int( const mpi *X, int z )
+{
+    mpi Y;
+    t_int p[1];
+
+    *p  = ( z < 0 ) ? -z : z;
+    Y.s = ( z < 0 ) ? -1 : 1;
+    Y.n = 1;
+    Y.p = p;
+
+    return( mpi_cmp_mpi( X, &Y ) );
+}
+
+/*
+ * Unsigned addition: X = |A| + |B|  (HAC 14.7)
+ */
+int mpi_add_abs( mpi *X, const mpi *A, const mpi *B )
+{
+    int ret, i, j;
+    t_int *o, *p, c;
+
+    if( X == B )
+    {
+        const mpi *T = A; A = X; B = T;
+    }
+
+    if( X != A )
+        MPI_CHK( mpi_copy( X, A ) );
+   
+    /*
+     * X should always be positive as a result of unsigned additions.
+     */
+    X->s = 1;
+
+    for( j = B->n - 1; j >= 0; j-- )
+        if( B->p[j] != 0 )
+            break;
+
+    MPI_CHK( mpi_grow( X, j + 1 ) );
+
+    o = B->p; p = X->p; c = 0;
+
+    for( i = 0; i <= j; i++, o++, p++ )
+    {
+        *p +=  c; c  = ( *p <  c );
+        *p += *o; c += ( *p < *o );
+    }
+
+    while( c != 0 )
+    {
+        if( i >= X->n )
+        {
+            MPI_CHK( mpi_grow( X, i + 1 ) );
+            p = X->p + i;
+        }
+
+        *p += c; c = ( *p < c ); i++;
+    }
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Helper for mpi substraction
+ */
+static void mpi_sub_hlp( int n, t_int *s, t_int *d )
+{
+    int i;
+    t_int c, z;
+
+    for( i = c = 0; i < n; i++, s++, d++ )
+    {
+        z = ( *d <  c );     *d -=  c;
+        c = ( *d < *s ) + z; *d -= *s;
+    }
+
+    while( c != 0 )
+    {
+        z = ( *d < c ); *d -= c;
+        c = z; i++; d++;
+    }
+}
+
+/*
+ * Unsigned substraction: X = |A| - |B|  (HAC 14.9)
+ */
+int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B )
+{
+    mpi TB;
+    int ret, n;
+
+    if( mpi_cmp_abs( A, B ) < 0 )
+        return( POLARSSL_ERR_MPI_NEGATIVE_VALUE );
+
+    mpi_init( &TB, NULL );
+
+    if( X == B )
+    {
+        MPI_CHK( mpi_copy( &TB, B ) );
+        B = &TB;
+    }
+
+    if( X != A )
+        MPI_CHK( mpi_copy( X, A ) );
+
+    /*
+     * X should always be positive as a result of unsigned substractions.
+     */
+    X->s = 1;
+
+    ret = 0;
+
+    for( n = B->n - 1; n >= 0; n-- )
+        if( B->p[n] != 0 )
+            break;
+
+    mpi_sub_hlp( n + 1, B->p, X->p );
+
+cleanup:
+
+    mpi_free( &TB, NULL );
+
+    return( ret );
+}
+
+/*
+ * Signed addition: X = A + B
+ */
+int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B )
+{
+    int ret, s = A->s;
+
+    if( A->s * B->s < 0 )
+    {
+        if( mpi_cmp_abs( A, B ) >= 0 )
+        {
+            MPI_CHK( mpi_sub_abs( X, A, B ) );
+            X->s =  s;
+        }
+        else
+        {
+            MPI_CHK( mpi_sub_abs( X, B, A ) );
+            X->s = -s;
+        }
+    }
+    else
+    {
+        MPI_CHK( mpi_add_abs( X, A, B ) );
+        X->s = s;
+    }
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Signed substraction: X = A - B
+ */
+int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B )
+{
+    int ret, s = A->s;
+
+    if( A->s * B->s > 0 )
+    {
+        if( mpi_cmp_abs( A, B ) >= 0 )
+        {
+            MPI_CHK( mpi_sub_abs( X, A, B ) );
+            X->s =  s;
+        }
+        else
+        {
+            MPI_CHK( mpi_sub_abs( X, B, A ) );
+            X->s = -s;
+        }
+    }
+    else
+    {
+        MPI_CHK( mpi_add_abs( X, A, B ) );
+        X->s = s;
+    }
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Signed addition: X = A + b
+ */
+int mpi_add_int( mpi *X, const mpi *A, int b )
+{
+    mpi _B;
+    t_int p[1];
+
+    p[0] = ( b < 0 ) ? -b : b;
+    _B.s = ( b < 0 ) ? -1 : 1;
+    _B.n = 1;
+    _B.p = p;
+
+    return( mpi_add_mpi( X, A, &_B ) );
+}
+
+/*
+ * Signed substraction: X = A - b
+ */
+int mpi_sub_int( mpi *X, const mpi *A, int b )
+{
+    mpi _B;
+    t_int p[1];
+
+    p[0] = ( b < 0 ) ? -b : b;
+    _B.s = ( b < 0 ) ? -1 : 1;
+    _B.n = 1;
+    _B.p = p;
+
+    return( mpi_sub_mpi( X, A, &_B ) );
+}
+
+/*
+ * Helper for mpi multiplication
+ */ 
+static void mpi_mul_hlp( int i, t_int *s, t_int *d, t_int b )
+{
+    t_int c = 0, t = 0;
+
+#if defined(MULADDC_HUIT)
+    for( ; i >= 8; i -= 8 )
+    {
+        MULADDC_INIT
+        MULADDC_HUIT
+        MULADDC_STOP
+    }
+
+    for( ; i > 0; i-- )
+    {
+        MULADDC_INIT
+        MULADDC_CORE
+        MULADDC_STOP
+    }
+#else
+    for( ; i >= 16; i -= 16 )
+    {
+        MULADDC_INIT
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_CORE   MULADDC_CORE
+
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_STOP
+    }
+
+    for( ; i >= 8; i -= 8 )
+    {
+        MULADDC_INIT
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_CORE   MULADDC_CORE
+
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_CORE   MULADDC_CORE
+        MULADDC_STOP
+    }
+
+    for( ; i > 0; i-- )
+    {
+        MULADDC_INIT
+        MULADDC_CORE
+        MULADDC_STOP
+    }
+#endif
+
+    t++;
+
+    do {
+        *d += c; c = ( *d < c ); d++;
+    }
+    while( c != 0 );
+}
+
+/*
+ * Baseline multiplication: X = A * B  (HAC 14.12)
+ */
+int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B )
+{
+    int ret, i, j;
+    mpi TA, TB;
+
+    mpi_init( &TA, &TB, NULL );
+
+    if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; }
+    if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; }
+
+    for( i = A->n - 1; i >= 0; i-- )
+        if( A->p[i] != 0 )
+            break;
+
+    for( j = B->n - 1; j >= 0; j-- )
+        if( B->p[j] != 0 )
+            break;
+
+    MPI_CHK( mpi_grow( X, i + j + 2 ) );
+    MPI_CHK( mpi_lset( X, 0 ) );
+
+    for( i++; j >= 0; j-- )
+        mpi_mul_hlp( i, A->p, X->p + j, B->p[j] );
+
+    X->s = A->s * B->s;
+
+cleanup:
+
+    mpi_free( &TB, &TA, NULL );
+
+    return( ret );
+}
+
+/*
+ * Baseline multiplication: X = A * b
+ */
+int mpi_mul_int( mpi *X, const mpi *A, t_int b )
+{
+    mpi _B;
+    t_int p[1];
+
+    _B.s = 1;
+    _B.n = 1;
+    _B.p = p;
+    p[0] = b;
+
+    return( mpi_mul_mpi( X, A, &_B ) );
+}
+
+/*
+ * Division by mpi: A = Q * B + R  (HAC 14.20)
+ */
+int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B )
+{
+    int ret, i, n, t, k;
+    mpi X, Y, Z, T1, T2;
+
+    if( mpi_cmp_int( B, 0 ) == 0 )
+        return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
+
+    mpi_init( &X, &Y, &Z, &T1, &T2, NULL );
+
+    if( mpi_cmp_abs( A, B ) < 0 )
+    {
+        if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) );
+        if( R != NULL ) MPI_CHK( mpi_copy( R, A ) );
+        return( 0 );
+    }
+
+    MPI_CHK( mpi_copy( &X, A ) );
+    MPI_CHK( mpi_copy( &Y, B ) );
+    X.s = Y.s = 1;
+
+    MPI_CHK( mpi_grow( &Z, A->n + 2 ) );
+    MPI_CHK( mpi_lset( &Z,  0 ) );
+    MPI_CHK( mpi_grow( &T1, 2 ) );
+    MPI_CHK( mpi_grow( &T2, 3 ) );
+
+    k = mpi_msb( &Y ) % biL;
+    if( k < (int) biL - 1 )
+    {
+        k = biL - 1 - k;
+        MPI_CHK( mpi_shift_l( &X, k ) );
+        MPI_CHK( mpi_shift_l( &Y, k ) );
+    }
+    else k = 0;
+
+    n = X.n - 1;
+    t = Y.n - 1;
+	MPI_CHK(mpi_shift_l( &Y, biL * (n - t) ));	
+
+    while( mpi_cmp_mpi( &X, &Y ) >= 0 )
+    {
+        Z.p[n - t]++;
+    	MPI_CHK(mpi_sub_mpi( &X, &X, &Y ));
+    }
+	MPI_CHK(mpi_shift_r( &Y, biL * (n - t) ));
+
+    for( i = n; i > t ; i-- )
+    {
+        if( X.p[i] >= Y.p[t] )
+            Z.p[i - t - 1] = ~0;
+        else
+        {
+#if defined(POLARSSL_HAVE_LONGLONG)
+            t_dbl r;
+
+            r  = (t_dbl) X.p[i] << biL;
+            r |= (t_dbl) X.p[i - 1];
+            r /= Y.p[t];
+            if( r > ((t_dbl) 1 << biL) - 1)
+                r = ((t_dbl) 1 << biL) - 1;
+
+            Z.p[i - t - 1] = (t_int) r;
+#else
+            /*
+             * __udiv_qrnnd_c, from gmp/longlong.h
+             */
+            t_int q0, q1, r0, r1;
+            t_int d0, d1, d, m;
+
+            d  = Y.p[t];
+            d0 = ( d << biH ) >> biH;
+            d1 = ( d >> biH );
+
+            q1 = X.p[i] / d1;
+            r1 = X.p[i] - d1 * q1;
+            r1 <<= biH;
+            r1 |= ( X.p[i - 1] >> biH );
+
+            m = q1 * d0;
+            if( r1 < m )
+            {
+                q1--, r1 += d;
+                while( r1 >= d && r1 < m )
+                    q1--, r1 += d;
+            }
+            r1 -= m;
+
+            q0 = r1 / d1;
+            r0 = r1 - d1 * q0;
+            r0 <<= biH;
+            r0 |= ( X.p[i - 1] << biH ) >> biH;
+
+            m = q0 * d0;
+            if( r0 < m )
+            {
+                q0--, r0 += d;
+                while( r0 >= d && r0 < m )
+                    q0--, r0 += d;
+            }
+            r0 -= m;
+
+            Z.p[i - t - 1] = ( q1 << biH ) | q0;
+#endif
+        }
+
+        Z.p[i - t - 1]++;
+        do
+        {
+            Z.p[i - t - 1]--;
+
+            MPI_CHK( mpi_lset( &T1, 0 ) );
+            T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
+            T1.p[1] = Y.p[t];
+            MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
+
+            MPI_CHK( mpi_lset( &T2, 0 ) );
+            T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
+            T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
+            T2.p[2] = X.p[i];
+        }
+        while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
+
+        MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
+        MPI_CHK( mpi_shift_l( &T1,  biL * (i - t - 1) ) );
+        MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) );
+
+        if( mpi_cmp_int( &X, 0 ) < 0 )
+        {
+            MPI_CHK( mpi_copy( &T1, &Y ) );
+            MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
+            MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) );
+            Z.p[i - t - 1]--;
+        }
+    }
+
+    if( Q != NULL )
+    {
+        MPI_CHK(mpi_copy( Q, &Z ));  
+        Q->s = A->s * B->s;
+    }
+
+    if( R != NULL )
+    {
+        MPI_CHK(mpi_shift_r( &X, k ));
+        MPI_CHK(mpi_copy( R, &X ));
+
+        R->s = A->s;
+        if( mpi_cmp_int( R, 0 ) == 0 )
+            R->s = 1;
+    }
+
+cleanup:
+
+    mpi_free( &X, &Y, &Z, &T1, &T2, NULL );
+
+    return( ret );
+}
+
+/*
+ * Division by int: A = Q * b + R
+ *
+ * Returns 0 if successful
+ *         1 if memory allocation failed
+ *         POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0
+ */
+int mpi_div_int( mpi *Q, mpi *R, const mpi *A, int b )
+{
+    mpi _B;
+    t_int p[1];
+
+    p[0] = ( b < 0 ) ? -b : b;
+    _B.s = ( b < 0 ) ? -1 : 1;
+    _B.n = 1;
+    _B.p = p;
+
+    return( mpi_div_mpi( Q, R, A, &_B ) );
+}
+
+/*
+ * Modulo: R = A mod B
+ */
+int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B )
+{
+    int ret;
+
+    if( mpi_cmp_int( B, 0 ) < 0 )
+        return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
+
+    MPI_CHK( mpi_div_mpi( NULL, R, A, B ) );
+
+    while( mpi_cmp_int( R, 0 ) < 0 )
+      MPI_CHK( mpi_add_mpi( R, R, B ) );
+
+    while( mpi_cmp_mpi( R, B ) >= 0 )
+      MPI_CHK( mpi_sub_mpi( R, R, B ) );
+
+cleanup:
+
+    return( ret );
+}
+
+/*
+ * Modulo: r = A mod b
+ */
+int mpi_mod_int( t_int *r, const mpi *A, int b )
+{
+    int i;
+    t_int x, y, z;
+
+    if( b == 0 )
+        return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO );
+
+    if( b < 0 )
+        return POLARSSL_ERR_MPI_NEGATIVE_VALUE;
+
+    /*
+     * handle trivial cases
+     */
+    if( b == 1 )
+    {
+        *r = 0;
+        return( 0 );
+    }
+
+    if( b == 2 )
+    {
+        *r = A->p[0] & 1;
+        return( 0 );
+    }
+
+    /*
+     * general case
+     */
+    for( i = A->n - 1, y = 0; i >= 0; i-- )
+    {
+        x  = A->p[i];
+        y  = ( y << biH ) | ( x >> biH );
+        z  = y / b;
+        y -= z * b;
+
+        x <<= biH;
+        y  = ( y << biH ) | ( x >> biH );
+        z  = y / b;
+        y -= z * b;
+    }
+
+    /*
+     * If A is negative, then the current y represents a negative value.
+     * Flipping it to the positive side.
+     */
+    if( A->s < 0 && y != 0 )
+        y = b - y;
+
+    *r = y;
+
+    return( 0 );
+}
+
+/*
+ * Fast Montgomery initialization (thanks to Tom St Denis)
+ */
+static void mpi_montg_init( t_int *mm, const mpi *N )
+{
+    t_int x, m0 = N->p[0];
+
+    x  = m0;
+    x += ( ( m0 + 2 ) & 4 ) << 1;
+    x *= ( 2 - ( m0 * x ) );
+
+    if( biL >= 16 ) x *= ( 2 - ( m0 * x ) );
+    if( biL >= 32 ) x *= ( 2 - ( m0 * x ) );
+    if( biL >= 64 ) x *= ( 2 - ( m0 * x ) );
+
+    *mm = ~x + 1;
+}
+
+/*
+ * Montgomery multiplication: A = A * B * R^-1 mod N  (HAC 14.36)
+ */
+static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_int mm, const mpi *T )
+{
+    int i, n, m;
+    t_int u0, u1, *d;
+
+    memset( T->p, 0, T->n * ciL );
+
+    d = T->p;
+    n = N->n;
+    m = ( B->n < n ) ? B->n : n;
+
+    for( i = 0; i < n; i++ )
+    {
+        /*
+         * T = (T + u0*B + u1*N) / 2^biL
+         */
+        u0 = A->p[i];
+        u1 = ( d[0] + u0 * B->p[0] ) * mm;
+
+        mpi_mul_hlp( m, B->p, d, u0 );
+        mpi_mul_hlp( n, N->p, d, u1 );
+
+        *d++ = u0; d[n + 1] = 0;
+    }
+
+    memcpy( A->p, d, (n + 1) * ciL );
+
+    if( mpi_cmp_abs( A, N ) >= 0 )
+        mpi_sub_hlp( n, N->p, A->p );
+    else
+        /* prevent timing attacks */
+        mpi_sub_hlp( n, A->p, T->p );
+}
+
+/*
+ * Montgomery reduction: A = A * R^-1 mod N
+ */
+static void mpi_montred( mpi *A, const mpi *N, t_int mm, const mpi *T )
+{
+    t_int z = 1;
+    mpi U;
+
+    U.n = U.s = z;
+    U.p = &z;
+
+    mpi_montmul( A, &U, N, mm, T );
+}
+
+/*
+ * Sliding-window exponentiation: X = A^E mod N  (HAC 14.85)
+ */
+int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR )
+{
+    int ret, i, j, wsize, wbits;
+    int bufsize, nblimbs, nbits;
+    t_int ei, mm, state;
+    mpi RR, T, W[64];
+
+    if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
+        return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+    /*
+     * Init temps and window size
+     */
+    mpi_montg_init( &mm, N );
+    mpi_init( &RR, &T, NULL );
+    memset( W, 0, sizeof( W ) );
+
+    i = mpi_msb( E );
+
+    wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
+            ( i >  79 ) ? 4 : ( i >  23 ) ? 3 : 1;
+
+    j = N->n + 1;
+    MPI_CHK( mpi_grow( X, j ) );
+    MPI_CHK( mpi_grow( &W[1],  j ) );
+    MPI_CHK( mpi_grow( &T, j * 2 ) );
+
+    /*
+     * If 1st call, pre-compute R^2 mod N
+     */
+    if( _RR == NULL || _RR->p == NULL )
+    {
+        MPI_CHK( mpi_lset( &RR, 1 ) );
+        MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
+        MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) );
+
+        if( _RR != NULL )
+            memcpy( _RR, &RR, sizeof( mpi ) );
+    }
+    else
+        memcpy( &RR, _RR, sizeof( mpi ) );
+
+    /*
+     * W[1] = A * R^2 * R^-1 mod N = A * R mod N
+     */
+    if( mpi_cmp_mpi( A, N ) >= 0 )
+    {
+        MPI_CHK(mpi_mod_mpi( &W[1], A, N ));
+    }
+    else
+	{
+	    MPI_CHK(mpi_copy( &W[1], A ));
+    }
+
+    mpi_montmul( &W[1], &RR, N, mm, &T );
+
+    /*
+     * X = R^2 * R^-1 mod N = R mod N
+     */
+    MPI_CHK( mpi_copy( X, &RR ) );
+    mpi_montred( X, N, mm, &T );
+
+    if( wsize > 1 )
+    {
+        /*
+         * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
+         */
+        j =  1 << (wsize - 1);
+
+        MPI_CHK( mpi_grow( &W[j], N->n + 1 ) );
+        MPI_CHK( mpi_copy( &W[j], &W[1]    ) );
+
+        for( i = 0; i < wsize - 1; i++ )
+            mpi_montmul( &W[j], &W[j], N, mm, &T );
+    
+        /*
+         * W[i] = W[i - 1] * W[1]
+         */
+        for( i = j + 1; i < (1 << wsize); i++ )
+        {
+            MPI_CHK( mpi_grow( &W[i], N->n + 1 ) );
+            MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) );
+
+            mpi_montmul( &W[i], &W[1], N, mm, &T );
+        }
+    }
+
+    nblimbs = E->n;
+    bufsize = 0;
+    nbits   = 0;
+    wbits   = 0;
+    state   = 0;
+
+    while( 1 )
+    {
+        if( bufsize == 0 )
+        {
+            if( nblimbs-- == 0 )
+                break;
+
+            bufsize = sizeof( t_int ) << 3;
+        }
+
+        bufsize--;
+
+        ei = (E->p[nblimbs] >> bufsize) & 1;
+
+        /*
+         * skip leading 0s
+         */
+        if( ei == 0 && state == 0 )
+            continue;
+
+        if( ei == 0 && state == 1 )
+        {
+            /*
+             * out of window, square X
+             */
+            mpi_montmul( X, X, N, mm, &T );
+            continue;
+        }
+
+        /*
+         * add ei to current window
+         */
+        state = 2;
+
+        nbits++;
+        wbits |= (ei << (wsize - nbits));
+
+        if( nbits == wsize )
+        {
+            /*
+             * X = X^wsize R^-1 mod N
+             */
+            for( i = 0; i < wsize; i++ )
+                mpi_montmul( X, X, N, mm, &T );
+
+            /*
+             * X = X * W[wbits] R^-1 mod N
+             */
+            mpi_montmul( X, &W[wbits], N, mm, &T );
+
+            state--;
+            nbits = 0;
+            wbits = 0;
+        }
+    }
+
+    /*
+     * process the remaining bits
+     */
+    for( i = 0; i < nbits; i++ )
+    {
+        mpi_montmul( X, X, N, mm, &T );
+
+        wbits <<= 1;
+
+        if( (wbits & (1 << wsize)) != 0 )
+            mpi_montmul( X, &W[1], N, mm, &T );
+    }
+
+    /*
+     * X = A^E * R * R^-1 mod N = A^E mod N
+     */
+    mpi_montred( X, N, mm, &T );
+
+cleanup:
+
+    for( i = (1 << (wsize - 1)); i < (1 << wsize); i++ )
+        mpi_free( &W[i], NULL );
+
+    if( _RR != NULL )
+         mpi_free( &W[1], &T, NULL );
+    else mpi_free( &W[1], &T, &RR, NULL );
+
+    return( ret );
+}
+
+/*
+ * Greatest common divisor: G = gcd(A, B)  (HAC 14.54)
+ */
+int mpi_gcd( mpi *G, const mpi *A, const mpi *B )
+{
+    int ret, lz, lzt;
+    mpi TG, TA, TB;
+
+    mpi_init( &TG, &TA, &TB, NULL );
+
+    MPI_CHK( mpi_copy( &TA, A ) );
+    MPI_CHK( mpi_copy( &TB, B ) );
+
+    lz = mpi_lsb( &TA );
+    lzt = mpi_lsb( &TB );
+
+    if ( lzt < lz )
+        lz = lzt;
+
+    MPI_CHK( mpi_shift_r( &TA, lz ) );
+    MPI_CHK( mpi_shift_r( &TB, lz ) );
+
+    TA.s = TB.s = 1;
+
+    while( mpi_cmp_int( &TA, 0 ) != 0 )
+    {
+        MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) );
+        MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) );
+
+        if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
+        {
+            MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) );
+            MPI_CHK( mpi_shift_r( &TA, 1 ) );
+        }
+        else
+        {
+            MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) );
+            MPI_CHK( mpi_shift_r( &TB, 1 ) );
+        }
+    }
+
+    MPI_CHK( mpi_shift_l( &TB, lz ) );
+    MPI_CHK( mpi_copy( G, &TB ) );
+
+cleanup:
+
+    mpi_free( &TB, &TA, &TG, NULL );
+
+    return( ret );
+}
+
+#if defined(POLARSSL_GENPRIME)
+
+/*
+ * Modular inverse: X = A^-1 mod N  (HAC 14.61 / 14.64)
+ */
+int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N )
+{
+    int ret;
+    mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
+
+    if( mpi_cmp_int( N, 0 ) <= 0 )
+        return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+    mpi_init( &TA, &TU, &U1, &U2, &G,
+              &TB, &TV, &V1, &V2, NULL );
+
+    MPI_CHK( mpi_gcd( &G, A, N ) );
+
+    if( mpi_cmp_int( &G, 1 ) != 0 )
+    {
+        ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
+        goto cleanup;
+    }
+
+    MPI_CHK( mpi_mod_mpi( &TA, A, N ) );
+    MPI_CHK( mpi_copy( &TU, &TA ) );
+    MPI_CHK( mpi_copy( &TB, N ) );
+    MPI_CHK( mpi_copy( &TV, N ) );
+
+    MPI_CHK( mpi_lset( &U1, 1 ) );
+    MPI_CHK( mpi_lset( &U2, 0 ) );
+    MPI_CHK( mpi_lset( &V1, 0 ) );
+    MPI_CHK( mpi_lset( &V2, 1 ) );
+
+    do
+    {
+        while( ( TU.p[0] & 1 ) == 0 )
+        {
+            MPI_CHK( mpi_shift_r( &TU, 1 ) );
+
+            if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
+            {
+                MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) );
+                MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
+            }
+
+            MPI_CHK( mpi_shift_r( &U1, 1 ) );
+            MPI_CHK( mpi_shift_r( &U2, 1 ) );
+        }
+
+        while( ( TV.p[0] & 1 ) == 0 )
+        {
+            MPI_CHK( mpi_shift_r( &TV, 1 ) );
+
+            if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
+            {
+                MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) );
+                MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
+            }
+
+            MPI_CHK( mpi_shift_r( &V1, 1 ) );
+            MPI_CHK( mpi_shift_r( &V2, 1 ) );
+        }
+
+        if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
+        {
+            MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
+            MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
+            MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
+        }
+        else
+        {
+            MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
+            MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
+            MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
+        }
+    }
+    while( mpi_cmp_int( &TU, 0 ) != 0 );
+
+    while( mpi_cmp_int( &V1, 0 ) < 0 )
+        MPI_CHK( mpi_add_mpi( &V1, &V1, N ) );
+
+    while( mpi_cmp_mpi( &V1, N ) >= 0 )
+        MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) );
+
+    MPI_CHK( mpi_copy( X, &V1 ) );
+
+cleanup:
+
+    mpi_free( &V2, &V1, &TV, &TB, &G,
+              &U2, &U1, &TU, &TA, NULL );
+
+    return( ret );
+}
+
+static const int small_prime[] =
+{
+        3,    5,    7,   11,   13,   17,   19,   23,
+       29,   31,   37,   41,   43,   47,   53,   59,
+       61,   67,   71,   73,   79,   83,   89,   97,
+      101,  103,  107,  109,  113,  127,  131,  137,
+      139,  149,  151,  157,  163,  167,  173,  179,
+      181,  191,  193,  197,  199,  211,  223,  227,
+      229,  233,  239,  241,  251,  257,  263,  269,
+      271,  277,  281,  283,  293,  307,  311,  313,
+      317,  331,  337,  347,  349,  353,  359,  367,
+      373,  379,  383,  389,  397,  401,  409,  419,
+      421,  431,  433,  439,  443,  449,  457,  461,
+      463,  467,  479,  487,  491,  499,  503,  509,
+      521,  523,  541,  547,  557,  563,  569,  571,
+      577,  587,  593,  599,  601,  607,  613,  617,
+      619,  631,  641,  643,  647,  653,  659,  661,
+      673,  677,  683,  691,  701,  709,  719,  727,
+      733,  739,  743,  751,  757,  761,  769,  773,
+      787,  797,  809,  811,  821,  823,  827,  829,
+      839,  853,  857,  859,  863,  877,  881,  883,
+      887,  907,  911,  919,  929,  937,  941,  947,
+      953,  967,  971,  977,  983,  991,  997, -103
+};
+
+/*
+ * Miller-Rabin primality test  (HAC 4.24)
+ */
+int mpi_is_prime( mpi *X, int (*f_rng)(void *), void *p_rng )
+{
+    int ret, i, j, n, s, xs;
+    mpi W, R, T, A, RR;
+    unsigned char *p;
+
+    if( mpi_cmp_int( X, 0 ) == 0 ||
+        mpi_cmp_int( X, 1 ) == 0 )
+        return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
+
+    if( mpi_cmp_int( X, 2 ) == 0 )
+        return( 0 );
+
+    mpi_init( &W, &R, &T, &A, &RR, NULL );
+
+    xs = X->s; X->s = 1;
+
+    /*
+     * test trivial factors first
+     */
+    if( ( X->p[0] & 1 ) == 0 )
+        return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
+
+    for( i = 0; small_prime[i] > 0; i++ )
+    {
+        t_int r;
+
+        if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
+            return( 0 );
+
+        MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) );
+
+        if( r == 0 )
+            return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
+    }
+
+    /*
+     * W = |X| - 1
+     * R = W >> lsb( W )
+     */
+    MPI_CHK( mpi_sub_int( &W, X, 1 ) );
+    s = mpi_lsb( &W );
+    MPI_CHK( mpi_copy( &R, &W ) );
+    MPI_CHK( mpi_shift_r( &R, s ) );
+
+    i = mpi_msb( X );
+    /*
+     * HAC, table 4.4
+     */
+    n = ( ( i >= 1300 ) ?  2 : ( i >=  850 ) ?  3 :
+          ( i >=  650 ) ?  4 : ( i >=  350 ) ?  8 :
+          ( i >=  250 ) ? 12 : ( i >=  150 ) ? 18 : 27 );
+
+    for( i = 0; i < n; i++ )
+    {
+        /*
+         * pick a random A, 1 < A < |X| - 1
+         */
+        MPI_CHK( mpi_grow( &A, X->n ) );
+
+        p = (unsigned char *) A.p;
+        for( j = 0; j < A.n * ciL; j++ )
+            *p++ = (unsigned char) f_rng( p_rng );
+
+        j = mpi_msb( &A ) - mpi_msb( &W );
+        MPI_CHK( mpi_shift_r( &A, j + 1 ) );
+        A.p[0] |= 3;
+
+        /*
+         * A = A^R mod |X|
+         */
+        MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
+
+        if( mpi_cmp_mpi( &A, &W ) == 0 ||
+            mpi_cmp_int( &A,  1 ) == 0 )
+            continue;
+
+        j = 1;
+        while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
+        {
+            /*
+             * A = A * A mod |X|
+             */
+            MPI_CHK( mpi_mul_mpi( &T, &A, &A ) );
+            MPI_CHK( mpi_mod_mpi( &A, &T, X  ) );
+
+            if( mpi_cmp_int( &A, 1 ) == 0 )
+                break;
+
+            j++;
+        }
+
+        /*
+         * not prime if A != |X| - 1 or A == 1
+         */
+        if( mpi_cmp_mpi( &A, &W ) != 0 ||
+            mpi_cmp_int( &A,  1 ) == 0 )
+        {
+            ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE;
+            break;
+        }
+    }
+
+cleanup:
+
+    X->s = xs;
+
+    mpi_free( &RR, &A, &T, &R, &W, NULL );
+
+    return( ret );
+}
+
+/*
+ * Prime number generation
+ */
+int mpi_gen_prime( mpi *X, int nbits, int dh_flag,
+                   int (*f_rng)(void *), void *p_rng )
+{
+    int ret, k, n;
+    unsigned char *p;
+    mpi Y;
+
+    if( nbits < 3 )
+        return( POLARSSL_ERR_MPI_BAD_INPUT_DATA );
+
+    mpi_init( &Y, NULL );
+
+    n = BITS_TO_LIMBS( nbits );
+
+    MPI_CHK( mpi_grow( X, n ) );
+    MPI_CHK( mpi_lset( X, 0 ) );
+
+    p = (unsigned char *) X->p;
+    for( k = 0; k < X->n * ciL; k++ )
+        *p++ = (unsigned char) f_rng( p_rng );
+
+    k = mpi_msb( X );
+    if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) );
+    if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) );
+
+    X->p[0] |= 3;
+
+    if( dh_flag == 0 )
+    {
+        while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 )
+        {
+            if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
+                goto cleanup;
+
+            MPI_CHK( mpi_add_int( X, X, 2 ) );
+        }
+    }
+    else
+    {
+        MPI_CHK( mpi_sub_int( &Y, X, 1 ) );
+        MPI_CHK( mpi_shift_r( &Y, 1 ) );
+
+        while( 1 )
+        {
+            if( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) == 0 )
+            {
+                if( ( ret = mpi_is_prime( &Y, f_rng, p_rng ) ) == 0 )
+                    break;
+
+                if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
+                    goto cleanup;
+            }
+
+            if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE )
+                goto cleanup;
+
+            MPI_CHK( mpi_add_int( &Y, X, 1 ) );
+            MPI_CHK( mpi_add_int(  X, X, 2 ) );
+            MPI_CHK( mpi_shift_r( &Y, 1 ) );
+        }
+    }
+
+cleanup:
+
+    mpi_free( &Y, NULL );
+
+    return( ret );
+}
+
+#endif
+
+#if defined(POLARSSL_SELF_TEST)
+
+#define GCD_PAIR_COUNT	3
+
+static const int gcd_pairs[GCD_PAIR_COUNT][3] =
+{
+    { 693, 609, 21 },
+    { 1764, 868, 28 },
+    { 768454923, 542167814, 1 }
+};
+
+/*
+ * Checkup routine
+ */
+int mpi_self_test( int verbose )
+{
+    int ret, i;
+    mpi A, E, N, X, Y, U, V;
+
+    mpi_init( &A, &E, &N, &X, &Y, &U, &V, NULL );
+
+    MPI_CHK( mpi_read_string( &A, 16,
+        "EFE021C2645FD1DC586E69184AF4A31E" \
+        "D5F53E93B5F123FA41680867BA110131" \
+        "944FE7952E2517337780CB0DB80E61AA" \
+        "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) );
+
+    MPI_CHK( mpi_read_string( &E, 16,
+        "B2E7EFD37075B9F03FF989C7C5051C20" \
+        "34D2A323810251127E7BF8625A4F49A5" \
+        "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
+        "5B5C25763222FEFCCFC38B832366C29E" ) );
+
+    MPI_CHK( mpi_read_string( &N, 16,
+        "0066A198186C18C10B2F5ED9B522752A" \
+        "9830B69916E535C8F047518A889A43A5" \
+        "94B6BED27A168D31D4A52F88925AA8F5" ) );
+
+    MPI_CHK( mpi_mul_mpi( &X, &A, &N ) );
+
+    MPI_CHK( mpi_read_string( &U, 16,
+        "602AB7ECA597A3D6B56FF9829A5E8B85" \
+        "9E857EA95A03512E2BAE7391688D264A" \
+        "A5663B0341DB9CCFD2C4C5F421FEC814" \
+        "8001B72E848A38CAE1C65F78E56ABDEF" \
+        "E12D3C039B8A02D6BE593F0BBBDA56F1" \
+        "ECF677152EF804370C1A305CAF3B5BF1" \
+        "30879B56C61DE584A0F53A2447A51E" ) );
+
+    if( verbose != 0 )
+        printf( "  MPI test #1 (mul_mpi): " );
+
+    if( mpi_cmp_mpi( &X, &U ) != 0 )
+    {
+        if( verbose != 0 )
+            printf( "failed\n" );
+
+        return( 1 );
+    }
+
+    if( verbose != 0 )
+        printf( "passed\n" );
+
+    MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
+
+    MPI_CHK( mpi_read_string( &U, 16,
+        "256567336059E52CAE22925474705F39A94" ) );
+
+    MPI_CHK( mpi_read_string( &V, 16,
+        "6613F26162223DF488E9CD48CC132C7A" \
+        "0AC93C701B001B092E4E5B9F73BCD27B" \
+        "9EE50D0657C77F374E903CDFA4C642" ) );
+
+    if( verbose != 0 )
+        printf( "  MPI test #2 (div_mpi): " );
+
+    if( mpi_cmp_mpi( &X, &U ) != 0 ||
+        mpi_cmp_mpi( &Y, &V ) != 0 )
+    {
+        if( verbose != 0 )
+            printf( "failed\n" );
+
+        return( 1 );
+    }
+
+    if( verbose != 0 )
+        printf( "passed\n" );
+
+    MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
+
+    MPI_CHK( mpi_read_string( &U, 16,
+        "36E139AEA55215609D2816998ED020BB" \
+        "BD96C37890F65171D948E9BC7CBAA4D9" \
+        "325D24D6A3C12710F10A09FA08AB87" ) );
+
+    if( verbose != 0 )
+        printf( "  MPI test #3 (exp_mod): " );
+
+    if( mpi_cmp_mpi( &X, &U ) != 0 )
+    {
+        if( verbose != 0 )
+            printf( "failed\n" );
+
+        return( 1 );
+    }
+
+    if( verbose != 0 )
+        printf( "passed\n" );
+
+    MPI_CHK( mpi_inv_mod( &X, &A, &N ) );
+
+    MPI_CHK( mpi_read_string( &U, 16,
+        "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
+        "C3DBA76456363A10869622EAC2DD84EC" \
+        "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) );
+
+    if( verbose != 0 )
+        printf( "  MPI test #4 (inv_mod): " );
+
+    if( mpi_cmp_mpi( &X, &U ) != 0 )
+    {
+        if( verbose != 0 )
+            printf( "failed\n" );
+
+        return( 1 );
+    }
+
+    if( verbose != 0 )
+        printf( "passed\n" );
+
+    if( verbose != 0 )
+        printf( "  MPI test #5 (simple gcd): " );
+
+    for ( i = 0; i < GCD_PAIR_COUNT; i++)
+    {
+        MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) );
+	MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) );
+
+	MPI_CHK( mpi_gcd( &A, &X, &Y ) );
+
+	if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 )
+	{
+		if( verbose != 0 )
+			printf( "failed at %d\n", i );
+
+		return( 1 );
+	}
+    }
+
+    if( verbose != 0 )
+        printf( "passed\n" );
+
+cleanup:
+
+    if( ret != 0 && verbose != 0 )
+        printf( "Unexpected error, return code = %08X\n", ret );
+
+    mpi_free( &V, &U, &Y, &X, &N, &E, &A, NULL );
+
+    if( verbose != 0 )
+        printf( "\n" );
+
+    return( ret );
+}
+
+#endif
+
+#endif
diff --git a/ap/app/zte_comm/zte_locknet/src/zctrm_ln_md5.c b/ap/app/zte_comm/zte_locknet/src/zctrm_ln_md5.c
new file mode 100755
index 0000000..68143dd
--- /dev/null
+++ b/ap/app/zte_comm/zte_locknet/src/zctrm_ln_md5.c
@@ -0,0 +1,306 @@
+/*
+ ***********************************************************************
+ ** 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 "zctrm_ln_md5.h"
+#include <string.h>
+
+/*
+ ***********************************************************************
+ **  Message-digest routines:                                         **
+ **  To form the message digest for a message M                       **
+ **    (1) Initialize a context buffer ctx using md5_init             **
+ **    (2) Call md5_update on ctx and M                               **
+ **    (3) Call md5_final on ctx                                      **
+ **  The message digest is now in ctx->digest[0...15]                 **
+ ***********************************************************************
+ */
+
+/* forward declaration */
+static void transform(u32_t *buf, u32_t *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) + (u32_t)(ac); \
+   (a) = ROTATE_LEFT ((a), (s)); \
+   (a) += (b); \
+  }
+#define GG(a, b, c, d, x, s, ac) \
+  {(a) += G ((b), (c), (d)) + (x) + (u32_t)(ac); \
+   (a) = ROTATE_LEFT ((a), (s)); \
+   (a) += (b); \
+  }
+#define HH(a, b, c, d, x, s, ac) \
+  {(a) += H ((b), (c), (d)) + (x) + (u32_t)(ac); \
+   (a) = ROTATE_LEFT ((a), (s)); \
+   (a) += (b); \
+  }
+#define II(a, b, c, d, x, s, ac) \
+  {(a) += I ((b), (c), (d)) + (x) + (u32_t)(ac); \
+   (a) = ROTATE_LEFT ((a), (s)); \
+   (a) += (b); \
+  }
+
+#ifdef __STDC__
+#define UL(x) x##UL
+#else
+#ifdef WIN32
+#define UL(x) x##UL
+#else
+#define UL(x) x
+#endif
+#endif
+
+/* The routine md5_init initializes the message-digest context
+   mdContext. All fields are set to zero.
+ */
+void
+md5_init(md5_ctx *ctx)
+{
+  ctx->i[0] = ctx->i[1] = (u32_t)0;
+
+  /* Load magic initialization constants. */
+  ctx->buf[0] = (u32_t)0x67452301UL;
+  ctx->buf[1] = (u32_t)0xefcdab89UL;
+  ctx->buf[2] = (u32_t)0x98badcfeUL;
+  ctx->buf[3] = (u32_t)0x10325476UL;
+}
+
+/* The routine md5_update updates the message-digest context to
+   account for the presence of each of the characters buf[0..inLen-1]
+   in the message whose digest is being computed.
+ */
+void
+md5_update(md5_ctx *ctx, unsigned char *buf, unsigned int len)
+{
+  u32_t in[16];
+  int mdi;
+  unsigned int i, ii;
+
+#if 0
+  ppp_trace(LOG_INFO, "MD5Update: %u:%.*H\n", len, MIN(len, 20) * 2, buf);
+  ppp_trace(LOG_INFO, "MD5Update: %u:%s\n", len, buf);
+#endif
+
+  /* compute number of bytes mod 64 */
+  mdi = (int)((ctx->i[0] >> 3) & 0x3F);
+
+  /* update number of bits */
+  if ((ctx->i[0] + ((u32_t)len << 3)) < ctx->i[0]) {
+    ctx->i[1]++;
+  }
+  ctx->i[0] += ((u32_t)len << 3);
+  ctx->i[1] += ((u32_t)len >> 29);
+
+  while (len--) {
+    /* add new character to buffer, increment mdi */
+    ctx->in[mdi++] = *buf++;
+
+    /* transform if necessary */
+    if (mdi == 0x40) {
+      for (i = 0, ii = 0; i < 16; i++, ii += 4) {
+        in[i] = (((u32_t)ctx->in[ii+3]) << 24) |
+                (((u32_t)ctx->in[ii+2]) << 16) |
+                (((u32_t)ctx->in[ii+1]) << 8)  |
+                ((u32_t)ctx->in[ii]);
+      }
+      transform (ctx->buf, in);
+      mdi = 0;
+    }
+  }
+}
+
+/* The routine md5_final terminates the message-digest computation and
+   ends with the desired message digest in ctx->digest[0...15].
+ */
+void md5_final(unsigned char hash[], md5_ctx *ctx)
+{
+  u32_t in[16];
+  int mdi;
+  unsigned int i, ii;
+  unsigned int pad_len;
+
+  /* save number of bits */
+  in[14] = ctx->i[0];
+  in[15] = ctx->i[1];
+
+  /* compute number of bytes mod 64 */
+  mdi = (int)((ctx->i[0] >> 3) & 0x3F);
+
+  /* pad out to 56 mod 64 */
+  pad_len = (mdi < 56) ? (56 - mdi) : (120 - mdi);
+  md5_update (ctx, PADDING, pad_len);
+
+  /* append length in bits and transform */
+  for (i = 0, ii = 0; i < 14; i++, ii += 4) {
+    in[i] = (((u32_t)ctx->in[ii+3]) << 24) |
+            (((u32_t)ctx->in[ii+2]) << 16) |
+            (((u32_t)ctx->in[ii+1]) << 8)  |
+            ((u32_t)ctx->in[ii]);
+  }
+  transform (ctx->buf, in);
+
+  /* store buffer in digest */
+  for (i = 0, ii = 0; i < 4; i++, ii += 4) {
+    ctx->digest[ii]   = (unsigned char)(ctx->buf[i] & 0xFF);
+    ctx->digest[ii+1] =
+      (unsigned char)((ctx->buf[i] >> 8)  & 0xFF);
+    ctx->digest[ii+2] =
+      (unsigned char)((ctx->buf[i] >> 16) & 0xFF);
+    ctx->digest[ii+3] =
+      (unsigned char)((ctx->buf[i] >> 24) & 0xFF);
+  }
+  SMEMCPY(hash, ctx->digest, 16);
+}
+
+/* Basic MD5 step. Transforms buf based on in.
+ */
+static void
+transform (u32_t *buf, u32_t *in)
+{
+  u32_t 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;
+}
diff --git a/ap/app/zte_comm/zte_locknet/src/zctrm_ln_rsa.c b/ap/app/zte_comm/zte_locknet/src/zctrm_ln_rsa.c
new file mode 100755
index 0000000..5cd1f5c
--- /dev/null
+++ b/ap/app/zte_comm/zte_locknet/src/zctrm_ln_rsa.c
@@ -0,0 +1,742 @@
+/*
+ *  The RSA public-key cryptosystem
+ *
+ *  Copyright (C) 2006-2010, Brainspark B.V.
+ *
+ *  This file is part of PolarSSL (http://www.polarssl.org)
+ *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ *
+ *  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+/*
+ *  RSA was designed by Ron Rivest, Adi Shamir and Len Adleman.
+ *
+ *  http://theory.lcs.mit.edu/~rivest/rsapaper.pdf
+ *  http://www.cacr.math.uwaterloo.ca/hac/about/chap8.pdf
+ */
+
+#include "zctrm_ln_config.h"
+
+#if defined(POLARSSL_RSA_C)
+
+#include "zctrm_ln_rsa.h"
+
+//#include <stdlib.h>
+//#include <string.h>
+//#include <stdio.h>
+
+/*
+ * Initialize an RSA context
+ */
+void rsa_init( rsa_context *ctx,
+               int padding,
+               int hash_id )
+{
+    memset( ctx, 0, sizeof( rsa_context ) );
+
+    ctx->padding = padding;
+    ctx->hash_id = hash_id;
+}
+
+#if defined(POLARSSL_GENPRIME)
+
+/*
+ * Generate an RSA keypair
+ */
+int rsa_gen_key( rsa_context *ctx,
+        int (*f_rng)(void *),
+        void *p_rng,
+        int nbits, int exponent )
+{
+    int ret;
+    mpi P1, Q1, H, G;
+
+    if( f_rng == NULL || nbits < 128 || exponent < 3 )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    mpi_init( &P1, &Q1, &H, &G, NULL );
+
+    /*
+     * find primes P and Q with Q < P so that:
+     * GCD( E, (P-1)*(Q-1) ) == 1
+     */
+    MPI_CHK( mpi_lset( &ctx->E, exponent ) );
+
+    do
+    {
+        MPI_CHK( mpi_gen_prime( &ctx->P, ( nbits + 1 ) >> 1, 0, 
+                                f_rng, p_rng ) );
+
+        MPI_CHK( mpi_gen_prime( &ctx->Q, ( nbits + 1 ) >> 1, 0,
+                                f_rng, p_rng ) );
+
+        if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 )
+            mpi_swap( &ctx->P, &ctx->Q );
+
+        if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 )
+            continue;
+
+        MPI_CHK( mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) );
+        if( mpi_msb( &ctx->N ) != nbits )
+            continue;
+
+        MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) );
+        MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) );
+        MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) );
+        MPI_CHK( mpi_gcd( &G, &ctx->E, &H  ) );
+    }
+    while( mpi_cmp_int( &G, 1 ) != 0 );
+
+    /*
+     * D  = E^-1 mod ((P-1)*(Q-1))
+     * DP = D mod (P - 1)
+     * DQ = D mod (Q - 1)
+     * QP = Q^-1 mod P
+     */
+    MPI_CHK( mpi_inv_mod( &ctx->D , &ctx->E, &H  ) );
+    MPI_CHK( mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) );
+    MPI_CHK( mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) );
+    MPI_CHK( mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) );
+
+    ctx->len = ( mpi_msb( &ctx->N ) + 7 ) >> 3;
+
+cleanup:
+
+    mpi_free( &G, &H, &Q1, &P1, NULL );
+
+    if( ret != 0 )
+    {
+        rsa_free( ctx );
+        return( POLARSSL_ERR_RSA_KEY_GEN_FAILED | ret );
+    }
+
+    return( 0 );   
+}
+
+#endif
+
+/*
+ * Check a public RSA key
+ */
+int rsa_check_pubkey( const rsa_context *ctx )
+{
+    if( !ctx->N.p || !ctx->E.p )
+        return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+
+    if( ( ctx->N.p[0] & 1 ) == 0 || 
+        ( ctx->E.p[0] & 1 ) == 0 )
+        return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+
+    if( mpi_msb( &ctx->N ) < 128 ||
+        mpi_msb( &ctx->N ) > 4096 )
+        return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+
+    if( mpi_msb( &ctx->E ) < 2 ||
+        mpi_msb( &ctx->E ) > 64 )
+        return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+
+    return( 0 );
+}
+
+/*
+ * Check a private RSA key
+ */
+int rsa_check_privkey( const rsa_context *ctx )
+{
+    int ret;
+    mpi PQ, DE, P1, Q1, H, I, G, G2, L1, L2;
+
+    if( ( ret = rsa_check_pubkey( ctx ) ) != 0 )
+        return( ret );
+
+    if( !ctx->P.p || !ctx->Q.p || !ctx->D.p )
+        return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );
+
+    mpi_init( &PQ, &DE, &P1, &Q1, &H, &I, &G, &G2, &L1, &L2, NULL );
+
+    MPI_CHK( mpi_mul_mpi( &PQ, &ctx->P, &ctx->Q ) );
+    MPI_CHK( mpi_mul_mpi( &DE, &ctx->D, &ctx->E ) );
+    MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) );
+    MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) );
+    MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) );
+    MPI_CHK( mpi_gcd( &G, &ctx->E, &H  ) );
+
+    MPI_CHK( mpi_gcd( &G2, &P1, &Q1 ) );
+    MPI_CHK( mpi_div_mpi( &L1, &L2, &H, &G2 ) );  
+    MPI_CHK( mpi_mod_mpi( &I, &DE, &L1  ) );
+
+    /*
+     * Check for a valid PKCS1v2 private key
+     */
+    if( mpi_cmp_mpi( &PQ, &ctx->N ) == 0 &&
+        mpi_cmp_int( &L2, 0 ) == 0 &&
+        mpi_cmp_int( &I, 1 ) == 0 &&
+        mpi_cmp_int( &G, 1 ) == 0 )
+    {
+        mpi_free( &G, &I, &H, &Q1, &P1, &DE, &PQ, &G2, &L1, &L2, NULL );
+        return( 0 );
+    }
+
+    
+cleanup:
+
+    mpi_free( &G, &I, &H, &Q1, &P1, &DE, &PQ, &G2, &L1, &L2, NULL );
+    return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED | ret );
+}
+
+/*
+ * Do an RSA public key operation
+ */
+int rsa_public( rsa_context *ctx,
+                const unsigned char *input,
+                unsigned char *output )
+{
+    int ret, olen;
+    mpi T;
+
+    mpi_init( &T, NULL );
+
+    MPI_CHK( mpi_read_binary( &T, input, ctx->len ) );
+
+    if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
+    {
+        mpi_free( &T, NULL );
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+    }
+
+    olen = ctx->len;
+    MPI_CHK( mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) );
+    MPI_CHK( mpi_write_binary( &T, output, olen ) );
+
+cleanup:
+
+    mpi_free( &T, NULL );
+
+    if( ret != 0 )
+        return( POLARSSL_ERR_RSA_PUBLIC_FAILED | ret );
+
+    return( 0 );
+}
+
+/*
+ * Do an RSA private key operation
+ */
+int rsa_private( rsa_context *ctx,
+                 const unsigned char *input,
+                 unsigned char *output )
+{
+    int ret, olen;
+    mpi T, T1, T2;
+
+    mpi_init( &T, &T1, &T2, NULL );
+
+    MPI_CHK( mpi_read_binary( &T, input, ctx->len ) );
+
+    if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
+    {
+        mpi_free( &T, NULL );
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+    }
+
+#if 0
+    MPI_CHK( mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) );
+#else
+    /*
+     * faster decryption using the CRT
+     *
+     * T1 = input ^ dP mod P
+     * T2 = input ^ dQ mod Q
+     */
+    MPI_CHK( mpi_exp_mod( &T1, &T, &ctx->DP, &ctx->P, &ctx->RP ) );
+    MPI_CHK( mpi_exp_mod( &T2, &T, &ctx->DQ, &ctx->Q, &ctx->RQ ) );
+
+    /*
+     * T = (T1 - T2) * (Q^-1 mod P) mod P
+     */
+    MPI_CHK( mpi_sub_mpi( &T, &T1, &T2 ) );
+    MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->QP ) );
+    MPI_CHK( mpi_mod_mpi( &T, &T1, &ctx->P ) );
+
+    /*
+     * output = T2 + T * Q
+     */
+    MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->Q ) );
+    MPI_CHK( mpi_add_mpi( &T, &T2, &T1 ) );
+#endif
+
+    olen = ctx->len;
+    MPI_CHK( mpi_write_binary( &T, output, olen ) );
+
+cleanup:
+
+    mpi_free( &T, &T1, &T2, NULL );
+
+    if( ret != 0 )
+        return( POLARSSL_ERR_RSA_PRIVATE_FAILED | ret );
+
+    return( 0 );
+}
+
+/*
+ * Add the message padding, then do an RSA operation
+ */
+int rsa_pkcs1_encrypt( rsa_context *ctx,
+                       int (*f_rng)(void *),
+                       void *p_rng,
+                       int mode, int  ilen,
+                       const unsigned char *input,
+                       unsigned char *output )
+{
+    int nb_pad, olen;
+    unsigned char *p = output;
+
+    olen = ctx->len;
+
+    switch( ctx->padding )
+    {
+        case RSA_PKCS_V15:
+
+            if( ilen < 0 || olen < ilen + 11 || f_rng == NULL )
+                return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+            nb_pad = olen - 3 - ilen;
+
+            *p++ = 0;
+            *p++ = RSA_CRYPT;
+
+            while( nb_pad-- > 0 )
+            {
+                int rng_dl = 100;
+
+                do {
+                    *p = (unsigned char) f_rng( p_rng );
+                } while( *p == 0 && --rng_dl );
+
+                // Check if RNG failed to generate data
+                //
+                if( rng_dl == 0 )
+                    return POLARSSL_ERR_RSA_RNG_FAILED;
+
+                p++;
+            }
+            *p++ = 0;
+            memcpy( p, input, ilen );
+            break;
+
+        default:
+
+            return( POLARSSL_ERR_RSA_INVALID_PADDING );
+    }
+
+    return( ( mode == RSA_PUBLIC )
+            ? rsa_public(  ctx, output, output )
+            : rsa_private( ctx, output, output ) );
+}
+
+/*
+ * Do an RSA operation, then remove the message padding
+ */
+int rsa_pkcs1_decrypt( rsa_context *ctx,
+                       int mode, int *olen,
+                       const unsigned char *input,
+                       unsigned char *output,
+                       int output_max_len)
+{
+    int ret, ilen;
+    unsigned char *p;
+    unsigned char buf[1024];
+
+    ilen = ctx->len;
+
+    if( ilen < 16 || ilen > (int) sizeof( buf ) )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    ret = ( mode == RSA_PUBLIC )
+          ? rsa_public(  ctx, input, buf )
+          : rsa_private( ctx, input, buf );
+
+    if( ret != 0 )
+        return( ret );
+
+    p = buf;
+
+    switch( ctx->padding )
+    {
+        case RSA_PKCS_V15:
+
+            if( *p++ != 0 || *p++ != RSA_CRYPT )
+                return( POLARSSL_ERR_RSA_INVALID_PADDING );
+
+            while( *p != 0 )
+            {
+                if( p >= buf + ilen - 1 )
+                    return( POLARSSL_ERR_RSA_INVALID_PADDING );
+                p++;
+            }
+            p++;
+            break;
+
+        default:
+
+            return( POLARSSL_ERR_RSA_INVALID_PADDING );
+    }
+
+    if (ilen - (int)(p - buf) > output_max_len)
+    	return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE );
+
+    *olen = ilen - (int)(p - buf);
+    memcpy( output, p, *olen );
+
+    return( 0 );
+}
+
+/*
+ * Do an RSA operation to sign the message digest
+ */
+int rsa_pkcs1_sign( rsa_context *ctx,
+                    int mode,
+                    int hash_id,
+                    int hashlen,
+                    const unsigned char *hash,
+                    unsigned char *sig )
+{
+    int nb_pad, olen;
+    unsigned char *p = sig;
+
+    olen = ctx->len;
+
+    switch( ctx->padding )
+    {
+        case RSA_PKCS_V15:
+
+            switch( hash_id )
+            {
+                case SIG_RSA_RAW:
+                    nb_pad = olen - 3 - hashlen;
+                    break;
+
+                case SIG_RSA_MD2:
+                case SIG_RSA_MD4:
+                case SIG_RSA_MD5:
+                    nb_pad = olen - 3 - 34;
+                    break;
+
+                case SIG_RSA_SHA1:
+                    nb_pad = olen - 3 - 35;
+                    break;
+
+                case SIG_RSA_SHA224:
+                    nb_pad = olen - 3 - 47;
+                    break;
+
+                case SIG_RSA_SHA256:
+                    nb_pad = olen - 3 - 51;
+                    break;
+
+                case SIG_RSA_SHA384:
+                    nb_pad = olen - 3 - 67;
+                    break;
+
+                case SIG_RSA_SHA512:
+                    nb_pad = olen - 3 - 83;
+                    break;
+
+
+                default:
+                    return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+            }
+
+            if( nb_pad < 8 )
+                return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+            *p++ = 0;
+            *p++ = RSA_SIGN;
+            memset( p, 0xFF, nb_pad );
+            p += nb_pad;
+            *p++ = 0;
+            break;
+
+        default:
+
+            return( POLARSSL_ERR_RSA_INVALID_PADDING );
+    }
+
+    switch( hash_id )
+    {
+        case SIG_RSA_RAW:
+            memcpy( p, hash, hashlen );
+            break;
+
+        case SIG_RSA_MD2:
+            memcpy( p, ASN1_HASH_MDX, 18 );
+            memcpy( p + 18, hash, 16 );
+            p[13] = 2; break;
+
+        case SIG_RSA_MD4:
+            memcpy( p, ASN1_HASH_MDX, 18 );
+            memcpy( p + 18, hash, 16 );
+            p[13] = 4; break;
+
+        case SIG_RSA_MD5:
+            memcpy( p, ASN1_HASH_MDX, 18 );
+            memcpy( p + 18, hash, 16 );
+            p[13] = 5; break;
+
+        case SIG_RSA_SHA1:
+            memcpy( p, ASN1_HASH_SHA1, 15 );
+            memcpy( p + 15, hash, 20 );
+            break;
+
+        case SIG_RSA_SHA224:
+            memcpy( p, ASN1_HASH_SHA2X, 19 );
+            memcpy( p + 19, hash, 28 );
+            p[1] += 28; p[14] = 4; p[18] += 28; break;
+
+        case SIG_RSA_SHA256:
+            memcpy( p, ASN1_HASH_SHA2X, 19 );
+            memcpy( p + 19, hash, 32 );
+            p[1] += 32; p[14] = 1; p[18] += 32; break;
+
+        case SIG_RSA_SHA384:
+            memcpy( p, ASN1_HASH_SHA2X, 19 );
+            memcpy( p + 19, hash, 48 );
+            p[1] += 48; p[14] = 2; p[18] += 48; break;
+
+        case SIG_RSA_SHA512:
+            memcpy( p, ASN1_HASH_SHA2X, 19 );
+            memcpy( p + 19, hash, 64 );
+            p[1] += 64; p[14] = 3; p[18] += 64; break;
+
+        default:
+            return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+    }
+
+    return( ( mode == RSA_PUBLIC )
+            ? rsa_public(  ctx, sig, sig )
+            : rsa_private( ctx, sig, sig ) );
+}
+
+/*
+ * Do an RSA operation and check the message digest
+ */
+int rsa_pkcs1_verify( rsa_context *ctx,
+                      int mode,
+                      int hash_id,
+                      int hashlen,
+                      const unsigned char *hash,
+                      unsigned char *sig )
+{
+    int ret, len, siglen;
+    unsigned char *p, c;
+    unsigned char buf[1024];
+
+    siglen = ctx->len;
+
+    if( siglen < 16 || siglen > (int) sizeof( buf ) )
+        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
+
+    ret = ( mode == RSA_PUBLIC )
+          ? rsa_public(  ctx, sig, buf )
+          : rsa_private( ctx, sig, buf );
+
+    if( ret != 0 )
+        return( ret );
+
+    p = buf;
+
+    switch( ctx->padding )
+    {
+        case RSA_PKCS_V15:
+
+            if( *p++ != 0 || *p++ != RSA_SIGN )
+                return( POLARSSL_ERR_RSA_INVALID_PADDING );
+
+            while( *p != 0 )
+            {
+                if( p >= buf + siglen - 1 || *p != 0xFF )
+                    return( POLARSSL_ERR_RSA_INVALID_PADDING );
+                p++;
+            }
+            p++;
+            break;
+
+        default:
+
+            return( POLARSSL_ERR_RSA_INVALID_PADDING );
+    }
+
+    len = siglen - (int)( p - buf );
+
+    if( len == 34 )
+    {
+        c = p[13];
+        p[13] = 0;
+
+        if( memcmp( p, ASN1_HASH_MDX, 18 ) != 0 )
+            return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+
+        if( ( c == 2 && hash_id == SIG_RSA_MD2 ) ||
+            ( c == 4 && hash_id == SIG_RSA_MD4 ) ||
+            ( c == 5 && hash_id == SIG_RSA_MD5 ) )
+        {
+            if( memcmp( p + 18, hash, 16 ) == 0 ) 
+                return( 0 );
+            else
+                return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+        }
+    }
+
+    if( len == 35 && hash_id == SIG_RSA_SHA1 )
+    {
+        if( memcmp( p, ASN1_HASH_SHA1, 15 ) == 0 &&
+            memcmp( p + 15, hash, 20 ) == 0 )
+            return( 0 );
+        else
+            return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+    }
+    if( ( len == 19 + 28 && p[14] == 4 && hash_id == SIG_RSA_SHA224 ) ||
+        ( len == 19 + 32 && p[14] == 1 && hash_id == SIG_RSA_SHA256 ) ||
+        ( len == 19 + 48 && p[14] == 2 && hash_id == SIG_RSA_SHA384 ) ||
+        ( len == 19 + 64 && p[14] == 3 && hash_id == SIG_RSA_SHA512 ) )
+    {
+    	c = p[1] - 17;
+        p[1] = 17;
+        p[14] = 0;
+
+        if( p[18] == c &&
+                memcmp( p, ASN1_HASH_SHA2X, 18 ) == 0 &&
+                memcmp( p + 19, hash, c ) == 0 )
+            return( 0 );
+        else
+            return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+    }
+
+    if( len == hashlen && hash_id == SIG_RSA_RAW )
+    {
+        if( memcmp( p, hash, hashlen ) == 0 )
+            return( 0 );
+        else
+            return( POLARSSL_ERR_RSA_VERIFY_FAILED );
+    }
+
+    return( POLARSSL_ERR_RSA_INVALID_PADDING );
+}
+
+/*
+ * Free the components of an RSA key
+ */
+void rsa_free( rsa_context *ctx )
+{
+    mpi_free( &ctx->RQ, &ctx->RP, &ctx->RN,
+              &ctx->QP, &ctx->DQ, &ctx->DP,
+              &ctx->Q,  &ctx->P,  &ctx->D,
+              &ctx->E,  &ctx->N,  NULL );
+}
+
+
+int myrand( void *rng_state )
+{
+    if( rng_state != NULL )
+        rng_state  = NULL;
+
+    return( rand() );
+}
+
+//RSA-1024
+#define KEY_LEN 128
+
+#define RSA_N   "7AD4B6862361FC78613274E368AB8997" \
+                "E3D8D0268176624F8CBD466B2FA9BF76" \
+                "541C86E8F759C9EA3D1250FDB50575DD" \
+                "3562F567667C96866D8C0887AC70D05C" \
+                "E40D87A918CA6511F5FD224FC90F51CF" \
+                "A481BF3A4813D22A96FE8B36515314C0" \
+                "A044CA60D04BA1381E475029FF62F352" \
+                "8CDC407292AD7CB02BF9F89E2E0B02CB"
+
+#define RSA_E   "65537"
+
+#define RSA_D   "23F9950763921D30C0F10290527978D2" \
+                "7786CCDAB46CD564FD8B9AD4C3F82DF8" \
+                "BD2B5A047466325D39D1B33F7C8C53A2" \
+                "C8EA375F8492FA71933979E5F3295728" \
+                "7F6C5D73DFDA92FE287EBA0408D0D264" \
+                "D4C32D91A1BE7A89F6F06F30EF1B2083" \
+                "F26AE55BE46E26279CDE13C5DC3F945C" \
+                "D593D5C359541271FEB1F588E1F023CF"
+
+#define RSA_P   "B81B60220C9C6B930E32AA8A5BA31683" \
+                "DAF23E20667D9260BA53F31D9CD979CA" \
+                "4B9F856C2C7F09D7B2F6162C8DC5A592" \
+                "16C9A833F81953792260A688EB7C3F1D"
+
+#define RSA_Q   "AACBC13F7CDC6DE0BEED53AF68CF69D5" \
+                "7ED27BDF36DD74F7E6CFF06632180648" \
+                "759251906FA33F3E2F979CDD41396042" \
+                "1AB3B781C3A65032C38BE9E4514B1D07"
+
+#define RSA_DP  "13AD57D729F248656D49B206C5C5D90A" \
+                "350907A004DADCA94BA56ADEEB2F6E02" \
+                "45295128ED2F125CF125A76E94A5698E" \
+                "D10AD5471CFE8906838BD64BA6AA041F"
+
+#define RSA_DQ  "43F654E13885AB914A4F74FE5D2A43D2" \
+                "47ADC44C52F8B958EE3EDD972C4CF513" \
+                "83F9CB230A1AACE73CC4C53DD935D141" \
+                "7FF2E997C933DE9789791160FF3860F5"
+
+#define RSA_QP  "6CB241916FAFC385CAC87F04F4FCDADA" \
+                "1584AF749F42F2FF239C9F32B6430FCC" \
+                "81CAD12196897BDFB40E2CD6FC968DA7" \
+                "C5672E607BE70159D933A0EFB2D034BA"
+
+int rsa_private_decrypt(const unsigned char *rsa_ciphertext, unsigned char *rsa_decrypted)
+{    
+    rsa_context rsa;
+    
+    rsa_init( &rsa, RSA_PKCS_V15, 0 );
+    
+    rsa.len = KEY_LEN;
+    mpi_read_string( &rsa.N , 16, RSA_N  );
+    mpi_read_string( &rsa.E , 16, RSA_E  );
+    mpi_read_string( &rsa.D , 16, RSA_D  );
+    mpi_read_string( &rsa.P , 16, RSA_P  );
+    mpi_read_string( &rsa.Q , 16, RSA_Q  );
+    mpi_read_string( &rsa.DP, 16, RSA_DP );
+    mpi_read_string( &rsa.DQ, 16, RSA_DQ );
+    mpi_read_string( &rsa.QP, 16, RSA_QP );
+    
+    if( rsa_check_pubkey(  &rsa ) != 0 ||
+                         rsa_check_privkey( &rsa ) != 0 )
+    {
+        at_print(AT_DEBUG, "rsa_check failed\n" );
+        return -1;
+    }
+    
+    if( rsa_private(&rsa, rsa_ciphertext, rsa_decrypted) != 0 )
+    {
+       at_print(AT_DEBUG,"rsa_private failed\n" );
+        return -1;
+    }
+    
+    rsa_free( &rsa );
+    
+    at_print(AT_DEBUG,"decrypt passed\n\n" );    
+    return 0;
+}
+
+#endif
diff --git a/ap/app/zte_comm/zte_locknet/src/zctrm_locknet_main.c b/ap/app/zte_comm/zte_locknet/src/zctrm_locknet_main.c
new file mode 100755
index 0000000..ed4968f
--- /dev/null
+++ b/ap/app/zte_comm/zte_locknet/src/zctrm_locknet_main.c
@@ -0,0 +1,90 @@
+#include <stdio.h>

+#include <unistd.h>

+#include "zctrm_locknet.h"

+

+int sendflag = 0;

+void locknet_msg_proc(MSG_BUF *msg_buf)

+{

+	switch (msg_buf->usMsgCmd) {

+	case MSG_CMD_LOCKLISTAUTH_REQ: 

+		zCtrm_LocknetAuthProc(msg_buf);

+		break;

+	

+	case MSG_CMD_LOCKNETLIST_SET_REQ: 

+		zCtrm_LocknetListSet(msg_buf);

+		break;

+		

+	case MSG_CMD_LOCKNETKEY_REQ: 

+		zCtrm_LocknetKeyProc(msg_buf);

+		break;

+

+	case MSG_CMD_LOCKNETAMTSTATUS_GET_REQ: 

+		zCtrm_LocknetAmtStatus(msg_buf);

+		break;

+

+	case MSG_CMD_LOCKNETDIGEST_GET_REQ:

+		zCtrm_LocknetDigestGet(msg_buf);

+		break;

+

+	case MSG_CMD_LOCKNETSIGN_SET_REQ:

+		zCtrm_LocknetSignSet(msg_buf);

+		break;

+

+	case MSG_CMD_LOCKNETLEVEL_GET_REQ:

+		zCtrm_LocknetLevel(msg_buf);

+		break;

+

+	case MSG_CMD_LOCKNETLIST_GET_REQ:

+		zCtrm_LocknetListGetProc(msg_buf);

+		break;

+		

+	case MSG_CMD_LOCKNETAUTH_REQ:

+		sendflag = 1;

+		zCtrm_makeLocknetAuth(msg_buf);

+		break;

+

+	case MSG_CMD_LOCKNETUNLOCKTIMES_GET_REQ:

+		zCtrm_LocknetUnlockTimes(msg_buf);

+		break;

+		

+	case MSG_CMD_LOCKNETSTATUS_GET_REQ: 

+		zCtrm_LocknetStatus(msg_buf);

+		break;

+	

+	case MSG_CMD_LOCKNETUNLOCK_REQ: 

+		zCtrm_LocknetUnlock(msg_buf);

+		break;

+	case MSG_CMD_ZURDY_LOCKAUTH_REQ:

+		zCtrm_makeLocknetAuth(msg_buf);

+		break;

+	default:

+		break;

+	}

+}

+

+int zte_locknet_main(int argc, char* argv[])

+{

+	int msg_handle = 0;

+	MSG_BUF msg;

+	LONG msg_size =  sizeof(MSG_BUF)-sizeof(LONG);

+	prctl(PR_SET_NAME, "locknet", 0, 0, 0);

+	/* ´´½¨ÏûÏ¢¶ÓÁÐ*/

+	msg_handle = msgget(MODULE_ID_LOCKNET, IPC_CREAT|0600);

+	while(1)

+	{

+		memset(&msg, 0x00, sizeof(MSG_BUF));

+

+		/* »ñÈ¡ÏûÏ¢¶ÓÁÐÏûÏ¢²¢´¦Àí*/

+		if (msgrcv(msg_handle, &msg, msg_size, 0, 0) >= 0)

+		{

+			locknet_msg_proc(&msg); 		   

+		}

+		else

+		{

+			if(errno != EINTR)

+				slog(AT_PRINT,SLOG_ERR,"locknet_main msgrcv errno = %d, errmsg = %s\n", errno,strerror(errno));

+		}

+	}

+

+	return 0;

+}

diff --git a/ap/app/zte_comm/zte_locknet/src/zctrm_locknet_proc.c b/ap/app/zte_comm/zte_locknet/src/zctrm_locknet_proc.c
new file mode 100755
index 0000000..01e220a
--- /dev/null
+++ b/ap/app/zte_comm/zte_locknet/src/zctrm_locknet_proc.c
@@ -0,0 +1,2191 @@
+#include "zctrm_locknet.h"

+//#include "drvs_efuse.h"

+#include "zctrm_ln_rsa.h"

+#include "zctrm_ln_md5.h"

+#include "RONvParam_AMT.h"

+//#include "ps_normal.h"

+//#include "ps_wifi.h"

+#include <limits.h>

+

+static BOOL g_IsDigestKeyGot = FALSE;

+static BOOL g_IsSetListKeyGot = FALSE;

+

+static BOOL g_IsSetListAuthSucc = FALSE;

+static BOOL g_NeedSecondList = FALSE;

+static BOOL g_IsKeyExist = FALSE;

+static BOOL g_IsDigestGotSucc = FALSE;

+

+static BOOL g_IsUnlockKeyGot = FALSE;

+static UINT8 g_UnlockKeyPlaint[LOCKNET_KEY_LEN+1] = {0};

+

+static UINT8 g_SetListPlaint[LOCKNET_KEY_LEN+1] = {0};

+

+static T_ZDrvEfuse_Secure g_Efuse_Secure={0};

+

+T_zCtrm_LockListPara simLockListPara = {0};

+T_zCtrm_SIMPara simPara = {0};

+SINT32 g_Sec_Status = ENCRYPT_INITING;

+extern int sendflag;

+

+SINT32 zCtrm_Atohex(CHAR c)

+{

+    SINT32 result = 0;

+    

+    if(c >= '0' && c <= '9')

+    {

+        result = c - '0';

+    }

+    else if(c>='a' && c<='f')

+    {

+        result = (c - 'a') + 10;

+    }

+    else if(c>='A' && c<='F')

+    {

+        result = (c - 'A') + 10;

+    }

+    else

+    {

+        at_print(AT_ERR,"zCtrm_Atohex error,can unknown char:%c\n",c);

+        return result;

+    }

+    return result;

+}

+

+static SINT32 zCtrm_Strnicmp(const CHAR * cs,const CHAR * ct,UINT32 count)

+{

+    SINT32 res = 0;

+    

+    while (count) 

+    {

+        if ((res = toupper(*cs)- toupper(*ct++)) != 0 || !*cs++)

+            break;

+        count--;

+    }

+    

+    return res;

+}

+VOID ConvertToBigEndian(unsigned int *data)

+{

+	*data = ((*data & 0xff000000) >> 24)

+            | ((*data & 0x00ff0000) >>  8)

+            | ((*data & 0x0000ff00) <<  8)

+            | ((*data & 0x000000ff) << 24) ;

+}

+

+static UINT32 zCtrm_Bytes2String(const UINT8* pSrc, CHAR* pDst, UINT16 srcLength)

+{

+	const UINT8 tab[]="0123456789ABCDEF";

+    int iSrc=0;

+

+#if 1   // cov M srcLength is unsigned

+    if(pSrc ==	NULL || pDst == NULL )

+    {

+    	return -1;

+    }

+

+#else

+    if(pSrc ==  NULL || pDst == NULL || srcLength < 0)

+    {

+    	return -1;

+    }

+#endif   

+    for(iSrc=0; iSrc<srcLength; iSrc++)

+    {

+        *pDst++ = tab[*pSrc >> 4];

+        *pDst++ = tab[*pSrc & 0x0f];

+        pSrc++;

+    }

+   

+    *pDst = '\0';

+   

+    return srcLength * 2;

+}

+

+static UINT32 makeLocknetKeyRandom(VOID)

+{

+    UINT32 val = 0;

+	UINT32 seed = (UINT32)time( NULL );

+	int fd = open("/dev/urandom",O_RDONLY);

+

+	if(fd >= 0)

+	{

+		int i = 0;

+		UINT32 rand = 0;

+		for(i = 0; i < 128; i++)

+		{

+			if(read(fd, &rand, sizeof(rand)) > 0)

+			{

+				if(rand > UINT_MAX-1)	// kw 3 cov M

+				{

+					rand = UINT_MAX;

+				}		

+				seed += rand;

+				if(seed > UINT_MAX-1)	// kw 3 cov M

+				{

+					seed = UINT_MAX;

+				}		

+			}

+		}

+		close(fd);

+	}

+   

+    srand(seed);

+    val = rand() + (rand() ^ 2) + 1;

+    val %= 100000000;

+   	

+    return val;

+}

+

+static VOID zCtrm_LocknetKeyGen(UINT8 *plainText, UINT16 len)

+{

+	UINT32 r1 = 0;

+    UINT32 r2 = 0;

+    UINT8 key[LOCKNET_KEY_LEN + 1] = {0};

+       

+    r1 = makeLocknetKeyRandom();

+    r2 = makeLocknetKeyRandom();

+    snprintf((char *)key, sizeof(key),"%08ld%08ld", r1, r2);        

+    memcpy(plainText, key, len);

+	at_print(AT_ERR,"zCtrm_LocknetKeyGen:plainText = %s\n",plainText); 

+}

+

+static UINT32 zCtrm_RsaPublicEncrypt(const UINT8 *plainText, UINT8 *cipherText,const char *rsa_n,const char *rsa_e)

+{    

+	rsa_context rsa;

+	   

+	rsa_init(&rsa, RSA_PKCS_V15, 0);

+	   

+	rsa.len = KEY_LEN;

+	mpi_read_string(&rsa.N, 16, rsa_n);

+	mpi_read_string(&rsa.E, 16, rsa_e);

+

+	if(rsa_check_pubkey(&rsa) != 0)

+	{

+		at_print(AT_ERR,"Encode check failed\n");

+	    return EXT_ERROR;

+	}

+	if(rsa_public(&rsa, plainText, cipherText) != 0)

+	{

+	    at_print(AT_ERR,"Encode check failed\n");

+	    return EXT_ERROR;

+	}

+	rsa_free(&rsa);

+

+	at_print(AT_ERR,"Encode passed\n");      

+	return EXT_SUCCESS;

+}

+

+//½«´ÓefuseÖжÁÈ¡µÄ¹«Ô¿²ÎÊý£¬½øÐдóС¶Ë´æ´¢×ª»»(±¾ÉíΪС¶Ë´æ´¢)

+UINT32 zCtrm_RsaPublicEncryptProc(const UINT8 *plainText, UINT8 *cipherText)

+{

+	UINT32 retCode = EXT_ERROR;  

+	unsigned int i;

+	UINT32 pubKeyRsaEOrder[32]={0};

+	UINT32 pubKeyRsaNOrder[32]={0};

+	char pubKeyRsaEtext[KEY_LEN*2+1]={0};

+	char pubKeyRsaNtext[KEY_LEN*2+1]={0};

+	int efuse_fd = -1;

+	int ret = -1;

+	

+	memset(&g_Efuse_Secure,0,sizeof(g_Efuse_Secure));

+	

+	efuse_fd = open("/dev/efuse", O_RDWR);

+	if (efuse_fd < 0) {

+		at_print(AT_ERR,"zCtrm_RsaPublicEncryptProc: efuse fd_func open fail.\n");

+		return EXT_ERROR;//klocwork

+	}

+

+	ret = ioctl(efuse_fd , EFUSE_GET_DATA, &g_Efuse_Secure);

+	

+	at_print(AT_ERR,"[zCtrm_RsaPublicEncryptProc]: pubKeyRsaE[%x] pubKeyRsaN[%x]\n",ret,g_Efuse_Secure.pubKeyRsaE[31],g_Efuse_Secure.pubKeyRsaN[0]);

+	close(efuse_fd);//klocwork

+	/*if(g_Efuse_Secure.pubKeyRsaN ==NULL || g_Efuse_Secure.pubKeyRsaE ==NULL)

+	{

+		at_print(AT_ERR,"Rsa NULL\n");  		

+		return EXT_ERROR;

+	}*/

+	

+	memcpy(pubKeyRsaEOrder,g_Efuse_Secure.pubKeyRsaE,sizeof(g_Efuse_Secure.pubKeyRsaE));

+	for(i=0;i<32;i++)

+	{

+	   ConvertToBigEndian(&pubKeyRsaEOrder[i]);

+	}

+	zCtrm_Bytes2String(pubKeyRsaEOrder, pubKeyRsaEtext, KEY_LEN);

+

+	memcpy(pubKeyRsaNOrder,g_Efuse_Secure.pubKeyRsaN,sizeof(g_Efuse_Secure.pubKeyRsaN));

+	for(i=0;i<32;i++)

+	{

+	   ConvertToBigEndian(&pubKeyRsaNOrder[i]);

+	}

+	zCtrm_Bytes2String(pubKeyRsaNOrder, pubKeyRsaNtext, KEY_LEN);

+	

+	at_print(AT_ERR,"zCtrm_RsaPublicEncryptProc:RsaN = %s\n",pubKeyRsaNtext);

+	at_print(AT_ERR,"zCtrm_RsaPublicEncryptProc:RsaE = %s\n",pubKeyRsaEtext);

+	

+	return zCtrm_RsaPublicEncrypt(plainText,cipherText,pubKeyRsaNtext,pubKeyRsaEtext);

+}

+

+static BOOL zCtrm_IsParaNum(UINT8 *data, UINT16 dataLen)

+{

+	UINT16 idata = 0;

+

+	if(*data == '\0')

+	{

+	   return TRUE;

+	}

+

+	for(idata = 0; idata < dataLen; idata++)

+	{

+	   if(*data < '0' || *data > '9')

+	   {

+	       at_print(AT_ERR,"zCtrm_IsParaNum error:%c!\n",*data);

+	       return FALSE;

+	   }

+	   data++;

+	}

+	return TRUE;

+}

+

+static UINT32 zCtrm_CheckListPara(UINT8 *data, UINT16 dataLen)

+{

+	UINT8 *pBegin = data;

+	UINT8 *pEnd = NULL;

+	UINT16 subLen = 0;

+	UINT16 iPara = 0;

+

+	for(iPara = 0; iPara < LOCKNET_ITEM_NUM; iPara++)

+	{        

+	   if(iPara < LOCKNET_ITEM_NUM - 1)

+	   {

+	       pEnd = strchr(pBegin,',');

+		   if (pEnd == NULL)//klocwork

+			   return EXT_ERROR;

+	       subLen = pEnd - pBegin;

+	   }

+	   else

+	   {

+	       subLen = dataLen - (pBegin - data);

+	   }

+	  

+	   switch(iPara)

+	   {

+	       case PARA_MCC:

+	       case PARA_MNC:

+	       {

+	           if(subLen > 3 || FALSE == zCtrm_IsParaNum(pBegin,subLen))

+	           {

+	               return EXT_ERROR;

+	           }

+	           break;

+	       }

+	       case PARA_IMSI6:

+	       case PARA_IMSI7:

+	       {

+	           if(subLen > 1 || FALSE == zCtrm_IsParaNum(pBegin,subLen))

+	           {

+	               return EXT_ERROR;

+	           }

+	           break;

+	       }

+	       case PARA_GID1:

+	       case PARA_GID2:

+	       {

+	           if(subLen > USED_GID_LEN) //one at, need opt

+	           {

+	               return EXT_ERROR;

+	           }

+	           break;

+	       }            

+	       default:

+	       {

+	           return EXT_ERROR;

+	       }

+	   }

+	   

+	   pBegin = pEnd + 1;                         

+	}

+

+	return EXT_SUCCESS;

+}

+

+static UINT32 zCtrm_CheckListNum(UINT8 *data, UINT16 dataLen, UINT16 *listnum)

+{

+	UINT8 *pBegin = NULL;

+	UINT8 *pEnd = NULL;

+	UINT16 iData = 0;

+	UINT16 count = 0;

+	UINT16 maxNum = LOCKNET_FIRST_NUM;

+

+	pBegin=data;

+	for(iData = 0; iData < dataLen; iData++)

+	{

+	   if(*pBegin == ';')

+	   {

+	       count++;

+	   }

+	   pBegin++;

+	}

+	   

+	if(g_NeedSecondList == TRUE)

+	{

+	   maxNum = LOCKNET_MAX_NUM - LOCKNET_FIRST_NUM;

+	}

+

+	if(count < 1 || count > maxNum)

+	{

+	   return EXT_ERROR;

+	}

+

+	pEnd=strrchr(data,';');

+	if (pEnd == NULL)//klocwork

+		return EXT_ERROR;

+	if(('\0' == *(char *)(pEnd+1))||(0 == strncmp(pEnd+1,"next",strlen("next")) && count == LOCKNET_FIRST_NUM) )

+	{

+	   *listnum = count;

+	   at_print(AT_ERR,"zCtrm_CheckListNum pEnd:--%s--\n",pEnd);

+	   return EXT_SUCCESS;

+	}

+

+	at_print(AT_ERR,"zCtrm_CheckListNum err:--%s--\n",pEnd);

+	return EXT_ERROR;

+

+}

+

+static VOID zCtrm_GetListPara(UINT8 *data, UINT16 dataLen, T_zCtrm_LockListPara *para)

+{

+	UINT8 *pBegin = data;

+	UINT8 *pEnd = NULL;

+	UINT16 subLen = 0;

+	UINT16 iPara = 0;

+

+	for(iPara = 0; iPara < LOCKNET_ITEM_NUM; iPara++)

+	{        

+		if(iPara < LOCKNET_ITEM_NUM -1)

+		{

+		   pEnd = strchr(pBegin,',');

+		   if (pEnd == NULL)//klocwork

+				return;

+		   subLen = pEnd - pBegin;

+		}

+		else

+		{

+		   subLen = dataLen - (pBegin - data);

+		}

+

+		switch(iPara)

+		{

+			case PARA_MCC:

+			{

+				if (subLen < sizeof(para->mcc)) {//klocwork

+					memset(para->mcc,0,sizeof(para->mcc));

+					snprintf(para->mcc,subLen+1,"%s",pBegin);

+					//strncpy(para->mcc,pBegin,subLen);  

+				}

+				break;

+			}

+			case PARA_MNC:

+			{

+				if (subLen < sizeof(para->mnc)) {

+					memset(para->mnc,0,sizeof(para->mnc));

+					snprintf(para->mnc,subLen+1,"%s",pBegin);

+					//strncpy(para->mnc,pBegin,subLen);  

+				}

+				break;

+			}

+			case PARA_IMSI6:

+			{

+				if (subLen < sizeof(para->imsi6)) {

+					memset(para->imsi6,0,sizeof(para->imsi6));

+					snprintf(para->imsi6,subLen+1,"%s",pBegin);

+					//strncpy(para->imsi6,pBegin,subLen);  

+				}

+				break;

+			}

+			case PARA_IMSI7:

+			{

+				if (subLen < sizeof(para->imsi7)) {

+					memset(para->imsi7,0,sizeof(para->imsi7));

+					snprintf(para->imsi7,subLen+1,"%s",pBegin);

+					//strncpy(para->imsi7,pBegin,subLen);

+				}

+				break;

+			}

+			case PARA_GID1:

+			{

+				if (subLen < sizeof(para->gid1)) {

+					memset(para->gid1,0,sizeof(para->gid1));

+					snprintf(para->gid1,subLen+1,"%s",pBegin);

+					//strncpy(para->gid1,pBegin,subLen); 

+				}

+				break;

+			}

+			case PARA_GID2:

+			{

+				if (subLen < sizeof(para->gid2)) {

+					memset(para->gid2,0,sizeof(para->gid2));

+					snprintf(para->gid2,subLen+1,"%s",pBegin);

+					//strncpy(para->gid2,pBegin,subLen);  

+				}

+				break;

+			}            

+			default:

+			{

+				break;

+			}

+		}

+

+		pBegin = pEnd + 1;                         

+	}

+

+}

+

+static UINT32 zCtrm_CleanAmtList(VOID)

+{

+	UINT32	retCode = EXT_ERROR;

+	UINT16 iList = 0;

+	T_zCtrm_LockListPara lockList = {0};

+	  

+	memset((UINT8 *)&lockList,0xFF,sizeof(lockList));

+	for(iList = 0; iList < LOCKNET_MAX_NUM; iList++)

+	{  

+	   

+	   

+	   cpnv_ChangeNvRoAttr(1);

+	   //retCode = zDrvNand_Program(AMT_LOCKNET_LIST + iList*sizeof(lockList), sizeof(lockList), (UINT8 *)&lockList);

+	   retCode = cpnv_NvItemWriteNvro(AMT_LOCKNET_LIST + iList*sizeof(lockList), (UINT8 *)&lockList, sizeof(lockList));

+	   cpnv_FsGcWait(FS_NVROFS);

+	   cpnv_ChangeNvRoAttr(0);

+	   if (EXT_SUCCESS != retCode )

+	   {   

+	       return EXT_ERROR;

+	   }

+	   

+	}

+	return EXT_SUCCESS;

+}

+

+static UINT32 zCtrm_WriteLocklist(UINT8 *data, UINT16 dataLen)

+{

+	UINT8 *pBegin = data;

+	UINT8 *pEnd = NULL;

+	UINT8 tStr[LOCKNET_MAX_AT_LEN] = {0};

+	UINT16 listCount = 0;

+	UINT16 iList = 0;

+	UINT16 offset = 0;

+	UINT32	retCode = EXT_ERROR;

+

+	if(EXT_SUCCESS != zCtrm_CheckListNum(data, dataLen, &listCount))

+	{        

+	   return EXT_ERROR;

+	}

+	at_print(AT_ERR,"zCtrm_WriteLocklist listcount:%d!\n",listCount);

+

+	if(g_NeedSecondList == TRUE)

+	{

+	   offset = LOCKNET_FIRST_NUM;

+	}

+	else

+	{

+	   if(zCtrm_CleanAmtList() != EXT_SUCCESS)

+	   {

+	       return EXT_ERROR;

+	   }

+	}

+

+	for(iList = 0; iList < listCount; iList++)

+	{  

+	   T_zCtrm_LockListPara lockList = {0};

+	   unsigned int slen = 0;//klocwork

+	   

+	   pEnd=strchr(pBegin,';');

+	   if (pEnd == NULL)//klocwork

+		   return EXT_ERROR;

+	   slen = pEnd-pBegin;

+	   if(slen < sizeof(tStr)) {

+		   memset(tStr,0,sizeof(tStr));

+		   snprintf(tStr,slen+1,"%s",pBegin);

+		   //strncpy(tStr,pBegin,slen); 

+	   } else {        

+	       return EXT_ERROR;

+	   }

+	    

+	   zCtrm_GetListPara(tStr,slen,&lockList);      

+	   	   

+	   cpnv_ChangeNvRoAttr(1);

+	   //retCode = zDrvNand_Program(AMT_LOCKNET_LIST + (offset + iList)*sizeof(lockList), sizeof(lockList), (UINT8 *)&lockList);

+	   retCode = cpnv_NvItemWriteNvro(AMT_LOCKNET_LIST + (offset + iList)*sizeof(lockList), (UINT8 *)&lockList, sizeof(lockList));

+	   cpnv_FsGcWait(FS_NVROFS);

+	   cpnv_ChangeNvRoAttr(0);

+	   if (EXT_SUCCESS != retCode )

+	   {   

+	       return EXT_ERROR;

+	   } 

+	   

+	   pBegin = pEnd + 1;                  

+	}

+

+	return EXT_SUCCESS;

+}

+

+static UINT32 zCtrm_GetUnlockMaxTime(VOID)

+{   

+	UINT32 retCode = EXT_ERROR;   

+	UINT32 timet = 0;

+	char time[AT_STR_LEN] = {0};

+	//timet = atoi(cfg_get("zunlocktimes"));

+	sc_cfg_get("zunlocktimes", time, sizeof(time));

+	timet = atoi(time);

+	at_print(AT_ERR,"zCtrm_GetUnlockMaxTime:%d---\n" ,timet);    

+

+	return timet;

+}

+

+static UINT32 zCtrm_LocknetNandSet(UINT8 *plainText, UINT16 len)

+{

+	T_zCtrm_LockLevel lockState = LOCKED;

+	UINT32 times = zCtrm_GetUnlockMaxTime();

+	UINT32 retCode = EXT_ERROR;

+

+	cpnv_ChangeNvRoAttr(1);

+

+	//retCode = zDrvNand_Program(AMT_LOCKNET_TIMES, sizeof(times),(UINT8 *)&times);

+	retCode = cpnv_NvItemWriteNvro(AMT_LOCKNET_TIMES, (UINT8 *)&times, sizeof(times));

+	if (EXT_SUCCESS != retCode)

+	{  

+	   cpnv_ChangeNvRoAttr(0);   

+	   return EXT_ERROR;

+	}

+

+	//retCode = zDrvNand_Program(AMT_LOCKNET_KEY, len, plainText);

+	retCode = cpnv_NvItemWriteNvro(AMT_LOCKNET_KEY, plainText, len);

+	if (EXT_SUCCESS != retCode)

+	{  

+	   cpnv_ChangeNvRoAttr(0);   

+	   return EXT_ERROR;

+	}

+

+	//retCode = zDrvNand_Program(AMT_LOCKNET_BASE, sizeof(lockState),(UINT8 *)&lockState);

+	retCode = cpnv_NvItemWriteNvro(AMT_LOCKNET_BASE, (UINT8 *)&lockState, sizeof(lockState));

+	if (EXT_SUCCESS != retCode)

+	{   

+	   cpnv_ChangeNvRoAttr(0);   

+	   return EXT_ERROR;

+	}

+	cpnv_FsGcWait(FS_NVROFS);

+	cpnv_ChangeNvRoAttr(0);    

+	return EXT_SUCCESS;

+}

+

+static UINT32 zCtrm_LocknetStaticCheck(VOID)

+{

+	T_zCtrm_LockLevel  lockState = LOCKFLAG_ERROR;

+	UINT32	retCode = EXT_ERROR;

+

+	//retCode = zDrvNand_Read(AMT_LOCKNET_BASE,sizeof(lockState),(UINT8 *)&lockState); //len=4

+	retCode = cpnv_NvItemRead(AMT_LOCKNET_BASE, (UINT8 *)&lockState, sizeof(lockState));

+	at_print(AT_ERR,"zCtrm_LocknetStaticCheck ret=%d lockstat=%d\n",retCode,lockState);

+	if (EXT_SUCCESS == retCode)

+	{

+	   if(lockState == NEVER_LOCKED)

+	   {

+	       return EXT_SUCCESS;

+	   }

+	}

+

+	return EXT_ERROR;

+}

+

+static UINT32 zCtrm_LocknetListCheck(VOID)

+{

+	T_zCtrm_LockListPara lockList = {0};

+	UINT32	retCode = EXT_ERROR;

+

+	//retCode = zDrvNand_Read(AMT_LOCKNET_LIST, sizeof(lockList), (UINT8 *)&lockList); 

+	retCode = cpnv_NvItemRead(AMT_LOCKNET_LIST, (UINT8 *)&lockList, sizeof(lockList));

+	if (EXT_SUCCESS != retCode )

+	{       

+	   return EXT_ERROR;        

+	}

+	   

+	if((lockList.mcc[0] == 0xFF)||(lockList.imsi6[0] == 0xFF)||(lockList.gid1[0] == 0xFF))

+	{

+	   at_print(AT_ERR,"zCtrm_LocknetListCheck FF\n");

+	   return EXT_ERROR;

+	}

+

+	return EXT_SUCCESS;

+}

+

+static UINT32 zCtrm_CheckLocklist(UINT8 *data, UINT16 dataLen)

+{

+	UINT8 *pBegin = data;

+	UINT8 *pEnd = NULL;

+	UINT16 iItem = 0;

+	UINT8 *pPara = NULL;

+	UINT16 listCount = 0;

+	UINT16 paraCount = 0;

+

+	if(EXT_SUCCESS != zCtrm_CheckListNum(data, dataLen, &listCount))

+	{        

+	   return EXT_ERROR;

+	}

+	at_print(AT_ERR,"zCtrm_CheckLocklist listCount = %d\n",listCount); 

+

+	for(iItem = 0; iItem < listCount; iItem++)

+	{        

+		pEnd = strchr(pBegin,';');

+		if (pEnd == NULL)//klocwork

+			return EXT_ERROR;

+	    paraCount = 0; 

+	    for(pPara = pBegin; pPara < pEnd; pPara++)

+	    {

+			if(!((*pPara == ',')||(*pPara>='0'&&*pPara<='9')||(*pPara>='a'&&*pPara<='f')||(*pPara>='A'&&*pPara<='F')))

+	        {

+	  	    	at_print(AT_ERR,"zCtrm_CheckLocklist error:%c!\n",*pPara); 

+	 			return EXT_ERROR;

+	        }

+	       

+	        if(*pPara == ',')

+	        {

+	            paraCount++;

+	        }

+	   }

+	   

+	   if(paraCount == LOCKNET_ITEM_NUM - 1)

+	   {   

+	       if(EXT_SUCCESS != zCtrm_CheckListPara(pBegin, pEnd - pBegin))

+	       {

+	             return EXT_ERROR;

+	       }

+	       pBegin = pEnd + 1;           

+	   }

+	   else

+	   {

+	 		at_print(AT_ERR,"zCtrm_CheckLocklist count:%d!\n",paraCount); 

+	        return EXT_ERROR;

+	   }    

+	   

+	}

+	at_print(AT_ERR,"zCtrm_CheckLocklist succ!\n");

+	return EXT_SUCCESS;

+}

+

+static UINT32 zCtrm_LocknetDigestMD5Hash(char *psDest)

+{

+	md5_ctx stStc;

+	UINT32 retCode = EXT_ERROR;

+	char TmpImei[ZPS_ImeiLen]={0};//imei³¤¶È×î´óÖµ

+	UINT16 iList = 0;

+	char lockList[LIST_LEN] = {0};

+	UINT8 plainText[KEY_LEN] = {0};

+	UINT8 sTempBuf[16];

+	unsigned int i;

+

+	char PTmpImei[ZPS_ImeiLen*2+1]={0};

+	char PlockList[LIST_LEN*2+1]={0};

+	char PplainText[KEY_LEN*2+1]={0};

+

+	md5_init(&stStc);

+	 

+	//retCode = zPS_NvAMTItemRead(ABIMEI_NVPARAM, (unsigned char *)TmpImei, ZPS_ImeiLen);

+	retCode = cpnv_NvItemRead(OS_FLASH_AMT_COMM_RO_IMEI_ADDRESS, (unsigned char *)TmpImei, OS_FLASH_AMT_COMM_RO_IMEI_SIZE);

+

+	if (CPNV_ERROR == retCode)

+	{

+		return EXT_ERROR;

+	}

+	zCtrm_Bytes2String(TmpImei, PTmpImei, ZPS_ImeiLen);

+	at_print(AT_ERR,"zCtrm_LocknetDigestMD5Hash TmpImei=%s!\n",PTmpImei);

+	md5_update(&stStc, (unsigned char *)TmpImei, ZPS_ImeiLen);

+

+

+	//ËøÍø²ÎÊý

+	for(iList = 0; iList < LOCKNET_MAX_NUM; iList++)  

+	{          

+		//retCode = zDrvNand_Read(AMT_LOCKNET_LIST + iList*sizeof(lockList), sizeof(lockList), (UINT8 *)lockList);  

+		retCode = cpnv_NvItemRead(AMT_LOCKNET_LIST + iList*sizeof(lockList), (UINT8 *)lockList, sizeof(lockList));

+		if (EXT_SUCCESS != retCode )

+		{   

+	  		return EXT_ERROR;

+		}

+	  	zCtrm_Bytes2String(lockList, PlockList, LIST_LEN);

+	  	at_print(AT_ERR,"zCtrm_LocknetDigestMD5Hash lockList=%s!\n",PlockList);

+	  	md5_update(&stStc, (unsigned char *)lockList, LIST_LEN);

+	}

+

+	//½âËøÂëÃÜÎÄ

+	//retCode = zDrvNand_Read(AMT_LOCKNET_KEY, sizeof(plainText), plainText);

+	retCode = cpnv_NvItemRead(AMT_LOCKNET_KEY, plainText, sizeof(plainText));

+	if (EXT_SUCCESS != retCode)

+	{   

+		return EXT_ERROR;

+	}

+	zCtrm_Bytes2String(plainText, PplainText, KEY_LEN);

+	at_print(AT_ERR,"zCtrm_LocknetDigestMD5Hash plainText=%s!\n",PplainText);

+	md5_update(&stStc, (unsigned char *)plainText, KEY_LEN);

+

+	md5_final(sTempBuf, &stStc);

+	for(i = 0; i < 16; i++)

+	{

+		snprintf(psDest + 2*i, 3, "%02x", sTempBuf[i]);

+	}

+	return EXT_SUCCESS;

+}

+

+static UINT32 zCtrm_String2Bytes(const CHAR* pSrc, UINT8* pDst, UINT16 srcLength)

+{

+	int i=0;

+

+	//УÑé²ÎÊý

+#if 1  // cov M srcLength is unsigned

+	if(pSrc ==  NULL || pDst == NULL)

+	{

+	   return -1;

+	}

+#else

+    if(pSrc ==	NULL || pDst == NULL || srcLength < 0)

+    {

+       return -1;

+    }

+

+#endif

+

+	for(i = 0; i < srcLength; 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 srcLength / 2;

+}

+

+int zCtrm_LocknetAuthList(char *at_paras)

+{

+	UINT8 *pBegin = NULL;

+    UINT8 *pEnd = NULL;

+    UINT16 keyLen = 0;

+    UINT8 keyBuf[LOCKNET_KEY_LEN+1] = {0}; 

+	UINT8 *pStrAt = NULL; 

+	CHAR at_str[AT_STR_LEN] = {0};

+	

+	pStrAt = strstr(at_paras,"a,");

+	if(pStrAt != NULL)

+	{

+		if (g_IsSetListKeyGot != TRUE)

+		{

+			at_print(AT_ERR,"zCtrm_LocknetAuthList:KeyGot false\n");

+			snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR\r\n");

+			goto end;

+		}

+		pEnd = at_paras+strlen(at_paras);

+

+		pBegin = pStrAt + strlen("a,");

+        keyLen = pEnd - pBegin;

+        if (keyLen != LOCKNET_KEY_LEN)

+		{

+			snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR\r\n");

+			goto end;

+		}

+		memcpy(keyBuf,pBegin,keyLen);

+        if(memcmp(keyBuf,g_SetListPlaint,keyLen) != 0)	

+		{

+			at_print(AT_ERR,"zCtrm_LocknetAuthList:Key error\n");

+			snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR\r\n");

+			goto end;

+		}

+		snprintf(at_str,AT_STR_LEN,"\r\nOK\r\n");

+		g_IsSetListKeyGot = FALSE;

+        g_IsSetListAuthSucc = TRUE;

+		goto end;

+	}

+	else 

+	{

+		snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR\r\n");

+		goto end;

+	}

+end:

+	send_rsp_str_to_farps(MODULE_ID_LOCKNET, at_str, strlen(at_str));

+	return 0;	

+}

+

+int zCtrm_LocknetAuthGen()

+{

+	UINT32 retCode = EXT_ERROR;

+	UINT8 plainText[LOCKNET_KEY_LEN+1] = {0};

+    UINT8 plainText128[KEY_LEN] = {0};

+    UINT8 cipherText[KEY_LEN] = {0};

+   	CHAR cipherHex[KEY_LEN*2+1] = {0};

+	CHAR at_str[AT_STR_LEN+KEY_LEN*2] = {0};  

+	

+	if (g_IsSetListKeyGot != FALSE)

+	{

+		snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR:Already authorized\r\n");

+		goto end;

+	}

+	zCtrm_LocknetKeyGen(plainText, LOCKNET_KEY_LEN);

+	memcpy(plainText128+KEY_LEN-LOCKNET_KEY_LEN, plainText, LOCKNET_KEY_LEN);

+	retCode = zCtrm_RsaPublicEncryptProc(plainText128, cipherText);

+    if (EXT_SUCCESS != retCode )

+    {   

+        snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR\r\n");

+		goto end;

+    }

+	zCtrm_Bytes2String(cipherText, cipherHex, KEY_LEN);                

+

+    memset(g_SetListPlaint,0,sizeof(g_SetListPlaint));

+    memcpy(g_SetListPlaint,plainText,sizeof(g_SetListPlaint)-1);

+	snprintf(at_str,AT_STR_LEN+KEY_LEN*2,"\r\n+LOCKLISTAUTH: %s\r\nOK\r\n",cipherHex);

+	g_IsSetListKeyGot = TRUE;

+	goto end;

+end:

+	send_rsp_str_to_farps(MODULE_ID_LOCKNET, at_str, strlen(at_str));

+	return 0;

+}

+

+int zCtrm_LocknetAuthProc(MSG_BUF *msg)

+{	

+	char at_str[AT_STR_LEN] = {0};

+	

+	at_print(AT_ERR,"zCtrm_LocknetAuthProc\n");

+	if('g' == (char*)msg->aucDataBuf[0])

+	{

+		zCtrm_LocknetAuthGen();

+	}

+	else if('a' == (char*)msg->aucDataBuf[0])

+	{

+		zCtrm_LocknetAuthList((char*)msg->aucDataBuf);

+	}

+	else 

+	{

+		at_print(AT_ERR,"zCtrm_LocknetAuthProc:param error!!!\n");

+		goto error;

+	}

+	return 0;

+error:

+	snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR\r\n");

+	send_rsp_str_to_farps(MODULE_ID_LOCKNET, at_str, strlen(at_str));

+	return 0;

+

+}

+

+int zCtrm_LocknetListSet(MSG_BUF *msg)

+{

+	UINT32 retCode = EXT_ERROR;

+    UINT16 dataLen = 0;

+	CHAR at_str[AT_STR_LEN] = {0};

+	char *at_paras = NULL; // cov M  PW.BRANCH_PAST_INITIALIZATION

+	

+	if (g_IsSetListAuthSucc != TRUE)

+    {   

+		snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR:unauthorized\r\n");

+		goto end;

+    }

+	at_paras = (char*)msg->aucDataBuf;

+	dataLen = strlen(at_paras);

+	at_print(AT_ERR,"dataLen = %d\n",dataLen); 

+	retCode = zCtrm_CheckLocklist((char*)msg->aucDataBuf, dataLen);

+	if (EXT_SUCCESS != retCode )

+	{   

+		snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR:invalid parameter\r\n");

+		goto end;

+    }

+	retCode = zCtrm_WriteLocklist(at_paras, dataLen);

+	if (EXT_SUCCESS != retCode )

+	{   

+		snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR:flash failed\r\n");

+		goto end;

+    }

+	if(NULL != strstr(at_paras,"next"))

+    {

+		g_NeedSecondList = TRUE;

+    } 

+    else

+    {

+    	g_NeedSecondList = FALSE;

+    }

+	snprintf(at_str,AT_STR_LEN,"\r\nOK\r\n");

+	goto end;

+end:

+	send_rsp_str_to_farps(MODULE_ID_LOCKNET, at_str, strlen(at_str));

+	return 0;

+}

+

+int zCtrm_LocknetKeyGenerate()

+{

+	UINT32 retCode = EXT_ERROR;    

+    UINT8 plainText[LOCKNET_KEY_LEN+1] = {0};

+    UINT8 plainText128[KEY_LEN] = {0};

+    UINT8 cipherText[KEY_LEN] = {0};

+	CHAR at_str[AT_STR_LEN] = {0};

+	//need open

+	retCode = zCtrm_LocknetStaticCheck();

+    if (EXT_SUCCESS != retCode )

+    {   

+		snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR:locknet already exists\r\n");

+		goto end;

+    }

+      

+    retCode = zCtrm_LocknetListCheck();

+    if (EXT_SUCCESS != retCode )

+    {   

+		snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR:missing locknet file\r\n");

+		goto end;

+    }

+ 	zCtrm_LocknetKeyGen(plainText, LOCKNET_KEY_LEN);

+    at_print(AT_ERR,"zCtrm_ExtLocknetKeyGenerate plainText=%s!\n",plainText);

+    memcpy(plainText128+KEY_LEN-LOCKNET_KEY_LEN, plainText, LOCKNET_KEY_LEN);

+    retCode = zCtrm_RsaPublicEncryptProc(plainText128, cipherText);

+    if (EXT_SUCCESS != retCode )

+    {   

+       	snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR:Encrypt error\r\n");

+		goto end;

+    }

+    retCode = zCtrm_LocknetNandSet(cipherText, sizeof(cipherText));

+    if (EXT_SUCCESS != retCode )

+    {   

+    	snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR:invalid command\r\n");

+		goto end;

+    }

+    snprintf(at_str,AT_STR_LEN,"\r\nOK\r\n");

+	g_IsKeyExist = TRUE;

+    goto end;

+end:

+	send_rsp_str_to_farps(MODULE_ID_LOCKNET, at_str, strlen(at_str));

+	return 0;

+}

+

+int zCtrm_LocknetDelRand()

+{

+	UINT32 retCode = EXT_ERROR;    

+	UINT8 pPtr[KEY_LEN*2+64] = {0};    

+	UINT8 plainText[LOCKNET_KEY_LEN+1] = {0};

+	UINT8 plainText128[KEY_LEN] = {0};

+	UINT8 cipherText[KEY_LEN] = {0};

+	CHAR cipherHex[KEY_LEN*2+1] = {0};

+	CHAR at_str[AT_STR_LEN+KEY_LEN*2] = {0};

+	

+	if (g_IsUnlockKeyGot != FALSE)

+	{   

+		snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR:Already authorized\r\n");

+		goto end;

+	}

+

+	zCtrm_LocknetKeyGen(plainText, LOCKNET_KEY_LEN);

+	memcpy(plainText128+KEY_LEN-LOCKNET_KEY_LEN, plainText, LOCKNET_KEY_LEN);

+	retCode = zCtrm_RsaPublicEncryptProc(plainText128, cipherText);

+	if (EXT_SUCCESS != retCode )

+	{   

+		 snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR\r\n");

+		 goto end;

+	}

+	   

+	zCtrm_Bytes2String(cipherText, cipherHex, KEY_LEN);               

+

+	memset(g_UnlockKeyPlaint,0,sizeof(g_UnlockKeyPlaint));

+	memcpy(g_UnlockKeyPlaint,plainText,sizeof(g_UnlockKeyPlaint)-1);

+

+	snprintf(at_str,AT_STR_LEN+KEY_LEN*2,"\r\n+UNLOCKKEY:%s\r\nOK\r\n",cipherHex);

+	g_IsUnlockKeyGot = TRUE;

+	goto end;

+end:

+	send_rsp_str_to_farps(MODULE_ID_LOCKNET, at_str, strlen(at_str));

+	return 0;

+

+}

+

+static UINT32 zCtrm_LocknetNandDel(VOID)

+{

+	T_zCtrm_LockLevel lockState = NEVER_LOCKED;

+	UINT8 keyBuf[KEY_LEN] = {0};  

+	UINT32 retCode = EXT_ERROR;

+

+	cpnv_ChangeNvRoAttr(1);

+	memset(keyBuf,0xFF,sizeof(keyBuf));

+	//retCode = zDrvNand_Program(AMT_LOCKNET_KEY, sizeof(keyBuf), keyBuf);

+	retCode = cpnv_NvItemWriteNvro(AMT_LOCKNET_KEY, keyBuf, sizeof(keyBuf));

+	if (EXT_SUCCESS != retCode)

+	{  

+	   cpnv_ChangeNvRoAttr(0);   

+	   return EXT_ERROR;

+	}

+

+	//retCode = zDrvNand_Program(AMT_LOCKNET_BASE, sizeof(lockState),(UINT8 *)&lockState);

+	retCode = cpnv_NvItemWriteNvro(AMT_LOCKNET_BASE, (UINT8 *)&lockState, sizeof(lockState));

+	if (EXT_SUCCESS != retCode)

+	{   

+	   cpnv_ChangeNvRoAttr(0);   

+	   return EXT_ERROR;

+	}

+	cpnv_FsGcWait(FS_NVROFS);

+	cpnv_ChangeNvRoAttr(0);    

+	return EXT_SUCCESS;

+}

+

+int zCtrm_LocknetKeyDelete(char *at_paras)

+{

+	UINT32 retCode = EXT_ERROR;    

+	UINT8 *pBegin = NULL;

+	UINT8 *pEnd = NULL;

+	UINT16 keyLen = 0;

+	UINT8 keyBuf[LOCKNET_KEY_LEN+1] = {0};  

+	UINT8 *pStrAt = NULL;

+	CHAR at_str[AT_STR_LEN] = {0};

+	

+	if (g_IsUnlockKeyGot != TRUE)

+	{   

+		 snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR\r\n");

+		 goto end;

+	}

+	pEnd = at_paras+strlen(at_paras);

+	pBegin = at_paras + strlen("d,");

+	keyLen = pEnd - pBegin;

+	if (keyLen != LOCKNET_KEY_LEN)

+	{   

+		snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR\r\n");

+		goto end;

+	}

+	memcpy(keyBuf,pBegin,keyLen);

+	if(memcmp(keyBuf,g_UnlockKeyPlaint,keyLen) != 0)

+	{   

+		snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR\r\n");

+		goto end;

+	}   

+	retCode = zCtrm_LocknetNandDel();

+	if (EXT_SUCCESS != retCode )

+	{   

+		snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR\r\n");

+		goto end;

+	}

+	   

+	snprintf(at_str,AT_STR_LEN,"\r\nOK\r\n"); 

+	g_IsUnlockKeyGot = FALSE;

+	goto end;

+end:

+	send_rsp_str_to_farps(MODULE_ID_LOCKNET, at_str, strlen(at_str));

+	return 0;

+}

+

+int zCtrm_LocknetKeyProc(MSG_BUF *msg)

+{

+	UINT32 retCode = EXT_ERROR;    

+    //UINT8 plainText[LOCKNET_KEY_LEN+1] = {0};

+    UINT8 plainText128[KEY_LEN] = {0};

+    UINT8 cipherText[KEY_LEN] = {0};

+	

+	char *at_paras = (char*)msg->aucDataBuf;

+	if('g' == at_paras[0])

+	{

+       	zCtrm_LocknetKeyGenerate();

+    }

+	if('c' == at_paras[0])

+	{

+		zCtrm_LocknetDelRand();

+	}

+	if('d' == at_paras[0])

+	{

+		zCtrm_LocknetKeyDelete(at_paras);

+	}

+	return 0;

+}

+

+int zCtrm_LocknetAmtStatus(MSG_BUF *msg)

+{

+	UINT32 retCode = EXT_ERROR;    

+	UINT8 cipherText[KEY_LEN] = {0};

+	CHAR cipherHex[KEY_LEN*2+1] = {0};

+	UINT8 keyBuf[KEY_LEN] = {0};  

+	CHAR at_str[AT_STR_LEN+KEY_LEN*2] = {0};

+	

+	//retCode = zDrvNand_Read(AMT_LOCKNET_KEY, sizeof(keyBuf), keyBuf);

+	retCode = cpnv_NvItemRead(AMT_LOCKNET_KEY, keyBuf, sizeof(keyBuf));

+	if (EXT_SUCCESS != retCode || keyBuf[0] == 0xFF)

+	{   

+		snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR:locknet not found\r\n");

+		goto end;

+	}

+	if(g_IsKeyExist != TRUE)

+	{   

+	    snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR:illegal command\r\n");

+		goto end;

+	} 

+

+	if (g_IsDigestGotSucc != TRUE)

+	{   

+		snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR:undigest\r\n");

+		goto end;

+	}

+	memcpy(cipherText, keyBuf, sizeof(keyBuf));

+	zCtrm_Bytes2String(cipherText, cipherHex, KEY_LEN);

+	   

+	snprintf(at_str,AT_STR_LEN+KEY_LEN*2,"\r\n+UNLOCKKEY:%s\r\nOK\r\n",cipherHex);

+	g_IsKeyExist = FALSE;

+	goto end;

+end:

+	send_rsp_str_to_farps(MODULE_ID_LOCKNET, at_str, strlen(at_str));

+	return 0;

+}

+

+/*

+*»ñȡժҪÐÅÏ¢

+*·µ»ØÉ豸ID¡¢ËøÍø²ÎÊýE¡¢½âËøÂëÃÜÎÄF¾­MD5¼ÆËãºóµÄÕªÒªÐÅÏ¢

+*/

+int zCtrm_LocknetDigestGet(MSG_BUF *msg)

+{

+	char psDest[LOCKNET_KEY_LEN*2+1] = {0};

+	UINT8 pPtr[MAX_AMT_AT_LEN] = {0};

+	UINT32 retCode = EXT_ERROR;

+	CHAR at_str[AT_STR_LEN+LOCKNET_KEY_LEN*2] = {0};

+	

+	if (g_IsDigestKeyGot != FALSE)

+	{   

+		snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR:Already Digestget\r\n");

+		goto end;

+	}

+

+	if(g_IsKeyExist != TRUE)

+	{   

+		snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR:illegal command\r\n");

+		goto end;

+	}

+	retCode=zCtrm_LocknetDigestMD5Hash(psDest);

+	if(retCode==EXT_ERROR)

+	{   

+		 snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR\r\n");

+		 goto end;

+	}

+	snprintf(at_str,AT_STR_LEN+LOCKNET_KEY_LEN*2,"\r\n+LOCKDIGEST: %s\r\nOK\r\n",psDest);

+	g_IsDigestKeyGot = TRUE;

+	goto end;

+end:

+	send_rsp_str_to_farps(MODULE_ID_LOCKNET, at_str, strlen(at_str));

+	return 0;

+

+}

+

+int zCtrm_LocknetSignSet(MSG_BUF *msg)

+{

+	UINT32 retCode = EXT_ERROR;    

+	UINT8 *pBegin = NULL;

+	UINT8 *pEnd = NULL;

+	UINT16 keyLen = 0;

+	CHAR keyText[KEY_LEN*2+1]={0};

+	UINT8 keyHex[KEY_LEN] = {0};  

+	CHAR at_str[AT_STR_LEN] = {0};

+

+	char *at_paras = NULL;// cov M  PW.BRANCH_PAST_INITIALIZATION

+	

+	if (g_IsDigestKeyGot != TRUE)

+	{   

+		snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR:NO Digestget\r\n");

+		goto end;

+	}

+	at_paras = (char*)msg->aucDataBuf;

+	pEnd = at_paras+strlen(at_paras);

+

+	pBegin = at_paras;

+	keyLen = pEnd - pBegin;

+	if (keyLen != KEY_LEN*2)

+	{   

+		 snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR\r\n");

+		 goto end;

+	}

+	memcpy(keyText,pBegin,keyLen);

+	   //°Ñ×Ö·û´®×ª³É¶þ½øÖÆÊý´æ½øÈ¥

+	zCtrm_String2Bytes(keyText, keyHex, keyLen);

+	cpnv_ChangeNvRoAttr(1);

+	//retCode = zDrvNand_Program(AMT_LOCKNET_SIGN, KEY_LEN, keyHex);

+	retCode = cpnv_NvItemWriteNvro(AMT_LOCKNET_SIGN, keyHex, KEY_LEN);

+	if (EXT_SUCCESS != retCode)

+	{   

+		snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR\r\n");

+		cpnv_ChangeNvRoAttr(0);

+		goto end;

+	}   

+	cpnv_FsGcWait(FS_NVROFS);

+	cpnv_ChangeNvRoAttr(0);

+	snprintf(at_str,AT_STR_LEN,"\r\nOK\r\n");

+	g_IsDigestKeyGot = FALSE;

+	g_IsDigestGotSucc = TRUE;

+	goto end;

+end:

+	send_rsp_str_to_farps(MODULE_ID_LOCKNET, at_str, strlen(at_str));

+	return 0;

+

+}

+

+int zCtrm_LocknetLevel(MSG_BUF *msg)

+{

+	UINT32 retCode = EXT_ERROR;    

+	CHAR at_str[AT_STR_LEN] = {0};    

+	T_zCtrm_LockLevel  lockState = LOCKFLAG_ERROR;   

+	//retCode = zDrvNand_Read(AMT_LOCKNET_BASE,sizeof(lockState),(UINT8 *)&lockState); //len=4

+	retCode = cpnv_NvItemRead(AMT_LOCKNET_BASE, (UINT8 *)&lockState, sizeof(lockState));

+	if (EXT_SUCCESS != retCode )

+	{   

+		at_print(AT_ERR,"zCtrm_ExtLocknetLevel read err\n");

+	    snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR\r\n");

+		goto end;

+	}

+	if(lockState == ALREADY_UNLOCKED)

+	{

+		snprintf(at_str,AT_STR_LEN,"\r\n+LOCKLEVEL:Already Unlocked\r\nOK\r\n");

+	}

+	else if(lockState == LOCKED)

+	{

+	 	snprintf(at_str,AT_STR_LEN,"\r\n+LOCKLEVEL:Locked\r\nOK\r\n");

+	}

+	else if(lockState == NEVER_LOCKED)

+	{

+	    snprintf(at_str,AT_STR_LEN,"\r\n+LOCKLEVEL:Never Locked\r\nOK\r\n");

+	}

+	else

+	{

+	    at_print(AT_ERR,"zCtrm_ExtLocknetLevel err flag:%x\n",lockState);

+	    snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR\r\n");

+		goto end;

+	}

+	goto end;

+end:

+	send_rsp_str_to_farps(MODULE_ID_LOCKNET, at_str, strlen(at_str));

+	return 0;

+}

+

+int zCtrm_LocknetListGet()

+{

+	UINT32 retCode = EXT_ERROR;

+	UINT16 iList = 0;

+	UINT8 pPtr[MAX_AMT_AT_LEN] = {0};

+	CHAR at_str[AT_STR_LEN+MAX_AMT_AT_LEN] = {0}; 

+	

+	T_zCtrm_LockListPara lockList = {0};

+	for(iList = 0; iList < LOCKNET_MAX_NUM; iList++)  

+	{

+		memset(&lockList, 0, sizeof(lockList));//cov

+		//retCode = zDrvNand_Read(AMT_LOCKNET_LIST + iList*sizeof(lockList), sizeof(lockList), (UINT8 *)&lockList);

+		retCode = cpnv_NvItemRead(AMT_LOCKNET_LIST + iList*sizeof(lockList), (UINT8 *)&lockList, sizeof(lockList));

+		if (EXT_SUCCESS != retCode )

+		{   

+			snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR\r\n");

+			send_rsp_str_to_farps(MODULE_ID_LOCKNET, at_str, strlen(at_str));

+	        return 0;

+		}

+		if((lockList.mcc[0] == 0xFF)||(lockList.imsi6[0] == 0xFF)||(lockList.gid1[0] == 0xFF))

+		{

+			at_print(AT_ERR,"zCtrm_ExtLocknetListGet break iList:[%d]\n",iList);

+			break;

+		}

+		//cov

+		lockList.mcc[LIST_MCCMNC_LEN-1] = '\0';

+		lockList.mnc[LIST_MCCMNC_LEN-1] = '\0';

+		lockList.imsi6[LIST_IMSI_LEN-1] = '\0';

+		lockList.imsi7[LIST_IMSI_LEN-1] = '\0';

+		lockList.gid1[LIST_GID_LEN-1] = '\0';

+		lockList.gid2[LIST_GID_LEN-1] = '\0';

+		if(iList < LOCKNET_FIRST_NUM)

+		{	

+			snprintf(pPtr+strlen(pPtr),sizeof(pPtr)-strlen(pPtr),"%s,%s,%s,%s,%s,%s;",

+			    lockList.mcc,lockList.mnc,lockList.imsi6,lockList.imsi7,lockList.gid1,lockList.gid2);            

+		}

+		else

+		{

+			strcat((char *)pPtr,"next"); 

+			break;

+		}

+

+	}

+	snprintf(at_str,AT_STR_LEN+MAX_AMT_AT_LEN,"\r\n+MEPCG:%s\r\nOK\r\n",pPtr);

+	send_rsp_str_to_farps(MODULE_ID_LOCKNET, at_str, strlen(at_str));

+	return 0;

+}

+

+int zCtrm_LocknetListGetNext()

+{

+	UINT32	retCode = EXT_ERROR;

+	UINT16 iList = 0;

+	UINT8 pPtr[MAX_AMT_AT_LEN] = {0};

+	CHAR at_str[AT_STR_LEN+MAX_AMT_AT_LEN] = {0}; 

+	

+	T_zCtrm_LockListPara lockList = {0};

+	for(iList = 0; iList < LOCKNET_MAX_NUM - LOCKNET_FIRST_NUM; iList++)  

+	{

+		memset(&lockList, 0, sizeof(lockList));//cov

+		//retCode = zDrvNand_Read(AMT_LOCKNET_LIST + (LOCKNET_FIRST_NUM+iList)*sizeof(lockList), sizeof(lockList), (UINT8 *)&lockList);  

+		retCode = cpnv_NvItemRead(AMT_LOCKNET_LIST + (LOCKNET_FIRST_NUM+iList)*sizeof(lockList), (UINT8 *)&lockList, sizeof(lockList));

+	    if (EXT_SUCCESS != retCode )

+	    {   

+	    	snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR\r\n");

+			send_rsp_str_to_farps(MODULE_ID_LOCKNET, at_str, strlen(at_str));

+	        return 0;

+		}

+	    if((lockList.mcc[0] == 0xFF)||(lockList.imsi6[0] == 0xFF)||(lockList.gid1[0] == 0xFF))

+	    {

+	     	at_print(AT_ERR,"zCtrm_ExtLocknetListGetNext break iList:[%d]\n",iList);

+	        break;

+	    }

+	    //cov

+	    lockList.mcc[LIST_MCCMNC_LEN-1] = '\0';

+		lockList.mnc[LIST_MCCMNC_LEN-1] = '\0';

+		lockList.imsi6[LIST_IMSI_LEN-1] = '\0';

+		lockList.imsi7[LIST_IMSI_LEN-1] = '\0';

+		lockList.gid1[LIST_GID_LEN-1] = '\0';

+		lockList.gid2[LIST_GID_LEN-1] = '\0';

+        snprintf(pPtr+strlen(pPtr),sizeof(pPtr)-strlen(pPtr),"%s,%s,%s,%s,%s,%s;",

+            lockList.mcc,lockList.mnc,lockList.imsi6,lockList.imsi7,lockList.gid1,lockList.gid2);

+	}

+	snprintf(at_str,AT_STR_LEN+MAX_AMT_AT_LEN,"\r\n+MEPCG:%s\r\nOK\r\n",pPtr);

+	send_rsp_str_to_farps(MODULE_ID_LOCKNET, at_str, strlen(at_str));

+	return 0;

+}

+

+int zCtrm_LocknetListGetProc(MSG_BUF *msg)

+{

+	CHAR at_str[AT_STR_LEN] = {0};

+	char *at_paras = (char*)msg->aucDataBuf;

+	if(NULL != strstr(at_paras, "all"))

+	{

+		zCtrm_LocknetListGet();

+	}

+	else if(NULL != strstr(at_paras, "next"))

+	{

+		zCtrm_LocknetListGetNext();

+	}

+	else 

+	{

+		snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR\r\n");

+		send_rsp_str_to_farps(MODULE_ID_LOCKNET, at_str, strlen(at_str));

+	}

+	return 0;

+}

+

+//¶ÁÈ¡ËøÍø²ÎÊý¡¢½âËøÂ롢ǩÃû£¬ÅжÏÊÇ·ñ´æÔÚ

+static UINT32 zCtrm_SignExistAuthMutex(VOID)

+{

+    UINT32 retCode=EXT_ERROR;

+    T_zCtrm_LockListPara lockList = {0};

+    T_zCtrm_LockListPara lockListTmp = {0};

+    UINT8 keyBuf[KEY_LEN] = {0};  

+    UINT8 signBuf[KEY_LEN] = {0};  

+    

+    //ËøÍø²ÎÊý

+    //retCode = zDrvNand_Read(AMT_LOCKNET_LIST, sizeof(lockList), (UINT8 *)&lockList); 

+    retCode = cpnv_NvItemRead(AMT_LOCKNET_LIST, (UINT8 *)&lockList, sizeof(lockList));   

+    if (EXT_SUCCESS != retCode)

+    {       

+        return READ_ERROR;        

+    }

+    if((lockList.mcc[0] == 0xFF)||(lockList.imsi6[0] == 0xFF)||(lockList.gid1[0] == 0xFF))

+    {

+        return LOCKKEY_ISNULL;

+    }

+	if(memcmp(&lockList,&lockListTmp,sizeof(T_zCtrm_LockListPara)) == 0)

+	{

+        return LOCKKEY_ISNULL;//¹æ±Ünvrowall.binÈ«0µÄÎÊÌâ

+	}

+

+    //½âËøÂë

+    //retCode = zDrvNand_Read(AMT_LOCKNET_KEY, sizeof(keyBuf), keyBuf);

+    retCode = cpnv_NvItemRead(AMT_LOCKNET_KEY, keyBuf, sizeof(keyBuf));

+    if (EXT_SUCCESS != retCode)

+    {   

+        return READ_ERROR;

+    }   

+    if(keyBuf[0] == 0xFF)

+    {

+        return LOCKKEY_ISNULL;

+    }

+

+    //Ç©Ãû

+    //retCode = zDrvNand_Read(AMT_LOCKNET_SIGN, sizeof(signBuf), signBuf);

+    retCode = cpnv_NvItemRead(AMT_LOCKNET_SIGN, signBuf, sizeof(signBuf));

+    if (EXT_SUCCESS != retCode)

+    {   

+        return READ_ERROR;

+    } 

+    if(signBuf[0] == 0xFF)

+    {

+        return LOCKKEY_ISNULL;

+    }

+

+    return READ_SUCCESS;

+

+}

+

+static UINT32 zCtrm_SignAuth(VOID)

+{

+    UINT32	retCode = EXT_ERROR;

+    UINT8 signBuf[KEY_LEN] = {0}; 

+    UINT8 signHex128[KEY_LEN] = {0}; 

+    char signtext[LOCKNET_KEY_LEN*2+1] = {0};

+    char psDest[LOCKNET_KEY_LEN*2+1] = {0};

+    

+    //Ç©Ãû

+    //retCode = zDrvNand_Read(AMT_LOCKNET_SIGN, sizeof(signBuf), signBuf);

+	retCode = cpnv_NvItemRead(AMT_LOCKNET_SIGN, signBuf, sizeof(signBuf));

+    if (EXT_SUCCESS != retCode)

+    {   

+        return RESULT_ERROR;

+    } 

+    

+    //¹«Ô¿½âÃÜ

+    retCode = zCtrm_RsaPublicEncryptProc(signBuf, signHex128);

+    if (EXT_SUCCESS != retCode)

+    {   

+        return RESULT_ERROR;

+    }

+    

+    zCtrm_Bytes2String(signHex128+KEY_LEN-LOCKNET_KEY_LEN, signtext, LOCKNET_KEY_LEN);

+    

+    //ÕªÒªÓëÇ©Ãû ±È½Ï ÕªÒªÓù«Ô¿½âÃÜ

+    retCode=zCtrm_LocknetDigestMD5Hash(psDest);

+    if (EXT_SUCCESS != retCode)

+    {   

+        return RESULT_ERROR;

+    } 

+

+    at_print(AT_ERR,"zCtrm_SignAuth signtext=%s,psDest=%s!",signtext,psDest);

+    if(0 != strcasecmp(signtext,psDest))

+    {

+        return RESULT_LOCKED;

+    }

+    return RESULT_UNLOCKED;

+}

+

+static UINT32 zCtrm_KeyAuth(VOID)

+{

+    UINT32	retCode = EXT_ERROR;

+    UINT8 keyBuf[KEY_LEN]  = {0};  

+    UINT8 usrkeyBuf[LOCKNET_KEY_LEN] = {0}; 

+    UINT8 usrkeyBuf128[KEY_LEN] = {0}; 

+    UINT8 usrKeyText[KEY_LEN] = {0};

+    

+    //½âËøÂë

+    //retCode = zDrvNand_Read(AMT_LOCKNET_KEY, sizeof(keyBuf), keyBuf);

+    retCode = cpnv_NvItemRead(AMT_LOCKNET_KEY, keyBuf, sizeof(keyBuf));

+    if (EXT_SUCCESS != retCode || keyBuf[0] == 0xFF)

+    {   

+        return RESULT_ERROR;

+    }   

+    

+    //Óû§½âËøÂë 

+    //retCode = zDrvNand_Read(AMT_LOCKNET_USRKEY, sizeof(usrkeyBuf), usrkeyBuf);

+    retCode = cpnv_NvItemRead(AMT_LOCKNET_USRKEY, usrkeyBuf, sizeof(usrkeyBuf));

+    if (EXT_SUCCESS != retCode || usrkeyBuf[0] == 0xFF)

+    {   

+        return RESULT_LOCKED;

+    } 

+

+    memcpy(usrkeyBuf128+KEY_LEN-LOCKNET_KEY_LEN, usrkeyBuf, LOCKNET_KEY_LEN);

+    retCode = zCtrm_RsaPublicEncryptProc(usrkeyBuf128, usrKeyText);

+    if (EXT_SUCCESS != retCode )

+    {   

+        return RESULT_ERROR;

+    }

+    

+    //Óû§½âËøÂëÓë½âËøÂë ±È½Ï ¼ÓÃܺó±È½Ï

+    if(memcmp(keyBuf,usrKeyText,KEY_LEN) != 0)

+    {

+        return RESULT_LOCKED;

+    }

+    return RESULT_UNLOCKED;

+}

+

+void zCtrm_DoSimAuth()

+{

+	char crsmrsp[256] = {0};

+	void *p[] = {crsmrsp};

+	UINT8 *pRes = NULL;

+	CHAR  fileSize[5] = {0};

+	char at_str[AT_STR_LEN] = {0};

+	int ret = -1;

+	

+	snprintf(at_str, AT_STR_LEN, "AT+CRSM=192,%ld,0,0,15,,\"3F007F20\"\r\n", IDENTIFIER_GID1);

+	ret = get_modem_info(at_str, "%s", p);

+	if (ret) 

+	{

+		at_print(AT_ERR,"zCtrm_SignExistAuthMutex crsm error!\n");

+		simPara.fileLen = 0;

+	}

+	else

+	{

+		pRes = strstr(crsmrsp, "144,0,");//±íʾÕýÈ·¶ÁÈ¡

+		if(NULL != pRes)

+		{

+			strncpy(fileSize, pRes+strlen("144,0,")+4, 4);

+			simPara.fileLen = zCtrm_Atohex(fileSize[0])*4096 + zCtrm_Atohex(fileSize[1])*256 + zCtrm_Atohex(fileSize[2])*16 + zCtrm_Atohex(fileSize[3]);

+			at_print(AT_ERR,"crsm_ok_act, fileLen1 = %ld \n", simPara.fileLen);

+		}

+		else

+		{

+			simPara.fileLen = 0;

+		}

+	}

+	snprintf(at_str, AT_STR_LEN, "AT+CRSM=176,%ld,0,0,%ld\r\n", IDENTIFIER_GID1, simPara.fileLen);

+	ret = get_modem_info(at_str, "%s", p);

+	if (ret) 

+		at_print(AT_ERR,"zCtrm_SignExistAuthMutex crsm error!\n");

+	else

+	{

+		pRes = strstr(crsmrsp, "144,0,");//±íʾÕýÈ·¶ÁÈ¡

+		if(NULL != pRes)

+		{

+			strncpy(simLockListPara.gid1, pRes+strlen("144,0,"), LIST_GID_LEN-1);

+			at_print(AT_ERR,"crsm_ok_act, gid1 = %s \n", simLockListPara.gid1);

+		}

+		

+	}

+	snprintf(at_str, AT_STR_LEN, "AT+CRSM=192,%ld,0,0,15,,\"3F007F20\"", IDENTIFIER_GID2);

+	ret = get_modem_info(at_str, "%s", p); 

+	if (ret) 

+	{

+		at_print(AT_ERR,"zCtrm_SignExistAuthMutex crsm error!\n");

+		simPara.fileLen = 0;

+	}

+	else

+	{

+		pRes = strstr(crsmrsp, "144,0,");//±íʾÕýÈ·¶ÁÈ¡

+		if(NULL != pRes)

+		{

+			strncpy(fileSize, pRes+strlen("144,0,")+4, 4);

+			simPara.fileLen = zCtrm_Atohex(fileSize[0])*4096 + zCtrm_Atohex(fileSize[1])*256 + zCtrm_Atohex(fileSize[2])*16 + zCtrm_Atohex(fileSize[3]);

+			at_print(AT_ERR,"crsm_ok_act, fileLen2 = %ld \n", simPara.fileLen);

+		}

+		else

+		{

+			simPara.fileLen = 0;

+		}

+	}

+	snprintf(at_str, AT_STR_LEN, "AT+CRSM=176,%ld,0,0,%ld\r\n", IDENTIFIER_GID2, simPara.fileLen);

+	ret = get_modem_info(at_str, "%s", p); 

+	if (ret) 

+		at_print(AT_ERR,"zCtrm_SignExistAuthMutex crsm error!\n");

+	else

+	{

+		pRes = strstr(crsmrsp, "144,0,");//±íʾÕýÈ·¶ÁÈ¡

+		if(NULL != pRes)

+		{

+			strncpy(simLockListPara.gid2, pRes+strlen("144,0,"), LIST_GID_LEN-1);

+			at_print(AT_ERR,"crsm_ok_act, gid2 = %s \n", simLockListPara.gid2);

+		}

+	}

+	ret = get_modem_info("AT+CRSM=176,28589,0,0,4\r\n", "%s", p); 

+	if (ret) 

+	{

+		simPara.mncLen = 2;

+		at_print(AT_ERR,"crsm_err_act, mncLen = %d \n", simPara.mncLen);

+	}

+	else

+	{

+		pRes = strstr(crsmrsp, "144,0,");//±íʾÕýÈ·¶ÁÈ¡

+		if((NULL != pRes)&&(0 == strcmp("03", pRes+strlen("144,0,")+6))) //use 02 test

+		{

+			simPara.mncLen = 3;

+		}

+		else

+		{

+			simPara.mncLen = 2;

+		}

+		at_print(AT_ERR,"crsm_ok_act, mncLen = %d \n", simPara.mncLen);

+	}

+	return;

+}

+

+void zCtrm_DoUsimAuth()

+{

+	char crsmrsp[256] = {0};

+	void *p[] = {crsmrsp};

+	UINT8 *pRes = NULL;

+	CHAR  fileSize[5] = {0};

+	int ret = -1;

+

+	ret = get_modem_info("AT+CRSM=176,28478,0,0,0\r\n", "%s", p);

+	if (ret) 

+		at_print(AT_ERR,"cardmode_err_act zCtrm_USimAuth ERROR!\n");

+	else

+	{

+		pRes = strstr(crsmrsp, "144,0,");

+		if(NULL != pRes)

+		{

+			strncpy(simLockListPara.gid1, pRes+strlen("144,0,"), LIST_GID_LEN-1);

+	 		at_print(AT_ERR,"crsm_ok_act, gid1 = %s \n", simLockListPara.gid1);

+		}

+	}

+	ret = get_modem_info("AT+CRSM=176,28479,0,0,0\r\n", "%s", p);

+	if (ret) 

+		at_print(AT_ERR,"cardmode_err_act zCtrm_USimAuth ERROR!\n");

+	else

+	{

+		pRes = strstr(crsmrsp, "144,0,");

+		if(NULL != pRes)

+		{

+			strncpy(simLockListPara.gid2, pRes+strlen("144,0,"), LIST_GID_LEN-1);

+	 		at_print(AT_ERR,"crsm_ok_act, gid2 = %s \n", simLockListPara.gid2);

+		}

+	}

+	ret = get_modem_info("AT+CRSM=176,28589,0,0,4\r\n", "%s", p);

+	if (ret) 

+	{

+		simPara.mncLen = 2;

+		at_print(AT_ERR,"crsm_err_act, mncLen = %d \n", simPara.mncLen);

+	}

+	else

+	{

+		pRes = strstr(crsmrsp, "144,0,");

+		if((NULL != pRes)&&(0 == strcmp("03", pRes+strlen("144,0,")+6))) //use 02 test

+		{

+			simPara.mncLen = 3;

+		}

+		else

+		{

+			simPara.mncLen = 2;

+		}

+	 	at_print(AT_ERR,"crsm_ok_act, mncLen = %d \n", simPara.mncLen);

+	}

+	return;	

+}

+

+VOID zCtrm_SIMPara2Auth(T_zCtrm_LockListPara *fromSim, T_zCtrm_SIMPara simPara)

+{

+	strncpy(fromSim->mcc,simPara.simImsi,3);

+	if (simPara.mncLen < sizeof(fromSim->mnc)) {

+		memset(fromSim->mnc,0,sizeof(fromSim->mnc));

+		snprintf(fromSim->mnc,simPara.mncLen+1,"%s",simPara.simImsi+3);

+		//strncpy(fromSim->mnc,simPara.simImsi+3,simPara.mncLen);

+	}

+	strncpy(fromSim->imsi6,simPara.simImsi+5,1);

+	strncpy(fromSim->imsi7,simPara.simImsi+6,1);

+}

+

+UINT32 zCtrm_AuthSIMPara(T_zCtrm_LockListPara *simPara)

+{

+    UINT32	retCode = EXT_ERROR;

+    UINT32 iNum = 0;

+

+    if(0 == strcmp("001",simPara->mcc) && 0 == strcmp("01",simPara->mnc))

+        //if(0 == strcmp("460",simPara.mcc) && 0 == strcmp("01",simPara.mnc))

+    {

+        at_print(AT_ERR,"sim ex\n");

+        return EXT_SUCCESS;

+    }

+    

+    for(iNum = 0; iNum < LOCKNET_MAX_NUM; iNum++)  

+    {    

+        T_zCtrm_LockListPara lockList = {0};

+        //retCode = zDrvNand_Read(AMT_LOCKNET_LIST + iNum*sizeof(lockList), sizeof(lockList), (UINT8 *)&lockList);  

+        retCode = cpnv_NvItemRead(AMT_LOCKNET_LIST + iNum*sizeof(lockList), (UINT8 *)&lockList, sizeof(lockList));

+        if (EXT_SUCCESS != retCode )

+        {              

+			at_print(AT_ERR,"zCtrm_AuthSIMPara:zDrvNand_Read error\n");

+			return EXT_ERROR;

+        }

+        

+        if((lockList.mcc[0] == 0xFF)||(lockList.imsi6[0] == 0xFF)||(lockList.gid1[0] == 0xFF))

+        {

+			at_print(AT_ERR,"zCtrm_AuthSIMPara: lockList value error\n");

+			return EXT_ERROR;

+        }

+		//cov

+		lockList.mcc[LIST_MCCMNC_LEN-1] = '\0';

+		lockList.mnc[LIST_MCCMNC_LEN-1] = '\0';

+		lockList.imsi6[LIST_IMSI_LEN-1] = '\0';

+		lockList.imsi7[LIST_IMSI_LEN-1] = '\0';

+        if( (lockList.mcc[0] == '\0'||0 == strcmp(lockList.mcc,simPara->mcc))

+          &&(lockList.mnc[0] == '\0'||0 == strcmp(lockList.mnc,simPara->mnc))

+          &&(lockList.imsi6[0] == '\0'||0 == strcmp(lockList.imsi6,simPara->imsi6))

+          &&(lockList.imsi7[0] == '\0'||0 == strcmp(lockList.imsi7,simPara->imsi7))

+          &&(lockList.gid1[0] == '\0'||0 == zCtrm_Strnicmp(lockList.gid1,simPara->gid1,USED_GID_LEN))

+          &&(lockList.gid2[0] == '\0'||0 == zCtrm_Strnicmp(lockList.gid2,simPara->gid2,USED_GID_LEN)) )

+        {   

+            at_print(AT_ERR,"sim checked\n");

+            return EXT_SUCCESS;

+        }       

+    }

+	

+    at_print(AT_ERR,"zCtrm_AuthSIMPara: other error\n");    

+    return EXT_ERROR;

+}

+

+static UINT32 zCtrm_SimAuth()

+{

+	int ret = -1;

+	int cardmode = 0;

+	void *p1[] = {&cardmode};

+	char imsi[MAX_IMSI_LEN] = {0};

+	void *p2[] = {imsi};

+		

+	ret = get_modem_info("AT^CARDMODE\r\n", "%d", p1);

+	if (ret) {

+		simPara.cardMode = CARDMODE_UNKNOW;

+		at_print(AT_ERR,"cardmode_err_act zCtrm_SimAuth ERROR!\n");

+		return RESULT_ERROR;

+	}

+	if(1 == cardmode)

+	{

+		simPara.cardMode = CARDMODE_SIM;

+		zCtrm_DoSimAuth();

+	}

+	else if(2 == cardmode)

+	{

+		simPara.cardMode = CARDMODE_USIM;

+		zCtrm_DoUsimAuth();

+	}

+	else 

+		return RESULT_ERROR;

+	ret = get_modem_info("AT+CIMI\r\n", "%s", p2); 

+	if (ret)

+	{

+		at_print(AT_ERR,"cimi_err_act zCtrm_SimAuth ERROR!\n");

+		return RESULT_ERROR;

+	}

+	else

+	{

+		strncpy(simPara.simImsi,imsi,sizeof(simPara.simImsi)-1);

+		if(*(simPara.simImsi) == '\0')

+     	{

+        	at_print(AT_ERR,"cimi_ok_act zCtrm_SimAuth ERROR!\n");

+			return RESULT_ERROR;

+    	}

+		zCtrm_SIMPara2Auth(&simLockListPara, simPara);

+		ret = zCtrm_AuthSIMPara(&simLockListPara);

+		if (EXT_SUCCESS != ret)

+		{

+			ret = get_modem_info("AT+CFUN=4;+ZSCHPLMN=0\r\n", NULL, NULL);

+			if (ret)

+			{

+				at_print(AT_ERR,"zCtrm_SimAuth ZSCHPLMN0 error!\n");

+			}

+			return RESULT_LOCKED;

+		}

+		else 

+		{

+			ret = get_modem_info("AT+ZSCHPLMN=1\r\n", NULL, NULL);

+			if (ret)

+			{

+				at_print(AT_ERR,"zCtrm_SimAuth ZSCHPLMN1 error!\n");

+			}

+			return RESULT_UNLOCKED;

+		}	

+	}

+

+}

+

+int zCtrm_makeLocknetAuth(MSG_BUF *msg)

+{     

+	UINT32 readCode = READ_ERROR;//¶ÁÈ¡ËøÍø²ÎÊý¡¢½âËøÂ롢ǩÃûÊÇ·ñ´æÔÚ

+	UINT32  result = RESULT_ERROR;//ÿһ²½µÄÅжϽá¹û

+	char at_str[AT_STR_LEN] = {0};

+	int ret = -1;

+		

+	at_print(AT_ERR,"zCtrm_ExtLocknetAuth,status = %d\n",g_Sec_Status);

+    if(g_Sec_Status != ENCRYPT_LOCK && g_Sec_Status != ENCRYPT_UNLOCK_CORRECT)

+    {

+		at_print(AT_ERR,"zCtrm_LocknetAuth, g_Sec_Status:%d\n",g_Sec_Status);

+

+	//ËøÍø²ÎÊý¡¢½âËøÂ롢ǩÃûÊÇ·ñ´æÔÚ

+	    readCode = zCtrm_SignExistAuthMutex();

+	    if(readCode == READ_ERROR)

+	    {       

+	        g_Sec_Status = ENCRYPT_ERROR;

+	        at_print(AT_ERR,"zCtrm_SignExistAuthMutex ERROR!\n");

+			snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR:149\r\n");

+			goto end;

+	    } 

+	    else if(readCode == LOCKKEY_ISNULL)

+	    {

+	    	ret = get_modem_info("AT+ZSCHPLMN=1\r\n", NULL, NULL);

+			if (ret) {

+				at_print(AT_ERR,"zCtrm_SignExistAuthMutex zschplmn1 error!\n");

+			}

+			g_Sec_Status = ENCRYPT_UNLOCK_CORRECT;

+			at_print(AT_ERR,"zCtrm_SignExistAuthMutex UNLOCK!\n");

+			snprintf(at_str,AT_STR_LEN,"\r\nOK\r\n");

+			goto end;

+	    }

+	    //²ÎÊý´æÔÚ£¬½øÒ»²½ÅжÏ

+	    else

+	    {

+	        //ÅжÏÕªÒªÓëÇ©ÃûÊÇ·ñÒ»Ö£¬Ç©ÃûÐèÒªÓù«Ô¿½âÃÜ

+	        result = zCtrm_SignAuth();

+	        if(result == RESULT_ERROR)

+	        {

+	        	g_Sec_Status = ENCRYPT_ERROR;

+		  		snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR:149\r\n");

+				goto end;

+	        }

+	        else if(result == RESULT_LOCKED)

+	        {

+	        	snprintf(at_str,AT_STR_LEN,"AT+CFUN=4;+ZSCHPLMN=0\r\n");

+				ret = get_modem_info(at_str, NULL, NULL);

+				if (ret) {

+					at_print(AT_ERR,"zCtrm_SignExistAuthMutex zschplmn0 error!\n");

+				}

+	            g_Sec_Status = ENCRYPT_LOCK;

+	            at_print(AT_ERR,"zCtrm_SignAuth LOCK!\n");

+	            snprintf(at_str,AT_STR_LEN,"\r\nOK\r\n");

+				goto end;

+	        }

+	        //½øÒ»²½ÅжÏ

+	        else

+	        {

+	            //ÅжϽâËøÂëÓëÓû§½âËøÂëÊÇ·ñÒ»Ö£¬Óû§½âËøÂëÐèÒªÓù«Ô¿¼ÓÃÜ

+	            //½öµ±Óû§½âËøÂë²»´æÔÚ»òÕßÓû§½âËøÂëÓë½âËøÂë²»Ò»Ñùʱ£¬½øÐÐsim¿¨ÅжÏ

+	            result = zCtrm_KeyAuth();

+	            if(result == RESULT_ERROR)

+	            {

+	                g_Sec_Status = ENCRYPT_ERROR;

+	                at_print(AT_ERR,"zCtrm_KeyAuth ERROR!\n");

+	               	snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR:149\r\n");

+					goto end;

+	            }

+	            else if(result == RESULT_UNLOCKED)

+	            {

+	                ret = get_modem_info("AT+ZSCHPLMN=1\r\n", NULL, NULL);

+					if (ret) {

+						at_print(AT_ERR,"zCtrm_SignExistAuthMutex zschplmn1 error!\n");

+					}

+					g_Sec_Status = ENCRYPT_UNLOCK_CORRECT;

+	                at_print(AT_ERR,"zCtrm_KeyAuth UNLOCK!\n");

+	                snprintf(at_str,AT_STR_LEN,"\r\nOK\r\n");

+					goto end;

+	            }

+	            //½øÒ»²½ÅжÏ

+	            else

+	            {       

+					result = zCtrm_SimAuth();

+					if(RESULT_ERROR == result)

+					{

+						g_Sec_Status = ENCRYPT_ERROR;

+						at_print(AT_ERR,"zCtrm_SimAuth ERROR!\n");

+						snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR:149\r\n");

+						goto end;

+					}

+					else if(RESULT_LOCKED == result)

+					{

+						g_Sec_Status = ENCRYPT_LOCK;

+						snprintf(at_str,AT_STR_LEN,"\r\nOK\r\n");

+						goto end;

+					}

+					else

+					{

+						g_Sec_Status = ENCRYPT_UNLOCK_CORRECT;

+						snprintf(at_str,AT_STR_LEN,"\r\nOK\r\n");

+						goto end;

+					}

+				}

+		

+	        }

+	    }

+		/* cov2

+	   	ret = get_modem_info("AT+ZSCHPLMN=1\r\n", NULL, NULL);

+		if (ret) {

+			at_print(AT_ERR,"zCtrm_SignExistAuthMutex zschplmn1 error!\n");

+		}

+		g_Sec_Status = ENCRYPT_UNLOCK_CORRECT;

+		snprintf(at_str,AT_STR_LEN,"\r\nOK\r\n");

+		goto end;

+		*/

+    }

+	snprintf(at_str,AT_STR_LEN,"\r\nOK\r\n");

+	goto end;

+end:

+	if(1 == sendflag)

+	{

+		send_rsp_str_to_farps(MODULE_ID_LOCKNET, at_str, strlen(at_str));//Èç¹ûÊÇzurdy´¥·¢µÄËøÍøÁ÷³Ì£¬²»ÐèÒªÏò´®¿Ú·¢·µ»ØÖµ

+		sendflag = 0;

+	}

+	return 0;

+}

+

+static UINT32 zCtrm_UnlockTimesCheck(UINT32 *curTimes)

+{

+	UINT32 retCode = EXT_ERROR;

+	UINT32 times = 0;

+	UINT32 maxTimes = 0;

+	T_zCtrm_LockLevel lockState = NEVER_LOCKED;

+

+	//retCode = zDrvNand_Read(AMT_LOCKNET_BASE, sizeof(lockState),(UINT8 *)&lockState);

+	retCode = cpnv_NvItemRead(AMT_LOCKNET_BASE,(UINT8 *)&lockState, sizeof(lockState));

+	at_print(AT_ERR,"zCtrm_UnlockCodeCheck lockState=%d,retCode=%d!\n",lockState,retCode);

+	if (EXT_SUCCESS != retCode || lockState != LOCKED)

+	{  

+	   return EXT_ERROR;

+	}

+

+

+	//retCode = zDrvNand_Read(AMT_LOCKNET_TIMES, sizeof(times),(UINT8 *)&times);

+	retCode = cpnv_NvItemRead(AMT_LOCKNET_TIMES,(UINT8 *)&times, sizeof(times));

+	at_print(AT_ERR,"zCtrm_UnlockCodeCheck times=%d,retCode=%d!\n",times,retCode);

+	if (EXT_SUCCESS != retCode)

+	{  

+	   return EXT_ERROR;

+	}

+

+	maxTimes = zCtrm_GetUnlockMaxTime();

+	if(times > 0 && times <= maxTimes)

+	{

+	   *curTimes = times;

+	   return EXT_SUCCESS;

+	}

+

+	return EXT_ERROR;

+}

+

+//Óû§ÊäÈëµÄ½âËøÂ룬ÐèÒªÓù«Ô¿¼ÓÃܺóÔÙÓë´æÈëROÖеĽâËøÂë±È½Ï¡£

+//(ROÖнâËøÂë128λ)

+static UINT32 zCtrm_UnlockCodeCheck(UINT8 *keyBuf,UINT16 keyLen)

+{

+	UINT32 retCode = EXT_ERROR;    

+	UINT8 lockkey[KEY_LEN] = {0};

+	UINT8 keyBufText[KEY_LEN] = {0};//Óû§ÊäÈë½âËøÂë¼ÓÃܺó×Ö·û

+	UINT8 test1[KEY_LEN*2+1]={0};

+	UINT8 test2[KEY_LEN*2+1]={0};

+	UINT8 keyBuf128[KEY_LEN]={0};

+

+

+	//retCode = zDrvNand_Read(AMT_LOCKNET_KEY, sizeof(lockkey), lockkey);

+	retCode = cpnv_NvItemRead(AMT_LOCKNET_KEY,lockkey, sizeof(lockkey));

+	zCtrm_Bytes2String(lockkey, test1, KEY_LEN);

+	at_print(AT_ERR,"zCtrm_UnlockCodeCheck lockkey=%s,len=%d!\n",test1,strlen(test1));

+	if (EXT_SUCCESS != retCode)

+	{   

+	   return EXT_ERROR;

+	}

+

+

+	memcpy(keyBuf128+KEY_LEN-LOCKNET_KEY_LEN, keyBuf, LOCKNET_KEY_LEN);

+	retCode = zCtrm_RsaPublicEncryptProc(keyBuf128, keyBufText);

+	zCtrm_Bytes2String(keyBufText, test2, KEY_LEN);

+	at_print(AT_ERR,"zCtrm_UnlockCodeCheck keyBufText=%s,len=%d!\n",test2,strlen(test2));

+	if (EXT_SUCCESS != retCode )

+	{   

+	   return EXT_ERROR;

+	}

+

+	if(memcmp(keyBufText,lockkey,keyLen) != 0)

+	{   

+	   return EXT_ERROR;

+	}

+

+	return EXT_SUCCESS;

+}

+

+static VOID zCtrm_UnlockTimesUpdate(UINT32 curTimes)

+{   

+	UINT32 retCode = EXT_ERROR;

+	UINT32 maxTimes = 0;

+

+	maxTimes = zCtrm_GetUnlockMaxTime();

+	if(curTimes > 0 && curTimes <= maxTimes)

+	{

+	  	curTimes = curTimes - 1;

+	}

+	else

+	{

+	   	curTimes = 0;

+	}

+

+	cpnv_ChangeNvRoAttr(1);

+	//retCode = zDrvNand_Program(AMT_LOCKNET_TIMES, sizeof(curTimes),(UINT8 *)&curTimes);

+	retCode = cpnv_NvItemWriteNvro(AMT_LOCKNET_TIMES, (UINT8 *)&curTimes, sizeof(curTimes));

+	if (EXT_SUCCESS != retCode)

+	{  

+		//retCode = zDrvNand_Program(AMT_LOCKNET_TIMES, sizeof(curTimes),(UINT8 *)&curTimes);

+		retCode = cpnv_NvItemWriteNvro(AMT_LOCKNET_TIMES, (UINT8 *)&curTimes, sizeof(curTimes));

+	    at_print(AT_ERR,"zCtrm_UnlockTimesUpdate: %ld\n",retCode);

+	}

+	cpnv_FsGcWait(FS_NVROFS);

+	cpnv_ChangeNvRoAttr(0);    

+	at_print(AT_ERR,"zCtrm_UnlockTimesUpdate cur: %ld\n",curTimes); 

+}

+

+static UINT32 zCtrm_UnlockNandSet(UINT8 *keyBuf,UINT16 len)

+{

+	T_zCtrm_LockLevel lockState = ALREADY_UNLOCKED;

+	T_zCtrm_LockLevel lockState_out = ALREADY_UNLOCKED;

+	UINT32 times = zCtrm_GetUnlockMaxTime();

+	UINT32 retCode =EXT_ERROR;

+

+	cpnv_ChangeNvRoAttr(1);

+	//retCode = zDrvNand_Program(AMT_LOCKNET_TIMES, sizeof(times),(UINT8 *)&times);

+	retCode = cpnv_NvItemWriteNvro(AMT_LOCKNET_TIMES, (UINT8 *)&times, sizeof(times));

+	at_print(AT_ERR,"zCtrm_UnlockNandSet len=%d,times=%d!\n",sizeof(times),times);

+	if (EXT_SUCCESS != retCode)

+	{  

+		cpnv_ChangeNvRoAttr(0);   

+	    return EXT_ERROR;

+	}

+

+	//retCode = zDrvNand_Program(AMT_LOCKNET_USRKEY, len,keyBuf);

+	retCode = cpnv_NvItemWriteNvro(AMT_LOCKNET_USRKEY, keyBuf, len);

+	at_print(AT_ERR,"zCtrm_UnlockNandSet len=%d,keyBuf=%s!\n",len,keyBuf);

+	if (EXT_SUCCESS != retCode)

+	{  

+	  	cpnv_ChangeNvRoAttr(0);   

+	   	return EXT_ERROR;

+	}

+

+	//retCode = zDrvNand_Program(AMT_LOCKNET_BASE, sizeof(lockState),(UINT8 *)&lockState);

+	retCode = cpnv_NvItemWriteNvro(AMT_LOCKNET_BASE, (UINT8 *)&lockState, sizeof(lockState));

+	at_print(AT_ERR,"zCtrm_UnlockNandSet len=%d,lockstate=%d!\n",sizeof(lockState),lockState);

+	if (EXT_SUCCESS != retCode)

+	{   

+		cpnv_ChangeNvRoAttr(0);   

+	   	return EXT_ERROR;

+	}

+

+	//zDrvNand_Read(AMT_LOCKNET_BASE, sizeof(lockState_out),(UINT8 *)&lockState_out);

+	retCode = cpnv_NvItemRead(AMT_LOCKNET_BASE,(UINT8 *)&lockState_out, sizeof(lockState_out));

+	at_print(AT_ERR,"zCtrm_UnlockNandSet len=%d,lockState_out=%d!\n",sizeof(lockState_out),lockState_out);

+	cpnv_FsGcWait(FS_NVROFS);

+	cpnv_ChangeNvRoAttr(0);    

+

+	return EXT_SUCCESS;

+}

+

+int zCtrm_LocknetUnlock(MSG_BUF *msg)

+{    

+	UINT32 retCode = EXT_ERROR;

+	UINT32 retryCount = 0;  

+    UINT16 keyLen = 0;

+    MSG_BUF *p_msg = (MSG_BUF *)msg;

+    UINT8 keyBuf[LOCKNET_KEY_LEN+1] = {0};  

+	char at_str[AT_STR_LEN] = {0};

+	int ret = -1;

+

+	at_print(AT_ERR,"zCtrm_LocknetUnlock\n");

+	retCode = zCtrm_UnlockTimesCheck(&retryCount);

+    if (EXT_SUCCESS != retCode )

+	{   

+	  	snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR:3\r\n");

+		goto end;

+    }

+    at_print(AT_ERR,"zCtrm_LocknetUnlock cur: %ld\n",retryCount);  

+	keyLen = p_msg->usDataLen;

+	if (keyLen != LOCKNET_KEY_LEN)

+	{

+		snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR:6004\r\n");

+		goto end;

+	}

+    memcpy(keyBuf,p_msg->aucDataBuf,keyLen);

+    at_print(AT_ERR,"zCtrm_ExtLocknetUnlock keyBuf=%s!\n",keyBuf);

+        

+    retCode = zCtrm_UnlockCodeCheck(keyBuf,keyLen);

+    if (EXT_SUCCESS != retCode )

+    {   

+    	zCtrm_UnlockTimesUpdate(retryCount);

+		snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR:6004\r\n");

+		goto end;

+    }

+

+    //Ã÷ÎÄ´æÈëÓû§ÊäÈëµÄ½âËøÂë(16λ×Ö·û)

+    retCode = zCtrm_UnlockNandSet(keyBuf,keyLen);

+	if (EXT_SUCCESS != retCode )

+    {   

+        zCtrm_UnlockTimesUpdate(retryCount);

+        snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR:6004\r\n");

+		goto end;

+    }

+	ret = get_modem_info("AT+ZSCHPLMN=1\r\n", NULL, NULL);

+	if (ret) {

+		at_print(AT_ERR,"zCtrm_LocknetUnlock zschplmn1 error!\n");

+	}

+	g_Sec_Status = ENCRYPT_UNLOCK_CORRECT;

+    at_print(AT_ERR,"zCtrm_UnlockModemSet\n");

+    snprintf(at_str,AT_STR_LEN,"\r\nOK\r\n");

+	goto end;

+ end:

+	send_rsp_str_to_farps(MODULE_ID_LOCKNET, at_str, strlen(at_str));

+	return 0;       

+}

+

+static UINT32 zCtrm_UnlockTimesGet(UINT32 *curTimes)

+{

+    UINT32 retCode = EXT_ERROR;

+    UINT32 times = 0;

+    UINT32 maxTimes = 0;

+    T_zCtrm_LockLevel lockState = NEVER_LOCKED;

+    

+    //retCode = zDrvNand_Read(AMT_LOCKNET_BASE, sizeof(lockState),(UINT8 *)&lockState);

+    retCode = cpnv_NvItemRead(AMT_LOCKNET_BASE,(UINT8 *)&lockState, sizeof(lockState));

+    at_print(AT_ERR,"zCtrm_UnlockTimesGet lockState=%d,retCode=%d!\n",lockState,retCode);

+    if (EXT_SUCCESS != retCode || lockState != LOCKED)

+    {  

+        return EXT_ERROR;

+    }

+    

+    

+    //retCode = zDrvNand_Read(AMT_LOCKNET_TIMES, sizeof(times),(UINT8 *)&times);

+    retCode = cpnv_NvItemRead(AMT_LOCKNET_TIMES,(UINT8 *)&times, sizeof(times));

+    at_print(AT_ERR,"zCtrm_UnlockTimesGet times=%d,retCode=%d!\n",times,retCode);

+    if (EXT_SUCCESS != retCode)

+    {  

+        return EXT_ERROR;

+    }

+

+    maxTimes = zCtrm_GetUnlockMaxTime();

+    if(times <= maxTimes)//klocwork

+    {

+        *curTimes = times;

+        return EXT_SUCCESS;

+    }

+    

+    return EXT_ERROR;

+}

+

+int zCtrm_LocknetUnlockTimes(MSG_BUF *msg)

+{

+	UINT32 retCode = EXT_ERROR;

+	UINT32 retryCount = 0; 

+	UINT8 pStr[4] = {0};

+	char at_str[AT_STR_LEN] = {0};

+		

+	retCode = zCtrm_UnlockTimesGet(&retryCount);

+	if (EXT_SUCCESS != retCode )

+	{   

+	   	snprintf(at_str,AT_STR_LEN,"\r\n+CME ERROR:3\r\n");

+		goto end;

+	}  

+	snprintf(at_str,AT_STR_LEN,"\r\n+ZNCK:%d\r\nOK\r\n",retryCount);

+	goto end;

+end:

+	send_rsp_str_to_farps(MODULE_ID_LOCKNET, at_str, strlen(at_str));

+	return 0;

+

+}

+

+int zCtrm_LocknetStatus(MSG_BUF *msg)

+{

+	T_zCtrm_SecItems secItems = NO_ACTION;

+	char at_str[AT_STR_LEN] = {0};

+

+	if(g_Sec_Status == ENCRYPT_LOCK)

+	{

+	    secItems = NET_LOCK;

+	}

+	snprintf(at_str,AT_STR_LEN,"\r\n+ZSEC:%d,%d\r\nOK\r\n",g_Sec_Status,secItems);

+	send_rsp_str_to_farps(MODULE_ID_LOCKNET, at_str, strlen(at_str));

+	return 0;

+}

+