C Porting Layer API Reference for Oracle Internet of Things Cloud Service Client Software Library. Release 21.1.1.0.0-3. E80003-19
|
The device and enterprise client libraries simplify working with the Oracle IoT Cloud Service. These client libraries are a low-level abstraction over top of messages and REST APIs. Device clients are primarily concerned with sending data and alert messages to the cloud service, and acting upon requests from the cloud service. Enterprise clients are primarily concerned with monitor and control of device endpoints.
The Oracle Internet of Things C Client Library is a high level native library for accessing the Oracle IoT Cloud Service. Basically, Cloud Service supports only low level REST API and this library provides higher level abstraction on top of that making development of client applications easier and faster.
This specification describes API of some functionality that required by Client Library but can't be implemented using C99 language standard. It contains some platform depended functionality like thread, mutexes, cryptography, etc.
C CL Porting Guide Draft
Optional diagnostic capability porting API
Optional for Message Dispatcher
Optional for Long Polling support
Optional for automatic device time adjustment
7. UTAM porting APILibrary needs a TAM module that provides trusted_assets_manager.h API. This API gives library access to IoT server URL, endpoint id, endpoint public key and encryption using shared secret and private key.
There is an internal TAM implementation that supports two modes: Default TAM (obsolete and deprecated - kept for compatibility) and Unified TAM (unified format for all client libraries).
void
iotcs_port_tam_init (void);
Initializes
porting layer for default TAM.
void
iotcs_port_tam_finalize(void);
Clears
all the resources allocated so far.
iotcs_result
iotcs_port_tam_set_ts_password(const char*
trust_store_password);
Save given
password for later use.
size_t
iotcs_port_tam_secret_hash(IOTCS_TYPE_SHA type, const unsigned char*
key, size_t key_length, const unsigned char* content, size_t
content_length, unsigned char *hash, size_t hash_maxsize);
Generates
secret hash used for authentication and to get access token.
iotcs_result
iotcs_port_tam_unified_credentials_decrypt(unsigned char *out,
size_t* out_len, const unsigned char* in, size_t in_len, const
unsigned char* iv);
Decrypts the
data from unified trusted assets store. Function uses password given
with iotcs_port_tam_set_ts_password call. Expands the password into
16 bytes using PKCS#5 PBKDF2 SHA1 HMAC with 10000 iterations. And
finally decrypt the data with 128 bit AES Cipher Block Chaining (CBC)
and PKCS#5 padding. iv argument is used as initialization vector in
decryption process.
iotcs_result
iotcs_port_tam_unified_credentials_encrypt(unsigned char *out,
size_t* out_len, const unsigned char* in, size_t in_len, const
unsigned char* iv);
Similar to
iotcs_port_tam_unified_credentials_decrypt but does inverse
transformation.
size_t
iotcs_port_tam_get_trust_anchors_count(void);
Get
number of trusted certificates
const char*
iotcs_port_crypto_get_trust_anchor_certificate(size_t index, size_t
*len);
Get certificate in index
position in DER format.
iotcs_result
iotcs_port_crypto_serialize_private_key(unsigned char *buf, size_t
buf_length, size_t *written);
Serialize
private key in PKCS#8 format into given buffer.
iotcs_result
iotcs_port_crypto_deserialize_private_key(unsigned char *buf, size_t
buf_length);
Load private key (and
public) in PKCS#8 format from given buffer.
iotcs_result
iotcs_port_ tam_generate_keypair(size_t key_size, unsigned char*
public_out, size_t* public_length);
Generates
RSA key pair and return public key in DER format.
size_t
iotcs_port_tam_sign_with_private_key(IOTCS_TYPE_SHA type, const
unsigned char* input, size_t input_length, char* signature, size_t
signature_maxsize);
Sign given input
with generated private key (in call iotcs_port_tam_generate_keypair)
or loaded private key (in call
iotcs_port_crypto_deserialize_private_key).
There is no need to implement these methods as long as no Default TAM support is required.
iotcs_result
iotcs_port_tam_decode_shared_secret(char* encrypted_shared_secret,
char *shared_secret, int shared_secret_length);
iotcs_result
iotcs_port_tam_check_file_signature(const char* file, size_t
signed_data_length, const char* signature);
iotcs_result
iotcs_port_tam_load_trust_store(const char*
trust_store_path);
iotcs_result
iotcs_port_tam_load_trust_store_achors(const unsigned char*
trust_store_anchors, int length);
iotcs_result
iotcs_port_tam_credentials_load(const char *client_id, char
*endpoint_id, size_t *endpoint_length, unsigned char *public_key,
size_t *public_key_len);
iotcs_result
iotcs_port_tam_credentials_store(void);
If Unified TAM doesn’t meet security requirements or target device doesn’t have local file system or for some other reason user could use his own Custom TAM implementation instead of UTAM. Custom TAM must provide TAM API to C CL library. TAM API that could be found in source bundle in file ./iotcs/csl/posix/src/shared/trusted_assets_manager/iotcs_tam.h (path for posix release). UTAM implementation could be used as an example (could be found in source bundle in file ./iotcs/csl/posix/src/shared/trusted_assets_manager/iotcs_tam.c - path for posix release).
There are existing ports that could serve as a good example. Probably the most demonstrative port example is the Posix port. This port uses:
OpenSSL library for cryptography and SSL
pthread library for thread API, mutex API, queue API implementation.
The rest functionality is implemented using: POSIX standard IEEE Std 1003.1with XSI Extension. E.g. <sys/time.h>, <sys/types.h>, <sys/socket.h>, <sys/utsname.h>, <sys/statvfs.h>, <net/if.h>, <arpa/inet.h>, <netinet/in.h>.
Another good example of porting, but this time to embedded system, is port to frdm-k64f board which is called “Mbed” port. Embedded systems tends to be a resource constrained devices with limited amount of memory and CPU power and this fact has an impact on implementation. This port uses:
MbedTLS library for cryptography and SSL
And Mbed RTOS for the rest: thread API, mutex API, queue API implementation and etc.
For building the library on a new platform probably it is worth to reuse existing build system. This section will describe required steps to do so.
Please note that all the instructions is this guide are for posix release, for other releases please substitute “posix” directory with the release platform name. Also this guide might not include all needed steps.
This is the instruction how to build the library with an implementation for a new porting layer.
Open iotcs/csl/posix/make/config/paths.cfg
Set the path to directory with port sources (<custom_port_src>) as a PORT_SRC_DIR variable value
Create your implementation for iotcs/csl/posix/src/include/port/iotcs_port_XXX.h API in < custom_port_src >/<custom_port_XXX.c> files. iotcs_port_tam.h could be not implemented.
Copy iotcs/csl/posix/src/include/port/iotcs_port_tam.h into <custom_port_src> folder. This needed to minimize changes in build system.
Otherwise you should change /csl/posix/make/posix/impl.mk at line 13 that contained target to compile port TAM sources like:
# Compile port TAM source files into .o files $(PORT_TAM_OBJ_DIR)/%.o: $(SRC_DIR)/$(PORT)/%.c $(A)mkdir -p $(dir $@) $(A)$(CC) $(CPPFLAGS) $(CPP_OPTS) $(CFLAGS) $(C_OPTS) $(PORT_FLAGS) $(PORT_OPTS) $(TAM_FLAGS) $(TAM_OPTS) $(OBJECT_FILE_NAME_OPT)$@ $< |
And add include in CPPINCLUDES variable in iotcs/csl/posix/make/common.mk at line 115:
CPPINCLUDES=-I$(PORT_INC_DIR) -I$(INC_DIR) -I$(SHARED_DIR) -I$(OUT_LIB_PATH) -I$(SRC_DIR)/$(PORT) |
(optional) Add target to compile c++ files in file/csl/posix/make/posix/impl.mk:
$(PORT_OBJ_DIR)/%.o: $(PORT_SRC_DIR)/%.cpp $(A)mkdir -p $(dir $@) $(A)$(CC) $(CPPFLAGS) $(CPP_OPTS) $(CXXFLAGS) $(CXX_OPTS) $(PORT_FLAGS) $(PORT_OPTS) $(OBJECT_FILE_NAME_OPT)$@ $< |
Build library
After these changes you could build library as usual, but library will have custom porting layer in it. In addition, you can build library with only porting layer.
Generate library with only porting layer:
make .library_porting_impl |
If target platform’s compiler is not GCC then in order to support new compiler in the build system it is required to follow these steps:
Go to /iotcs/csl/posix/make/cc
Copy gcc.cfg to <compiler>.cfg
(optional) Set default values for custom arguments. For example,
TOOLS_PREFIX?=/<compiler_path>/bin OUT_CC_SUBDIR?=<compiler> |
Set internal variables
CC=$(TOOLS_PREFIX)<compiler> CXX=$(TOOLS_PREFIX)<compiler for c++> AS=$(TOOLS_PREFIX) <compiler for assembler files> LD=$(TOOLS_PREFIX) <linker> AR=$(TOOLS_PREFIX)< archiver> OBJCPY=$(TOOLS_PREFIX) <object copy tool> |
Go to /iotcs/csl/posix/make and execute next command:
make CC_CFG=<compiler> |
Create your implementation for iotcs/csl/posix/src/shared/trusted_assets_manager/iotcs_tam.h API in file < custom_tam _path>/<custom_tam.c>
Open iotcs/csl/posix/make/common.mk at line 313 that contained target to compile TAM sources
# targets for compile TAM sources $(TAM_OBJ_DIR)/%.o: $(SHARED_DIR)/%.c $(A)mkdir -p $(dir $@) $(A)$(CC) $(CPPFLAGS) $(CPP_OPTS) $(CFLAGS) $(C_OPTS) $(TAM_FLAGS) $(TAM_OPTS) $(OBJECT_FILE_NAME_OPT)$@ $< |
Change this target:
# targets for compile TAM sources $(TAM_OBJ_DIR)/%.o: < custom_tam _path>/<custom_tam.c> $(A)mkdir -p $(dir $@) $(A)$(CC) $(CPPFLAGS) $(CPP_OPTS) $(CFLAGS) $(C_OPTS) $(TAM_FLAGS) $(TAM_OPTS) $(OBJECT_FILE_NAME_OPT)$@ $< |
< custom_tam _path> must be either an absolute path or a path relative to the iotcs/csl/posix folder ($(PROJ_DIR) variable)
If required it is possible to support porting layer for a custom TAM.
Create your implementation for iotcs/csl/posix/src/include/port/iotcs_port_tam.h API in file < custom_port_tam _path >/<custom_port_tam.c>
Open iotcs/csl/posix/make/posix/impl.mk at line 13 that contained target to compile port TAM sources
# Compile port TAM source files into .o files $(PORT_TAM_OBJ_DIR)/%.o: $(PORT_SRC_DIR)/%.c $(A)mkdir -p $(dir $@) $(A)$(CC) $(CPPFLAGS) $(CPP_OPTS) $(CFLAGS) $(C_OPTS) $(PORT_FLAGS) $(PORT_OPTS) $(TAM_FLAGS) $(TAM_OPTS) $(OBJECT_FILE_NAME_OPT)$@ $< |
Change this target:
# Compile port TAM source files into .o files $(PORT_TAM_OBJ_DIR)/%.o: < custom_port_tam _path >/<custom_port_tam.c> $(A)mkdir -p $(dir $@) $(A)$(CC) $(CPPFLAGS) $(CPP_OPTS) $(CFLAGS) $(C_OPTS) $(PORT_FLAGS) $(PORT_OPTS) $(TAM_FLAGS) $(TAM_OPTS) $(OBJECT_FILE_NAME_OPT)$@ $< |
< custom_port_tam _path > must be either an absolute path or a path relative to the iotcs/csl/posix folder ($(PROJ_DIR) variable)
After these changes you could build library as usual, but library will have custom TAM in it. In addition, you can build only TAM library.
Generate only TAM library:
make .tam_library_impl |