SSL connection with trusted authority certificate


#1

Modem : Q2686RD
Firmware : 7.44
Security plugin : 1.4

I have an OpenAT application that do an SSL connection to a server. Every thing goes well as long as I use a self signed certificate. But when I use a certificate provided by a trusted authority (GlobalSign), the connexion fails with error “Bad certificate”.

I‘ve used successfully this certificate with a browser. I guess that the issue is related to a check with GlobalSign in the modem.

Can someone tell me what I should do?

Here’s my code:

ret = wip_SSLInitOpts(WIP_COPT_CERT_AUTHORITY, myCertificate,
                      WIP_COPT_VERIFY, WIP_SSL_ALWAYS,
/…/
// ret always == 0 (Success)


channel = wip_SSLClientCreateOpts(srv, port, eventHandler, ctx,
                                  WIP_COPT_PORT, portNo,
                                  WIP_COPT_END);
/…/


// Socket event handler :
void eventHandler (wip_event_t *evt, void * ctx)
{
  switch(evt->kind)
  {
  case WIP_CEV_OPEN: // 2
    // Ends here when I use a self signed certificate
    break;
  case WIP_CEV_ERROR: // 1
    if ((int)evt->content.error.errnum == 1) {
      // Certificate error
      // Ends here when I use a certificate provided by GlobalSign
    }
    else {
      // Other errors
    }
/…/

I’ve tried successfully

WIP_COPT_VERIFY = WIP_SSL_NEVER

But, I don’t know exactly what it means. Anyway, I want to check the certificate (Such as its valid dates, etc.).

Any trick to get a more specific error code is welcome.


#2

Hi,

It simply means that the certificate will not be verified and hence it is successful.

Please do check the validity of the certificate first. If it is valid and you are still facing the issue, then check the rtc clock (AT+CCLK) and make sure it is properly set.

Regards,
Rex_alex


#3

Hello,

I’m trying to do a SSL connection like client but i didn’t find any documentation :open_mouth: Could anyone say me the name of the SSL guide and where can I download it??

Searching in google I found this code: (I don’t know if it works because i don’t know how it works if I don’t have documentation :frowning: )

#include "https.h"
#include "wip.h"
#include <assert.h>
#include "oatlua.h"
#ifdef __Security_PLUGIN_VERSION__
#include "wip_ssl.h"
#endif

/* State automaton:
 *  - initial state = IDLE
 *  - when a request is made from Lua, a TCP connection is requested,
 *    state = OPENING;
 *  - when the connection is accepted (WIP_CEV_OPEN), we start sending
 *    the request to the peer, state = SENDING;
 *  - when the whole body has been sent, we expect to get the response,
 *    state = RECEIVING;
 *  - when  the response is complete, we go back to state = IDLE.
 *    We're then ready to perform another HTTP request.
 *
 *  If anything goes wrong at any point, we revert to STATE = IDLE.
 *
 *  The algorithm is not reentrant: it's the Lua wrapper's responsibility
 *  to ensure that two requests don't mix with each other.
 */
enum { IDLE, OPENING, SENDING, RECEIVING } state;

/* TCP channel used for the request. */
wip_channel_t channel = NULL;

/* Try to reuse last SSL session. */
#ifdef __Security_PLUGIN_VERSION__
wip_SSLSession_t lastSSLSession = NULL;
#endif

/* How many bytes of the request have already been sent. */
int send_offset = 0;

/* In addition to the C globals, the system relies on the "https_body"
 * field in Lua's registry.
 *
 * - In OPENING and SENDING states, it contains the request to send,
 *   as a string.
 * - In RECEIVING state, it contains the partial response,
 *   as a list of strings.
 * - In IDLE state, it's left as nil.
 */

/* Signal an error (the signal argument is popped from top of stack),
 * revert to IDLE state,
 * free any taken resource.
 */
static void error( lua_State *L) {
	const char *msg = luaL_checkstring(L, -1);
	lua_pushnil( L);
	lua_setfield( L, LUA_REGISTRYINDEX, "https_body");
	state = IDLE;
	wip_close( channel);
	luaW_signal_str( L, "https", "error", LUAW_SIG_STRING, msg, LUAW_SIG_END);
}

/* React to WIP events */
static void evh_request( wip_event_t *ev, void *ctx) {
	lua_State *L = GlobalL;
	switch( ev->kind) {

	case WIP_CEV_OPEN:
		assert( OPENING == state);
		state = SENDING;
		send_offset = 0;
#		ifdef __Security_PLUGIN_VERSION__
		if( wip_hasType( ev->channel, WIP_CTYPE_SSL))	{
			if( lastSSLSession) wip_SSLReleaseSession( lastSSLSession);
			lastSSLSession = wip_SSLGetSession( ev->channel);
		}
#		endif
		break;

	case WIP_CEV_ERROR:
		lua_pushinteger( L, ev->content.error.errnum);
		error( L);
		break;

	case WIP_CEV_READ: {
		if( RECEIVING != state) {
			luaW_debug( "https", "ERROR", "Peer doesn't respect HTTP protocol");
			lua_pushstring( L, "protocol violation");
			error( L);
		} else {
#			define READ_BUFFER_SIZE 256
			int read;
			lua_getfield( L, LUA_REGISTRYINDEX, "https_body");
			if( ! lua_istable( L, -1)) {
				luaW_debug( "https", "ERROR", "https_body must be a table when receiving");
				lua_pushstring( L, "internal inconsistency");
				error( L);
			} else do { // https_body
				char buffer [READ_BUFFER_SIZE];
				int n_received_segments = lua_objlen( L, -1);
				read = wip_read( channel, buffer, sizeof( buffer));
				luaW_debug("https", "DEBUG", "Read %d bytes", read);
				if( read > 0) {                                 // https_body
					lua_pushinteger( L, ++n_received_segments); // https_body, n
					lua_pushlstring( L, buffer, read);          // https_body, n, segment
					lua_settable( L, -3);                       // https_body
				}
			} while( READ_BUFFER_SIZE == read);
			lua_pop( L, 1);
			luaW_signal_str( L, "https", "data", LUAW_SIG_END); // -
#			undef READ_BUFFER_SIZE
		}
		break;
	}

	case WIP_CEV_WRITE: {
		const char *buffer;
		size_t len, to_send;
		lua_getfield( L, LUA_REGISTRYINDEX, "https_body");
		buffer = luaL_checklstring( L, -1, & len);
		to_send = len - send_offset;
		if( to_send > 0) {
			size_t sent = wip_write( channel, (void*) (buffer + send_offset), to_send);
			if( sent>0) {
				to_send -= sent;
				send_offset += sent;
			}
		}
		if( 0 == to_send) {
			lua_newtable( L); lua_setfield( L, LUA_REGISTRYINDEX, "https_body");
			state = RECEIVING;
		}
		break;
	}

	case WIP_CEV_PEER_CLOSE: {
		lua_getfield( L, LUA_REGISTRYINDEX, "https_body");
		//lua_pushnil( L);
		//lua_setfield( L, LUA_REGISTRYINDEX, "https_body");
		if( state == RECEIVING && lua_istable( L, -1)) {
			luaW_signal_str( L, "https", "response", LUAW_SIG_END);
		} else {
			luaW_debug( "https", "ERROR", "Closed before sending response");
		}
		state = IDLE;
		wip_close( channel);
		break;
	}

	default:
		luaW_debug( "https", "WARNING", "Unexpected TCP event %d", ev->kind);
	}
}

/* Signal the the channel, the last resource being kept, has been released. */
static void finalizer( void *ctx) {
	luaW_signal_str( GlobalL, "https", "released", 0);
}

/* Receive a request from Lua. Parameters:
 * - the server name
 * - the server port
 * - the complete request to send, as a string
 *
 * Produce no result, the request's response will eventually be broadcast as a signal.
 */
static int api_request( lua_State *L)  {
#	define CHECK( test, msg) \
		if( ! (test)){ lua_pushnil( L); lua_pushstring( L, msg); return 2; }
	const char *protocol = luaL_checkstring(  L, 1);
	const char *host = luaL_checkstring(  L, 2);
	int         port = luaL_checkinteger( L, 3);
	(void) luaL_checkstring(  L, 4); // Request body

	CHECK( state == IDLE, "request pending");

	/* Save body in the registry, for future reference
	 * and to protect against garbage collection. */
	lua_setfield( L, LUA_REGISTRYINDEX, "https_body");

	if( ! strcmp( "https", protocol)) {
#		ifdef __Security_PLUGIN_VERSION__
		if( lastSSLSession) {
			channel = wip_SSLClientCreateOpts( (ascii*) host, port, evh_request, NULL,
					WIP_COPT_SESSION, lastSSLSession,
					WIP_COPT_FINALIZER, finalizer,
					WIP_COPT_END);
		} else {
			channel = wip_SSLClientCreateOpts( (ascii*) host, port, evh_request, NULL,
					WIP_COPT_FINALIZER, finalizer,
					WIP_COPT_END);
		}
#		else
		CHECK( 0, "HTTPS protocol not supported, recompile with security plugin.");
#		endif
	} else {
		channel = wip_TCPClientCreateOpts( (ascii*) host, port, evh_request, NULL,
				WIP_COPT_FINALIZER, finalizer,
				WIP_COPT_END);
	}
	CHECK( channel, "cannot open channel");

	state = OPENING;
	lua_pushboolean( L, 1);
	return 1;
#	undef CHECK
}

static int api_abort( lua_State *L) {
	wip_close( channel);
	state = IDLE;
	lua_pushnil( L);
	lua_setfield( L, LUA_REGISTRYINDEX, "https_body");
	return 0;
}

static int api_getbody( lua_State *L) {
	lua_getfield( L, LUA_REGISTRYINDEX, "https_body");
	return 1;
}

#ifdef __Security_PLUGIN_VERSION__

static int api_sslinit( lua_State *L) {
	const char *certificate  = luaL_checkstring( L, 1);
	const char *key          = luaL_checkstring( L, 2);
	const char *authority    = luaL_optstring( L, 3, certificate);
	const char *verifystr    = luaL_optstring( L, 4, "always");
	int verify;

	if( ! strcmp( verifystr, "once")) verify = WIP_SSL_ONCE;
	else if( ! strcmp( verifystr, "never")) verify = WIP_SSL_NEVER;
	else verify = WIP_SSL_ALWAYS;

	int r = wip_SSLInitOpts(
			WIP_COPT_CERT_AUTHORITY, authority,
			WIP_COPT_CERT,           certificate,
			WIP_COPT_PRIVATE_KEY,    key,
			WIP_COPT_VERIFY,         verify,
			//WIP_COPT_KEY,          WIP_SSL_ALL,
			WIP_COPT_AUTHENTICATION, WIP_SSL_RSA,
			WIP_COPT_ENCRYPTION,     WIP_SSL_3DES,
			//WIP_COPT_VERSION,      WIP_SSL_ALL,
			WIP_COPT_END);

	if( 0 == r) { lua_pushboolean( L, 1); return 1; }
	else { lua_pushnil( L); lua_pushinteger( L, r); return 2; }
}
#endif

/* Register the functions. */
int luaopen_https_core( lua_State *L) {
	lua_getglobal( L, "internal");
#	define REGISTER( name) \
		lua_pushcfunction( L, api_##name); lua_setfield( L, -2, "https_"#name)
	REGISTER( request);
	REGISTER( abort);
	REGISTER( getbody);
#	ifdef __Security_PLUGIN_VERSION__
	REGISTER( sslinit);
#	endif
#	undef REGISTER
	lua_pop( L, 1);
	return 0;
}

#4

For a documentation, you have to install “Sierra Wireless Software Suite”

It can be downloaded from Sierra’s website (You have to log in) :
sierrawireless.com/en/Suppor … Q2686.aspx

With defaut setup, the documentation should be there :
C:\Program Files\Sierra Wireless\Embedded Software\com.wavecom.openat.ide.spm.lib.plugin.model.WIP.5.40.0.201007290812_5.40.0.201007290812\resources\doc

There is also a few samples …


#5

Thanks for your answer GMarnier0 :slight_smile:

My problem its that i’m searching a User guide like the Open AT IP connectivity development guide (WIPlib v2.00)

In this guide they explain how to use concepts like wip_HTTPClientCreateOpts.

For this cause, i’m searching a document where they explain concepts like wip_SSLClientCreateOpts

A lot of thanks


#6

Sorry, I did a mistake.

The documentaiton for the Security plugin is there :

C:\Program Files\Sierra Wireless\Embedded Software\com.wavecom.openat.ide.spm.lib.plugin.model.Security.1.5.0.201108111447_1.5.0.201108111447\resources\doc

File : SSL_UGD.pdf


#7

Did you ever find a resolution to this problem?


#8

I do “WIP_COPT_VERIFY = WIP_SSL_NEVER”
Not a solution, imo.