初始版本

This commit is contained in:
xiaozhengsheng
2025-08-19 09:49:41 +08:00
parent 10f1ddf1c1
commit 6df0f7d96e
2974 changed files with 1712873 additions and 54 deletions

90
external/infineon/CONTRIBUTING.md vendored Normal file
View File

@@ -0,0 +1,90 @@
# Contributing
When contributing to this repository, please first discuss the change you wish to make via issue,
email, or any other method with the owners of this repository before making a change.
Please note we have a code of conduct, please follow it in all your interactions with the project.
## Pull Request Process
1. Ensure any install or build dependencies are removed before the end of the layer when doing a
build.
2. Update the README.md with details of changes to the interface, this includes new environment
variables, useful file locations and parameters.
3. You may merge the Pull Request in once you have the sign-off of two other developers, or if you
do not have permission to do that, you may request the second reviewer to merge it for you.
## Code of Conduct
### Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
nationality, personal appearance, race, religion, or sexual identity and
orientation.
### Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
### Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
### Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
### Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team.
All complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
### Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

21
external/infineon/LICENSE vendored Normal file
View File

@@ -0,0 +1,21 @@
The MIT License
Copyright (c) 2018 Infineon Technologies AG
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE

45
external/infineon/README.md vendored Normal file
View File

@@ -0,0 +1,45 @@
# Infineon's OPTIGA™ Trust X1 hostcode
## Description
<img src="https://github.com/Infineon/Assets/blob/master/Pictures/OPTIGA-Trust-X.png">
This repository contains a C library for [OPTIGA™ Trust X1](www.infineon.com/optiga-trust-x) security chip.
## Summary
The [OPTIGA™ Trust X1](https://www.infineon.com/dgdl/Infineon-DPS310-DS-v01_00-EN.pdf) is a security solution based on a secure micrcontroller. Each device is shipped with a unique elliptic-curve keypair and a corresponding X.509 certificate. OPTIGA™ Trust X enables easy integration into existing PKI infrastructure.
## Key Features and Benefits
* High-end security controller
* Turnkey solution
* One-way authentication using ECDSA
* Mutual authentication using DTLS client (IETF standard RFC 6347)
* Secure communication using DTLS
* Compliant with the USB Type-C™ Authentication standard
* I2C interface
* Up to 10 KB user memory
* Cryptographic support: ECC256, AES128, SHA-256, TRNG, DRNG
* PG-USON-10-2 package (3 x 3 mm)
* Standard & extended temperature ranges
* Full system integration support
* Common Criteria Certified EAL6+ (high) hardware
* Cryptographic Tool Box based on ECC NIST P256, P384 and SHA256 (sign, verify, key generation, ECDH, session key derivation)
## Hostcode strucuture
Detailed modules description you can find on [Wiki page](https://github.com/Infineon/optiga-trust-x/wiki) of this project
## Get started and Application Notes
Get started guide is based on the OPTIGA™ Trust X evaluation kit hardware and DAVE™ 4 (Digital Application Virtual Engineer) IDE. The detailed description you can find in the respective GitHub [repository](https://github.com/Infineon/getstarted-optiga-trust-x).
Infineon's GitHub offers various application notes for OPTIGA™ Trust X security solutions, you can find get started guide mentioned above there as well. The up-to-date list of application notes is [here](https://github.com/Infineon/appnotes-optiga-trust-x)
## Evaluation and developement kits
* [OPTIGA™ Trust X evaluation and demonstration kit](https://www.infineon.com/cms/en/product/evaluation-boards/optiga-trust-x-eval-kit/)
* OPTIGA™ Trust X Shield2Go (link pending)
## Contributing
Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on our code of conduct, and the process for submitting pull requests to us.
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details

View File

@@ -0,0 +1,7 @@
# ECDSA Utils
This folder provides a small library with functions to convert between the raw
ECDSA signature format and the ASN.1 encoding used in X.509 certificates.
It is used by the nrf5x PAL and provided here as example on how to implement
this conversion.

View File

@@ -0,0 +1,327 @@
/**
* MIT License
*
* Copyright (c) 2019 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file ecdsa_utils.c
*
* \brief This file provides functions to convert raw r and s components of the ECDSA signature to asn1 encoding
*
*
* \addtogroup grOptigaUtil
* @{
*/
#include "ecdsa_utils.h"
#include <string.h>
// This implementation only supports a single byte LENGTH field. The maximum
// possible value than can be encoded within a single byte is 0x7F (127 dec).
// For higher values, the length must be coded in a multi-byte field.
#define DER_INTEGER_MAX_LEN 0x7F
// This implementation only supports a single byte LENGTH field. The maximum
// possible value than can be encoded within a single byte is 0x7F (127 dec).
// For higher values, the length must be coded in a multi-byte field.
#define DER_SEQUENCE_MAX_LEN 0x7F
// ASN.1 DER TAG field offset
#define ASN1_DER_TAG_OFFSET 0
// ASN.1 DER LENGTH field offset
#define ASN1_DER_LEN_OFFSET 1
// ASN.1 DER VALUE field offset
// Only for this implementation!
#define ASN1_DER_VAL_OFFSET 2
// ASN.1 DER Tag for INTEGER
#define DER_TAG_INTEGER 0x02
// ASN.1 DER Tag for SEQUENCE
#define DER_TAG_SEQUENCE 0x30
#define DER_UINT_MASK 0x80
/**
* @brief Encodes a byte buffer as unsigned ASN.1 DER INTEGER
*
* @param data[in] Buffer containing the bytes to be encoded
* @param data_len[in] Length of the data buffer
* @param out_buf[out] Output buffer for the encoded ASN.1 bytes
* @param out_buf_len[in] Size of the out_buf buffer
* @return The number of bytes of the ASN.1 encoded stream on success, 0 on error
* @note The parameters to this function must not be NULL.
*/
static size_t encode_der_integer(const uint8_t* data, size_t data_len,
uint8_t* out_buf, size_t out_buf_len)
{
// all write access must be smaller or equal to this pointer
const uint8_t* const out_end = out_buf + out_buf_len - 1;
// fixed position fields
uint8_t* const tag_field = &out_buf[ASN1_DER_TAG_OFFSET];
uint8_t* const length_field = &out_buf[ASN1_DER_LEN_OFFSET];
uint8_t* const integer_field_start = &out_buf[ASN1_DER_VAL_OFFSET];
// write pointer
uint8_t* integer_field_cur = integer_field_start;
// search for beginning of integer
const uint8_t* cur_data = data;
const uint8_t* const data_end = data + data_len;
// check if something to encode, else next loop condition overflows
if (data_len == 0) {
return 0;
}
// don't check the last byte, it will always be a data byte
for(; cur_data < (data_end - 1); cur_data++) {
if (*cur_data != 0x00) {
break;
}
}
// check if stuffing byte needed
if (*cur_data & DER_UINT_MASK) {
integer_field_cur++;
}
// calculate number of bytes left in data
const size_t write_length = data_end - cur_data;
// check if it fits in the output buffer
if ((integer_field_cur + write_length - 1) > out_end) {
// Prevented out-of-bounds write
return 0;
}
// ensure we can encode the length
const size_t integer_len = (integer_field_cur + write_length) - integer_field_start;
if (integer_len > DER_INTEGER_MAX_LEN) {
// This implementation support single-byte LENGTH fields only
return 0;
}
// commit writes
memcpy(integer_field_cur, cur_data, write_length);
*tag_field = DER_TAG_INTEGER;
*length_field = integer_len;
// check if we have a stuffing byte, and explicitly zero it
if (integer_field_cur != integer_field_start) {
*integer_field_start = 0x00;
}
return integer_len + ASN1_DER_VAL_OFFSET;
}
bool ecdsa_rs_to_asn1_integers(const uint8_t* r, const uint8_t* s, size_t rs_len,
uint8_t* asn_sig, size_t* asn_sig_len)
{
if (r == NULL || s == NULL || asn_sig == NULL || asn_sig_len == NULL) {
// No NULL paramters allowed
return false;
}
// encode R component
const size_t out_len_r = encode_der_integer(r, rs_len, asn_sig, *asn_sig_len);
if (out_len_r == 0) {
// error while encoding R as DER INTEGER
return false;
}
uint8_t* const s_start = asn_sig + out_len_r;
const size_t s_len = *asn_sig_len - out_len_r;
// encode S component
const size_t out_len_s = encode_der_integer(s, rs_len, s_start, s_len);
if (out_len_s == 0) {
// error while encoding S as DER INTEGER
return false;
}
*asn_sig_len = out_len_r + out_len_s;
return true;
}
bool ecdsa_rs_to_asn1_signature(const uint8_t* r, const uint8_t* s, size_t rs_len,
uint8_t* asn_sig, size_t* asn_sig_len)
{
if (r == NULL || s == NULL || asn_sig == NULL || asn_sig_len == NULL) {
// No NULL paramters allowed
return false;
}
if (*asn_sig_len < ASN1_DER_VAL_OFFSET) {
// Not enough space, can't encode anything
return false;
}
// fixed position fields
uint8_t* const tag_field = &asn_sig[ASN1_DER_TAG_OFFSET];
uint8_t* const length_field = &asn_sig[ASN1_DER_LEN_OFFSET];
uint8_t* const value_field_start = &asn_sig[ASN1_DER_VAL_OFFSET];
// compute size left after SEQUENCE header TAG and LENGTH fields
size_t integers_len = *asn_sig_len - ASN1_DER_VAL_OFFSET;
if (!ecdsa_rs_to_asn1_integers(r, s, rs_len, value_field_start, &integers_len)) {
// Failed to encode R and S as INTEGERs
return false;
}
if (integers_len > DER_SEQUENCE_MAX_LEN) {
// This implementation support single-byte LENGTH fields only
return false;
}
// write SEQUENCE header
*tag_field = DER_TAG_SEQUENCE;
*length_field = integers_len;
*asn_sig_len = integers_len + ASN1_DER_VAL_OFFSET;
return true;
}
/**
* @brief Decodes an ASN.1 encoded integer to a byte buffer
*
* @param asn1[in] Buffer containing the ASN.1 encoded data
* @param asn1_len[in] Length of the asn1 buffer
* @param out_int[out] Output buffer for the decoded integer bytes
* @param out_int_len[in,out] Size of the out_int buffer, contains the number of written bytes afterwards
* @return The number of bytes advanced in the ASN.1 stream on success, 0 on failure
* @note The parameters to this function must not be NULL.
*/
static size_t decode_asn1_uint(const uint8_t* asn1, size_t asn1_len,
uint8_t* out_int, size_t* out_int_len)
{
if (asn1_len < (ASN1_DER_VAL_OFFSET + 1)) {
// Not enough data to decode anything
return 0;
}
// all read access must be before this pointer
const uint8_t* const asn1_end = asn1 + asn1_len;
// fixed position fields
const uint8_t* const tag_field = &asn1[ASN1_DER_TAG_OFFSET];
const uint8_t* const length_field = &asn1[ASN1_DER_LEN_OFFSET];
if (*tag_field != DER_TAG_INTEGER) {
// Not an DER INTEGER
return 0;
}
if (*length_field == 0 || *length_field > DER_INTEGER_MAX_LEN) {
// Invalid length value
return 0;
}
uint8_t integer_length = *length_field;
const uint8_t* integer_field_cur = &asn1[ASN1_DER_VAL_OFFSET];
if ((integer_field_cur + integer_length - 1) > (asn1_end - 1)) {
// prevented out-of-bounds read
return 0;
}
// one byte can never be a stuffing byte
if (integer_length > 1) {
if (*integer_field_cur == 0x00) {
// remove stuffing byte
integer_length--;
integer_field_cur++;
}
if (*integer_field_cur == 0x00) {
// second zero byte is an encoding error
return 0;
}
}
if (integer_length > *out_int_len) {
// prevented out-of-bounds write
return 0;
}
// insert padding zeros to ensure position of least significant byte matches
const size_t padding = *out_int_len - integer_length;
memset(out_int, 0, padding);
memcpy(out_int + padding, integer_field_cur, integer_length);
*out_int_len = integer_length;
// return number of consumed ASN.1 bytes
return integer_field_cur + integer_length - tag_field;
}
bool asn1_to_ecdsa_rs_sep(const uint8_t* asn1, size_t asn1_len,
uint8_t* r, size_t* r_len,
uint8_t* s, size_t* s_len)
{
if (asn1 == NULL || r == NULL || r_len == NULL || s == NULL || s_len == NULL) {
// No NULL paramters allowed
return false;
}
// decode R component
const size_t consumed_r = decode_asn1_uint(asn1, asn1_len, r, r_len);
if (consumed_r == 0) {
// error while decoding R component
return false;
}
const uint8_t* const asn1_s = asn1 + consumed_r;
const size_t asn1_s_len = asn1_len - consumed_r;
// decode S component
const size_t consumed_s = decode_asn1_uint(asn1_s, asn1_s_len, s, s_len);
if (consumed_s == 0) {
// error while decoding R component
return false;
}
return true;
}
bool asn1_to_ecdsa_rs(const uint8_t* asn1, size_t asn1_len,
uint8_t* rs, size_t rs_len)
{
if (asn1 == NULL || rs == NULL || rs_len == 0) {
// No NULL paramters allowed
return false;
}
if ((rs_len % 2) != 0) {
// length of the output buffer must be 2 times the component size and even
return false;
}
const size_t component_length = rs_len / 2;
size_t r_len = component_length;
size_t s_len = component_length;
return asn1_to_ecdsa_rs_sep(asn1, asn1_len, rs, &r_len, rs + component_length, &s_len);
}

View File

@@ -0,0 +1,131 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file ecdsa_utils.h
*
* \brief This file contains utilities for ECDSA signature encoding/decoding
*
*
* \addtogroup grOptigaUtil
* @{
*/
#ifndef _H_ECDSA_UTILS_H_
#define _H_ECDSA_UTILS_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
// Encode two integers in DER format
// TAG + LENGTH needs 2 bytes for this implementation.
// If the highest bit of the integer is set we need an extra byte.
/** @brief Maximum overhead of the ASN.1 encoding for the R and S components as concatenated DER INTEGERs */
#define ECDSA_RS_MAX_ASN1_OVERHEAD ((2 + 1) * 2)
// Encode two integers as SEQUENCE of INTEGERs in DER format
// TAG + LENGTH fields need 2 bytes and if the highest bit of the integer is set,
// we need an extra byte, so we have 3 bytes overhead per INTEGER.
// SEQUENCE encoding needs an addtional 2 bytes overhead, for TAG + LENGTH fields.
// By limiting the LENGTH field to one byte, we are limited to 127 bytes for the two DER INTEGERS,
// this allows a maximum of 60 bytes per R and S component which is sufficient for the
// NIST P-256 and NIST P-384 curves we deal with.
/** @brief Maximum overhead of the ASN.1 encoding for the R and S components as SEQUENCE of INTEGERs */
#define ECDSA_SIGNATURE_MAX_ASN1_OVERHEAD (ECDSA_RS_MAX_ASN1_OVERHEAD + 2)
/**
* @brief Encodes the ECDSA signature components (r, s) as two concatenated ASN.1 INTEGERs. This is the format
* the OPTIGA hostcode expects.
*
* @param[in] r Component R of the ECDSA signature
* @param[in] s Component S of the ECDSA signature
* @param[in] rs_len Length of each buffer for the R and S components of the ECDSA signature, must be smaller than 127
* @param[out] asn_sig Buffer where the ASN.1 encoded result will be stored
* @param[out] asn_sig_len Length of the ASN.1 encoded data that was copied into the output buffer
* @returns true on success, false on error
* @note The output buffer must be at least 2*rs_len + ECDSA_SIGNATURE_MAX_ASN1_OVERHEAD to fit the result in all cases.
* @note If the function returns false, all output values are invalid.
*/
bool ecdsa_rs_to_asn1_integers(const uint8_t* r, const uint8_t* s, size_t rs_len,
uint8_t* asn_sig, size_t* asn_sig_len);
/**
* @brief Encodes the ECDSA signature components (r, s) as ASN.1 SEQUENCE of two INTEGERs. This is the format
* mbedTLS and OpenSSL use.
*
* @param[in] r Component R of the ECDSA signature
* @param[in] s Component S of the ECDSA signature
* @param[in] rs_len Length of each buffer for the R and S components of the ECDSA signature, must be smaller than 127
* @param[out] asn_sig Buffer where the ASN.1-encoded ECDSA signature will be stored
* @param[out] asn_sig_len Length of the actual data that was copied into the output buffer
* @returns true on success, false on error
* @note The output buffer must be at least 2*rs_len + ECDSA_RS_MAX_ASN1_OVERHEAD to fit the result in all cases
* @note If the function returns false, all output values are invalid.
*/
bool ecdsa_rs_to_asn1_signature(const uint8_t* r, const uint8_t* s, size_t rs_len,
uint8_t* asn_sig, size_t* asn_sig_len);
/**
* @brief decodes two concatenated ASN.1 integers to the R and S components of an ECDSA signature
* @param[in] asn1 Buffer containing the ASN.1 encoded R and S values as two concatenated DER INTEGERs
* @param[in] asn1_len Length of the asn1 buffer
* @param[out] rs Output buffer for the concatenated R and S values
* @param[in] rs_len Length of the rs buffer
* @returns true on success, false else
* @note The R and S components will be padded with zeros in the output buffer and each component will take rs_len/2 bytes.
* e.g.: [ (0x00) R | S ], where '|' denotes the border for half the rs buffer,
* 'R' and 'S' the bytes of the R and S components and '(0x00)' one or multiple padding bytes
* needed to completely fill the buffer.
* If you need to know the exact length of R and S use asn1_to_ecdsa_rs_sep(...)
* @note If the function returns false, all output values are invalid.
*/
bool asn1_to_ecdsa_rs(const uint8_t* asn1, size_t asn1_len,
uint8_t* rs, size_t rs_len);
/**
* @brief decodes two concatenated ASN.1 integers to the R and S components of an ECDSA signature with separate buffers for R and S
* @param[in] asn1 Buffer containing the ASN.1 encoded R and S values as two concatenated DER INTEGERs
* @param[in] asn1_len Length of the asn1 buffer
* @param[out] r Output buffer for the R value
* @param[in,out] r_len Length of the r buffer, contains the number of non padding bytes afterwards
* @param[out] s Output buffer for the S value
* @param[in,out] s_len Length of the s buffer, contains the number of non padding bytes afterwards
* @returns true on success, false else
* @note The r and s buffers will be padded at the least significant byte with zeros to the length of the buffer.
* @note If the function returns false, all output values are invalid.
*/
bool asn1_to_ecdsa_rs_sep(const uint8_t* asn1, size_t asn1_len,
uint8_t* r, size_t* r_len,
uint8_t* s, size_t* s_len);
#ifdef __cplusplus
}
#endif
#endif // _H_ECDSA_UTILS_H_
/**
* @}
*/

2975
external/infineon/optiga/cmd/CommandLib.c vendored Normal file

File diff suppressed because it is too large Load Diff

769
external/infineon/optiga/common/Logger.c vendored Normal file
View File

@@ -0,0 +1,769 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
* \file
*
* \brief This file contains a light weight logger implementation.
*
*
* \addtogroup grLogger
* @{
*
*/
#include <stdio.h>
#include "optiga/common/Logger.h"
#include "optiga/pal/pal_os_timer.h"
/// @cond hidden
/*****************************************************************************
* Defines
*****************************************************************************/
//If ENABLE_UARTLOG is defined, assign UartWriteData as log writer
#ifdef ENABLE_UARTLOG
#include "Uart.h"
pFWriteData pfWriter = (pFWriteData)UartWriteData;
#else
//The function does nothing
static int32_t WriteData(uint32_t PdwHandle, const uint8_t* PprgbBuf, uint32_t PdwDataLen)
{
//lint --e{715} suppress "The parameters are not used as this is filler function"
return 1;
}
pFWriteData pfWriter = (pFWriteData)WriteData;
#endif
/*****************************************************************************
* Common Functions
*****************************************************************************/
/**
* Convert Byte to Hex String
*
*/
void ConvUint8ToHexString (uint8_t* PprgbHexByteArray, uint8_t* PprgbHexString, \
uint32_t dwNoOfBytes, uint8_t PbIsSpaceReq)
{
//lint --e{818} suppress "PprgbHexString is modified in function"
uint32_t dwLoop = 0;
uint8_t bNibble = 0, bHexByte = 0;
do
{
if((NULL == PprgbHexByteArray) || (NULL == PprgbHexString))
{
return;
}
for (dwLoop = 0; dwLoop < dwNoOfBytes; dwLoop++)
{
bHexByte = PprgbHexByteArray[dwLoop];
/*Convert Byte to HexString */
bNibble = (bHexByte & 0xF0)>>4;
if (bNibble > 0x09)
PprgbHexString [0] = bNibble + 0x37;
else
PprgbHexString [0] = bNibble + 0x30;
bNibble = bHexByte & 0x0F;
if (bNibble > 0x09)
PprgbHexString [1] = bNibble + 0x37;
else
PprgbHexString [1] = bNibble + 0x30;
if(PbIsSpaceReq)
{
PprgbHexString [2] = ' ';
PprgbHexString += 3;
}
else
{
PprgbHexString += 2;
}
}
*PprgbHexString = 0x00;
} while(0);
}
/**
* Convert Uint32 to Hex String
*
*/
void ConvUint32ToHexString (uint32_t dwVal, uint8_t* PprgbHexString)
{
uint8_t rgbByteArray [5];
do
{
if(NULL == PprgbHexString)
{
return;
}
rgbByteArray [0] = (uint8_t)(dwVal >> 24);
rgbByteArray [1] = (uint8_t)((dwVal & 0x00FF0000) >> 16);
rgbByteArray [2] = (uint8_t)((dwVal & 0x0000FF00) >> 8);
rgbByteArray [3] = (uint8_t)((dwVal & 0x000000FF));
ConvUint8ToHexString(rgbByteArray, PprgbHexString, 4, 0);
} while(0);
}
/**
* Convert Uint32 to Decimal String
*
*/
void ConvUint32ToDecString (uint32_t dwVal, uint8_t* PprgbDecStr, \
uint8_t bExpStrLen, uint8_t bFillChar)
{
uint8_t rgbTempStr [12] = {0};
uint8_t bCount;
do
{
if(NULL ==PprgbDecStr)
{
return;
}
bCount = 0;
for (;;)
{
rgbTempStr [bCount] = (dwVal % 10) + 0x30;
dwVal = dwVal / 10;
bCount++;
if(0x00 == dwVal)
{
break;
}
}
while(bExpStrLen > bCount)
{
*PprgbDecStr = bFillChar;
PprgbDecStr++;
bExpStrLen--;
}
bCount--;
for(;;)
{
*PprgbDecStr = rgbTempStr[bCount];
PprgbDecStr++;
if(0x00 == bCount)
{
break;
}
bCount--;
}
*PprgbDecStr = 0x00;
} while(0);
}
/*****************************************************************************
* Static functions
*****************************************************************************/
#ifdef ENABLE_LOG
/**
* Return current system time in milliseconds as a string
*
*/
static void GetSystemDateTime(char_t *pszSystemTime)
{
uint32_t dwTimeInMilliSecs = 0;
if(pszSystemTime == NULL)
{
return;
}
dwTimeInMilliSecs = pal_os_timer_get_time_in_milliseconds();
ConvUint32ToDecString (dwTimeInMilliSecs, (uint8_t *)pszSystemTime, 10, '0');
}
/**
* Perform packet analysis. This is specific to IFX I2C protocol
*
*/
static void DumpPacketAnalysis(uint8_t* prgbBuf, uint16_t wLen, bool_t fDirection)
{
uint16_t wOffset = 0, wFrameLength, wTemp;
uint8_t bFctr, bPctr, bTemp, bAckNumber;
char_t pszTemp[256];
bool_t bControlFrame = TRUE;
//for packet analysis there must be minimum 5 bytes
if(wLen < 5)
{
return;
}
if(prgbBuf == NULL)
{
return;
}
//0 for send
if(fDirection == TX_DIRECTION)
{
wOffset = 1;
CONSOLE_LOGSTRINGLINE("->->->->-> Packet Analysis ->->->->->");
}
else
{
CONSOLE_LOGSTRINGLINE("<-<-<-<-<- Packet Analysis <-<-<-<-<-");
}
do
{
//frame type
bFctr = *(prgbBuf+wOffset);
bAckNumber = bFctr & 0x03;
if(bFctr & 0x80)
{
CONSOLE_LOGSTRINGLINE("Frame type: Control frame");
}
else
{
bControlFrame = FALSE;
CONSOLE_LOGSTRINGLINE("Frame type: Data frame");
}
//seq counter 0110 0000 = 0x60
bTemp = ((bFctr & 0x60) >> 5);
switch(bTemp)
{
case 0x00:
CONSOLE_LOGSTRING("Seq Counter: Ack for ");
ConvUint32ToDecString((uint32_t)bAckNumber,(uint8_t*)pszTemp, 0, '0');
CONSOLE_LOGSTRINGLINE(pszTemp);
break;
case 0x01:
CONSOLE_LOGSTRING("Seq Counter: Nak for ");
ConvUint32ToDecString((uint32_t)bAckNumber,(uint8_t*)pszTemp, 0, '0');
CONSOLE_LOGSTRINGLINE(pszTemp);
break;
case 0x02:
CONSOLE_LOGSTRINGLINE("Seq Counter: Re-synch");
break;
default:
CONSOLE_LOGSTRINGLINE("************************** Seq Counter: RFU ***********************");
}
//frame number 0000 1100 = 0x60
bTemp = ((bFctr & 0x0C) >> 2);
CONSOLE_LOGSTRING("Frame number: ");
ConvUint32ToDecString((uint32_t)bTemp,(uint8_t*)pszTemp, 0, '0');
CONSOLE_LOGSTRINGLINE(pszTemp);
//ack number
CONSOLE_LOGSTRING("Ack number: ");
ConvUint32ToDecString((uint32_t)bAckNumber,(uint8_t*)pszTemp, 0, '0');
CONSOLE_LOGSTRINGLINE(pszTemp);
//Frame length:
wOffset++;
wFrameLength = ((uint16_t)*(prgbBuf + wOffset) << 8) | (uint16_t)*(prgbBuf + wOffset + 1);
CONSOLE_LOGSTRING("Frame length: ");
ConvUint32ToDecString((uint32_t)wFrameLength,(uint8_t*)pszTemp, 0, '0');
CONSOLE_LOGSTRINGLINE(pszTemp);
wOffset += 2;
//N/w and transport info not present for control frame
if(bControlFrame)
{
break;
}
//channel info
bPctr = *(prgbBuf+wOffset);
bTemp = bPctr >> 4;
CONSOLE_LOGSTRING("Channel info: ");
ConvUint32ToDecString((uint32_t)bTemp,(uint8_t*)pszTemp, 0, '0');
CONSOLE_LOGSTRINGLINE(pszTemp);
bTemp = bPctr & 0x07;
switch(bTemp)
{
case 0x00:
CONSOLE_LOGSTRINGLINE("Chaining info: Single packet");
break;
case 0x01:
CONSOLE_LOGSTRINGLINE("Chaining info: First packet");
break;
case 0x02:
CONSOLE_LOGSTRINGLINE("Chaining info: Intermediate packet");
break;
case 0x04:
CONSOLE_LOGSTRINGLINE("Chaining info: Last packet");
break;
case 0x07:
CONSOLE_LOGSTRINGLINE("********************* Chaining info: Chaining error ********************* ");
break;
default:
CONSOLE_LOGSTRINGLINE("********************* Chaining info: RFU***********************");
}
wOffset += 1;
//exclude till offset and checksum
wTemp = wOffset+2;
if(wLen > wTemp)
{
wTemp = wLen - wTemp;
}
else
{
// no data bytes
break;
}
if(fDirection == TX_DIRECTION)
{
CONSOLE_LOGSTRING("Command data : ");
}
else
{
CONSOLE_LOGSTRING("Response data : ");
}
Util_DumpHex((prgbBuf+wOffset), wTemp);
CONSOLE_LOGSTRINGLINE(" ");
}while(0);
//0 for send
if(fDirection == TX_DIRECTION)
{
CONSOLE_LOGSTRINGLINE("->->->->-> Packet Analysis ->->->->->");
}
else
{
CONSOLE_LOGSTRINGLINE("<-<-<-<-<- Packet Analysis <-<-<-<-<-");
}
}
#endif
/*****************************************************************************
* Exposed Logging APIs
*****************************************************************************/
/**
* Logs a New Line
*/
void Util_NewLine(uint32_t PdwUartPort)
{
uint8_t rgbcrlf [2] = {0x0D, 0x0A};
//lint --e{534} The return value is not used*/
pfWriter(PdwUartPort, rgbcrlf, 2);
}
/**
* Logs a string with new line
*/
void Util_LogStringLine(uint32_t PdwUartPort, const char_t *pszString)
{
if(pszString == NULL)
{
return;
}
//lint --e{534} The return value is not used*/
pfWriter(PdwUartPort, (uint8_t *)pszString, strlen(pszString));
Util_NewLine(PdwUartPort);
}
/**
* Logs a string
*/
void Util_LogString(uint32_t PdwUartPort, const char_t *PpszString)
{
if(PpszString == NULL)
{
return;
}
//lint --e{534} The return value is not used*/
pfWriter(PdwUartPort, (uint8_t *)PpszString, strlen(PpszString));
}
#ifdef ENABLE_LOG
/**
* Logs a byte array
*/
void Util_LogArray(uint8_t* prgbBuf, uint16_t wLen, bool_t fDirection, bool_t fDumpPacketAnalysis)
{
char_t szTemp[50];
if(prgbBuf == NULL)
{
return;
}
memset(szTemp,0, 50);
GetSystemDateTime(szTemp);
//lint --e{534} The return value is not used*/
pfWriter(CONSOLE_PORT, (uint8_t*)szTemp, strlen(szTemp));
//lint --e{534} The return value is not used*/
pfWriter(CONSOLE_PORT, (uint8_t*)" ", 1);
if(fDirection == TX_DIRECTION)
{
//lint --e{534} The return value is not used*/
pfWriter(CONSOLE_PORT, (uint8_t*)">> ", 4);
}
else
{
//lint --e{534} The return value is not used*/
pfWriter(CONSOLE_PORT, (uint8_t*)"<< ", 4);
}
Util_DumpHex(prgbBuf, wLen);
Util_NewLine(CONSOLE_PORT);
if(fDumpPacketAnalysis)
{
DumpPacketAnalysis(prgbBuf, wLen, fDirection);
}
return;
}
#endif
/**
* Logs a four byte value
*/
void Util_LogInt(uint32_t PdwUartPort, const char_t *pszMsg, uint32_t dwValue)
{
uint8_t rgbString [12] = {0};
if(pszMsg == NULL)
{
return;
}
Util_LogString(PdwUartPort, pszMsg);
Util_LogString(PdwUartPort, " 0x");
ConvUint32ToHexString((uint32_t)dwValue, rgbString);
Util_LogString(PdwUartPort, (char_t*)rgbString);
Util_LogString(PdwUartPort, "(");
ConvUint32ToDecString((uint32_t)dwValue, rgbString, 0, '0');
Util_LogString(PdwUartPort, (char_t*)rgbString);
Util_LogStringLine(PdwUartPort, ")");
}
/**
* Logs an array in hex format
*/
void Util_DumpHex(uint8_t* prgbBuf, uint16_t wLen)
{
uint16_t wIndex;
uint8_t rgbHexString[5];
if(prgbBuf == NULL)
{
return;
}
for(wIndex = 0; wIndex < wLen; wIndex++)
{
ConvUint8ToHexString ((uint8_t*)(prgbBuf+wIndex), rgbHexString, 1, 1);
//lint --e{534} The return value is not used*/
pfWriter(CONSOLE_PORT, rgbHexString, 3);
}
}
/*****************************************************************************
* Level based logging Exposed APIs
*****************************************************************************/
/// @endcond
#ifdef ENABLE_LOG
//This is second log writer
pFWriteData2 pfWriter2 = NULL;
//This is the arguement to be passed to pfWriter.It refers to the handle to writer context/structure.
void* pHandle = NULL;
//Stores the level of Logging
static uint32_t dwLevelEnabler = (uint32_t)((1<<eInfo)|(1<<eWarning)|(1<<eError));
//Store the layer type of Logging
static uint32_t dwLayerEnabler = 0;
/**
* \brief This structure contains Logging information
*/
typedef struct sLogMessage {
///Message to be logged
char_t* pzStringMessage;
///Message Type
eLogLayer eLogMsgLayer;
///Message Level
eLogLevel eLogMsgLevel;
}sLogMessage;
/**
* Sets the state of the Logging Level.
*
* \param[in] eLevel Logging Level
* \param[in] eValue Set value
*/
void Util_SetLogLevelState(eLogLevel PeLevel,eSetState PeValue)
{
//Validate Level
if((eInfo <= PeLevel)&&(eError >= PeLevel))
{
switch(PeValue)
{
case eEnable:
{
dwLevelEnabler |= (uint32_t)(1<<PeLevel);
break;
}
case eDisable:
{
dwLevelEnabler &= (uint32_t)(~(1<<PeLevel));
break;
}
case eInvalid:
default:
break;
}
}
}
/**
* Returns the current state of Logging level.
*
* \param[in] eLevel Logging Level
*
* \retval #eSetState
*/
eSetState Util_GetLogLevelState(eLogLevel PeLevel)
{
//Validate Level
if((eInfo <= PeLevel)&&(eError >= PeLevel))
return (((dwLevelEnabler)&(1<<PeLevel))?eEnable:eDisable);
else
return eInvalid;
}
/**
* Sets the state of the Logging Layer.
*
* \param[in] eLayer Logging Layer
* \param[in] eValue Set value
*/
void Util_SetLogLayerState(eLogLayer PeLayer,eSetState PeValue)
{
//Validate Layer
if((eHS <= PeLayer)&&(eTL >= PeLayer))
{
switch(PeValue)
{
case eEnable:
{
dwLayerEnabler |= (uint32_t)(1<<PeLayer);
break;
}
case eDisable:
{
dwLayerEnabler &= (uint32_t)(~(1<<PeLayer));
break;
}
case eInvalid:
default:
break;
}
}
}
/**
* Returns the current state of the Logging Layer.
*
* \param[in] eLayer Logging Level
*
* \retval #eSetState
*/
eSetState Util_GetLogLayerState(eLogLayer PeLayer)
{
//Validate Layer
if((eHS <= PeLayer)&&(eTL >= PeLayer))
return (((dwLayerEnabler)&(1<<PeLayer))?eEnable:eDisable);
else
return eInvalid;
}
/**
* Sets the Log Writer and handle.
*
* \param[in] pWriter function pointer to pFWriteData2
* \param[in] pHdl Handle to writer context/structure
*
*/
void Util_SetLogWriter(pFWriteData2 pWriter,void* pHdl)
{
pfWriter2 = pWriter;
pHandle = pHdl;
}
/**
* \brief Logs a message.
*/
static void Util_WriteMessage(sLogMessage* psLogMessage)
{
char_t charBuffer[103];
char timeString[9]; // space for "HH:MM:SS\0"
char_t* szMsgLevel[eError] = {LOGGER_LEVEL_INFO,
LOGGER_LEVEL_WARNING,
LOGGER_LEVEL_ERROR};
char_t* szMsgType[eTL] = {LOGGER_TYPE_HANDSHAKE,
LOGGER_TYPE_RECORDLAYER,
LOGGER_TYPE_TRANSPORTLAYER};
GetSystemDateTime(timeString);
#ifndef WIN32
sprintf(charBuffer,LOG_FORMAT,timeString,szMsgLevel[psLogMessage->eLogMsgLevel -1 ],
szMsgType[psLogMessage->eLogMsgLayer -1 ],psLogMessage->pzStringMessage,"\n");
#else
sprintf_s(charBuffer,103,LOG_FORMAT,timeString,szMsgLevel[psLogMessage->eLogMsgLevel -1 ],
szMsgType[psLogMessage->eLogMsgLayer -1 ],psLogMessage->pzStringMessage,"\n");
#endif
pfWriter2(pHandle,(uint8_t*)charBuffer,strlen(charBuffer));
}
/**
* Logs a message with type and level information and content of the buffer.
* Currently the message cannot be greater than 80 bytes.This will be upgraded in future
*
* \param[in] pzMsg Message to be logged
* \param[in] eLayer Logging Layer
* \param[in] eLevel Logging Level
* \param[in] PrgbBuffer Pointer to the buffer to be logged
* \param[in] wLen Length message to be logged
*
*/
void Util_LogMsgArray(char* pzMsg, uint8_t* PrgbBuffer, uint16_t wLen, eLogLayer eLayer, eLogLevel eLevel)
{
sLogMessage sLogMes;
uint16_t wCount = wLen;
uint8_t bBytes = 25;
uint8_t * prgbbuf = PrgbBuffer;
eSetState eCurrentState = Util_GetLogLevelState(eLevel);
uint8_t rgbHexString[100];
do
{
if((NULL==pHandle)||(NULL ==pfWriter2) || (eEnable != eCurrentState) || (PrgbBuffer == NULL))
{
break;
}
sLogMes.eLogMsgLevel = eLevel;
sLogMes.eLogMsgLayer = eLayer;
sLogMes.pzStringMessage = pzMsg;
Util_WriteMessage(&sLogMes);
while(wCount > 0)
{
if(wCount < 25)
{
bBytes = (uint8_t)wCount;
}
ConvUint8ToHexString ((uint8_t*)(prgbbuf), rgbHexString, bBytes, 1);
pfWriter2(pHandle, rgbHexString, (bBytes*3));
prgbbuf+= bBytes;
wCount-=bBytes;
}
pfWriter2(pHandle, (uint8_t *)"\n", 1);
}while (0);
}
/**
* Logs a message with type and level information.
* Currently the message cannot be greater than 80 bytes.This will be upgraded in future
*
* \param[in] pzMsg Message to be logged
* \param[in] eLayer Logging Layer
* \param[in] eLevel Logging Level
*
*/
void Util_LogMessage(char* pzMsg, eLogLayer eLayer, eLogLevel eLevel)
{
sLogMessage sLogMes;
eSetState eCurrentState = Util_GetLogLevelState(eLevel);
do
{
if((NULL==pHandle)||(NULL ==pfWriter2) || (eEnable != eCurrentState))
{
break;
}
sLogMes.eLogMsgLevel = eLevel;
sLogMes.eLogMsgLayer = eLayer;
sLogMes.pzStringMessage = pzMsg;
Util_WriteMessage(&sLogMes);
}while (0);
}
/**
* Logs a 4 byte debug value with type and level information.
*
* Currently the message cannot be greater than 80 bytes.This will be upgraded in future
* \param[in] dwDBValue 4 byte value to be logged
* \param[in] eLayer Logging Layer
* \param[in] eLevel Logging Level
*
*/
void Util_LogDebugVal(uint32_t dwDBValue, eLogLayer eLayer, eLogLevel eLevel)
{
uint8_t rgbString [12];
if((NULL!=pHandle)&&(NULL !=pfWriter2))
{
ConvUint32ToHexString(dwDBValue, rgbString);
Util_LogMessage((char_t*)rgbString,eLayer,eLevel);
}
}
#endif //#ENABLE_LOG
/**
* @}
*/

490
external/infineon/optiga/common/Util.c vendored Normal file
View File

@@ -0,0 +1,490 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
*
* \file
*
* \brief This file contains utility functions
*
*
*
*/
#ifndef WIN32
#endif
#ifdef WIN32
#include <Windows.h>
#include <stdio.h>
#endif
#include "optiga/common/Util.h"
/**
*
* Compare PprgbBuf1 uint64 data with the PprgbBuf2 uint64 data.<br>
*
* \param[in] PpsSrc1 Pointer to the uint64 structure
* \param[in] PpsSrc2 Pointer to the uint64 structure
*
* \retval GREATER_THAN if PpsSrc1 > PpsSrc2
* \retval LESSER_THAN if PpsSrc1 < PpsSrc2
* \retval EQUAL if PpsSrc1 == PpsSrc2
* \retval UTIL_ERROR for NULL parameter
*
*/
int32_t CompareUint64(const sUint64 *PpsSrc1, const sUint64 *PpsSrc2)
{
int32_t i4Retval = (int32_t) UTIL_ERROR;
do
{
#ifdef ENABLE_NULL_CHECKS
if((NULL == PpsSrc1) || (NULL == PpsSrc2))
{
break;
}
#endif
if(PpsSrc1->dwHigherByte == PpsSrc2->dwHigherByte)
{
if(PpsSrc1->dwLowerByte > PpsSrc2->dwLowerByte)
{
i4Retval = GREATER_THAN;
}
else if(PpsSrc1->dwLowerByte < PpsSrc2->dwLowerByte)
{
i4Retval = LESSER_THAN;
}
//PpsSrc1->dwLowerByte == PpsSrc2->dwLowerByte
else
{
i4Retval = EQUAL;
}
}
else
{
if(PpsSrc1->dwHigherByte > PpsSrc2->dwHigherByte)
{
i4Retval = GREATER_THAN;
}
// PpsSrc1->dwHigherByte < PpsSrc2->dwHigherByte
else
{
i4Retval = LESSER_THAN;
}
}
}while(0);
return i4Retval;
}
/**
* Subtraction of PpsSubtrahend uint64 data type from PpsMinuend uint64 data
* PpsMinuend should be greater than PpsSubtrahend else will return error
*
* \param[in] PpsMinuend Minued
* \param[in] PpsSubtrahend Subtrahend
* \param[in] PpsDifference Difference
*
* \retval UTIL_SUCCESS if PpsMinuend > PpsSubtrahend
* \retval UTIL_ERROR if PpsMinuend < PpsSubtrahend and for NULL parameter
*/
int32_t SubtractUint64(const sUint64 *PpsMinuend, const sUint64 *PpsSubtrahend,sUint64 *PpsDifference)
{
int32_t i4Retval = (int32_t) UTIL_ERROR;
sUint64 sIntermediateVal;
do
{
#ifdef ENABLE_NULL_CHECKS
if((NULL == PpsMinuend) || (NULL == PpsSubtrahend) || (NULL == PpsDifference))
{
break;
}
#endif
i4Retval = CompareUint64(PpsMinuend, PpsSubtrahend);
//Check if Minuend is greater than Subtrahend to avoid overflow
if((GREATER_THAN != i4Retval) && (EQUAL != i4Retval))
{
i4Retval = (int32_t) UTIL_ERROR;
break;
}
sIntermediateVal.dwLowerByte = PpsMinuend->dwLowerByte - PpsSubtrahend->dwLowerByte;
sIntermediateVal.dwHigherByte = PpsMinuend->dwHigherByte - PpsSubtrahend->dwHigherByte;
if(sIntermediateVal.dwLowerByte > PpsMinuend->dwLowerByte)
{
--sIntermediateVal.dwHigherByte;
}
PpsDifference->dwLowerByte = sIntermediateVal.dwLowerByte;
PpsDifference->dwHigherByte = sIntermediateVal.dwHigherByte;
i4Retval = (int32_t) UTIL_SUCCESS;
}while(0);
return i4Retval;
}
/**
* Shift left the PpsWindow uint64 data for shiftcount times based on the window size
*
*/
int32_t ShiftLeftUint64(sUint64 *PpsWindow, sUint64 PsShiftCount, uint8_t PbWindowSize, uint8_t PbMaxWindowSize)
{
int32_t i4Retval = (int32_t) UTIL_ERROR;
uint32_t dwShiftCount = 0;
uint32_t dwMaskShiftCount = MASK_DOUBLE_WORD;
sUint64 sWindowSize = {0} ;
do
{
#ifdef ENABLE_NULL_CHECKS
if(NULL == PpsWindow)
{
break;
}
#endif
sWindowSize.dwLowerByte = (uint32_t) PbWindowSize;
i4Retval = CompareUint64(&PsShiftCount, &sWindowSize);
//If Shift Count size is greater than or equal to window size
if((GREATER_THAN == i4Retval) || (EQUAL == i4Retval))
{
///Set the window with all bit zero
PpsWindow->dwLowerByte = DEFAULT_LOWBOUND_DOUBLEWORD;
PpsWindow->dwHigherByte = DEFAULT_LOWBOUND_DOUBLEWORD;
i4Retval = (int32_t) UTIL_SUCCESS;
break;
}
//If Shift count is less than the window size
//Set the window shift count
dwShiftCount = PsShiftCount.dwLowerByte;
//Mask the lower byte data
dwMaskShiftCount &= PpsWindow->dwLowerByte ;
//If window size is equal to 32
if(WORD_SIZE == PbWindowSize)
{
///Shift only higher byte if window size is 32
PpsWindow->dwLowerByte = DEFAULT_LOWBOUND_DOUBLEWORD ;
PpsWindow->dwHigherByte <<= dwShiftCount ;
i4Retval = (int32_t) UTIL_SUCCESS;
break;
}
//Shift count is greater than 32
if(WORD_SIZE <= dwShiftCount)
{
//Set the lower byte to zero which is equal to shift by 32
PpsWindow->dwLowerByte = DEFAULT_LOWBOUND_DOUBLEWORD ;
//Set the Higher byte to zero which is equal to shift by 32
PpsWindow->dwHigherByte = DEFAULT_LOWBOUND_DOUBLEWORD ;
//copy the data of lower byte
PpsWindow->dwHigherByte |= dwMaskShiftCount;
//Remaining shift count to be done
dwShiftCount -= WORD_SIZE;
//Shift the left higher byte data with the remaining count
PpsWindow->dwHigherByte <<= dwShiftCount;
//Reset the outside of window bits
PpsWindow->dwHigherByte &= MASK_DOUBLE_WORD >> (PbMaxWindowSize - PbWindowSize);
i4Retval = (int32_t) UTIL_SUCCESS;
break;
}
//Shift count is lesser than 32
//Shift the lower byte for shift count times
PpsWindow->dwLowerByte <<= dwShiftCount ;
//Shift the higher byte for shift count times
PpsWindow->dwHigherByte <<= dwShiftCount ;
//To mask the data to be copied to higher byte
dwMaskShiftCount >>= WORD_SIZE - dwShiftCount;
//Copy data shifted from lower byte to higher byte
PpsWindow->dwHigherByte |= dwMaskShiftCount;
//Reset the outside of window bits
PpsWindow->dwHigherByte &= MASK_DOUBLE_WORD >> (PbMaxWindowSize - PbWindowSize);
i4Retval = (int32_t) UTIL_SUCCESS;
}while(0);
return i4Retval;
}
/**
* Addition of two uint64 data type
*
*/
int32_t AddUint64(const sUint64 *PpsSrc1, const sUint64 *PpsSrc2,sUint64 *PpsDest)
{
int32_t i4Retval = (int32_t) UTIL_ERROR;
sUint64 sIntermediateval;
sIntermediateval.dwLowerByte = PpsSrc1->dwLowerByte + PpsSrc2->dwLowerByte;
sIntermediateval.dwHigherByte = PpsSrc1->dwHigherByte + PpsSrc2->dwHigherByte;
if(sIntermediateval.dwLowerByte < PpsSrc1->dwLowerByte)
{
++sIntermediateval.dwHigherByte;
}
PpsDest->dwLowerByte = sIntermediateval.dwLowerByte;
PpsDest->dwHigherByte = sIntermediateval.dwHigherByte;
i4Retval = (int32_t) UTIL_SUCCESS;
return i4Retval;
}
int32_t IncrementUint64(sUint64 *PpsSrc1)
{
int32_t i4Retval = (int32_t) UTIL_ERROR;
sUint64 sOne;
sOne.dwHigherByte = 0;
sOne.dwLowerByte = 1;
i4Retval = AddUint64(PpsSrc1,&sOne,PpsSrc1);
return i4Retval;
}
/**
*
* Prepares uint16 [Big endian] type value from the buffer.<br>
*
* \param[in] PprgbData Pointer to the buffer
*
* \retval return 16 bit value
*
*/
uint16_t Utility_GetUint16 (const uint8_t* PprgbData)
{
uint16_t wVal;
wVal = (uint16_t)(*PprgbData << 8);
wVal |= (uint16_t)(*(PprgbData+1));
return wVal;
}
/**
*
* Copies LSB 3 bytes of uint32 [Big endian] type value to the buffer and store .<br>
*
* \param[in,out] PprgbData Pointer to the buffer
* \param[in] Pdwvalue 32 bit value
*
*/
void Utility_SetUint24 (uint8_t* PprgbData,uint32_t Pdwvalue)
{
#define prgbBuffer PprgbData
*(prgbBuffer) = (uint8_t)(Pdwvalue>>16);
*(prgbBuffer+1) = (uint8_t)(Pdwvalue>>8);
*(prgbBuffer+2) = (uint8_t)(Pdwvalue);
#undef prgbBuffer
}
/**
*
* Prepares uint24 [Big endian] type value from the buffer and store .<br>
*
* \param[in] PprgbData Pointer to the buffer
*
* \retval return 32 bit value
*
*/
uint32_t Utility_GetUint24 (const uint8_t* PprgbData)
{
uint32_t dwVal;
dwVal = ((uint32_t)(*PprgbData))<< 16;
dwVal |= ((uint32_t)(*(PprgbData+1)))<<8;
dwVal |= (uint32_t)(*(PprgbData+2));
return dwVal;
}
/**
*
* Prepares uint24 [Big endian] type value from the buffer and store .<br>
*
* \param[in] PprgbData Pointer to the buffer
*
* \retval return 32 bit value
*
*/
uint32_t Utility_GetUint32 (const uint8_t* PprgbData)
{
uint32_t dwVal;
dwVal = ((uint32_t)(*PprgbData))<< 24 | ((uint32_t)(*(PprgbData + 1))<< 16 | ((uint32_t)(*(PprgbData + 2)))<< 8 | (uint32_t)(*(PprgbData + 3)));
return dwVal;
}
/**
*
* Copies 2 bytes of uint16 type value to the buffer<br>
*
* \param[in,out] PprgbData Pointer to the buffer
* \param[in] PwValue 16 bit value
*
*/
void Utility_SetUint16 (puint8_t PprgbData,uint16_t PwValue)
{
*PprgbData = (uint8_t)(PwValue>>8);
*(PprgbData+1) = (uint8_t)(PwValue);
}
/**
*
* sets the bit position to high in the window frame.<br>
*
* \param[in,out] PprgbData Pointer to the uint64 data
* \param[in] bWindowSize Window size
* \param[in] bBitPosition bit position from low bound of the window(Bit is set at lowbound+bBitPosition )
*
* \retval UTIL_SUCCESS for successful execution
* \retval UTIL_ERROR if execution is failure
*/
int32_t Utility_SetBitUint64(sUint64* PprgbData, uint8_t bWindowSize, uint8_t bBitPosition)
{
int32_t i4Retval = (int32_t) UTIL_ERROR;
uint8_t bShiftCount = 0;
do
{
#ifdef ENABLE_NULL_CHECKS
if(NULL == PprgbData)
{
break;
}
#endif
if(bBitPosition > bWindowSize)
{
break;
}
//Window size is equal to bit position
if(bBitPosition == bWindowSize)
{
if(WORD_SIZE == bWindowSize)
{
PprgbData->dwHigherByte |= LEAST_SIGNIFICANT_BIT_HIGH;
i4Retval = (int32_t) UTIL_SUCCESS;
break;
}
PprgbData->dwLowerByte |= LEAST_SIGNIFICANT_BIT_HIGH;
i4Retval = (int32_t) UTIL_SUCCESS;
break;
}
//Bit Position from the Higher bound
bShiftCount = bWindowSize - bBitPosition;
//Window size is equal to 32
if(WORD_SIZE == bWindowSize)
{
PprgbData->dwHigherByte |= LEAST_SIGNIFICANT_BIT_HIGH << (bShiftCount - 1);
i4Retval = (int32_t) UTIL_SUCCESS;
break;
}
//If Bit position from High Bound is greater than 32 then bit set is to be in Higher byte
if(WORD_SIZE < bShiftCount)
{
bShiftCount -= WORD_SIZE;
PprgbData->dwHigherByte |= LEAST_SIGNIFICANT_BIT_HIGH << (bShiftCount - 1);
i4Retval = (int32_t) UTIL_SUCCESS;
break;
}
//If Bit position from High Bound is lesser or equal 32 then bit set is to be in lower byte
PprgbData->dwLowerByte |= LEAST_SIGNIFICANT_BIT_HIGH << (bShiftCount - 1);
i4Retval = (int32_t) UTIL_SUCCESS;
}while(0);
return i4Retval;
}
/**
*
* Copies 4 bytes of uint32 [Big endian] type value to the buffer and store .<br>
*
* \param[in,out] PprgbData Pointer to the buffer
* \param[in] Pdwvalue 32 bit value
*
*/
void Utility_SetUint32 (uint8_t* PprgbData,uint32_t Pdwvalue)
{
#define prgbBuffer PprgbData
*(prgbBuffer) = (uint8_t)(Pdwvalue>>24);
*(prgbBuffer + 1) = (uint8_t)(Pdwvalue>>16);
*(prgbBuffer+2) = (uint8_t)(Pdwvalue>>8);
*(prgbBuffer+3) = (uint8_t)(Pdwvalue);
#undef prgbBuffer
}
/**
*
* Copies the data from source buffer to destination buffer.<br>
*
* \param[in,out] PprgbDestBuf Pointer to the destination buffer
* \param[in,out] PprgbSrcBuf Pointer to the source buffer
* \param[in] PwLength Number of bytes to be copied/moved
*
*/
void Utility_Memmove(puint8_t PprgbDestBuf, const puint8_t PprgbSrcBuf, uint16_t PwLength)
{
uint16_t wIndex=0;
puint8_t pTempSrcBuf = PprgbSrcBuf;
do
{
//if source and destination are the same buffer. and the buffers overlap
if((PprgbDestBuf > pTempSrcBuf) && (PprgbDestBuf <= (pTempSrcBuf + PwLength - 1)))
{
while(0 < PwLength)
{
PwLength -= 1;
*(PprgbDestBuf + PwLength) = *(pTempSrcBuf + PwLength);
}
}
else
{
while(wIndex < PwLength)
{
*(PprgbDestBuf + wIndex) = *(pTempSrcBuf + wIndex);
wIndex++;
}
}
}while(0);
}

View File

@@ -0,0 +1,433 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file ifx_i2c.c
*
* \brief This file implements the wrapper API Layer for IFX I2C protocol v1.65.
*
* \addtogroup grIFXI2C
* @{
*/
/***********************************************************************************************************************
* HEADER FILES
**********************************************************************************************************************/
#include "optiga/ifx_i2c/ifx_i2c.h"
#include "optiga/ifx_i2c/ifx_i2c_transport_layer.h"
#include "optiga/pal/pal_os_event.h"
/// @cond hidden
/***********************************************************************************************************************
* MACROS
**********************************************************************************************************************/
// IFX I2C states
#define IFX_I2C_STATE_UNINIT (0x01)
#define IFX_I2C_STATE_IDLE (0x02)
#define IFX_I2C_STATUS_BUSY (0x03)
#define IFX_I2C_STATUS_NOT_BUSY (0x04)
/// IFX I2C Reset states
#define IFX_I2C_STATE_RESET_PIN_LOW (0xB1)
#define IFX_I2C_STATE_RESET_PIN_HIGH (0xB2)
#define IFX_I2C_STATE_RESET_INIT (0xB3)
/***********************************************************************************************************************
* ENUMS
**********************************************************************************************************************/
/***********************************************************************************************************************
* DATA STRUCTURES
***********************************************************************************************************************/
/***********************************************************************************************************************
* GLOBAL
***********************************************************************************************************************/
/***********************************************************************************************************************
* LOCAL ROUTINES
***********************************************************************************************************************/
/// Transport Layer event handler
void ifx_i2c_tl_event_handler(ifx_i2c_context_t* p_ctx,host_lib_status_t event, const uint8_t* p_data, uint16_t data_len);
/// Performs initialization
static host_lib_status_t ifx_i2c_init(ifx_i2c_context_t* ifx_i2c_context);
//lint --e{526} suppress "This API is defined in ifx_i2c_physical_layer. Since it is a low level API,
//to avoid exposing, header file is not included "
extern host_lib_status_t ifx_i2c_pl_write_slave_address(ifx_i2c_context_t *p_ctx, uint8_t slave_address, uint8_t storage_type);
/// @endcond
/***********************************************************************************************************************
* API PROTOTYPES
**********************************************************************************************************************/
/**
* Initializes the IFX I2C protocol stack for the given context.
* <br>
* <br>
* \image html ifx_i2c_open.png "ifx_i2c_open()" width=20cm
*
*<b>Pre Conditions:</b>
* - None<br>
*
*<b>API Details:</b>
* - Performs a reset sequence.<br>
* - Initializes the I2C slave device.<br>
* - Initializes the ifx i2c protocol stack and registers the event callbacks.
* - Negotiates the frame size and bit rate with the I2C slave.<br>
*<br>
*
*<b>User Input:</b><br>
* - The input #ifx_i2c_context_t p_ctx must not be NULL.
* - The following parameters in #ifx_i2c_context_t must be initialized with appropriate values <br>
* - <b>slave address</b> : Address of I2C slave
* - <b>frame_size</b> : Frame size in bytes.Minimum supported value is 16 bytes.<br>
* - It is recommended not to use a value greater than the slave's frame size.
* - The user specified frame size is written to I2C slave's frame size register.
* The frame size register is read back from I2C slave.
* This frame value is used by the ifx-i2c protocol even if it is not equal to the user specified value.
*
* - <b>frequency</b> : Frequency/speed of I2C master in KHz.
* - This must be lowest of the maximum frequency supported by the devices (master/slave) connected on the bus.
* - Initial negotiation starts with a frequency of 100KHz.
* - If the user specified frequency is more than 400 KHz, the I2C slave is configured to operate in "Fm+" mode,
* otherwise the I2C slave is configured for "SM & Fm" mode. <br>
* - If the user specified frequency frequency negotiation fails, the I2C master frequency remains at 100KHz<br>
*
* - <b>upper_layer_event_handler</b> : Upper layer event handler.This is invoked when #ifx_i2c_open() is asynchronously completed.
* - <b>upper_layer_ctx</b> : Context of upper layer.
* - <b>p_slave_vdd_pin</b> : GPIO pin for VDD. If not set, cold reset is not done.
* - <b>p_slave_reset_pin</b> : GPIO pin for Reset. If not set, warm reset is not done.
*
*<b>Notes:</b>
* - The values of registers MAX_SCL_FREQU and DATA_REG_LEN, read from slave are not validated.
* - At present, only single instance of #ifx_i2c_context_t is supported.
*
*<br>
*
* \param[in,out] p_ctx Pointer to #ifx_i2c_context_t
*
* \retval #IFX_I2C_STACK_SUCCESS
* \retval #IFX_I2C_STACK_ERROR
*/
host_lib_status_t ifx_i2c_open(ifx_i2c_context_t *p_ctx)
{
host_lib_status_t api_status = (int32_t)IFX_I2C_STACK_ERROR;
//If api status is not busy, proceed
if ((IFX_I2C_STATUS_BUSY != p_ctx->status))
{
p_ctx->p_pal_i2c_ctx->upper_layer_ctx = p_ctx;
#ifndef OPTIGA_USE_SOFT_RESET
p_ctx->reset_type = (uint8_t)IFX_I2C_COLD_RESET;
#else
p_ctx->reset_type = (uint8_t)IFX_I2C_SOFT_RESET;
#endif
p_ctx->reset_state = IFX_I2C_STATE_RESET_PIN_LOW;
p_ctx->do_pal_init = TRUE;
p_ctx->state = IFX_I2C_STATE_UNINIT;
api_status = ifx_i2c_init(p_ctx);
if(IFX_I2C_STACK_SUCCESS == api_status)
{
p_ctx->status = IFX_I2C_STATUS_BUSY;
}
}
return api_status;
}
/**
* Resets the I2C slave and initializes the IFX I2C protocol stack for the given context.
* <br>
* <br>
* \image html ifx_i2c_reset.png "ifx_i2c_reset()" width=20cm
*
*<b>Pre Conditions:</b>
* - IFX I2C protocol stack must be initialized.<br>
*
*<b>API Details:</b>
* - Resets the I2C slave.<br>
* - Initializes the ifx i2c protocol stack.<br>
* - Re-Initializes and negotiates the frame size and bit rate with the I2C slave.
* The values remain same as that in previous #ifx_i2c_open().<br>
*<br>
*
*<b>User Input:</b><br>
* - The input #ifx_i2c_context_t p_ctx must not be NULL.
*
*<b>Notes:</b>
* For COLD and WARM reset type: If the gpio(vdd and/or reset) pins are not configured,
* the API continues without any failure return status<br>
*
* \param[in,out] p_ctx Pointer to #ifx_i2c_context_t
* \param[in,out] reset_type type of reset
*
* \retval #IFX_I2C_STACK_SUCCESS
* \retval #IFX_I2C_STACK_ERROR
*/
host_lib_status_t ifx_i2c_reset(ifx_i2c_context_t *p_ctx, ifx_i2c_reset_type_t reset_type)
{
host_lib_status_t api_status = (int32_t)IFX_I2C_STACK_ERROR;
// Proceed, if not busy and in idle state
if ((IFX_I2C_STATE_IDLE == p_ctx->state) && (IFX_I2C_STATUS_BUSY != p_ctx->status))
{
p_ctx->reset_type = (uint8_t)reset_type;
p_ctx->reset_state = IFX_I2C_STATE_RESET_PIN_LOW;
p_ctx->do_pal_init = FALSE;
api_status = ifx_i2c_init(p_ctx);
if(IFX_I2C_STACK_SUCCESS == api_status)
{
p_ctx->status = IFX_I2C_STATUS_BUSY;
}
}
return api_status;
}
/**
* Sends a command and receives a response for the command.<br>
* <br>
* \image html ifx_i2c_transceive.png "ifx_i2c_transceive()" width=20cm
*
*
*<b>Pre Conditions:</b>
* - IFX I2C protocol stack must be initialized.<br>
*
*<b>API Details:</b>
* - Transmit data(Command) to I2C slave.<br>
* - Receive data(Response) from I2C slave.<br>
*<br>
*
*<b>User Input:</b><br>
* - The input #ifx_i2c_context_t p_ctx must not be NULL.
* - The following parameters in #ifx_i2c_context_t must be initialized with appropriate values <br>
* - <b>upper_layer_event_handler</b> : Upper layer event handler, if it is different from that in #ifx_i2c_open().
* This is invoked when #ifx_i2c_transceive is asynchronously completed.
* - <b>upper_layer_ctx</b> : Context of upper layer, if it is different from that in #ifx_i2c_open.
*
*<b>Notes:</b>
* - The actual number of bytes received is stored in p_rx_buffer_len. In case of error,p_rx_buffer_len is set to 0.<br>
* - If the size of p_rx_buffer is zero or insufficient to copy the response bytes then
* #IFX_I2C_STACK_MEM_ERROR error is returned.
*
* \param[in,out] p_ctx Pointer to #ifx_i2c_context_t
* \param[in] p_data Pointer to the write data buffer
* \param[in] p_data_length Pointer to the length of the write data buffer
* \param[in,out] p_rx_buffer Pointer to the receive data buffer
* \param[in,out] p_rx_buffer_len Pointer to the length of the receive data buffer
*
* \retval #IFX_I2C_STACK_SUCCESS
* \retval #IFX_I2C_STACK_ERROR
* \retval #IFX_I2C_STACK_MEM_ERROR
*/
host_lib_status_t ifx_i2c_transceive(ifx_i2c_context_t *p_ctx,const uint8_t* p_data, const uint16_t* p_data_length,
uint8_t* p_rx_buffer, uint16_t* p_rx_buffer_len)
{
host_lib_status_t api_status = (int32_t)IFX_I2C_STACK_ERROR;
// Proceed, if not busy and in idle state
if ((IFX_I2C_STATE_IDLE == p_ctx->state) && (IFX_I2C_STATUS_BUSY != p_ctx->status))
{
p_ctx->p_upper_layer_rx_buffer = p_rx_buffer;
p_ctx->p_upper_layer_rx_buffer_len = p_rx_buffer_len;
api_status = ifx_i2c_tl_transceive(p_ctx,(uint8_t*)p_data, (*p_data_length),
(uint8_t*)p_rx_buffer , p_rx_buffer_len);
if (IFX_I2C_STACK_SUCCESS == api_status)
{
p_ctx->status = IFX_I2C_STATUS_BUSY;
}
}
return api_status;
}
/**
* Closes the IFX I2C protocol stack for a given context.
* <br>
* <br>
* \image html ifx_i2c_close.png "ifx_i2c_close()" width=20cm
*
*<b>Pre Conditions:</b>
* - None<br>
*
*<b>API Details:</b>
* - De-Initializes the I2C slave device.<br>
* - Power downs the I2C slave.<br>
*<br>
*
*<b>User Input:</b><br>
* - The input #ifx_i2c_context_t p_ctx must not be NULL.
*
*<b>Notes:</b>
*
* \param[in,out] p_ctx Pointer to #ifx_i2c_context_t
*
* \retval #IFX_I2C_STACK_SUCCESS
*/
host_lib_status_t ifx_i2c_close(ifx_i2c_context_t *p_ctx)
{
host_lib_status_t api_status = (int32_t)IFX_I2C_STACK_ERROR;
// Proceed, if not busy and in idle state
if (IFX_I2C_STATUS_BUSY != p_ctx->status)
{
api_status = IFX_I2C_STACK_SUCCESS;
//lint --e{534} suppress "Return value is not required to be checked"
// Close I2C master
pal_i2c_deinit(p_ctx->p_pal_i2c_ctx);
// Also power off the device
pal_gpio_set_low(p_ctx->p_slave_vdd_pin);
pal_gpio_set_low(p_ctx->p_slave_reset_pin);
ifx_i2c_tl_event_handler(p_ctx,IFX_I2C_STACK_SUCCESS,NULL,0);
p_ctx->state = IFX_I2C_STATE_UNINIT;
p_ctx->status = IFX_I2C_STATUS_NOT_BUSY;
}
return api_status;
}
/**
* Writes new I2C slave Address to the target device.<br>
*
*<b>Pre Conditions:</b>
* - IFX I2C protocol stack must be initialized.<br>
*
*<b>API Details:</b>
* - This API is implemented in synchronous mode.
* - If the write fails due to the following reasons, this API repeats the write for #PL_POLLING_MAX_CNT times
* with a fixed interval of #PL_POLLING_INVERVAL_US microseconds and exits with respective return status.
* - I2C bus is in busy state, returns #IFX_I2C_STACK_BUSY
* - No-acknowledge(NACK) received from slave, returns #IFX_I2C_STACK_ERROR
* - I2C errors, returns #IFX_I2C_STACK_ERROR
* - Only bits [6:0] from parameter "slave_address" are considered as slave address. Hence the bit 7 is ignored.
* - Slave address validation is not done in the implementation. Provide a valid slave address as input.
*
*<b>Notes:</b>
* - If persistent mode is selected, the ifx i2c context slave address will be over-written with the new slave address.
* Even after ifx i2c open/reset, all future executions will use the new slave address.<br>
* - If volatile mode is selected, the pal_i2c_context slave address will be over-written with the new slave address.
* This persists only till the next ifx_i2c open/reset is called.
*
* \param[in,out] p_ctx Pointer to #ifx_i2c_context_t
* \param[in] slave_address Holds new slave address[7 Bit] to be set.
* \param[in] persistent 0 - To set the Slave address until next reset.<br>
* Non-zero - To set the slave address to persistent memory.
*
* \retval #IFX_I2C_STACK_SUCCESS
* \retval #IFX_I2C_STACK_ERROR
*/
host_lib_status_t ifx_i2c_set_slave_address(ifx_i2c_context_t *p_ctx, uint8_t slave_address, uint8_t persistent)
{
host_lib_status_t api_status = (int32_t)IFX_I2C_STACK_ERROR;
if ((IFX_I2C_STATE_IDLE == p_ctx->state))
{
p_ctx->p_pal_i2c_ctx->upper_layer_ctx = p_ctx;
api_status = ifx_i2c_pl_write_slave_address(p_ctx, slave_address, persistent);
}
return api_status;
}
/// @cond hidden
//lint --e{715} suppress "This is ignored as ifx_i2c_event_handler_t handler function prototype requires this argument"
void ifx_i2c_tl_event_handler(ifx_i2c_context_t* p_ctx,host_lib_status_t event, const uint8_t* p_data, uint16_t data_len)
{
// If there is no upper layer handler, don't do anything and return
if (NULL != p_ctx->upper_layer_event_handler)
{
p_ctx->upper_layer_event_handler(p_ctx->p_upper_layer_ctx,event);
}
p_ctx->status = IFX_I2C_STATUS_NOT_BUSY;
switch(p_ctx->state)
{
case IFX_I2C_STATE_UNINIT:
if (IFX_I2C_STACK_SUCCESS == event)
{
p_ctx->state = IFX_I2C_STATE_IDLE;
}
break;
default:
break;
}
}
static host_lib_status_t ifx_i2c_init(ifx_i2c_context_t* p_ifx_i2c_context)
{
host_lib_status_t api_status = IFX_I2C_STACK_ERROR;
if ((p_ifx_i2c_context->reset_type == (uint8_t)IFX_I2C_WARM_RESET)||
(p_ifx_i2c_context->reset_type == (uint8_t)IFX_I2C_COLD_RESET))
{
switch(p_ifx_i2c_context->reset_state)
{
case IFX_I2C_STATE_RESET_PIN_LOW:
// Setting the Vdd & Reset pin to low
if (p_ifx_i2c_context->reset_type == (uint8_t)IFX_I2C_COLD_RESET)
{
pal_gpio_set_low(p_ifx_i2c_context->p_slave_vdd_pin);
}
pal_gpio_set_low(p_ifx_i2c_context->p_slave_reset_pin);
p_ifx_i2c_context->reset_state = IFX_I2C_STATE_RESET_PIN_HIGH;
pal_os_event_register_callback_oneshot((register_callback)ifx_i2c_init,
(void *)p_ifx_i2c_context, RESET_LOW_TIME_MSEC);
api_status = IFX_I2C_STACK_SUCCESS;
break;
case IFX_I2C_STATE_RESET_PIN_HIGH:
// Setting the Vdd & Reset pin to high
if (p_ifx_i2c_context->reset_type == (uint8_t)IFX_I2C_COLD_RESET)
{
pal_gpio_set_high(p_ifx_i2c_context->p_slave_vdd_pin);
}
pal_gpio_set_high(p_ifx_i2c_context->p_slave_reset_pin);
p_ifx_i2c_context->reset_state = IFX_I2C_STATE_RESET_INIT;
pal_os_event_register_callback_oneshot((register_callback)ifx_i2c_init,
(void *)p_ifx_i2c_context, STARTUP_TIME_MSEC);
api_status = IFX_I2C_STACK_SUCCESS;
break;
case IFX_I2C_STATE_RESET_INIT:
//Frequency and frame size negotiation
api_status = ifx_i2c_tl_init(p_ifx_i2c_context,ifx_i2c_tl_event_handler);
break;
default:
break;
}
}
//soft reset
else
{
p_ifx_i2c_context->pl.request_soft_reset = (uint8_t)TRUE; //Soft reset
api_status = ifx_i2c_tl_init(p_ifx_i2c_context,ifx_i2c_tl_event_handler);
}
return api_status;
}
/// @endcond
/**
* @}
*/

View File

@@ -0,0 +1,86 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file ifx_i2c_config.c
*
* \brief This file provides the ifx i2c platform specific context configurations.
*
* \addtogroup grIFXI2C
* @{
*/
/***********************************************************************************************************************
* HEADER FILES
**********************************************************************************************************************/
// Protocol Stack Includes
#include "optiga/pal/pal_ifx_i2c_config.h"
#include "optiga/ifx_i2c/ifx_i2c_config.h"
/***********************************************************************************************************************
* MACROS
**********************************************************************************************************************/
/***********************************************************************************************************************
* ENUMS
**********************************************************************************************************************/
/***********************************************************************************************************************
* DATA STRUCTURES
***********************************************************************************************************************/
/** @brief This is IFX I2C context. Only one context is supported per slave.*/
//lint --e{785} suppress "Only required fields are initialized, the rest are handled by consumer of this structure"
ifx_i2c_context_t ifx_i2c_context_0 =
{
/// Slave address
0x30,
/// i2c-master frequency
400,
/// IFX-I2C frame size
#if (DL_MAX_FRAME_SIZE >= 0x0115)
0x0115,
#else
DL_MAX_FRAME_SIZE,
#endif
/// Vdd pin
&optiga_vdd_0,
/// Reset pin
&optiga_reset_0,
/// optiga pal i2c context
&optiga_pal_i2c_context_0,
};
/***********************************************************************************************************************
* GLOBAL
***********************************************************************************************************************/
/***********************************************************************************************************************
* LOCAL ROUTINES
***********************************************************************************************************************/
/***********************************************************************************************************************
* API PROTOTYPES
**********************************************************************************************************************/
/**
* @}
**/

View File

@@ -0,0 +1,583 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file ifx_i2c_data_link_layer.c
*
* \brief This file implements the IFX I2C Datalink Layer.
*
* \addtogroup grIFXI2C
* @{
*/
/***********************************************************************************************************************
* HEADER FILES
**********************************************************************************************************************/
#include "optiga/ifx_i2c/ifx_i2c_data_link_layer.h"
#include "optiga/ifx_i2c/ifx_i2c_physical_layer.h" // include lower layer header
/// @cond hidden
/***********************************************************************************************************************
* MACROS
**********************************************************************************************************************/
// Data Link layer internal states
#define DL_STATE_UNINIT (0x00)
#define DL_STATE_IDLE (0x01)
#define DL_STATE_TX (0x02)
#define DL_STATE_RX (0x03)
#define DL_STATE_ACK (0x04)
#define DL_STATE_RESEND (0x05)
#define DL_STATE_NACK (0x06)
#define DL_STATE_ERROR (0x08)
#define DL_STATE_DISCARD (0x09)
#define DL_STATE_RX_DF (0x0A)
#define DL_STATE_RX_CF (0x0B)
// Data Link Layer Frame Control Constants
#define DL_FCTR_FTYPE_MASK (0x80)
#define DL_FCTR_FTYPE_OFFSET (7)
#define DL_FCTR_VALUE_CONTROL_FRAME (0x01)
#define DL_FCTR_SEQCTR_MASK (0x60)
#define DL_FCTR_SEQCTR_OFFSET (5)
#define DL_FCTR_SEQCTR_VALUE_ACK (0x00)
#define DL_FCTR_SEQCTR_VALUE_NACK (0x01)
#define DL_FCTR_SEQCTR_VALUE_RESYNC (0x02)
#define DL_FCTR_SEQCTR_VALUE_RFU (0x03)
#define DL_FCTR_FRNR_MASK (0x0C)
#define DL_FCTR_FRNR_OFFSET (2)
#define DL_FCTR_ACKNR_MASK (0x03)
#define DL_FCTR_ACKNR_OFFSET (0)
// Data Link Layer frame counter max value
#define DL_MAX_FRAME_NUM (0x03)
// Data link layer length
#define DL_CONTROL_FRAME_LENGTH (5)
// Setup debug log statements
#if IFX_I2C_LOG_DL == 1
#include "common/Log_api.h"
#define LOG_DL(args...) ifx_debug_log(IFX_I2C_LOG_ID_DL, args)
#else
#define LOG_DL(...) //printf(__VA_ARGS__)
#endif
/***********************************************************************************************************************
* ENUMS
**********************************************************************************************************************/
/***********************************************************************************************************************
* DATA STRUCTURES
***********************************************************************************************************************/
/***********************************************************************************************************************
* GLOBAL
***********************************************************************************************************************/
/***********************************************************************************************************************
* LOCAL ROUTINES
***********************************************************************************************************************/
/// Helper function to calculate CRC of a byte
_STATIC_H host_lib_status_t ifx_i2c_dl_calc_crc_byte(uint16_t wSeed, uint8_t bByte);
/// Helper function to calculate CRC of a frame
_STATIC_H host_lib_status_t ifx_i2c_dl_calc_crc(const uint8_t* p_data, uint16_t data_len);
/// Internal function to send frame
_STATIC_H host_lib_status_t ifx_i2c_dl_send_frame_internal(ifx_i2c_context_t *p_ctx,uint16_t frame_len,uint8_t seqctr_value, uint8_t resend);
/// Helper function to send resync
_STATIC_H host_lib_status_t ifx_i2c_dl_resync(ifx_i2c_context_t* p_ctx);
/// Helper function to resend frame
_STATIC_H void ifx_i2c_dl_resend_frame(ifx_i2c_context_t* p_ctx,uint8_t seqctr_value);
/// Data Link Layer state machine
_STATIC_H void ifx_i2c_pl_event_handler(ifx_i2c_context_t* p_ctx,host_lib_status_t event, const uint8_t* p_data, uint16_t data_len);
/// @endcond
/***********************************************************************************************************************
* API PROTOTYPES
**********************************************************************************************************************/
host_lib_status_t ifx_i2c_dl_init(ifx_i2c_context_t *p_ctx,ifx_i2c_event_handler_t handler)
{
LOG_DL("[IFX-DL]: Init\n");
p_ctx->dl.state = DL_STATE_UNINIT;
// Initialize Physical Layer (and register event handler)
if (ifx_i2c_pl_init(p_ctx, ifx_i2c_pl_event_handler) != IFX_I2C_STACK_SUCCESS)
{
return IFX_I2C_STACK_ERROR;
}
// Initialize internal variables
p_ctx->dl.upper_layer_event_handler = handler;
p_ctx->dl.state = DL_STATE_IDLE;
p_ctx->dl.tx_seq_nr = DL_MAX_FRAME_NUM;
p_ctx->dl.rx_seq_nr = DL_MAX_FRAME_NUM;
p_ctx->dl.resynced = 0;
p_ctx->dl.error = 0;
p_ctx->dl.p_tx_frame_buffer = p_ctx->tx_frame_buffer;
p_ctx->dl.p_rx_frame_buffer = p_ctx->rx_frame_buffer;
return IFX_I2C_STACK_SUCCESS;
}
host_lib_status_t ifx_i2c_dl_send_frame(ifx_i2c_context_t *p_ctx,uint16_t frame_len)
{
LOG_DL("[IFX-DL]: Start TX Frame\n");
// State must be idle and payload available
if (p_ctx->dl.state != DL_STATE_IDLE || !frame_len)
{
return IFX_I2C_STACK_ERROR;
}
p_ctx->dl.state = DL_STATE_TX;
p_ctx->dl.retransmit_counter = 0;
p_ctx->dl.action_rx_only = 0;
p_ctx->dl.tx_buffer_size = frame_len;
p_ctx->dl.data_poll_timeout = PL_TRANS_TIMEOUT_MS;
return ifx_i2c_dl_send_frame_internal(p_ctx,frame_len, DL_FCTR_SEQCTR_VALUE_ACK, 0);
}
host_lib_status_t ifx_i2c_dl_receive_frame(ifx_i2c_context_t *p_ctx)
{
LOG_DL("[IFX-DL]: Start RX Frame\n");
if (p_ctx->dl.state != DL_STATE_IDLE)
{
return IFX_I2C_STACK_ERROR;
}
// Set internal state
p_ctx->dl.state = DL_STATE_RX;
p_ctx->dl.retransmit_counter = 0;
p_ctx->dl.action_rx_only = 1;
p_ctx->dl.frame_start_time = pal_os_timer_get_time_in_milliseconds();
p_ctx->dl.data_poll_timeout = TL_MAX_EXIT_TIMEOUT*1000;
return ifx_i2c_pl_receive_frame(p_ctx);
}
_STATIC_H host_lib_status_t ifx_i2c_dl_calc_crc_byte(uint16_t wSeed, uint8_t bByte)
{
uint16_t wh1;
uint16_t wh2;
uint16_t wh3;
uint16_t wh4;
wh1 = (wSeed ^ bByte) & 0xFF;
wh2 = wh1 & 0x0F;
wh3 = ((uint16_t)(wh2 << 4)) ^ wh1;
wh4 = wh3 >> 4;
return ((uint16_t)((((uint16_t)((((uint16_t)(wh3 << 1)) ^ wh4) << 4)) ^ wh2) << 3)) ^ wh4
^ (wSeed >> 8);
}
_STATIC_H host_lib_status_t ifx_i2c_dl_calc_crc(const uint8_t* p_data, uint16_t data_len)
{
uint16_t i;
uint16_t crc = 0;
for (i = 0; i < data_len; i++)
{
crc = ifx_i2c_dl_calc_crc_byte(crc, p_data[i]);
}
return crc;
}
_STATIC_H host_lib_status_t ifx_i2c_dl_send_frame_internal(ifx_i2c_context_t *p_ctx,uint16_t frame_len,
uint8_t seqctr_value, uint8_t resend)
{
uint16_t crc;
uint16_t ack_nr = p_ctx->dl.rx_seq_nr;
uint8_t* p_buffer;
LOG_DL("[IFX-DL]: TX Frame len %d\n", frame_len);
// In case of sending a NACK the next frame is referenced
if (seqctr_value == DL_FCTR_SEQCTR_VALUE_NACK)
{
ack_nr = (p_ctx->dl.rx_seq_nr + 1) & DL_MAX_FRAME_NUM;
}
if(seqctr_value == DL_FCTR_SEQCTR_VALUE_RESYNC)
{
ack_nr = 0;
// Use rx buffer to send resync
p_buffer = p_ctx->dl.p_rx_frame_buffer;
}
else
{
p_buffer = p_ctx->dl.p_tx_frame_buffer;
}
// Set sequence control value (ACK or NACK) and referenced frame number
p_buffer[0] = (uint8_t)(ack_nr << DL_FCTR_ACKNR_OFFSET);
p_buffer[0] |= (uint8_t)(seqctr_value << DL_FCTR_SEQCTR_OFFSET);
if (frame_len) // Data frame
{
// Increment and set frame transmit sequence number
if ((!resend)||(p_ctx->dl.resynced))
{
p_ctx->dl.tx_seq_nr = (p_ctx->dl.tx_seq_nr + 1) & DL_MAX_FRAME_NUM;
}
p_buffer[0] |= (uint8_t)(p_ctx->dl.tx_seq_nr << DL_FCTR_FRNR_OFFSET);
// Reset resync received
p_ctx->dl.resynced = 0;
}
else // Control frame
{
p_buffer[0] |= DL_FCTR_FTYPE_MASK;
}
// Set frame length
p_buffer[1] = (uint8_t)(frame_len >> 8);
p_buffer[2] = (uint8_t)frame_len;
// Calculate frame CRC
crc = ifx_i2c_dl_calc_crc(p_buffer, 3 + frame_len);
p_buffer[3 + frame_len] = (uint8_t) (crc >> 8);
p_buffer[4 + frame_len] = (uint8_t)crc;
// Transmit frame
return ifx_i2c_pl_send_frame(p_ctx,p_buffer, DL_HEADER_SIZE + frame_len);
}
_STATIC_H host_lib_status_t ifx_i2c_dl_resync(ifx_i2c_context_t* p_ctx)
{
host_lib_status_t api_status = IFX_I2C_STACK_SUCCESS;
// Reset tx and rx counters
p_ctx->dl.tx_seq_nr = DL_MAX_FRAME_NUM;
p_ctx->dl.rx_seq_nr = DL_MAX_FRAME_NUM;
p_ctx->dl.resynced = 1;
LOG_DL("[IFX-DL]: Send Re-Sync Frame\n");
p_ctx->dl.state = DL_STATE_RESEND;
api_status = ifx_i2c_dl_send_frame_internal(p_ctx,0,DL_FCTR_SEQCTR_VALUE_RESYNC,0);
return api_status;
}
_STATIC_H void ifx_i2c_dl_resend_frame(ifx_i2c_context_t* p_ctx,uint8_t seqctr_value)
{
host_lib_status_t status;
// If exit timeout not violated
uint32_t current_time_stamp = pal_os_timer_get_time_in_milliseconds();
if ((current_time_stamp - p_ctx->tl.api_start_time) < (TL_MAX_EXIT_TIMEOUT * 1000))
{
if(p_ctx->dl.retransmit_counter == DL_TRANS_REPEAT)
{
LOG_DL("[IFX-DL]: Re-Sync counters\n");
p_ctx->dl.retransmit_counter = 0;
status = ifx_i2c_dl_resync(p_ctx);
}
else
{
LOG_DL("[IFX-DL]: Re-TX Frame\n");
p_ctx->dl.retransmit_counter++;
p_ctx->dl.state = DL_STATE_TX;
status = ifx_i2c_dl_send_frame_internal(p_ctx,p_ctx->dl.tx_buffer_size,seqctr_value, 1);
}
// Handle error in above case by sending NACK
if (IFX_I2C_STACK_SUCCESS != status)
{
p_ctx->dl.state = DL_STATE_NACK;
}
}
else
{
p_ctx->dl.state = DL_STATE_ERROR;
}
}
_STATIC_H void ifx_i2c_pl_event_handler(ifx_i2c_context_t* p_ctx,host_lib_status_t event, const uint8_t* p_data, uint16_t data_len)
{
uint8_t fctr = 0;
uint8_t fr_nr = 0;
uint8_t ack_nr = 0;
uint8_t seqctr = 0;
uint8_t current_event;
uint8_t ftype;
uint8_t continue_state_machine = TRUE;
uint16_t packet_len = 0;
uint16_t crc_received = 0;
uint16_t crc_calculated = 0;
LOG_DL("[IFX-DL]: #Enter DL Handler\n");
do
{
if((event == IFX_I2C_FATAL_ERROR) && (DL_STATE_IDLE != p_ctx->dl.state))
{ // Exit in case of fatal error
LOG_DL("[IFX-DL]: Fatal error received\n");
p_ctx->dl.state = DL_STATE_ERROR;
}
switch(p_ctx->dl.state)
{
case DL_STATE_IDLE:
{
current_event = (event != IFX_I2C_STACK_SUCCESS)?IFX_I2C_DL_EVENT_ERROR:IFX_I2C_DL_EVENT_TX_SUCCESS;
continue_state_machine = FALSE;
p_ctx->dl.upper_layer_event_handler(p_ctx,current_event, 0, 0);
}
break;
case DL_STATE_TX:
{
// If writing a frame failed retry sending
if (event == IFX_I2C_STACK_ERROR)
{
p_ctx->dl.state = DL_STATE_RESEND;
break;
}
LOG_DL("[IFX-DL]: Frame Sent\n");
// Transmission successful, start receiving frame
p_ctx->dl.frame_start_time = pal_os_timer_get_time_in_milliseconds();
p_ctx->dl.state = DL_STATE_RX;
if (ifx_i2c_pl_receive_frame(p_ctx))
{
p_ctx->dl.state = DL_STATE_NACK;
}
else
{
continue_state_machine = FALSE;
}
}
break;
case DL_STATE_RX:
{
if (event == IFX_I2C_STACK_ERROR)
{ // If no frame was received retry sending
p_ctx->dl.state = DL_STATE_RESEND;
break;
}
// Received frame from device, start analyzing
LOG_DL("[IFX-DL]: Received Frame of length %d\n",data_len);
if (data_len < DL_HEADER_SIZE)
{ // Received length is less than minimum size
LOG_DL("[IFX-DL]: received data_len < DL_HEADER_SIZE\n");
p_ctx->dl.state = DL_STATE_NACK;
break;
}
// Check transmit frame sequence number
fctr = p_data[0];
ftype = (fctr & DL_FCTR_FTYPE_MASK) >> DL_FCTR_FTYPE_OFFSET;
seqctr = (fctr & DL_FCTR_SEQCTR_MASK) >> DL_FCTR_SEQCTR_OFFSET;
ack_nr = (fctr & DL_FCTR_ACKNR_MASK) >> DL_FCTR_ACKNR_OFFSET;
fr_nr = (fctr & DL_FCTR_FRNR_MASK) >> DL_FCTR_FRNR_OFFSET;
packet_len = (p_data[1] << 8) | p_data[2];
// Check frame CRC value
crc_received = (p_data[data_len - 2] << 8) | p_data[data_len - 1];
crc_calculated = ifx_i2c_dl_calc_crc(p_data, data_len - 2);
p_ctx->dl.state = (ftype == DL_FCTR_VALUE_CONTROL_FRAME)?DL_STATE_RX_CF:DL_STATE_RX_DF;
}
break;
case DL_STATE_RX_DF:
{
LOG_DL("[IFX-DL]: Data Frame Received\n");
if ((crc_received != crc_calculated)||(packet_len == 0)||(data_len != DL_HEADER_SIZE + packet_len)||
(seqctr == DL_FCTR_SEQCTR_VALUE_RFU) || (seqctr == DL_FCTR_SEQCTR_VALUE_RESYNC))
{
// CRC,Length of data frame is 0/ SEQCTR has RFU/Re-sync in Data frame
LOG_DL("[IFX-DL]: NACK for CRC error,Data frame length is not correct,RFU in SEQCTR\n");
p_ctx->dl.state = DL_STATE_NACK;
break;
}
if (fr_nr != ((p_ctx->dl.rx_seq_nr + 1) & DL_MAX_FRAME_NUM))
{
LOG_DL("[IFX-DL]: Data frame number not expected\n");
p_ctx->dl.state = DL_STATE_DISCARD;
continue_state_machine = FALSE;
//lint --e{534} suppress "Return value is not required to be checked"
ifx_i2c_dl_send_frame_internal(p_ctx,0, DL_FCTR_SEQCTR_VALUE_ACK, 0);
break;
}
if (ack_nr != p_ctx->dl.tx_seq_nr)
{
// ack number error
LOG_DL("[IFX-DL]: Error in ack number\n");
//lint --e{534} suppress "Return value is not required to be checked"
p_ctx->dl.state = DL_STATE_DISCARD;
break;
}
if (seqctr == DL_FCTR_SEQCTR_VALUE_NACK)
{
// NACK for transmitted frame
LOG_DL("[IFX-DL]: NACK received in data frame\n");
p_ctx->dl.state = DL_STATE_RESEND;
break;
}
p_ctx->dl.rx_seq_nr = (p_ctx->dl.rx_seq_nr + 1) & DL_MAX_FRAME_NUM;
memcpy(p_ctx->dl.p_rx_frame_buffer, p_data, data_len);
p_ctx->dl.rx_buffer_size = data_len;
// Send control frame to acknowledge reception of this data frame
LOG_DL("[IFX-DL]: Read Data Frame -> Send ACK\n");
p_ctx->dl.retransmit_counter = 0;
p_ctx->dl.state = DL_STATE_ACK;
continue_state_machine = FALSE;
//lint --e{534} suppress "Return value is not required to be checked"
ifx_i2c_dl_send_frame_internal(p_ctx,0, DL_FCTR_SEQCTR_VALUE_ACK, 0);
}
break;
case DL_STATE_RX_CF:
{
LOG_DL("[IFX-DL]: Control Frame Received\n");
// Discard Control frame when in receiver mode except for Re-Sync
//lint --e{514} suppress "The check is intended to be done this way"
if((p_ctx->dl.action_rx_only) ^ (seqctr == DL_FCTR_SEQCTR_VALUE_RESYNC))
{
//If control frame already received for data frame, ignore any received control frame
LOG_DL("[IFX-DL]: CF in receiver mode,Discard\n");
p_ctx->dl.state = DL_STATE_DISCARD;
break;
}
if (crc_received != crc_calculated)
{
// Re-Transmit frame in case of CF CRC error
LOG_DL("[IFX-DL]: Retransmit frame for CF CRC error\n");
p_ctx->dl.state = DL_STATE_RESEND;
break;
}
if((data_len > DL_CONTROL_FRAME_LENGTH)||(packet_len != 0))
{
// Control frame is more than 5/Control frame with non-zero FRNR/packet len is not 0
LOG_DL("[IFX-DL]: Errors in control frame\n");
p_ctx->dl.state = DL_STATE_DISCARD;
break;
}
if(seqctr == DL_FCTR_SEQCTR_VALUE_RESYNC)
{ // Re-sync received
LOG_DL("[IFX-DL]: Re-Sync received\n");
p_ctx->dl.state = DL_STATE_DISCARD;
p_ctx->dl.resynced = 1;
p_ctx->dl.tx_seq_nr = DL_MAX_FRAME_NUM;
p_ctx->dl.rx_seq_nr = DL_MAX_FRAME_NUM;
break;
}
if((fr_nr!=0)||(seqctr == DL_FCTR_SEQCTR_VALUE_RFU)||(ack_nr != p_ctx->dl.tx_seq_nr))
{
// Control frame with non-zero FRNR/ ACK not received/ ack number != tx number
LOG_DL("[IFX-DL]: Errors in control frame\n");
p_ctx->dl.state = DL_STATE_DISCARD;
break;
}
if (seqctr == DL_FCTR_SEQCTR_VALUE_NACK)
{
// NACK for transmitted frame
LOG_DL("[IFX-DL]: NACK received\n");
p_ctx->dl.state = DL_STATE_RESEND;
break;
}
LOG_DL("[IFX-DL]: ACK received\n");
// Report frame reception to upper layer and go in idle state
p_ctx->dl.state = DL_STATE_IDLE;
continue_state_machine = FALSE;
p_ctx->dl.upper_layer_event_handler(p_ctx,IFX_I2C_DL_EVENT_TX_SUCCESS, 0, 0);
}
break;
case DL_STATE_DISCARD:
{
LOG_DL("[IFX-DL]: Discard frame\n");
p_ctx->dl.state = DL_STATE_RX;
continue_state_machine = FALSE;
//lint --e{534} suppress "Return value is not required to be checked"
ifx_i2c_pl_receive_frame(p_ctx);
}
break;
case DL_STATE_ACK:
{
LOG_DL("[IFX-DL]: ACK sent\n");
if (event == IFX_I2C_STACK_ERROR)
{
// If writing the ACK frame failed, Re-Send
LOG_DL("[IFX-DL]: Physical Layer error -> Resend ACK\n");
p_ctx->dl.state = DL_STATE_RESEND;
break;
}
// Control frame successful transmitted
p_ctx->dl.state = DL_STATE_IDLE;
continue_state_machine = FALSE;
if (p_ctx->dl.action_rx_only)
{
p_ctx->dl.upper_layer_event_handler(p_ctx,IFX_I2C_DL_EVENT_RX_SUCCESS, p_ctx->dl.p_rx_frame_buffer + 3,
p_ctx->dl.rx_buffer_size - DL_HEADER_SIZE);
}
else
{
p_ctx->dl.upper_layer_event_handler(p_ctx,IFX_I2C_DL_EVENT_TX_SUCCESS | IFX_I2C_DL_EVENT_RX_SUCCESS,
p_ctx->dl.p_rx_frame_buffer + 3, p_ctx->dl.rx_buffer_size - DL_HEADER_SIZE);
}
}
break;
case DL_STATE_NACK:
{
// Sending NACK
LOG_DL("[IFX-DL]: Sending NACK\n");
p_ctx->dl.state = DL_STATE_TX;
continue_state_machine = FALSE;
//lint --e{534} suppress "Return value is not required to be checked"
ifx_i2c_dl_send_frame_internal(p_ctx,0, DL_FCTR_SEQCTR_VALUE_NACK, 0);
}
break;
case DL_STATE_RESEND:
{
//Resend frame
ifx_i2c_dl_resend_frame(p_ctx,DL_FCTR_SEQCTR_VALUE_ACK);
if(p_ctx->dl.state != DL_STATE_ERROR)
{
continue_state_machine = FALSE;
}
}
break;
case DL_STATE_ERROR:
{
if(!p_ctx->dl.resynced)
{
p_ctx->dl.error = 1;
}
if(0 == p_ctx->dl.error)
{
LOG_DL("[IFX-DL]: Exit error after fatal error\n");
//After sending resync, inform upper layer
p_ctx->dl.state = DL_STATE_IDLE;
p_ctx->dl.upper_layer_event_handler(p_ctx,IFX_I2C_DL_EVENT_ERROR, 0, 0);
}
else
{
LOG_DL("[IFX-DL]: Sending re-sync after fatal error\n");
// Send re-sync to slave on error
//lint --e{534} suppress "As this is last step, no effect of checking return code"
ifx_i2c_dl_resync(p_ctx);
p_ctx->dl.state = DL_STATE_ERROR;
p_ctx->dl.error = 0;
}
continue_state_machine = FALSE;
}
break;
default:
LOG_DL("[IFX-DL]: Default condition occurred. Exiting with error\n");
p_ctx->dl.state = DL_STATE_IDLE;
p_ctx->dl.upper_layer_event_handler(p_ctx,IFX_I2C_DL_EVENT_ERROR, 0, 0);
continue_state_machine = FALSE;
break;
}
}while(continue_state_machine == TRUE);
LOG_DL("[IFX-DL]: #Exiting DL Handler\n");
}

View File

@@ -0,0 +1,755 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file ifx_i2c_physical_layer.c
*
* \brief This file implements the IFX I2C Physical Layer.
*
* \addtogroup grIFXI2C
* @{
*/
/***********************************************************************************************************************
* HEADER FILES
**********************************************************************************************************************/
#include "optiga/ifx_i2c/ifx_i2c_physical_layer.h"
#include "optiga/pal/pal_os_event.h"
/// @cond hidden
/***********************************************************************************************************************
* MACROS
**********************************************************************************************************************/
// Physical Layer Register addresses
#define PL_REG_DATA (0x80)
#define PL_REG_DATA_REG_LEN (0x81)
#define PL_REG_I2C_STATE (0x82)
#define PL_REG_BASE_ADDR (0x83)
#define PL_REG_MAX_SCL_FREQU (0x84)
#define PL_REG_SOFT_RESET (0x88)
#define PL_REG_I2C_MODE (0x89)
// Physical Layer Register lengths
#define PL_REG_LEN_I2C_STATE (4)
#define PL_REG_LEN_MAX_SCL_FREQU (4)
#define PL_REG_LEN_I2C_MODE (2)
#define PL_REG_LEN_DATA_REG_LEN (2)
#define PL_REG_LEN_SOFT_RESET (2)
#define PL_REG_LEN_BASE_ADDR (2)
// Physical Layer State Register masks
#define PL_REG_I2C_STATE_RESPONSE_READY (0x40)
#define PL_REG_I2C_STATE_SOFT_RESET (0x08)
// Physical Layer low level interface constants
#define PL_ACTION_READ_REGISTER (0x01)
#define PL_ACTION_WRITE_REGISTER (0x02)
#define PL_I2C_CMD_WRITE (0x01)
#define PL_I2C_CMD_READ (0x02)
// Physical Layer high level interface constants
#define PL_ACTION_WRITE_FRAME (0x01)
#define PL_ACTION_READ_FRAME (0x02)
#define PL_STATE_UNINIT (0x00)
#define PL_STATE_INIT (0x01)
#define PL_STATE_READY (0x02)
#define PL_STATE_DATA_AVAILABLE (0x03)
#define PL_STATE_RXTX (0x04)
#define PL_STATE_SOFT_RESET (0x05)
//Physical Layer negotiation constants
#define PL_INIT_SET_DATA_REG_LEN (0x11)
#define PL_INIT_GET_DATA_REG_LEN (0x22)
#define PL_INIT_GET_FREQ_REG (0x33)
#define PL_INIT_SET_FREQ_REG (0x44)
#define PL_INIT_READ_FREQ (0x55)
#define PL_INIT_VERIFY_FREQ (0x66)
#define PL_INIT_AGREE_FREQ (0x77)
#define PL_INIT_VERIFY_DATA_REG (0x88)
#define PL_INIT_GET_STATUS_REG (0x99)
#define PL_INIT_DONE (0xAA)
#define PL_INIT_SET_FREQ_DEFAULT (0xBB)
//Physical layer soft reset states
#define PL_RESET_INIT (0xA1)
#define PL_RESET_WRITE (0xA2)
#define PL_RESET_STARTUP (0xA3)
#define PL_REG_I2C_MODE_PERSISTANT (0x80)
#define PL_REG_I2C_MODE_SM_FM (0x03)
#define PL_REG_I2C_MODE_FM_PLUS (0x04)
#define PL_SM_FM_MAX_FREQUENCY (0x190)
#define PL_DEFAULT_FREQUENCY (0x64)
#define PL_REG_BASE_ADDR_PERSISTANT (0x80)
#define PL_REG_BASE_ADDR_VOLATILE (0x00)
// Physical Layer Base Address Register mask
#define PL_REG_I2C_BASE_ADDRESS_MASK (0x7F)
// Setup debug log statements
#if IFX_I2C_LOG_PL == 1
#include "common/Log_api.h"
#define LOG_PL(args...) ifx_debug_log(IFX_I2C_LOG_ID_PL, args)
#else
#define LOG_PL(...) //printf(__VA_ARGS__)
#endif
/***********************************************************************************************************************
* ENUMS
**********************************************************************************************************************/
/***********************************************************************************************************************
* DATA STRUCTURES
***********************************************************************************************************************/
/***********************************************************************************************************************
* GLOBAL
***********************************************************************************************************************/
static host_lib_status_t pal_event_status;
/***********************************************************************************************************************
* LOCAL ROUTINES
***********************************************************************************************************************/
/// Physical Layer low level interface function
static void ifx_i2c_pl_read_register(ifx_i2c_context_t *p_ctx,uint8_t reg_addr, uint16_t reg_len);
/// Physical Layer low level interface function
static void ifx_i2c_pl_write_register(ifx_i2c_context_t *p_ctx,uint8_t reg_addr, uint16_t reg_len, const uint8_t* p_content);
/// Physical Layer high level interface timer callback (Status register polling)
static void ifx_i2c_pl_status_poll_callback(void *p_ctx);
/// Physical Layer intermediate state machine (Negotiation with slave)
static void ifx_i2c_pl_negotiation_event_handler(void *p_input_ctx);
/// Physical Layer intermediate state machine(Set bit rate)
static host_lib_status_t ifx_i2c_pl_set_bit_rate(ifx_i2c_context_t *p_ctx, uint16_t bitrate);
/// Physical Layer intermediate state machine (soft reset)
static void ifx_i2c_pl_soft_reset(ifx_i2c_context_t *p_ctx);
/// Physical Layer high level interface state machine (read/write frames)
static void ifx_i2c_pl_frame_event_handler(ifx_i2c_context_t *p_ctx,host_lib_status_t event);
/// Physical Layer low level interface timer callback (I2C Nack/Busy polling)
static void ifx_i2c_pal_poll_callback(void *p_ctx);
/// Physical Layer low level guard time callback
static void ifx_i2c_pl_guard_time_callback(void *p_ctx);
/// Physical Layer low level interface state machine (read/write registers)
static void ifx_i2c_pl_pal_event_handler(void *p_ctx, host_lib_status_t event);
/// Physical layer low level event handler for set slave address
static void ifx_i2c_pl_pal_slave_addr_event_handler(void *p_input_ctx, host_lib_status_t event);
/// @endcond
/***********************************************************************************************************************
* API PROTOTYPES
**********************************************************************************************************************/
/// Physical Layer high level interface function
host_lib_status_t ifx_i2c_pl_init(ifx_i2c_context_t *p_ctx,ifx_i2c_event_handler_t handler)
{
LOG_PL("[IFX-PL]: Init\n");
p_ctx->pl.upper_layer_event_handler = handler;
p_ctx->pl.frame_state = PL_STATE_UNINIT;
p_ctx->pl.negotiate_state = PL_INIT_SET_FREQ_DEFAULT;
p_ctx->p_pal_i2c_ctx->slave_address = p_ctx->slave_address;
p_ctx->p_pal_i2c_ctx->upper_layer_event_handler = (void*)ifx_i2c_pl_pal_event_handler;
p_ctx->pl.retry_counter = PL_POLLING_MAX_CNT;
if(TRUE == p_ctx->do_pal_init)
{
// Initialize I2C driver
if (PAL_STATUS_SUCCESS != pal_i2c_init(p_ctx->p_pal_i2c_ctx))
{
return IFX_I2C_STACK_ERROR;
}
}
// Set Physical Layer internal state
if(p_ctx->pl.request_soft_reset == (uint8_t)TRUE)
{
//Set the soft reset request to initial state to read register
p_ctx->pl.request_soft_reset = PL_INIT_GET_STATUS_REG;
p_ctx->pl.frame_state = PL_STATE_SOFT_RESET;
}
else
{
p_ctx->pl.frame_state = PL_STATE_INIT;
}
ifx_i2c_pl_frame_event_handler(p_ctx,IFX_I2C_STACK_SUCCESS);
return IFX_I2C_STACK_SUCCESS;
}
/// Physical Layer high level interface function
host_lib_status_t ifx_i2c_pl_send_frame(ifx_i2c_context_t *p_ctx,uint8_t* p_frame, uint16_t frame_len)
{
// Physical Layer must be idle, set requested action
if (p_ctx->pl.frame_state != PL_STATE_INIT && p_ctx->pl.frame_state != PL_STATE_READY)
{
return IFX_I2C_STACK_ERROR;
}
p_ctx->pl.frame_action = PL_ACTION_WRITE_FRAME;
// Store reference to frame for sending it later
p_ctx->pl.p_tx_frame = p_frame;
p_ctx->pl.tx_frame_len = frame_len;
ifx_i2c_pl_frame_event_handler(p_ctx,IFX_I2C_STACK_SUCCESS);
return IFX_I2C_STACK_SUCCESS;
}
/// Physical Layer high level interface function
host_lib_status_t ifx_i2c_pl_receive_frame(ifx_i2c_context_t *p_ctx)
{
// Physical Layer must be idle, set requested action
if (p_ctx->pl.frame_state != PL_STATE_INIT && p_ctx->pl.frame_state != PL_STATE_READY)
{
return IFX_I2C_STACK_ERROR;
}
p_ctx->pl.frame_action = PL_ACTION_READ_FRAME;
ifx_i2c_pl_frame_event_handler(p_ctx,IFX_I2C_STACK_SUCCESS);
return IFX_I2C_STACK_SUCCESS;
}
host_lib_status_t ifx_i2c_pl_write_slave_address(ifx_i2c_context_t *p_ctx, uint8_t slave_address, uint8_t persistent)
{
host_lib_status_t status = IFX_I2C_STACK_ERROR;
app_event_handler_t * temp_upper_layer_event_handler;
/// @cond hidden
#define PAL_WRITE_INIT_STATUS (0x00FF)
#define ADDRESS_OFFSET (0x02)
#define BASE_ADDRESS_REG_OFFSET (0x00)
#define MODE_OFFSET (0x01)
/// @endcond
//lint --e{611} suppress "void* function pointer is type casted to app_event_handler_t type"
//ifx i2c wrapper api for setting slave address in synchronous. hence the event handler is backed up.
temp_upper_layer_event_handler = (app_event_handler_t *)(p_ctx->p_pal_i2c_ctx->upper_layer_event_handler);
//since the lower level APIs are asynchronous, a temporary event handler for set slave address is assigned
p_ctx->p_pal_i2c_ctx->upper_layer_event_handler = (void*)ifx_i2c_pl_pal_slave_addr_event_handler;
p_ctx->pl.buffer[BASE_ADDRESS_REG_OFFSET] = PL_REG_BASE_ADDR;
p_ctx->pl.buffer[MODE_OFFSET] = PL_REG_BASE_ADDR_VOLATILE;
//supported base addresses are 0x00 - 0x7F. Hence 8th bit is ignored
p_ctx->pl.buffer[ADDRESS_OFFSET] = slave_address & PL_REG_I2C_BASE_ADDRESS_MASK;
p_ctx->pl.buffer_tx_len = 1 + PL_REG_LEN_BASE_ADDR;
if(PL_REG_BASE_ADDR_VOLATILE != persistent)
{
p_ctx->pl.buffer[MODE_OFFSET] = PL_REG_BASE_ADDR_PERSISTANT;
}
p_ctx->pl.retry_counter = PL_POLLING_MAX_CNT;
while(p_ctx->pl.retry_counter)
{
pal_event_status = PAL_WRITE_INIT_STATUS;
//lint --e{534} suppress "Return value is not required to be checked"
pal_i2c_write(p_ctx->p_pal_i2c_ctx,p_ctx->pl.buffer, p_ctx->pl.buffer_tx_len);
while(PAL_WRITE_INIT_STATUS == pal_event_status){};
if(PAL_I2C_EVENT_SUCCESS == pal_event_status)
{
break;
}
p_ctx->pl.retry_counter--;
pal_os_timer_delay_in_milliseconds(PL_POLLING_INVERVAL_US);
}
if(PAL_I2C_EVENT_SUCCESS == pal_event_status)
{
p_ctx->p_pal_i2c_ctx->slave_address = p_ctx->pl.buffer[ADDRESS_OFFSET];
if(PL_REG_BASE_ADDR_VOLATILE != persistent)
{
p_ctx->slave_address = p_ctx->pl.buffer[ADDRESS_OFFSET];
}
status = IFX_I2C_STACK_SUCCESS;
}
//restoring the backed up event handler
p_ctx->p_pal_i2c_ctx->upper_layer_event_handler = temp_upper_layer_event_handler;
/// @cond hidden
#undef PAL_WRITE_INIT_STATUS
#undef ADDRESS_OFFSET
#undef BASE_ADDRESS_REG_OFFSET
#undef MODE_OFFSET
/// @endcond
return status;
}
static void ifx_i2c_pl_read_register(ifx_i2c_context_t *p_ctx,uint8_t reg_addr, uint16_t reg_len)
{
LOG_PL("[IFX-PL]: Read register %x len %d\n", reg_addr, reg_len);
// Prepare transmit buffer to write register address
p_ctx->pl.buffer[0] = reg_addr;
p_ctx->pl.buffer_tx_len = 1;
// Set low level interface variables and start transmission
p_ctx->pl.buffer_rx_len = reg_len;
p_ctx->pl.register_action = PL_ACTION_READ_REGISTER;
p_ctx->pl.retry_counter = PL_POLLING_MAX_CNT;
p_ctx->pl.i2c_cmd = PL_I2C_CMD_WRITE;
//lint --e{534} suppress "Return value is not required to be checked"
pal_i2c_write(p_ctx->p_pal_i2c_ctx,p_ctx->pl.buffer, p_ctx->pl.buffer_tx_len);
}
static void ifx_i2c_pl_write_register(ifx_i2c_context_t *p_ctx,uint8_t reg_addr, uint16_t reg_len, const uint8_t* p_content)
{
LOG_PL("[IFX-PL]: Write register %x len %d\n", reg_addr, reg_len);
// Prepare transmit buffer to write register address and content
p_ctx->pl.buffer[0] = reg_addr;
memcpy(p_ctx->pl.buffer + 1, p_content, reg_len);
p_ctx->pl.buffer_tx_len = 1 + reg_len;
// Set Physical Layer low level interface variables and start transmission
p_ctx->pl.register_action = PL_ACTION_WRITE_REGISTER;
p_ctx->pl.retry_counter = PL_POLLING_MAX_CNT;
p_ctx->pl.i2c_cmd = PL_I2C_CMD_WRITE;
//lint --e{534} suppress "Return value is not required to be checked"
pal_i2c_write(p_ctx->p_pal_i2c_ctx,p_ctx->pl.buffer, p_ctx->pl.buffer_tx_len);
}
static void ifx_i2c_pl_status_poll_callback(void *p_ctx)
{
LOG_PL("[IFX-PL]: Status poll Timer elapsed -> Read STATUS register\n");
ifx_i2c_pl_read_register((ifx_i2c_context_t*)p_ctx,PL_REG_I2C_STATE, PL_REG_LEN_I2C_STATE);
}
static host_lib_status_t ifx_i2c_pl_set_bit_rate(ifx_i2c_context_t *p_ctx, uint16_t bitrate)
{
host_lib_status_t status;
void* pal_ctx_upper_layer_handler;
// Save upper layer context in pal
pal_ctx_upper_layer_handler = p_ctx->p_pal_i2c_ctx->upper_layer_event_handler;
// Pass context as NULL to avoid callback invocation
p_ctx->p_pal_i2c_ctx->upper_layer_event_handler = NULL;
status = pal_i2c_set_bitrate(p_ctx->p_pal_i2c_ctx , bitrate);
// Restore callback
p_ctx->p_pal_i2c_ctx->upper_layer_event_handler = pal_ctx_upper_layer_handler;
if(PAL_I2C_EVENT_SUCCESS != status)
{
if (p_ctx->pl.retry_counter--)
{
LOG_PL("[IFX-PL]: Set bit rate failed, Retry setting.\n");
pal_os_event_register_callback_oneshot(ifx_i2c_pl_negotiation_event_handler,((void*)p_ctx),PL_POLLING_INVERVAL_US);
status = IFX_I2C_STACK_BUSY;
}
else
{
status = IFX_I2C_STACK_ERROR;
}
}
else
{
status = IFX_I2C_STACK_SUCCESS;
}
return status;
}
static void ifx_i2c_pl_negotiation_event_handler(void *p_input_ctx)
{
host_lib_status_t event = (uint8_t)IFX_I2C_STACK_ERROR;
uint8_t continue_negotiation;
ifx_i2c_context_t* p_ctx = (ifx_i2c_context_t*)p_input_ctx;
uint8_t i2c_mode_value[2];
uint8_t max_frame_size[2] = { (uint8_t)(p_ctx->frame_size >> 8), (uint8_t)(p_ctx->frame_size) };
uint16_t buffer_len = 0;
uint16_t slave_frequency;
uint16_t slave_frame_len;
uint8_t* p_buffer = NULL;
do
{
continue_negotiation = FALSE;
LOG_PL("[IFX-PL]: Negotiation started\n");
switch(p_ctx->pl.negotiate_state)
{
// Set initial frequency to PL_DEFAULT_FREQUENCY to be able to negotiate with slave
case PL_INIT_SET_FREQ_DEFAULT:
{
// Default frequency set to master
event = ifx_i2c_pl_set_bit_rate(p_input_ctx,PL_DEFAULT_FREQUENCY);
if(IFX_I2C_STACK_SUCCESS == event)
{
p_ctx->pl.negotiate_state = PL_INIT_GET_FREQ_REG;
continue_negotiation = TRUE;
}
else if (IFX_I2C_STACK_ERROR == event)
{
p_ctx->pl.negotiate_state = PL_INIT_DONE;
p_buffer = NULL;
buffer_len = 0;
}
}
break;
// Read the current Max frequency supported by slave
case PL_INIT_GET_FREQ_REG:
{
p_ctx->pl.negotiate_state = PL_INIT_SET_FREQ_REG;
ifx_i2c_pl_read_register(p_ctx,PL_REG_MAX_SCL_FREQU, PL_REG_LEN_MAX_SCL_FREQU);
}
break;
// Set the I2C mode register
case PL_INIT_SET_FREQ_REG:
{
slave_frequency = (p_ctx->pl.buffer[2] << 8) | p_ctx->pl.buffer[3];
i2c_mode_value[0] = PL_REG_I2C_MODE_PERSISTANT;
if((p_ctx->frequency > PL_SM_FM_MAX_FREQUENCY)&&(slave_frequency<=PL_SM_FM_MAX_FREQUENCY))
{
//Change to FM+ mode if slave's current supported frequency is below user's requested frequency
i2c_mode_value[1] = PL_REG_I2C_MODE_FM_PLUS;
p_ctx->pl.negotiate_state = PL_INIT_READ_FREQ;
ifx_i2c_pl_write_register(p_ctx,PL_REG_I2C_MODE, PL_REG_LEN_I2C_MODE, i2c_mode_value);
}
else if((p_ctx->frequency <= PL_SM_FM_MAX_FREQUENCY)&&(slave_frequency>PL_SM_FM_MAX_FREQUENCY))
{
//Change to SM&FM mode if slave's current supported frequency is above user's requested frequency
i2c_mode_value[1] = PL_REG_I2C_MODE_SM_FM;
p_ctx->pl.negotiate_state = PL_INIT_READ_FREQ;
ifx_i2c_pl_write_register(p_ctx,PL_REG_I2C_MODE, PL_REG_LEN_I2C_MODE, i2c_mode_value);
}
else
{
p_ctx->pl.negotiate_state = PL_INIT_VERIFY_FREQ;
continue_negotiation = TRUE;
}
}
break;
// After setting I2C mode register, read the slave's supported frequency
case PL_INIT_READ_FREQ:
{
p_ctx->pl.negotiate_state = PL_INIT_VERIFY_FREQ;
ifx_i2c_pl_read_register(p_ctx,PL_REG_MAX_SCL_FREQU, PL_REG_LEN_MAX_SCL_FREQU);
}
break;
// Verify the requested frequency and slave's supported frequency
case PL_INIT_VERIFY_FREQ:
{
slave_frequency = (p_ctx->pl.buffer[2] << 8) | p_ctx->pl.buffer[3];
if(p_ctx->frequency > slave_frequency)
{
LOG_PL("[IFX-PL]: Unexpected frequency in MAX_SCL_FREQU\n");
p_buffer = NULL;
buffer_len = 0;
p_ctx->pl.negotiate_state = PL_INIT_DONE;
}
else
{
p_ctx->pl.negotiate_state = PL_INIT_AGREE_FREQ;
}
continue_negotiation = TRUE;
}
break;
// Frequency negotiated, Set frequency at master
case PL_INIT_AGREE_FREQ:
{
// Frequency negotiation between master and slave is complete
event = ifx_i2c_pl_set_bit_rate(p_input_ctx, p_ctx->frequency);
if(IFX_I2C_STACK_SUCCESS == event)
{
p_ctx->pl.negotiate_state = PL_INIT_SET_DATA_REG_LEN;
continue_negotiation = TRUE;
}
else if (IFX_I2C_STACK_ERROR == event)
{
p_ctx->pl.negotiate_state = PL_INIT_DONE;
p_buffer = NULL;
buffer_len = 0;
}
}
break;
// Start frame length negotiation by writing the requested frame length
case PL_INIT_SET_DATA_REG_LEN:
{
p_ctx->pl.negotiate_state = PL_INIT_GET_DATA_REG_LEN;
ifx_i2c_pl_write_register(p_ctx,PL_REG_DATA_REG_LEN, sizeof(max_frame_size), max_frame_size);
}
break;
// Read the frame length to verify
case PL_INIT_GET_DATA_REG_LEN:
{
p_ctx->pl.negotiate_state = PL_INIT_VERIFY_DATA_REG;
ifx_i2c_pl_read_register(p_ctx,PL_REG_DATA_REG_LEN,PL_REG_LEN_DATA_REG_LEN);
}
break;
// Check is slave accepted the new frame length
case PL_INIT_VERIFY_DATA_REG:
{
p_ctx->pl.negotiate_state = PL_INIT_DONE;
slave_frame_len = (p_ctx->pl.buffer[0] << 8) | p_ctx->pl.buffer[1];
// Error if slave's frame length is more than requested frame length
if(p_ctx->frame_size >= slave_frame_len)
{
p_ctx->frame_size = slave_frame_len;
event = IFX_I2C_STACK_SUCCESS;
}
p_buffer = NULL;
buffer_len = 0;
continue_negotiation = TRUE;
}
break;
case PL_INIT_DONE:
{
if(IFX_I2C_STACK_SUCCESS == event)
{
p_ctx->pl.frame_state = PL_STATE_READY;
}
else
{
p_ctx->pl.frame_state = PL_STATE_UNINIT;
}
// Negotiation between master and slave is complete
p_ctx->pl.upper_layer_event_handler(p_ctx,event, p_buffer, buffer_len);
}
break;
default:
break;
}
}while(continue_negotiation);
}
static void ifx_i2c_pl_frame_event_handler(ifx_i2c_context_t *p_ctx,host_lib_status_t event)
{
uint16_t frame_size;
if (event != IFX_I2C_STACK_SUCCESS)
{
p_ctx->pl.frame_state = PL_STATE_READY;
// I2C read or write failed, report to upper layer
p_ctx->pl.upper_layer_event_handler(p_ctx,event, 0, 0);
}
else
{
switch(p_ctx->pl.frame_state)
{
// Perform soft reset
case PL_STATE_SOFT_RESET:
{
ifx_i2c_pl_soft_reset(p_ctx);
}
break;
// Negotiate frame and frequency with slave
case PL_STATE_INIT:
{
ifx_i2c_pl_negotiation_event_handler(p_ctx);
}
break;
// Check status of slave data
case PL_STATE_READY:
{
// Start polling status register
p_ctx->pl.frame_state = PL_STATE_DATA_AVAILABLE;
ifx_i2c_pl_read_register(p_ctx,PL_REG_I2C_STATE, PL_REG_LEN_I2C_STATE);
}
break;
// Do read/write frame
case PL_STATE_DATA_AVAILABLE:
{
// Read frame, if response is ready. Ignore busy flag
if ((p_ctx->pl.frame_action == PL_ACTION_READ_FRAME)
&& (p_ctx->pl.buffer[0] & PL_REG_I2C_STATE_RESPONSE_READY))
{
frame_size = (p_ctx->pl.buffer[2] << 8) | p_ctx->pl.buffer[3];
if ((frame_size > 0) && (frame_size <= p_ctx->frame_size))
{
p_ctx->pl.frame_state = PL_STATE_RXTX;
ifx_i2c_pl_read_register(p_ctx,PL_REG_DATA, frame_size);
}
else
{
// Continue polling STATUS register if retry limit is not reached
if ((pal_os_timer_get_time_in_milliseconds() - p_ctx->dl.frame_start_time) < p_ctx->dl.data_poll_timeout)
{
pal_os_event_register_callback_oneshot(ifx_i2c_pl_status_poll_callback, (void *)p_ctx, PL_DATA_POLLING_INVERVAL_US);
}
else
{
p_ctx->pl.frame_state = PL_STATE_READY;
p_ctx->pl.upper_layer_event_handler(p_ctx,IFX_I2C_STACK_ERROR, 0, 0);
}
}
}
// Write frame is slave is not busy
else if (p_ctx->pl.frame_action == PL_ACTION_WRITE_FRAME)
{
// Write frame if device is not busy, otherwise wait and poll STATUS again later
p_ctx->pl.frame_state = PL_STATE_RXTX;
ifx_i2c_pl_write_register(p_ctx,PL_REG_DATA, p_ctx->pl.tx_frame_len, (uint8_t*)p_ctx->pl.p_tx_frame);
}
// Continue checking the slave status register
else
{
// Continue polling STATUS register if retry limit is not reached
if ((pal_os_timer_get_time_in_milliseconds() - p_ctx->dl.frame_start_time) < p_ctx->dl.data_poll_timeout)
{
pal_os_event_register_callback_oneshot(ifx_i2c_pl_status_poll_callback, (void *)p_ctx, PL_DATA_POLLING_INVERVAL_US);
}
else
{
p_ctx->pl.frame_state = PL_STATE_READY;
p_ctx->pl.upper_layer_event_handler(p_ctx,IFX_I2C_STACK_ERROR, 0, 0);
}
}
}
break;
// Frame reading is complete
case PL_STATE_RXTX:
{
// Writing/reading of frame to/from DATA register complete
p_ctx->pl.frame_state = PL_STATE_READY;
p_ctx->pl.upper_layer_event_handler(p_ctx,IFX_I2C_STACK_SUCCESS, p_ctx->pl.buffer, p_ctx->pl.buffer_rx_len);
}
break;
default:
break;
}
}
}
static void ifx_i2c_pal_poll_callback(void *p_ctx)
{
ifx_i2c_context_t* p_local_ctx = (ifx_i2c_context_t *)p_ctx;
if (p_local_ctx->pl.i2c_cmd == PL_I2C_CMD_WRITE)
{
LOG_PL("[IFX-PL]: Poll Timer elapsed -> Restart TX\n");
//lint --e{534} suppress "Return value is not required to be checked"
pal_i2c_write(p_local_ctx->p_pal_i2c_ctx, p_local_ctx->pl.buffer, p_local_ctx->pl.buffer_tx_len);
}
else if (p_local_ctx->pl.i2c_cmd == PL_I2C_CMD_READ)
{
LOG_PL("[IFX-PL]: Poll Timer elapsed -> Restart Read Register -> Start TX\n");
//lint --e{534} suppress "Return value is not required to be checked"
pal_i2c_read(p_local_ctx->p_pal_i2c_ctx,p_local_ctx->pl.buffer, p_local_ctx->pl.buffer_rx_len);
}
}
static void ifx_i2c_pl_guard_time_callback(void *p_ctx)
{
ifx_i2c_context_t* p_local_ctx = (ifx_i2c_context_t*)p_ctx;
if (p_local_ctx->pl.register_action == PL_ACTION_READ_REGISTER)
{
if (p_local_ctx->pl.i2c_cmd == PL_I2C_CMD_WRITE)
{
LOG_PL("[IFX-PL]: GT done-> Start RX\n");
p_local_ctx->pl.i2c_cmd = PL_I2C_CMD_READ;
//lint --e{534} suppress "Return value is not required to be checked"
pal_i2c_read(p_local_ctx->p_pal_i2c_ctx,p_local_ctx->pl.buffer, p_local_ctx->pl.buffer_rx_len);
}
else if (p_local_ctx->pl.i2c_cmd == PL_I2C_CMD_READ)
{
LOG_PL("[IFX-PL]: GT done -> REG is read\n");
ifx_i2c_pl_frame_event_handler(p_local_ctx,IFX_I2C_STACK_SUCCESS);
}
}
else if (p_local_ctx->pl.register_action == PL_ACTION_WRITE_REGISTER)
{
LOG_PL("[IFX-PL]: GT done -> REG written\n");
ifx_i2c_pl_frame_event_handler(p_local_ctx,IFX_I2C_STACK_SUCCESS);
}
}
static void ifx_i2c_pl_pal_event_handler(void *p_ctx, host_lib_status_t event)
{
ifx_i2c_context_t* p_local_ctx = (ifx_i2c_context_t*)p_ctx;
switch (event)
{
case PAL_I2C_EVENT_ERROR:
case PAL_I2C_EVENT_BUSY:
// Error event usually occurs when the device is in sleep mode and needs time to wake up
if (p_local_ctx->pl.retry_counter--)
{
LOG_PL("[IFX-PL]: PAL Error -> Continue polling\n");
pal_os_event_register_callback_oneshot(ifx_i2c_pal_poll_callback,p_local_ctx,PL_POLLING_INVERVAL_US);
}
else
{
LOG_PL("[IFX-PL]: PAL Error -> Stop\n");
ifx_i2c_pl_frame_event_handler(p_local_ctx,IFX_I2C_FATAL_ERROR);
}
break;
case PAL_I2C_EVENT_SUCCESS:
LOG_PL("[IFX-PL]: PAL Success -> Wait Guard Time\n");
pal_os_event_register_callback_oneshot(ifx_i2c_pl_guard_time_callback,p_local_ctx,PL_GUARD_TIME_INTERVAL_US);
break;
default:
break;
}
}
static void ifx_i2c_pl_soft_reset(ifx_i2c_context_t *p_ctx)
{
uint8_t i2c_mode_value[2] = {0};
switch(p_ctx->pl.request_soft_reset)
{
case PL_INIT_GET_STATUS_REG:
p_ctx->pl.request_soft_reset = PL_RESET_WRITE;
//Read the status register to check if soft reset is supported
ifx_i2c_pl_read_register(p_ctx, PL_REG_I2C_STATE, PL_REG_LEN_I2C_STATE);
break;
case PL_RESET_WRITE:
//Mask for soft reset bit(5th bit) from the 1st byte of status register
p_ctx->pl.buffer[0] &= PL_REG_I2C_STATE_SOFT_RESET;
if(p_ctx->pl.buffer[0] == PL_REG_I2C_STATE_SOFT_RESET)
{
p_ctx->pl.request_soft_reset = PL_RESET_STARTUP;
//Write 88 register with 0 value
ifx_i2c_pl_write_register(p_ctx, PL_REG_SOFT_RESET, PL_REG_LEN_SOFT_RESET, i2c_mode_value);
}
else
{
//Soft reset is not supported by the slave
p_ctx->pl.frame_state = PL_STATE_UNINIT;
ifx_i2c_pl_frame_event_handler(p_ctx, IFX_I2C_STACK_ERROR);
}
break;
case PL_RESET_STARTUP:
p_ctx->pl.request_soft_reset= PL_RESET_INIT;
pal_os_event_register_callback_oneshot((register_callback)ifx_i2c_pl_soft_reset, (void *)p_ctx, STARTUP_TIME_MSEC);
break;
case PL_RESET_INIT:
p_ctx->pl.frame_state = PL_STATE_INIT;
ifx_i2c_pl_frame_event_handler(p_ctx,IFX_I2C_STACK_SUCCESS);
break;
default:
break;
}
}
//lint --e{715} suppress "This is used for synchromous implementation, hence p_ctx not used"
//lint --e{818} suppress "This is ignored as upper layer handler function prototype requires this argument"
static void ifx_i2c_pl_pal_slave_addr_event_handler(void *p_ctx, host_lib_status_t event)
{
pal_event_status = event;
}

View File

@@ -0,0 +1,517 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file ifx_i2c_transport_layer.c
*
* \brief This file implements the IFX I2C Transport Layer.
*
* \addtogroup grIFXI2C
* @{
*/
/***********************************************************************************************************************
* HEADER FILES
**********************************************************************************************************************/
#include "optiga/ifx_i2c/ifx_i2c_transport_layer.h"
#include "optiga/ifx_i2c/ifx_i2c_data_link_layer.h" // include lower layer header
/// @cond hidden
/***********************************************************************************************************************
* MACROS
**********************************************************************************************************************/
// Transport Layer states
#define TL_STATE_UNINIT (0x00)
#define TL_STATE_IDLE (0x01)
#define TL_STATE_TX (0x02)
#define TL_STATE_RX (0x04)
#define TL_STATE_CHAINING (0x05)
#define TL_STATE_ERROR (0x06)
#define TL_STATE_CHAINING_ERROR (0x07)
#define TL_STATE_RESEND (0x08)
// Transport Layer header size
#define TL_HEADER_SIZE 1
// Transport Layer chaining values
#define TL_CHAINING_NO (0x00)
#define TL_CHAINING_FIRST (0x01)
#define TL_CHAINING_INTERMEDIATE (0x02)
#define TL_CHAINING_LAST (0x04)
#define TL_CHAINING_ERROR (0x07)
#define TL_PCTR_CHANNEL_MASK (0xF8)
#define TL_PCTR_CHAIN_MASK (0x07)
// Setup debug log statements
#if IFX_I2C_LOG_TL == 1
#include "common/Log_api.h"
#define LOG_TL(args...) ifx_debug_log(IFX_I2C_LOG_ID_TL, args)
#else
#define LOG_TL(...) //printf(__VA_ARGS__);
#endif
/***********************************************************************************************************************
* ENUMS
**********************************************************************************************************************/
/***********************************************************************************************************************
* DATA STRUCTURES
***********************************************************************************************************************/
static uint8_t pctr_states_table[5][2]={
{TL_CHAINING_NO,TL_CHAINING_LAST},
{TL_CHAINING_NO,TL_CHAINING_LAST},
{TL_CHAINING_FIRST,TL_CHAINING_INTERMEDIATE},
{0xFF,0xFF},
{TL_CHAINING_FIRST,TL_CHAINING_INTERMEDIATE},
};
/***********************************************************************************************************************
* GLOBAL
***********************************************************************************************************************/
/***********************************************************************************************************************
* LOCAL ROUTINES
***********************************************************************************************************************/
/// Sends available fragment
_STATIC_H host_lib_status_t ifx_i2c_tl_send_next_fragment(ifx_i2c_context_t *p_ctx);
/// Datalink Layer event handler
_STATIC_H void ifx_i2c_dl_event_handler(ifx_i2c_context_t* p_ctx,host_lib_status_t event, const uint8_t* p_data, uint16_t data_len);
/// Resends all the packets
_STATIC_H host_lib_status_t ifx_i2c_tl_resend_packets(ifx_i2c_context_t *p_ctx);
/// Sends chaining error to I2C slave
_STATIC_H host_lib_status_t ifx_i2c_tl_send_chaining_error(ifx_i2c_context_t *p_ctx);
/// Calculates the pctr value
_STATIC_H uint8_t ifx_i2c_tl_calculate_pctr(const ifx_i2c_context_t *p_ctx);
/// Checks if chaining error occured based on current and previous pctr
_STATIC_H host_lib_status_t ifx_i2c_tl_check_chaining_error(uint8_t current_chaning, uint8_t previous_chaining);
/// @endcond
/***********************************************************************************************************************
* API PROTOTYPES
**********************************************************************************************************************/
/// Transport Layer initialization function
host_lib_status_t ifx_i2c_tl_init(ifx_i2c_context_t *p_ctx,ifx_i2c_event_handler_t handler)
{
LOG_TL("[IFX-TL]: Init\n");
p_ctx->tl.state = TL_STATE_UNINIT;
// Initialize Data Link layer (and register event handler)
if (ifx_i2c_dl_init(p_ctx,ifx_i2c_dl_event_handler) != IFX_I2C_STACK_SUCCESS)
{
return IFX_I2C_STACK_ERROR;
}
p_ctx->tl.upper_layer_event_handler = handler;
p_ctx->tl.state = TL_STATE_IDLE;
p_ctx->tl.max_packet_length = p_ctx->frame_size - (DL_HEADER_SIZE + TL_HEADER_SIZE);
return IFX_I2C_STACK_SUCCESS;
}
host_lib_status_t ifx_i2c_tl_transceive(ifx_i2c_context_t *p_ctx,uint8_t* p_packet, uint16_t packet_len,
uint8_t* p_recv_packet, uint16_t* recv_packet_len)
{
host_lib_status_t status = IFX_I2C_STACK_ERROR;
LOG_TL("[IFX-TL]: Transceive txlen %d\n", packet_len);
do
{
// Check function arguments
if (p_packet == NULL || packet_len == 0 )
{
break;
}
// Transport Layer must be idle
if (p_ctx->tl.state != TL_STATE_IDLE)
{
break;
}
p_ctx->tl.state = TL_STATE_TX;
p_ctx->tl.api_start_time = pal_os_timer_get_time_in_milliseconds();
p_ctx->tl.p_actual_packet = p_packet;
p_ctx->tl.actual_packet_length = packet_len;
p_ctx->tl.packet_offset = 0;
p_ctx->tl.p_recv_packet_buffer = p_recv_packet;
p_ctx->tl.p_recv_packet_buffer_length = recv_packet_len;
p_ctx->tl.total_recv_length = 0;
p_ctx->tl.chaining_error_count = 0;
p_ctx->tl.master_chaining_error_count = 0;
p_ctx->tl.transmission_completed = 0;
p_ctx->tl.error_event = IFX_I2C_STACK_ERROR;
status = ifx_i2c_tl_send_next_fragment(p_ctx);
}while(FALSE);
return status;
}
_STATIC_H host_lib_status_t ifx_i2c_tl_resend_packets(ifx_i2c_context_t *p_ctx)
{
// Transport Layer must be idle
if (p_ctx->tl.state != TL_STATE_IDLE)
{
return IFX_I2C_STACK_ERROR;
}
p_ctx->tl.packet_offset = 0;
p_ctx->tl.total_recv_length = 0;
p_ctx->tl.state = TL_STATE_TX;
return ifx_i2c_tl_send_next_fragment(p_ctx);
}
_STATIC_H uint8_t ifx_i2c_tl_calculate_pctr(const ifx_i2c_context_t *p_ctx)
{
uint8_t pctr;
uint16_t fragment_size = p_ctx->tl.max_packet_length;
uint16_t remaining_data = p_ctx->tl.actual_packet_length - p_ctx->tl.packet_offset;
// No chain
if((p_ctx->tl.packet_offset==0)&&(remaining_data<=fragment_size))
{
pctr = TL_CHAINING_NO;
}
// First chain
else if((p_ctx->tl.packet_offset==0)&&(remaining_data>fragment_size))
{
pctr = TL_CHAINING_FIRST;
}
// Intermediate chain
else if((p_ctx->tl.packet_offset!=0)&&(remaining_data>fragment_size))
{
pctr = TL_CHAINING_INTERMEDIATE;
}
// Last chain
else
{
pctr = TL_CHAINING_LAST;
}
return pctr;
}
_STATIC_H host_lib_status_t ifx_i2c_tl_send_next_fragment(ifx_i2c_context_t *p_ctx)
{
uint8_t pctr = 0;
// Calculate size of fragment (last one might be shorter)
uint16_t tl_fragment_size = p_ctx->tl.max_packet_length;
pctr = ifx_i2c_tl_calculate_pctr(p_ctx);
if ((p_ctx->tl.actual_packet_length - p_ctx->tl.packet_offset) < tl_fragment_size)
{
tl_fragment_size = p_ctx->tl.actual_packet_length - p_ctx->tl.packet_offset;
}
// Assign the pctr
p_ctx->tx_frame_buffer[IFX_I2C_TL_HEADER_OFFSET] = pctr;
//copy the data
memcpy(p_ctx->tx_frame_buffer+IFX_I2C_TL_HEADER_OFFSET+1,p_ctx->tl.p_actual_packet + p_ctx->tl.packet_offset,tl_fragment_size);
p_ctx->tl.packet_offset += tl_fragment_size;
//send the fragment to dl layer
return ifx_i2c_dl_send_frame(p_ctx,tl_fragment_size+1);
}
_STATIC_H host_lib_status_t ifx_i2c_tl_send_chaining_error(ifx_i2c_context_t *p_ctx)
{
uint16_t tl_fragment_size = 1;
p_ctx->tx_frame_buffer[IFX_I2C_TL_HEADER_OFFSET] = 0x07;
p_ctx->tl.total_recv_length = 0;
//send the fragment to dl layer
return ifx_i2c_dl_send_frame(p_ctx,tl_fragment_size);
}
_STATIC_H host_lib_status_t ifx_i2c_tl_check_chaining_error(uint8_t current_chaning, uint8_t previous_chaining)
{
host_lib_status_t status = IFX_I2C_STACK_ERROR;
if(((current_chaning == TL_CHAINING_ERROR) || (current_chaning == TL_CHAINING_NO) || (current_chaning == TL_CHAINING_LAST)
|| (current_chaning == TL_CHAINING_INTERMEDIATE) || (current_chaning == TL_CHAINING_FIRST)))
{
if((pctr_states_table[current_chaning][0] == previous_chaining) || (pctr_states_table[current_chaning][1] == previous_chaining))
{
status = IFX_I2C_STACK_SUCCESS;
}
}
return status;
}
_STATIC_H void ifx_i2c_dl_event_handler(ifx_i2c_context_t* p_ctx,host_lib_status_t event, const uint8_t* p_data, uint16_t data_len)
{
uint8_t pctr = 0;
uint8_t chaining = 0;
uint8_t exit_machine = TRUE;
do
{
if(NULL != p_data)
{
pctr = p_data[0];
chaining = pctr & TL_PCTR_CHAIN_MASK;
}
// Propagate errors to upper layer
if ((event & IFX_I2C_DL_EVENT_ERROR)||(pctr & TL_PCTR_CHANNEL_MASK))
{
p_ctx->tl.state = TL_STATE_ERROR;
p_ctx->tl.error_event = IFX_I2C_STACK_ERROR;
}
switch(p_ctx->tl.state)
{
case TL_STATE_IDLE:
{
exit_machine = FALSE;
p_ctx->tl.upper_layer_event_handler(p_ctx,IFX_I2C_STACK_SUCCESS, 0, 0);
}
break;
case TL_STATE_TX:
{
// Frame transmission in Data Link layer complete, start receiving frames
if (event & IFX_I2C_DL_EVENT_TX_SUCCESS)
{
if (p_ctx->tl.packet_offset < p_ctx->tl.actual_packet_length)
{
// Transmission of one fragment complete, send next fragment
LOG_TL("[IFX-TL]: Tx:Fragment sent,now send next\n");
// Chaining error from slave
if(TL_CHAINING_ERROR == chaining)
{
LOG_TL("[IFX-TL]: Tx:Chaining error received while Tx\n");
p_ctx->tl.state = TL_STATE_RESEND;
break;
}
// Any fragment received before complete transmission is error
if(data_len)
{
LOG_TL("[IFX-TL]: Tx:Data received while Tx\n");
p_ctx->tl.state = TL_STATE_ERROR;
break;
}
exit_machine = FALSE;
//lint --e{534} suppress "Return value is not required to be checked"
ifx_i2c_tl_send_next_fragment(p_ctx);
}
else
{
// Transmission of all fragments complete, start receiving fragments
LOG_TL("[IFX-TL]: Tx:All fragment sent\n");
p_ctx->tl.state = TL_STATE_RX;
p_ctx->tl.total_recv_length = 0;
p_ctx->tl.previous_chaining = TL_CHAINING_NO;
p_ctx->tl.transmission_completed = 1;
// if data is received after sending last frame
if (!(event & IFX_I2C_DL_EVENT_RX_SUCCESS))
{
LOG_TL("[IFX-TL]: Tx:Data already received after Tx\n");
// Received CTRL frame, trigger reception in Data Link layer
if (ifx_i2c_dl_receive_frame(p_ctx))
{
LOG_TL("[IFX-TL]: Tx:RX Received CTRL frame fail -> Inform UL\n");
p_ctx->tl.state = TL_STATE_ERROR;
}
exit_machine = FALSE;
}
}
}
else
{
LOG_TL("[IFX-TL]: Tx:IFX_I2C_DL_EVENT_TX_SUCCESS is not satisfied Tx\n");
p_ctx->tl.state = TL_STATE_ERROR;
break;
}
}
break;
case TL_STATE_RX:
{
// Reception of frame from Data Link layer
if (event & IFX_I2C_DL_EVENT_RX_SUCCESS)
{
// Message must contain at least the transport layer header
if (data_len < TL_HEADER_SIZE)
{
LOG_TL("[IFX-TL]: Rx : Data received is more than header len\n");
p_ctx->tl.state = TL_STATE_ERROR;
break;
}
if(p_ctx->tl.error_event == IFX_I2C_STACK_MEM_ERROR)
{
if ((chaining == TL_CHAINING_LAST) || (ifx_i2c_dl_receive_frame(p_ctx)))
{
p_ctx->tl.state = TL_STATE_ERROR;
break;
}
p_ctx->tl.state = TL_STATE_RX;
exit_machine = FALSE;
break;
}
// If chaining error detected
if(IFX_I2C_STACK_SUCCESS != ifx_i2c_tl_check_chaining_error(chaining,p_ctx->tl.previous_chaining))
{
LOG_TL("[IFX-TL]: Rx : Chaining state is not correct\n");
p_ctx->tl.state = TL_STATE_RESEND;
break;
}
p_ctx->tl.previous_chaining = chaining;
if(NULL == p_data)
{
p_ctx->tl.state = TL_STATE_ERROR;
break;
}
// No chaining and Last
if ((chaining == TL_CHAINING_NO)||(chaining == TL_CHAINING_LAST))
{
LOG_TL("[IFX-TL]: Rx : No chain/Last chain received, Inform UL\n");
exit_machine = FALSE;
// Copy frame payload to transport layer receive buffer
memcpy(p_ctx->tl.p_recv_packet_buffer + p_ctx->tl.total_recv_length, p_data + 1, data_len - 1);
p_ctx->tl.total_recv_length += (data_len - 1);
// Inform upper layer that a packet has arrived
p_ctx->tl.state = TL_STATE_IDLE;
*p_ctx->tl.p_recv_packet_buffer_length = p_ctx->tl.total_recv_length;
p_ctx->tl.upper_layer_event_handler(p_ctx,IFX_I2C_STACK_SUCCESS, p_ctx->tl.p_recv_packet_buffer, *p_ctx->tl.p_recv_packet_buffer_length);
}
else
{
p_ctx->tl.state = TL_STATE_CHAINING;
}
}
else
{
LOG_TL("[IFX-TL]: Tx:IFX_I2C_DL_EVENT_TX_SUCCESS is not satisfied Tx\n");
p_ctx->tl.state = TL_STATE_ERROR;
break;
}
}
break;
case TL_STATE_CHAINING:
{
LOG_TL("[IFX-TL]: Chain : Chaining mode entered\n");
// When receiving a starting fragment, fragment length must be max frame size for intermediate and last frame
// the buffer should not be empty
if (data_len != (p_ctx->tl.max_packet_length+1))
{
LOG_TL("[IFX-TL]: Chain : Data len not equal to max frame size\n");
p_ctx->tl.state = TL_STATE_CHAINING_ERROR;
break;
}
// Check for possible receive buffer overflow
if ((p_ctx->tl.total_recv_length + data_len - 1) > (*p_ctx->tl.p_recv_packet_buffer_length))
{
LOG_TL("[IFX-TL]: Chain : Buffer overflow\n");
p_ctx->tl.error_event = IFX_I2C_STACK_MEM_ERROR;
p_ctx->tl.state = TL_STATE_RX;
break;
}
if(NULL == p_data)
{
p_ctx->tl.state = TL_STATE_ERROR;
break;
}
// Copy frame payload to transport layer receive buffer
memcpy(p_ctx->tl.p_recv_packet_buffer + p_ctx->tl.total_recv_length, p_data + 1, data_len - 1);
p_ctx->tl.total_recv_length += (data_len - 1);
p_ctx->tl.previous_chaining = pctr;
LOG_TL("[IFX-TL]: Chain : Continue in receive mode\n");
p_ctx->tl.state = TL_STATE_RX;
// Continue receiving frames until packet is complete
if (ifx_i2c_dl_receive_frame(p_ctx))
{
p_ctx->tl.state = TL_STATE_ERROR;
}
exit_machine = FALSE;
}
break;
case TL_STATE_RESEND:
{
LOG_TL("[IFX-TL]: Resend Enter\n");
// In received mode , for wrong pctr with data
if((data_len > 1) && (p_ctx->tl.transmission_completed == 1))
{
LOG_TL("[IFX-TL]: Resend : Send chaining error\n");
p_ctx->tl.state = TL_STATE_CHAINING_ERROR;
break;
}
// Master Resend the packets,Resend only once, otherwise exit with error
if(0 == (p_ctx->tl.chaining_error_count++))
{
LOG_TL("[IFX-TL]: Resend : Resending\n");
p_ctx->tl.state = TL_STATE_IDLE;
if(ifx_i2c_tl_resend_packets(p_ctx))
{
p_ctx->tl.state = TL_STATE_ERROR;
}
else
{
exit_machine = FALSE;
}
}
else
{
LOG_TL("[IFX-TL]: Resend : chaining_error_count exceeded\n");
p_ctx->tl.state = TL_STATE_ERROR;
}
}
break;
case TL_STATE_CHAINING_ERROR:
{
// Send chaining error to slave
p_ctx->tl.state = TL_STATE_TX;
if(0 == (p_ctx->tl.master_chaining_error_count++))
{
LOG_TL("[IFX-TL]: Chain error : Sending chain error\n");
// Send chaining error only once
if(ifx_i2c_tl_send_chaining_error(p_ctx))
{
p_ctx->tl.state = TL_STATE_ERROR;
}
else
{
exit_machine = FALSE;
}
}
else
{
LOG_TL("[IFX-TL]: Chain error : master_chaining_error_count exceeded\n");
p_ctx->tl.state = TL_STATE_ERROR;
}
}
break;
case TL_STATE_ERROR:
{
LOG_TL("[IFX-TL]: Error\n");
exit_machine = FALSE;
if ((event & IFX_I2C_DL_EVENT_ERROR) || (data_len))
{
p_ctx->tl.state = TL_STATE_IDLE;
}
p_ctx->tl.upper_layer_event_handler(p_ctx,p_ctx->tl.error_event, 0u, 0u);
}
break;
default:
LOG_TL("[IFX-TL]: Exit from default case\n");
p_ctx->tl.state = TL_STATE_IDLE;
exit_machine = FALSE;
p_ctx->tl.upper_layer_event_handler(p_ctx,p_ctx->tl.error_event, 0u, 0u);
break;
}
}while(exit_machine);
}

View File

@@ -0,0 +1,264 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file
*
* \brief This file implements optiga comms abstraction layer for IFX I2C Protocol.
*
* \addtogroup grOptigaComms
* @{
*/
/**********************************************************************************************************************
* HEADER FILES
*********************************************************************************************************************/
#include "optiga/comms/optiga_comms.h"
#include "optiga/ifx_i2c/ifx_i2c.h"
/// @cond hidden
/**********************************************************************************************************************
* MACROS
*********************************************************************************************************************/
/// Optiga comms is in use
#define OPTIGA_COMMS_INUSE (0x01)
/// Optiga comms is free
#define OPTIGA_COMMS_FREE (0x00)
/**********************************************************************************************************************
* LOCAL DATA
*********************************************************************************************************************/
/**********************************************************************************************************************
* LOCAL ROUTINES
*********************************************************************************************************************/
static host_lib_status_t check_optiga_comms_state(optiga_comms_t *p_ctx);
static void ifx_i2c_event_handler(void* upper_layer_ctx, host_lib_status_t event);
/// @endcond
/**********************************************************************************************************************
* API IMPLEMENTATION
*********************************************************************************************************************/
/**
* Initializes the commmunication with OPTIGA.<br>
*
*<b>Pre Conditions:</b>
* - None<br>
*
*<b>API Details:</b>
* - Initializes OPTIGA and establishes the communication channel.<br>
* - Initializes the ifx i2c protocol stack and registers the event callbacks.<br>
* - Negotiates the frame size and bit rate with the OPTIGA.<br>
*<br>
*
*<b>User Input:</b><br>
* - The input #optiga_comms_t p_ctx must not be NULL.<br>
* - The following parameters in #optiga_comms_t must be initialized with appropriate values.<br>
* - The <b>comms_ctx</b> must be initialized with a valid #ifx_i2c_context.<br>
* - The <b>upper_layer_event_handler</b> parameter must be properly initialized.
* This is invoked when #optiga_comms_open is asynchronously completed.<br>
* - The <b>upper_layer_ctx</b> must be properly initialized.<br>
*
*<b>Notes:</b>
* - None<br>
*
*<br>
* \param[in,out] p_ctx Pointer to optiga comms context
*
* \retval #OPTIGA_COMMS_SUCCESS
* \retval #OPTIGA_COMMS_ERROR
*/
host_lib_status_t optiga_comms_open(optiga_comms_t *p_ctx)
{
host_lib_status_t status = OPTIGA_COMMS_ERROR;
if (OPTIGA_COMMS_SUCCESS == check_optiga_comms_state(p_ctx))
{
((ifx_i2c_context_t*)(p_ctx->comms_ctx))->p_upper_layer_ctx = (void*)p_ctx;
((ifx_i2c_context_t*)(p_ctx->comms_ctx))->upper_layer_event_handler = ifx_i2c_event_handler;
status = ifx_i2c_open((ifx_i2c_context_t*)(p_ctx->comms_ctx));
if (IFX_I2C_STACK_SUCCESS != status)
{
p_ctx->state = OPTIGA_COMMS_FREE;
}
}
return status;
}
/**
* Resets the OPTIGA.<br>
*
*<b>Pre Conditions:</b>
* - Communication channel must be established with OPTIGA.<br>
*
*<b>API Details:</b>
* - Resets the OPTIGA device.<br>
* - Initializes the ifx i2c protocol stack.<br>
* - Re-Initializes and negotiates the frame size and bit rate with the OPTIGA.
* The values remain same as that in previous #optiga_comms_open().<br>
*<br>
*
*<b>User Input:</b><br>
* - The input #optiga_comms_t p_ctx must not be NULL.
*
*<b>Notes:</b>
* For COLD and WARM reset type: If the gpio(vdd and/or reset) pins are not configured,
* the API continues without returning error status<br>
*
*
* \param[in,out] p_ctx Pointer to #optiga_comms_t
* \param[in,out] reset_type type of reset
*
* \retval #OPTIGA_COMMS_SUCCESS
* \retval #OPTIGA_COMMS_ERROR
*/
host_lib_status_t optiga_comms_reset(optiga_comms_t *p_ctx,uint8_t reset_type)
{
host_lib_status_t status = OPTIGA_COMMS_ERROR;
if (OPTIGA_COMMS_SUCCESS == check_optiga_comms_state(p_ctx))
{
((ifx_i2c_context_t*)(p_ctx->comms_ctx))->p_upper_layer_ctx = (void*)p_ctx;
((ifx_i2c_context_t*)(p_ctx->comms_ctx))->upper_layer_event_handler = ifx_i2c_event_handler;
status = ifx_i2c_reset((ifx_i2c_context_t*)(p_ctx->comms_ctx),(ifx_i2c_reset_type_t)reset_type);
if (IFX_I2C_STACK_SUCCESS != status)
{
p_ctx->state = OPTIGA_COMMS_FREE;
}
}
return status;
}
/**
* Sends a command to OPTIGA and receives a response.<br>
*
*
*<b>Pre Conditions:</b>
* - Communication channel must be established with OPTIGA.<br>
*
*<b>API Details:</b>
* - Transmit data(Command) to OPTIGA.<br>
* - Receive data(Response) from OPTIGA.<br>
*<br>
*
*<b>User Input:</b><br>
* - The input #optiga_comms_t p_ctx must not be NULL.<br>
* - The following parameters in #optiga_comms_t must be initialized with appropriate values <br>
* - The <b>comms_ctx</b> must be initialized with a valid #ifx_i2c_context<br>
* - The <b>upper_layer_event_handler</b> parameter must be properly initialized,
* if it is different from that in #optiga_comms_open().
* This is invoked when optiga_comms_transceive is asynchronously completed.<br>
* - The <b>upper_layer_ctx</b> must be properly initialized,
* if it is different from that in #optiga_comms_open().<br>
*
*<b>Notes:</b>
* - The actual number of bytes received is stored in p_buffer_len. In case of error, p_buffer_len is set to 0.<br>
* - If the size of p_buffer is zero or insufficient to copy the response bytes then
* #IFX_I2C_STACK_MEM_ERROR error is returned.
*
*
* \param[in,out] p_ctx Pointer to #optiga_comms_t
* \param[in] p_data Pointer to the write data buffer
* \param[in] p_data_length Pointer to the length of the write data buffer
* \param[in,out] p_buffer Pointer to the receive data buffer
* \param[in,out] p_buffer_len Pointer to the length of the receive data buffer
*
* \retval #OPTIGA_COMMS_SUCCESS
* \retval #OPTIGA_COMMS_ERROR
* \retval #IFX_I2C_STACK_MEM_ERROR
*/
host_lib_status_t optiga_comms_transceive(optiga_comms_t *p_ctx,const uint8_t* p_data,
const uint16_t* p_data_length,
uint8_t* p_buffer, uint16_t* p_buffer_len)
{
host_lib_status_t status = OPTIGA_COMMS_ERROR;
if (OPTIGA_COMMS_SUCCESS == check_optiga_comms_state(p_ctx))
{
((ifx_i2c_context_t*)(p_ctx->comms_ctx))->p_upper_layer_ctx = (void*)p_ctx;
((ifx_i2c_context_t*)(p_ctx->comms_ctx))->upper_layer_event_handler = ifx_i2c_event_handler;
status = (ifx_i2c_transceive((ifx_i2c_context_t*)(p_ctx->comms_ctx),p_data,p_data_length,p_buffer,p_buffer_len));
if (IFX_I2C_STACK_SUCCESS != status)
{
p_ctx->state = OPTIGA_COMMS_FREE;
}
}
return status;
}
/**
* Closes the communication with OPTIGA.<br>
*
*<b>Pre Conditions:</b>
* - None<br>
*
*<b>API Details:</b>
* - De-Initializes the OPTIGA and closes the communication channel.<br>
* - Power downs the OPTIGA.<br>
*<br>
*
*<b>User Input:</b><br>
* - The input #optiga_comms_t p_ctx must not be NULL.<br>
* - The #optiga_comms_t comms_ctx must be initialized with a valid #ifx_i2c_context<br>
*
* \param[in,out] p_ctx Pointer to #optiga_comms_t
*
* \retval #OPTIGA_COMMS_SUCCESS
* \retval #OPTIGA_COMMS_ERROR
*/
host_lib_status_t optiga_comms_close(optiga_comms_t *p_ctx)
{
host_lib_status_t status = OPTIGA_COMMS_ERROR;
if (OPTIGA_COMMS_SUCCESS == check_optiga_comms_state(p_ctx))
{
((ifx_i2c_context_t*)(p_ctx->comms_ctx))->p_upper_layer_ctx = (void*)p_ctx;
((ifx_i2c_context_t*)(p_ctx->comms_ctx))->upper_layer_event_handler = ifx_i2c_event_handler;
status = ifx_i2c_close((ifx_i2c_context_t*)(p_ctx->comms_ctx));
if (IFX_I2C_STACK_SUCCESS != status)
{
p_ctx->state = OPTIGA_COMMS_FREE;
}
}
return status;
}
/// @cond hidden
static host_lib_status_t check_optiga_comms_state(optiga_comms_t *p_ctx)
{
host_lib_status_t status = OPTIGA_COMMS_ERROR;
if ((NULL != p_ctx) && (p_ctx->state != OPTIGA_COMMS_INUSE))
{
p_ctx->state = OPTIGA_COMMS_INUSE;
status = OPTIGA_COMMS_SUCCESS;
}
return status;
}
//lint --e{818} suppress "This is ignored as upper layer handler function prototype requires this argument"
static void ifx_i2c_event_handler(void* upper_layer_ctx, host_lib_status_t event)
{
void* ctx = ((optiga_comms_t*)upper_layer_ctx)->upper_layer_ctx;
((optiga_comms_t*)upper_layer_ctx)->upper_layer_handler(ctx,event);
((optiga_comms_t*)upper_layer_ctx)->state = OPTIGA_COMMS_FREE;
}
/// @endcond
/**
* @}
*/

View File

@@ -0,0 +1,458 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
* \file
*
* \brief This file implements the OPTIGA Crypto toolbox APIs.
*
* \addtogroup grOptigaCrypt
* @{
*/
#include "optiga/optiga_crypt.h"
#include "optiga/pal/pal_os_lock.h"
optiga_lib_status_t optiga_crypt_random(optiga_rng_types_t rng_type,
uint8_t * random_data,
uint16_t random_data_length)
{
optiga_lib_status_t return_value = OPTIGA_LIB_ERROR;
sRngOptions_d rand_options;
sCmdResponse_d rand_response;
rand_options.eRngType = (eRngType_d)rng_type;
rand_options.wRandomDataLen = random_data_length;
rand_response.prgbBuffer = random_data;
rand_response.wBufferLength = random_data_length;
rand_response.wRespLength = 0;
while (pal_os_lock_acquire() != OPTIGA_LIB_SUCCESS);
return_value = CmdLib_GetRandom(&rand_options,&rand_response);
pal_os_lock_release();
if (CMD_LIB_OK != return_value)
{
return OPTIGA_LIB_ERROR;
}
return OPTIGA_LIB_SUCCESS;
}
optiga_lib_status_t optiga_crypt_hash_start(optiga_hash_context_t * hash_ctx)
{
optiga_lib_status_t return_value;
uint8_t rgbDataStream[1];
sCalcHash_d hash_options;
hash_options.eHashAlg = (eHashAlg_d)(hash_ctx->hash_algo);
hash_options.eHashDataType = eDataStream;
hash_options.eHashSequence = eStartHash;
hash_options.sDataStream.prgbStream = rgbDataStream;
hash_options.sDataStream.wLen =0x00; //No data
hash_options.sContextInfo.pbContextData = hash_ctx->context_buffer;
hash_options.sContextInfo.dwContextLen = hash_ctx->context_buffer_length;
hash_options.sContextInfo.eContextAction = eExport;
while (pal_os_lock_acquire() != OPTIGA_LIB_SUCCESS);
return_value = CmdLib_CalcHash(&hash_options);
pal_os_lock_release();
if (CMD_LIB_OK != return_value)
{
return OPTIGA_LIB_ERROR;
}
return OPTIGA_LIB_SUCCESS;
}
optiga_lib_status_t optiga_crypt_hash_update(optiga_hash_context_t * hash_ctx,
uint8_t source_of_data_to_hash,
void * data_to_hash)
{
optiga_lib_status_t return_value;
sCalcHash_d hash_options;
//To read the maximum communication buffer size.
uint16_t max_comms_buffer;
//To hold the remaining communication buffer size to hold the data
uint16_t remaining_comm_buffer_size = 0;
//Hash the data
//Available_Size = (wMaxCommsBuffer - #CALC_HASH_FIXED_OVERHEAD_SIZE)
uint16_t remaining_comm_bfr_sz_basic;
//Import context to security chip, calculate hash and export hash
//Available_Size = (wMaxCommsBuffer - #CALC_HASH_FIXED_OVERHEAD_SIZE - #CALC_HASH_IMPORT_AND_EXPORT_OVERHEAD_SIZE - #CALC_HASH_SHA256_CONTEXT_SIZE)
uint16_t remaining_comm_bfr_sz_with_import_export;
//Import context to security chip and calculate hash
//Available_Size = (wMaxCommsBuffer - #CALC_HASH_FIXED_OVERHEAD_SIZE - #CALC_HASH_IMPORT_OR_EXPORT_OVERHEAD_SIZE - #CALC_HASH_SHA256_CONTEXT_SIZE)
uint16_t remaining_comm_bfr_sz_with_import;
//Calulate hash and export context out of security chip
//Available_Size = (wMaxCommsBuffer - CALC_HASH_FIXED_OVERHEAD_SIZE - CALC_HASH_IMPORT_OR_EXPORT_OVERHEAD_SIZE)
uint16_t remaining_comm_bfr_sz_with_export;
uint32_t size_of_data_to_hash = 0;
uint8_t chaining = 0;
hash_options.eHashAlg = (eHashAlg_d)(hash_ctx->hash_algo);
hash_options.eHashDataType = source_of_data_to_hash == OPTIGA_CRYPT_HOST_DATA?eDataStream:eOIDData;
hash_options.eHashSequence = eContinueHash;
//Hash context
hash_options.sContextInfo.pbContextData = hash_ctx->context_buffer;
hash_options.sContextInfo.dwContextLen = hash_ctx->context_buffer_length;
hash_options.sContextInfo.eContextAction = eImportExport;
max_comms_buffer = CmdLib_GetMaxCommsBufferSize();
remaining_comm_bfr_sz_basic = max_comms_buffer - CALC_HASH_FIXED_OVERHEAD_SIZE;
remaining_comm_bfr_sz_with_import_export = max_comms_buffer -(CALC_HASH_FIXED_OVERHEAD_SIZE + \
CALC_HASH_IMPORT_AND_EXPORT_OVERHEAD_SIZE + \
CALC_HASH_SHA256_CONTEXT_SIZE);
remaining_comm_bfr_sz_with_import = max_comms_buffer -(CALC_HASH_FIXED_OVERHEAD_SIZE+ \
CALC_HASH_IMPORT_OR_EXPORT_OVERHEAD_SIZE+ \
CALC_HASH_SHA256_CONTEXT_SIZE);
remaining_comm_bfr_sz_with_export = max_comms_buffer -(CALC_HASH_FIXED_OVERHEAD_SIZE + \
CALC_HASH_IMPORT_OR_EXPORT_OVERHEAD_SIZE);
if ((eDataType_d)source_of_data_to_hash == OPTIGA_CRYPT_HOST_DATA)
{
hash_options.sDataStream.prgbStream = (uint8_t *)(((hash_data_from_host_t *)data_to_hash)->buffer);
size_of_data_to_hash = ((hash_data_from_host_t *)data_to_hash)->length;
remaining_comm_buffer_size = size_of_data_to_hash;
//Verify whether (Import & export) + data options can be set in one command or not
if (remaining_comm_bfr_sz_with_import_export<size_of_data_to_hash)
{
chaining = 1;
remaining_comm_buffer_size = remaining_comm_bfr_sz_with_import;
if (remaining_comm_bfr_sz_with_import>size_of_data_to_hash)
{
remaining_comm_buffer_size = size_of_data_to_hash;
}
hash_options.sContextInfo.eContextAction = eImport;
}
hash_options.sDataStream.wLen = remaining_comm_buffer_size;
}
else
{
hash_options.sOIDData.wOID = ((hash_data_in_optiga_t *)data_to_hash)->oid;
hash_options.sOIDData.wOffset = ((hash_data_in_optiga_t *)data_to_hash)->offset;
hash_options.sOIDData.wLength = ((hash_data_in_optiga_t *)data_to_hash)->length;
}
while (1)
{
while (pal_os_lock_acquire() != OPTIGA_LIB_SUCCESS);
return_value = CmdLib_CalcHash(&hash_options);
pal_os_lock_release();
if (CMD_LIB_OK != return_value)
{
break;
}
if (!chaining)
{
return_value = OPTIGA_LIB_SUCCESS;
break;
}
else
{
hash_options.sDataStream.prgbStream += remaining_comm_buffer_size;
size_of_data_to_hash -= remaining_comm_buffer_size;
remaining_comm_buffer_size = size_of_data_to_hash;
hash_options.sContextInfo.eContextAction = eUnused;
//Verify whether export + data options can be set in one command or not
if (remaining_comm_bfr_sz_with_export < size_of_data_to_hash)
{
remaining_comm_buffer_size = remaining_comm_bfr_sz_basic;
if (remaining_comm_bfr_sz_basic > size_of_data_to_hash)
{
remaining_comm_buffer_size = size_of_data_to_hash;
}
}
else
{
hash_options.sContextInfo.eContextAction = eExport;
chaining = 0;
}
hash_options.sDataStream.wLen = remaining_comm_buffer_size;
}
}
return return_value;
}
optiga_lib_status_t optiga_crypt_hash_finalize(optiga_hash_context_t * hash_ctx,
uint8_t * hash_output)
{
optiga_lib_status_t return_value;
uint8_t datastream[1];
sCalcHash_d hash_options;
hash_options.eHashAlg = (eHashAlg_d)hash_ctx->hash_algo;
hash_options.eHashDataType = eDataStream;
hash_options.eHashSequence = eFinalizeHash;
hash_options.sDataStream.prgbStream = datastream;
hash_options.sDataStream.wLen = 0x00; //No data
hash_options.sContextInfo.pbContextData = hash_ctx->context_buffer;
hash_options.sContextInfo.dwContextLen = hash_ctx->context_buffer_length;
hash_options.sContextInfo.eContextAction = eImport;
hash_options.sOutHash.prgbBuffer = hash_output;
if(hash_options.eHashAlg == eSHA256)
{
hash_options.sOutHash.wBufferLength = 32;
}
while (pal_os_lock_acquire() != OPTIGA_LIB_SUCCESS);
return_value = CmdLib_CalcHash(&hash_options);
pal_os_lock_release();
if (CMD_LIB_OK != return_value)
{
return OPTIGA_LIB_ERROR;
}
return OPTIGA_LIB_SUCCESS;
}
optiga_lib_status_t optiga_crypt_ecc_generate_keypair(optiga_ecc_curve_t curve_id,
uint8_t key_usage,
bool_t export_private_key,
void * private_key,
uint8_t * public_key,
uint16_t * public_key_length)
{
optiga_lib_status_t return_value;
sKeyPairOption_d keypair_options;
sOutKeyPair_d public_key_out;
keypair_options.eAlgId = (eAlgId_d)curve_id;
keypair_options.eKeyUsage = (eKeyUsage_d)key_usage;
if (export_private_key)
{
keypair_options.eKeyExport = eExportKeyPair;
public_key_out.sPublicKey.prgbStream = public_key;
public_key_out.sPublicKey.wLen = *public_key_length;
public_key_out.sPrivateKey.prgbStream = private_key;
public_key_out.sPrivateKey.wLen = 0xffff;
}
else
{
keypair_options.eKeyExport = eStorePrivKeyOnly;
keypair_options.wOIDPrivKey = *(uint16_t *)private_key;
public_key_out.sPublicKey.prgbStream = public_key;
public_key_out.sPublicKey.wLen = *public_key_length;
}
while (pal_os_lock_acquire() != OPTIGA_LIB_SUCCESS);
return_value = CmdLib_GenerateKeyPair(&keypair_options,&public_key_out);
pal_os_lock_release();
if (CMD_LIB_OK != return_value)
{
return OPTIGA_LIB_ERROR;
}
//store updated public key length .
*( public_key_length) = public_key_out.sPublicKey.wLen;
return OPTIGA_LIB_SUCCESS;
}
optiga_lib_status_t optiga_crypt_ecdsa_sign (uint8_t * digest,
uint8_t digest_length,
optiga_key_id_t private_key,
uint8_t * signature,
uint16_t * signature_length)
{
optiga_lib_status_t return_value;
sbBlob_d sign;
sCalcSignOptions_d sign_options;
sign_options.eSignScheme = eECDSA_FIPS_186_3_WITHOUT_HASH;
sign_options.wOIDSignKey = private_key;
sign_options.sDigestToSign.prgbStream = digest;
sign_options.sDigestToSign.wLen = digest_length;
sign.prgbStream = signature;
sign.wLen = *signature_length;
while (pal_os_lock_acquire() != OPTIGA_LIB_SUCCESS);
return_value = CmdLib_CalculateSign(&sign_options,&sign);
pal_os_lock_release();
if (CMD_LIB_OK != return_value)
{
return OPTIGA_LIB_ERROR;
}
*signature_length = sign.wLen;
return OPTIGA_LIB_SUCCESS;
}
optiga_lib_status_t optiga_crypt_ecdsa_verify (uint8_t * digest,
uint8_t digest_length,
uint8_t * signature,
uint16_t signature_length,
uint8_t public_key_source_type,
void * public_key)
{
optiga_lib_status_t return_value;
sVerifyOption_d verifysign_options;
sbBlob_d sign, dgst;
verifysign_options.eSignScheme = eECDSA_FIPS_186_3_WITHOUT_HASH;
verifysign_options.sPubKeyInput.eAlgId = (eAlgId_d )(((public_key_from_host_t *)public_key)->curve);
if (public_key_source_type == OPTIGA_CRYPT_HOST_DATA)
{
verifysign_options.eVerifyDataType = eDataStream;
verifysign_options.sPubKeyInput.sDataStream.prgbStream = (uint8_t *)((( public_key_from_host_t *)public_key)->public_key);
verifysign_options.sPubKeyInput.sDataStream.wLen = (((public_key_from_host_t *)public_key)->length);
}
else if (public_key_source_type == OPTIGA_CRYPT_OID_DATA)
{
verifysign_options.eVerifyDataType = eOIDData;
verifysign_options.wOIDPubKey = *((uint16_t *)public_key);
}
dgst.prgbStream = digest;
dgst.wLen = digest_length;
sign.prgbStream = signature;
sign.wLen = signature_length;
while (pal_os_lock_acquire() != OPTIGA_LIB_SUCCESS);
return_value = CmdLib_VerifySign(&verifysign_options, &dgst, &sign);
pal_os_lock_release();
if(CMD_LIB_OK == return_value)
{
return_value = OPTIGA_LIB_SUCCESS;
}
return return_value;
}
optiga_lib_status_t optiga_crypt_ecdh(optiga_key_id_t private_key,
public_key_from_host_t * public_key,
bool_t export_to_host,
uint8_t * shared_secret)
{
optiga_lib_status_t return_value = OPTIGA_LIB_ERROR;
sCalcSSecOptions_d shared_secret_options;
sbBlob_d sharedsecret;
shared_secret_options.eKeyAgreementType = eECDH_NISTSP80056A;
shared_secret_options.wOIDPrivKey = private_key;
public_key->curve == OPTIGA_ECC_NIST_P_256 ? (sharedsecret.wLen = 32) : (sharedsecret.wLen = 64);
shared_secret_options.ePubKeyAlgId = (eAlgId_d)public_key->curve;
shared_secret_options.sPubKey.prgbStream = public_key->public_key;
shared_secret_options.sPubKey.wLen = public_key->length;
if (export_to_host == 1)
{
shared_secret_options.wOIDSharedSecret = 0x0000;
sharedsecret.prgbStream = (uint8_t *)shared_secret;
}
else
{
//shared secret is stored in OID of OPTIGA
shared_secret_options.wOIDSharedSecret = *((uint16_t *)shared_secret);
}
while (pal_os_lock_acquire() != OPTIGA_LIB_SUCCESS);
return_value = CmdLib_CalculateSharedSecret(&shared_secret_options, &sharedsecret);
pal_os_lock_release();
if(CMD_LIB_OK == return_value)
{
return_value = OPTIGA_LIB_SUCCESS;
}
return return_value;
}
optiga_lib_status_t optiga_crypt_tls_prf_sha256(uint16_t secret,
uint8_t * label,
uint16_t label_length,
uint8_t * seed,
uint16_t seed_length,
uint16_t derived_key_length,
bool_t export_to_host,
uint8_t * derived_key)
{
optiga_lib_status_t return_value = OPTIGA_LIB_ERROR;
sDeriveKeyOptions_d derivekey_options;
sbBlob_d derivekey_output_buffer;
derivekey_options.eKDM = eTLS_PRF_SHA256;
derivekey_options.sSeed.prgbStream = seed;
derivekey_options.sSeed.wLen = seed_length;
derivekey_options.wOIDSharedSecret = secret;
if (derived_key_length < 16)
{
derived_key_length += (16 - derived_key_length);
}
derivekey_options.wDerivedKeyLen = derived_key_length;
if (export_to_host == 1)
{
derivekey_options.wOIDDerivedKey = 0x0000;
derivekey_output_buffer.prgbStream = (uint8_t *)derived_key;
derivekey_output_buffer.wLen = derived_key_length;
}
else
{
derivekey_options.wOIDDerivedKey = *((uint16_t *)derived_key);
}
while (pal_os_lock_acquire() != OPTIGA_LIB_SUCCESS);
return_value = CmdLib_DeriveKey(&derivekey_options, &derivekey_output_buffer);
pal_os_lock_release();
if(CMD_LIB_OK == return_value)
{
return_value = OPTIGA_LIB_SUCCESS;
}
return return_value;
}

View File

@@ -0,0 +1,480 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file AlertProtocol.c
*
* \brief This file implements the DTLS Alert Protocol.
*
* \addtogroup grMutualAuth
* @{
*/
#include "optiga/dtls/DtlsRecordLayer.h"
#include "optiga/dtls/AlertProtocol.h"
#include "optiga/dtls/DtlsFlightHandler.h"
#ifdef MODULE_ENABLE_DTLS_MUTUAL_AUTH
/// @cond hidden
/// Maximum size of Alert Message
#define LENGTH_ALERT_MSG 0x02
/// Offset for Alert Message
#define OFFSET_ALERT_MSG 0x01
//Device Error codes
///Invalid OID
#define INVALID_OID 0x01
///Invalid param field in the command
#define INVALID_PARAM_FIELD 0x03
///Invalid length field in the command
#define INVALID_LENGTH_FIELD 0x04
///Invalid parameter in the data field
#define INVALID_PARAMETER_DATA_FIELD 0x05
///Device internal error
#define INTERNAL_PROCESS_ERROR 0x06
///Invalid command field
#define INVALID_COMMAND_FIELD 0x0A
///Command out of sequence
#define COMMAND_OUT_SEQUENCE 0x0B
///Command not available
#define COMMAND_NOT_AVAILABLE 0x0C
///Illegal parameter in the Handshake header
#define INVALID_HANDSHAKE_MESSAGE 0x21
///DTLS Protocol version mismatch
#define VERSION_MISMATCH 0x22
///Cipher suite mismatch between client and server
#define INSUFFICIENT_UNSUPPORTED_CIPHERSUITE 0x23
///Unsupported extension
#define UNSUPPORTED_EXTENSION 0x24
///Unsupported parameters
#define UNSUPPORTED_PARAMETERS 0x25
///Invalid Trust Anchor
#define INVALID_TRUST_ANCHOR 0x26
///Trust Anchor expired
#define TRUST_ANCHOR_EXPIRED 0x27
///Unsupported Trust Anchor
#define UNSUPPORTED_TRUST_ANCHOR 0x28
///Invalid Certificate format
#define INVALID_CERTIFICATE_FORMAT 0x29
///Unsupported certificate/Unsupported Hash or Sign Algorithm
#define UNSUPPORTED_CERTIFICATE_HASHSIGN 0x2A
///Certificate expired
#define CERTIFICATE_EXPIRED 0x2B
///Signature verification failed
#define SIGNATURE_VERIFICATION_FAILURE 0x2C
/**
* \brief DTLS Alert Level.
*/
typedef enum eAlertLevel_d
{
///Connection can continue
eWARNING = 0x01,
///Terminate the connection
eFATAL = 0x02
}eAlertLevel_d;
/**
* \brief DTLS Alert Types.
*/
typedef enum eAlertMsg_d
{
/// Notifies the recipient that the sender will not send any more messages on this connection
eCLOSE_NOTIFY = 0x00,
/// Inappropriate message was received
eUNEXPECTED_MESSAGE = 0x0A ,
/// Notifies record is received with an incorrect MAC
eBAD_RECORD_MAC = 0x14,
///Decryption Failure
eDECRYPTION_FAILURE = 0x15,
/// Notifies record received length is more than 2^14+2048
eRECORD_OVERFLOW = 0x16,
/// Notifies decompression function received improper input
eDECOMPRESSION_FAILURE = 0x1E,
/// Indicates sender was not able to negotiate with the security parameters
eHANDSHAKE_FAILURE = 0x28,
/// Notifies certificate was corrupt
eBAD_CERTIFICATE = 0x2A,
///No certificate
eNO_CERTIFICATE = 0x29,
/// Notifies certificate was unsupported type
eUNSUPPORTED_CERTIFICATE = 0x2B,
/// Notifies the certificate was revoked by signer
eCERTIFICATE_REVOKED = 0x2C,
/// Indicates the certificate is Expired
eCERTIFICATE_EXPIRED = 0x2D,
/// Indicates unknown issue in processing the certificate
eCERTIFICATE_UNKNOWN = 0x2E,
/// Notifies field in handshake is out of range or inconsistent
eILLEGAL_PARAMETER = 0x2F,
/// Indicates CA certificate could not be found or not matched
eUNKNOWN_CA = 0x30,
/// Notifies the access denied
eACCESS_DENIED = 0x31,
/// Notifies message could not be decoded or some field is missing
eDECODE_ERROR = 0x32,
/// Notifies cryptographic operation failed
eDECRYPT_ERROR = 0x33,
///Export restriction
eEXPORT_RESTRICTION = 0x3C,
/// Notifies protocol version attempted to negotiate is not supported
ePROTOCOL_VERSION = 0x46,
/// Notifies negotiation has failed specifically because the server requires ciphers more secure
eINSUFFICIENT_SECURITY = 0x47,
/// Notifies error is unrelated to peer or protocol
eINTERNAL_ERROR = 0x50,
/// Indicates that the handshake is canceled
eUSER_CANCELLED = 0x5A,
/// Notifies that the renegotiation is not initiated
eNO_RENEGOTIATION = 0x64,
/// Notifies unsupported extension was sent to server
eUNSUPPORTED_EXTENSION = 0x6E
}eAlertMsg_d;
/// @endcond
/**
* \brief Maps the Alert types and level to error code.<br>
*/
_STATIC_H int32_t DtlsAlertErrorMapping(const sbBlob_d* PpsAlertMsg, int32_t* Ppi4ErrorCode);
//Alert protocol is defined by default. To disable define DISABLE_ALERT
#ifndef DISABLE_ALERT
/**
* \brief Maps the error code to Alert types and level.<br>
*/
_STATIC_H Void DtlsErrorAlertMapping(int32_t Pi4ErrorCode, sbBlob_d* PpsAlertMsg);
/**
* \brief Forms the alert message based on the given internal error code.<br>
*/
_STATIC_H Void Alert_FormMsg(int32_t Pi4ErrorCode,sbBlob_d* PpsAlertMsg);
/**
* Maps the error code to Alert types and level.<br>
*
* \param[in] Pi4ErrorCode DTLS Internal error code
* \param[in,out] PpsAlertMsg Pointer to a blob containing Alert message as per DTLS Specification
*
*/
_STATIC_H Void DtlsErrorAlertMapping(int32_t Pi4ErrorCode, sbBlob_d* PpsAlertMsg)
{
do
{
if((int32_t)OCP_LIB_NO_RENEGOTIATE == Pi4ErrorCode)
{
*PpsAlertMsg->prgbStream = (uint8_t)eWARNING;
}
else
{
*PpsAlertMsg->prgbStream = (uint8_t)eFATAL;
}
//Set the Blob length to Alert message length
PpsAlertMsg->wLen = LENGTH_ALERT_MSG;
switch(Pi4ErrorCode)
{
case (int32_t)OCP_RL_ERROR:
case (int32_t)OCP_FL_MSG_MAXCOUNT:
//Prepare Alert Message
*(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eCLOSE_NOTIFY;
break;
case (int32_t)(CMD_DEV_ERROR | INVALID_HANDSHAKE_MESSAGE):
case (int32_t)(CMD_DEV_ERROR | UNSUPPORTED_PARAMETERS):
case (int32_t)(CMD_DEV_ERROR | VERSION_MISMATCH):
case (int32_t) OCP_FL_HS_ERROR:
//Prepare Alert Message
*(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eILLEGAL_PARAMETER;
break;
case (int32_t)OCP_LIB_NO_RENEGOTIATE:
//Prepare Alert Message
*(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eNO_RENEGOTIATION;
break;
case (int32_t)(CMD_DEV_ERROR | INSUFFICIENT_UNSUPPORTED_CIPHERSUITE):
//Prepare Alert Message
*(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eINSUFFICIENT_SECURITY;
break;
case (int32_t)(CMD_DEV_ERROR | UNSUPPORTED_EXTENSION):
//Prepare Alert Message
*(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eUNSUPPORTED_EXTENSION;
break;
case (int32_t)(CMD_DEV_ERROR | INVALID_TRUST_ANCHOR):
//Prepare Alert Message
*(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eUNKNOWN_CA;
break;
case (int32_t)(CMD_DEV_ERROR | TRUST_ANCHOR_EXPIRED):
//Prepare Alert Message
*(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eCERTIFICATE_EXPIRED;
break;
case (int32_t)(CMD_DEV_ERROR | UNSUPPORTED_TRUST_ANCHOR):
//Prepare Alert Message
*(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eUNSUPPORTED_CERTIFICATE;
break;
case (int32_t)(CMD_DEV_ERROR | INVALID_CERTIFICATE_FORMAT):
//Prepare Alert Message
*(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eBAD_CERTIFICATE;
break;
case (int32_t)(CMD_DEV_ERROR | UNSUPPORTED_CERTIFICATE_HASHSIGN):
//Prepare Alert Message
*(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eUNSUPPORTED_CERTIFICATE;
break;
case (int32_t)(CMD_DEV_ERROR | CERTIFICATE_EXPIRED):
//Prepare Alert Message
*(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eCERTIFICATE_EXPIRED;
break;
case (int32_t)(CMD_DEV_ERROR | SIGNATURE_VERIFICATION_FAILURE):
//Prepare Alert Message
*(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eDECRYPT_ERROR;
break;
default:
//lint -e750 "The remaining errors returned by the security chip is mapped to Internal error Alert"
//Prepare Alert Message
*(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG) = (uint8_t)eINTERNAL_ERROR;
break;
}
}while(0);
}
/**
* Forms the alert message based on the given internal error code.<br>
*
* \param[in] Pi4ErrorCode DTLS Internal error code
* \param[in,out] PpsAlertMsg Pointer to a blob containing Alert message as per DTLS Specification
*
*/
_STATIC_H Void Alert_FormMsg(int32_t Pi4ErrorCode,sbBlob_d* PpsAlertMsg)
{
//Maps the internal error code to the Alert messages
DtlsErrorAlertMapping(Pi4ErrorCode,PpsAlertMsg);
}
#endif //DISABLE_ALERT
/**
* Maps the Alert types and level to error code.<br>
*
* \param[in] PpsAlertMsg Pointer to a blob containing Alert message as per DTLS Specification
* \param[in,out] Ppi4ErrorCode Pointer to the DTLS Internal error code
*
* \retval #OCP_AL_OK Successful execution
* \retval #OCP_AL_ERROR Failure in execution
*
*/
_STATIC_H int32_t DtlsAlertErrorMapping(const sbBlob_d* PpsAlertMsg, int32_t* Ppi4ErrorCode)
{
int32_t i4Status = (int32_t)OCP_AL_ERROR;
do
{
//Check for the Alert level type
if(eFATAL == (eAlertLevel_d)*PpsAlertMsg->prgbStream)
{
//Check for various fatal alert messages
switch((eAlertMsg_d) *(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG))
{
case eCLOSE_NOTIFY:
case eUNEXPECTED_MESSAGE:
case eBAD_RECORD_MAC:
case eDECRYPTION_FAILURE:
case eRECORD_OVERFLOW:
case eDECOMPRESSION_FAILURE:
case eHANDSHAKE_FAILURE:
case eBAD_CERTIFICATE:
case eUNSUPPORTED_CERTIFICATE:
case eNO_CERTIFICATE:
case eCERTIFICATE_REVOKED:
case eCERTIFICATE_EXPIRED:
case eCERTIFICATE_UNKNOWN:
case eUSER_CANCELLED:
case eNO_RENEGOTIATION:
case eILLEGAL_PARAMETER:
case eUNKNOWN_CA:
case eACCESS_DENIED:
case eDECODE_ERROR:
case eDECRYPT_ERROR:
case eEXPORT_RESTRICTION:
case ePROTOCOL_VERSION:
case eINSUFFICIENT_SECURITY:
case eINTERNAL_ERROR:
case eUNSUPPORTED_EXTENSION:
{
*Ppi4ErrorCode = (int32_t)OCP_AL_FATAL_ERROR;
i4Status = (int32_t)OCP_AL_OK;
}
break;
default:
//Indicates the received Alert is not a valid Fatal Error
break;
}
}
//Check for Warning Alert level type
else if (eWARNING == (eAlertLevel_d)*PpsAlertMsg->prgbStream)
{
//Check for various warning alert messages
switch((eAlertMsg_d) *(PpsAlertMsg->prgbStream + OFFSET_ALERT_MSG))
{
case eBAD_CERTIFICATE:
case eUNSUPPORTED_CERTIFICATE:
case eCERTIFICATE_REVOKED:
case eCERTIFICATE_EXPIRED:
case eCERTIFICATE_UNKNOWN:
case eUSER_CANCELLED:
case eNO_RENEGOTIATION:
{
*Ppi4ErrorCode = (int32_t)OCP_AL_WARNING_ERROR;
i4Status = (int32_t)OCP_AL_OK;
break;
}
default:
//lint -e788 suppress "As the enum values are divided between Fatal and warning levels"
//Indicates the received Alert is not a valid warning Error
break;
}
}
}while(0);
return i4Status;
}
#ifndef DISABLE_ALERT
/**
* Sends Alert based on the internal error code via the Record Layer.<br>
*
* \param[in] PpsConfigRL Pointer to structure containing Record Layer information.
* \param[in] Pi4ErrorCode DTLS Internal error code
*
*/
void Alert_Send(sConfigRL_d *PpsConfigRL,int32_t Pi4ErrorCode)
{
int32_t i4Status = (int32_t)OCP_AL_ERROR;
sbBlob_d sAlertMsg;
uint8_t bEncFlag = 0;
uint8_t bFlagIncr = 0;
uint8_t rgbAlertMsg[LENGTH_ALERT_MSG];
//Null checks
if((NULL != PpsConfigRL) && (NULL != PpsConfigRL->pfSend) && (NULL != PpsConfigRL->sRL.phRLHdl))
{
do
{
/// @cond hidden
#define PS_RECORDLAYER ((sRecordLayer_d*)PpsConfigRL->sRL.phRLHdl)
/// @endcond
sAlertMsg.prgbStream = rgbAlertMsg;
sAlertMsg.wLen = LENGTH_ALERT_MSG;
//Form the Alert message based on internal error code
Alert_FormMsg(Pi4ErrorCode, &sAlertMsg);
PpsConfigRL->sRL.bMemoryAllocated = FALSE;
PpsConfigRL->sRL.bContentType = CONTENTTYPE_ALERT;
//Until successful completion of Mutual Authentication Public Key Scheme (DTLS) the Client should use previous epoch and messages must not be encrypted
if(((PS_RECORDLAYER->wServerEpoch != PS_RECORDLAYER->wClientNextEpoch) && (*PS_RECORDLAYER->pbDec != 0x01)) ||
(Pi4ErrorCode == (int32_t)OCP_FL_INT_ERROR) || (Pi4ErrorCode == (int32_t)OCP_FL_HS_ERROR))
{
if((PS_RECORDLAYER->bEncDecFlag == ENC_DEC_ENABLED) && (PS_RECORDLAYER->wClientEpoch != PS_RECORDLAYER->wClientNextEpoch))
{
bEncFlag = PS_RECORDLAYER->bEncDecFlag;
PS_RECORDLAYER->bEncDecFlag = ENC_DEC_DISABLED;
PS_RECORDLAYER->wClientNextEpoch--;
bFlagIncr = 0x01;
}
}
//Send the Alert message via record layer
i4Status = PpsConfigRL->pfSend(&PpsConfigRL->sRL, sAlertMsg.prgbStream, sAlertMsg.wLen);
if(bFlagIncr == 0x01)
{
PS_RECORDLAYER->bEncDecFlag = bEncFlag;
PS_RECORDLAYER->wClientNextEpoch++;
}
if(OCP_RL_OK != i4Status)
{
break;
}
}while(FALSE);
/// @cond hidden
#undef PS_RECORDLAYER
/// @endcond
}
}
#endif //DISABLE_ALERT
/**
* Processes the received Alert Message<br>
* Returns the corresponding internal error code.<br>
*
* \param[in] PpsAlertMsg Pointer to a blob containing Alert message as per DTLS Specification
* \param[in,out] Ppi4ErrorCode Pointer to the DTLS Internal error code
*
* \retval #OCP_AL_OK Successful execution
* \retval #OCP_AL_ERROR Failure in execution
\if ENABLE_NULL_CHECKS
* \retval #OCP_AL_NULL_PARAM Null parameter(s)
\endif
* \retval #OCP_AL_LENZERO_ERROR Length of input parameter is zero
*
*/
int32_t Alert_ProcessMsg(const sbBlob_d* PpsAlertMsg,int32_t* Ppi4ErrorCode)
{
int32_t i4Status = (int32_t)OCP_AL_ERROR;
do
{
#ifdef ENABLE_NULL_CHECKS
//NULL check for the input parameters
if((NULL == PpsAlertMsg) || (NULL == Ppi4ErrorCode)|| (NULL == PpsAlertMsg->prgbStream))
{
i4Status = (int32_t)OCP_AL_NULL_PARAM;
break;
}
#endif
//Check for length is less than Alert message size
if(LENGTH_ALERT_MSG != PpsAlertMsg->wLen)
{
break;
}
//Maps the received Alert messages to the internal error codes
i4Status = DtlsAlertErrorMapping(PpsAlertMsg, Ppi4ErrorCode);
}while(0);
return i4Status;
}
/**
* @}
*/
#endif /*MODULE_ENABLE_DTLS_MUTUAL_AUTH */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,311 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file DtlsTransportLayer.c
*
* \brief This file provides APIs for the transport layer functionalities.
*
* \addtogroup grOCP
* @{
*
*/
#include "optiga/dtls/DtlsTransportLayer.h"
#include "optiga/common/MemoryMgmt.h"
#ifdef MODULE_ENABLE_DTLS_MUTUAL_AUTH
/// @cond hidden
/// @endcond
/**
* This API initialises transport layer communication structure.
*
* \param[in,out] PpsTL Pointer to the transport layer communication structure
*
* \return #OCP_TL_OK on successful execution
* \return #OCP_TL_ERROR on failure
* \return #OCP_TL_NULL_PARAM on parameter received is NULL
* \return #E_COMMS_UDP_ALLOCATE_FAILURE on failure to allocate memory
*/
int32_t DtlsTL_Init(sTL_d* PpsTL)
{
int32_t i4Status = (int32_t)OCP_TL_ERROR;
do
{
//NULL check
if((NULL == PpsTL) || (NULL == PpsTL->pzIpAddress))
{
i4Status = (int32_t)OCP_TL_NULL_PARAM;
break;
}
//Allocate the memory for the ethernet communication structure
PpsTL->phTLHdl = (pal_socket_t*)OCP_MALLOC(sizeof(pal_socket_t));
if(NULL == PpsTL->phTLHdl)
{
i4Status = (int32_t)OCP_TL_MALLOC_FAILURE;
break;
}
/// @cond hidden
#define PS_COMMS_HANDLE ((pal_socket_t*)PpsTL->phTLHdl)
/// @endcond
PS_COMMS_HANDLE->wPort = PpsTL->wPort;
//Converting IP address from string format to hex format
i4Status = pal_socket_assign_ip_address(PpsTL->pzIpAddress,&(PS_COMMS_HANDLE->sIPAddress));
if(i4Status != E_COMMS_SUCCESS)
{
break;
}
//Assigning the timeout value
PS_COMMS_HANDLE->wTimeout = PpsTL->wTimeout ;
//Non Blockage receive mode
PS_COMMS_HANDLE->bMode = (uint8_t)PpsTL->eCallType;
//Add logging
LOG_TRANSPORTMSG("Initializing UDP Connection",eInfo);
//Initialize the communication handle with the parameters
i4Status = pal_socket_init(PS_COMMS_HANDLE);
if(E_COMMS_SUCCESS != i4Status)
{
break;
}
i4Status = (int32_t)OCP_TL_OK;
}while(FALSE);
if(OCP_TL_OK != i4Status)
{
if((NULL != PpsTL)&& (NULL != PpsTL->phTLHdl))
{
OCP_FREE(PpsTL->phTLHdl);
PpsTL->phTLHdl = NULL;
}
}
/// @cond hidden
#undef PS_COMMS_HANDLE
/// @endcond
return i4Status;
}
/**
* This API creates client port
*
* \param[in,out] PpsTL Pointer to the transport layer communication structure
*
* \return #OCP_TL_OK on successful execution
* \return #OCP_TL_NULL_PARAM on parameter received is NULL
* \return #E_COMMS_UDP_BINDING_FAILURE on port binding failure
* \return #OCP_TL_ERROR on failure
*/
int32_t DtlsTL_Connect(sTL_d* PpsTL)
{
int32_t i4Status = (int32_t)OCP_TL_ERROR;
do
{
//NULL check
if((NULL == PpsTL) || (NULL == PpsTL->phTLHdl))
{
i4Status = (int32_t)OCP_TL_NULL_PARAM;
break;
}
/// @cond hidden
#define PS_COMMS_HANDLE ((pal_socket_t*)PpsTL->phTLHdl)
/// @endcond
//Logging
LOG_TRANSPORTMSG("Connecting to UDP",eInfo);
//Open the client port with the port number initialised
i4Status = pal_socket_connect(PS_COMMS_HANDLE, PS_COMMS_HANDLE->wPort);
if(E_COMMS_SUCCESS != i4Status)
{
LOG_TRANSPORTMSG("Error connecting to UDP",eError);
break;
}
PpsTL->eIsConnected = eConnected;
i4Status = (int32_t)OCP_TL_OK;
}while(FALSE);
/// @cond hidden
#undef PS_COMMS_HANDLE
/// @endcond
return i4Status;
}
/**
* This API transmits the data to the server.
*
* \param[in,out] PpsTL Pointer to the transport layer communication structure
* \param[in] PpbBuffer Pointer to buffer containing data to be transmitted
* \param[in] PdwLen Length of the data to be transmitted
*
* \return #OCP_TL_OK on successful execution
* \return #OCP_TL_NULL_PARAM on parameter received is NULL
* \return #E_COMMS_UDP_NO_DATA_TO_SEND on no date present to send
* \return #E_COMMS_INSUFFICIENT_MEMORY on out of memory failure
* \return #E_COMMS_UDP_ROUTING_FAILURE on failure to route the UDP packet
* \return #E_COMMS_UDP_DEALLOCATION_FAILURE on failure to deallocate
* \return #OCP_TL_ERROR on failure
*/
int32_t DtlsTL_Send(const sTL_d* PpsTL,uint8_t* PpbBuffer,uint16_t PdwLen)
{
int32_t i4Status = (int32_t)OCP_TL_ERROR;
do
{
//NULL check
if((NULL == PpsTL) || (NULL == PpsTL->phTLHdl) ||(NULL == PpbBuffer))
{
i4Status = (int32_t)OCP_TL_NULL_PARAM;
break;
}
LOG_TRANSPORTDBARY("Sending Data over UDP", PpbBuffer, PdwLen, eInfo);
//Send the data over IP address and Port initialized
/// @cond hidden
#define PS_COMMS_HANDLE ((pal_socket_t*)PpsTL->phTLHdl)
/// @endcond
i4Status = pal_socket_send(PS_COMMS_HANDLE, PpbBuffer, PdwLen);
if (E_COMMS_SUCCESS != i4Status)
{
LOG_TRANSPORTMSG("Error while sending data",eError);
break;
}
i4Status = (int32_t)OCP_TL_OK;
}while(FALSE);
/// @cond hidden
#undef PS_COMMS_HANDLE
/// @endcond
return i4Status;
}
/**
* This API receives the data from the server
*
* \param[in] PpsTL Pointer to the transport layer communication structure
* \param[in,out] PpbBuffer Pointer to buffer where data is to be received
* \param[in,out] PpdwLen Length of the buffer/Length of the received data
*
* \return #OCP_TL_OK on successful execution
* \return #OCP_TL_NULL_PARAM on parameter received is NULL
* \return #OCP_TL_NO_DATA on no data received from the target
* \return #E_COMMS_INSUFFICIENT_BUF_SIZE on insufficient buffer size
* \return #OCP_TL_ERROR on failure
*/
int32_t DtlsTL_Recv(const sTL_d* PpsTL,uint8_t* PpbBuffer,uint16_t* PpdwLen)
{
int32_t i4Status = (int32_t)OCP_TL_ERROR;
uint32_t dwRecvLen;
do
{
//NULL check
if((NULL == PpsTL) || (NULL == PpsTL->phTLHdl) || (NULL == PpbBuffer))
{
i4Status = (int32_t)OCP_TL_NULL_PARAM;
break;
}
//logging
LOG_TRANSPORTMSG("Receiving over UDP",eInfo);
/// @cond hidden
#define PS_COMMS_HANDLE ((pal_socket_t*)PpsTL->phTLHdl)
/// @endcond
PS_COMMS_HANDLE->wTimeout = PpsTL->wTimeout;
dwRecvLen = *PpdwLen;
//Listen the server port and receive the data
i4Status = pal_socket_listen(PS_COMMS_HANDLE, PpbBuffer, &dwRecvLen);
if ((int32_t)E_COMMS_UDP_NO_DATA_RECEIVED == i4Status)
{
i4Status = (int32_t)OCP_TL_NO_DATA;
LOG_TRANSPORTMSG("No data received over UDP",eError);
break;
}
if (E_COMMS_SUCCESS != i4Status)
{
LOG_TRANSPORTMSG("Error while receiving data over UDP",eError);
break;
}
LOG_TRANSPORTMSG("Received Data",eInfo);
LOG_TRANSPORTDBARY("Received Data over UDP", PpbBuffer, dwRecvLen, eInfo);
*PpdwLen = (uint16_t)dwRecvLen;
i4Status = (int32_t)OCP_TL_OK;
}while(FALSE);
/// @cond hidden
#undef PS_COMMS_HANDLE
/// @endcond
return i4Status;
}
/**
* This API closes the UDP communication and releases all the resources
*
* \param[in,out] PpsTL Pointer to the transport layer communication structure
*
* \return None
*/
Void DtlsTL_Disconnect(sTL_d* PpsTL)
{
//NULL check
if(NULL != PpsTL)
{
if(NULL != PpsTL->phTLHdl)
{
//logging
LOG_TRANSPORTMSG("Closing UDP Connection",eInfo);
/// @cond hidden
#define PS_COMMS_HANDLE ((pal_socket_t*)PpsTL->phTLHdl)
/// @endcond
//Close the UDP connection
pal_socket_close(PS_COMMS_HANDLE);
//Free the allocated memory for ethernet structure
OCP_FREE(PS_COMMS_HANDLE);
PpsTL->phTLHdl = NULL;
PpsTL->eIsConnected = eDisconnected;
/// @cond hidden
#undef PS_COMMS_HANDLE
/// @endcond
}
}
}
/**
* @}
*/
#endif /*MODULE_ENABLE_DTLS_MUTUAL_AUTH*/

View File

@@ -0,0 +1,214 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file
*
* \brief This file implements the APIs, types used in the
* for DTLS windowing.
*
* \addtogroup grMutualAuth
* @{
*/
#include <stdint.h>
#include "optiga/dtls/DtlsWindowing.h"
#include "optiga/dtls/DtlsRecordLayer.h"
#ifdef MODULE_ENABLE_DTLS_MUTUAL_AUTH
/// @cond hidden
///Maximum window size supported
#define MAX_WINDOW_SIZE 64
/// @endcond
/**
* Implementation for Record Replay Detection.<br>
* Return status as #OCP_RL_WINDOW_IGNORE if record is already received or record sequence number is less then lower bound of window.<br>
* Under some erroneous conditions, error codes from Record Layer can also be returned.<br>
*
* \param[in] PpsWindow Pointer to the structure that contains details required for windowing like
* record sequence number, lower and higher boundaries.
*
* \retval OCP_RL_WINDOW_UPDATED Valid record is received and window is updated.
* \retval OCP_RL_WINDOW_MOVED Valid record is received and window is updated and moved.
* \retval OCP_RL_WINDOW_IGNORE Failure in execution and record already received.
*
*/
int32_t DtlsCheckReplay(sWindow_d *PpsWindow)
{
int32_t i4Status = (int32_t) OCP_RL_WINDOW_IGNORE;
int32_t i4Retval;
sUint64 sIntermidateVal;
do
{
#ifdef ENABLE_NULL_CHECKS
if((NULL == PpsWindow) || (NULL == PpsWindow->fValidateRecord))
{
break;
}
#endif
if((MAX_WINDOW_SIZE < PpsWindow->bWindowSize) || (WORD_SIZE > PpsWindow->bWindowSize))
{
break;
}
//Compare the received sequence number with the Lower window boundary
i4Retval = CompareUint64(&PpsWindow->sRecvSeqNumber, &PpsWindow->sLowerBound);
//If sequence number is lesser than the low bound of window
if(LESSER_THAN == i4Retval)
{
break;
}
//If sequence number is greater than low bound window
//Compare the received sequence number with the Higher window boundary
i4Retval = CompareUint64(&PpsWindow->sRecvSeqNumber, &PpsWindow->sHigherBound);
//If Sequence number is greater than high bound of the window
//Slide the window
if(GREATER_THAN == i4Retval)
{
//Record validation
i4Retval = PpsWindow->fValidateRecord(PpsWindow->pValidateArgs);
//If record validation fails
if(OCP_RL_OK != i4Retval)
{
if(((int32_t)CMD_LIB_DECRYPT_FAILURE == i4Retval) || ((int32_t)OCP_RL_MALLOC_FAILURE == i4Retval))
{
i4Status = i4Retval;
}
break;
}
else
{
//Calculate the count to slide the window
//lint --e{534} suppress "The return value check is suppressed as this function always return Success.Only error condition where
//RecvSeqNumber < sHigherBound is not possible as it will enter this path only when RecvSeqNumber > sHigherBound"
i4Retval = SubtractUint64(&PpsWindow->sRecvSeqNumber, &PpsWindow->sHigherBound, &sIntermidateVal);
//Slide the window
i4Retval = ShiftLeftUint64(&PpsWindow->sWindowFrame, sIntermidateVal, PpsWindow->bWindowSize, (uint8_t)MAX_WINDOW_SIZE);
if(UTIL_SUCCESS != i4Retval)
{
break;
}
//Set the sequence number received as the Higher Bound
PpsWindow->sHigherBound = PpsWindow->sRecvSeqNumber;
sIntermidateVal.dwHigherByte = DEFAULT_LOWBOUND_DOUBLEWORD ;
sIntermidateVal.dwLowerByte = (uint32_t)PpsWindow->bWindowSize - 1;
//Difference of Higher bound and window size is set as lower bound
i4Retval = SubtractUint64(&PpsWindow->sHigherBound, &sIntermidateVal, &PpsWindow->sLowerBound);
if(UTIL_SUCCESS != i4Retval)
{
break;
}
//Set the bit position of sequence number to 1 which is the MSB of the window frame
i4Retval = Utility_SetBitUint64(&PpsWindow->sWindowFrame, PpsWindow->bWindowSize, PpsWindow->bWindowSize);
if(UTIL_SUCCESS != i4Retval)
{
break;
}
i4Status = (int32_t) OCP_RL_WINDOW_MOVED;
break;
}
}
//Compare the received sequence number with the Higher and Lower window boundary
//lint --e{534} suppress "The return value check is suppressed as this function always return Success.Only error condition where
//RecvSeqNumber > sHigherBound is not possible as it will enter this path only when RecvSeqNumber < sHigherBound"
//Calculate bit position of sequence number from high bound of the window
i4Retval = SubtractUint64(&PpsWindow->sHigherBound, &PpsWindow->sRecvSeqNumber, &sIntermidateVal);
//If window size is equal to 32
if(WORD_SIZE == PpsWindow->bWindowSize)
{
if((MOST_SIGNIFICANT_BIT_HIGH == ((PpsWindow->sWindowFrame.dwHigherByte << (uint32_t)((WORD_SIZE - sIntermidateVal.dwLowerByte) - 1))
& MOST_SIGNIFICANT_BIT_HIGH)))
{
break;
}
}
else
{
//Received sequence number is in the lower byte of the window frame
if((DEFAULT_LOWBOUND_DOUBLEWORD == sIntermidateVal.dwHigherByte) && (sIntermidateVal.dwLowerByte < WORD_SIZE))
{
if((MOST_SIGNIFICANT_BIT_HIGH == ((PpsWindow->sWindowFrame.dwLowerByte << (uint32_t)((WORD_SIZE - sIntermidateVal.dwLowerByte) - 1 )) & MOST_SIGNIFICANT_BIT_HIGH)))
{
break;
}
}
//Received sequence number is in the higher byte of the window frame
else if((DEFAULT_LOWBOUND_DOUBLEWORD == sIntermidateVal.dwHigherByte) && (sIntermidateVal.dwLowerByte >= WORD_SIZE))
{
if((MOST_SIGNIFICANT_BIT_HIGH == ((PpsWindow->sWindowFrame.dwHigherByte << (uint32_t)((MAX_WINDOW_SIZE - sIntermidateVal.dwLowerByte) - 1)) & MOST_SIGNIFICANT_BIT_HIGH)))
{
break;
}
}
}
//Record validation
i4Retval = PpsWindow->fValidateRecord(PpsWindow->pValidateArgs);
//If record validation fails
if(OCP_RL_OK != i4Retval)
{
if(((int32_t)CMD_LIB_DECRYPT_FAILURE == i4Retval) || ((int32_t)OCP_RL_MALLOC_FAILURE == i4Retval))
{
i4Status = i4Retval;
}
break;
}
else
{
i4Retval = SubtractUint64(&PpsWindow->sRecvSeqNumber, &PpsWindow->sLowerBound,&sIntermidateVal);
if(UTIL_SUCCESS != i4Retval)
{
break;
}
//Set the bit position of sequence number to 1
i4Retval = Utility_SetBitUint64(&PpsWindow->sWindowFrame, PpsWindow->bWindowSize, (uint8_t)sIntermidateVal.dwLowerByte);
if(UTIL_SUCCESS != i4Retval)
{
break;
}
if(PpsWindow->bWindowSize > WORD_SIZE)
{
PpsWindow->sWindowFrame.dwHigherByte &= MASK_DOUBLE_WORD >> (MAX_WINDOW_SIZE - PpsWindow->bWindowSize);
}
i4Status = (int32_t)OCP_RL_WINDOW_UPDATED;
}
}while(0);
return i4Status;
}
#endif /*MODULE_ENABLE_DTLS_MUTUAL_AUTH*/

View File

@@ -0,0 +1,227 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file HardwareCrypto.c
*
* \brief This file provides APIs for hardware crypto layer.
*
* \addtogroup grMutualAuth
* @{
*
*/
#include "optiga/common/Util.h"
#include "optiga/dtls/HardwareCrypto.h"
#include "optiga/dtls/OcpCommon.h"
#include "optiga/cmd/CommandLib.h"
#ifdef MODULE_ENABLE_DTLS_MUTUAL_AUTH
/**
* Initialises the Hardware Crypto Layer.
*
* \param[in,out] PpsCL Pointer to #sHardwareCrypto_d structure.
* \param[in] PpParam Pointer to the sessionKeyOID to be used for Encryption and Decryption.
*
* \retval #OCP_CL_OK Successful execution
* \retval #OCP_CL_ERROR Failure in execution
*
*/
int32_t HWCL_Init(sCL_d* PpsCL, const void* PpParam)
{
int32_t i4Status = (int32_t)OCP_CL_ERROR;
do
{
PpsCL->phCryptoHdl = (sHardwareCrypto_d*)OCP_MALLOC(sizeof(sHardwareCrypto_d));
if(NULL == PpsCL->phCryptoHdl)
{
i4Status = (int32_t)OCP_CL_MALLOC_FAILURE;
break;
}
memset(PpsCL->phCryptoHdl, 0x00, sizeof(sHardwareCrypto_d));
((sHardwareCrypto_d*)PpsCL->phCryptoHdl)->wSessionKeyOID = *((uint16_t*)PpParam);
i4Status = OCP_CL_OK;
}while(FALSE);
return i4Status;
}
/**
* Encrypts the input plain text using Security chip.
* Under some erroneous conditions, error codes from Command Library can also be returned. <br>
*
* \param[in] PpsCL Pointer to #sHardwareCrypto_d structure.
* \param[in] PpsBlobPlainText Pointer to sbBlob_d containing plain text.
* \param[in,out] PpsBlobCipherText Pointer to sbBlob_d containing cipher text.
* \param[in] PwLen Length of data to be encrypted.
*
* \retval #OCP_CL_OK Successful execution
* \retval #OCP_CL_ERROR Failure in execution
*
*/
int32_t HWCL_Encrypt(const sCL_d* PpsCL, const sbBlob_d* PpsBlobPlainText,sbBlob_d* PpsBlobCipherText,uint16_t PwLen)
{
int32_t i4Status = (int32_t)OCP_CL_ERROR;
sProcCryptoData_d sProcCryptoData;
do
{
//Null Check
if((NULL == PpsBlobPlainText)||(NULL == PpsBlobPlainText->prgbStream) ||
(NULL == PpsBlobCipherText)|| (NULL == PpsBlobCipherText->prgbStream) || (NULL == PpsCL))
{
i4Status = (int32_t)OCP_CL_NULL_PARAM;
break;
}
//Length check for input parameters
if(0 == PwLen)
{
i4Status = (int32_t)OCP_CL_ZERO_LEN;
break;
}
//Length check for input parameters
if(PpsBlobPlainText->wLen < (PwLen + OVERHEAD_UPDOWNLINK) ||
(PpsBlobCipherText->wLen < (PwLen + OVERHEAD_ENCDEC_RESPONSE + MAC_LENGTH + EXPLICIT_NOUNCE_LENGTH)))
{
i4Status = (int32_t)OCP_CL_INSUFFICIENT_MEMORY;
break;
}
//Assign the required parameter(s) for the Encrypt Message command
sProcCryptoData.sInData.prgbStream = PpsBlobPlainText->prgbStream;
sProcCryptoData.sInData.wLen = PpsBlobPlainText->wLen;
sProcCryptoData.wInDataLength = PwLen;
sProcCryptoData.wSessionKeyOID = ((sHardwareCrypto_d*)PpsCL->phCryptoHdl)->wSessionKeyOID;
sProcCryptoData.sOutData.prgbBuffer = PpsBlobCipherText->prgbStream;
sProcCryptoData.sOutData.wBufferLength = PpsBlobCipherText->wLen;
//Invoke the encrypt command API from the command library
i4Status = CmdLib_Encrypt(&sProcCryptoData);
if(CMD_LIB_OK != i4Status)
{
break;
}
PpsBlobCipherText->wLen = sProcCryptoData.sOutData.wRespLength;
i4Status = (int32_t)OCP_CL_OK;
}while(FALSE);
return i4Status;
}
/**
* Decrypts the input cipher text using Security chip.
* Under some erroneous conditions, error codes from Command Library can also be returned. <br>
*
* \param[in] PpsCL Pointer to #sHardwareCrypto_d structure.
* \param[in] PpsBlobCipherText Pointer to sbBlob_d containing cipher text.
* \param[in,out] PpsBlobPlainText Pointer to sbBlob_d containing plain text.
* \param[in] PwLen Length of data to be decrypted.
*
* \retval #OCP_CL_OK Successful execution
* \retval #OCP_CL_ERROR Failure in execution
*
*/
int32_t HWCL_Decrypt(const sCL_d* PpsCL,const sbBlob_d* PpsBlobCipherText,sbBlob_d* PpsBlobPlainText,uint16_t PwLen)
{
int32_t i4Status = (int32_t)OCP_CL_ERROR;
sProcCryptoData_d sProcCryptoData;
do
{
//Null Check
if((NULL == PpsBlobPlainText)||(NULL == PpsBlobPlainText->prgbStream) ||
(NULL == PpsBlobCipherText)|| (NULL == PpsBlobCipherText->prgbStream) || (NULL == PpsCL))
{
i4Status = (int32_t)OCP_CL_NULL_PARAM;
break;
}
//Length check for input parameters
if(0 == PwLen)
{
i4Status = (int32_t)OCP_CL_ZERO_LEN;
break;
}
//Length check for input parameters
if((PpsBlobPlainText->wLen < (PwLen + OVERHEAD_ENCDEC_RESPONSE - (MAC_LENGTH + EXPLICIT_NOUNCE_LENGTH))) ||
(PpsBlobCipherText->wLen < (PwLen + OVERHEAD_UPDOWNLINK)))
{
i4Status = (int32_t)OCP_CL_INSUFFICIENT_MEMORY;
break;
}
//Assign the required parameter(s) for the Decrypt Message command
sProcCryptoData.sInData.prgbStream = PpsBlobCipherText->prgbStream;
sProcCryptoData.sInData.wLen = PpsBlobCipherText->wLen;
sProcCryptoData.wInDataLength = PwLen;
sProcCryptoData.wSessionKeyOID = ((sHardwareCrypto_d*)PpsCL->phCryptoHdl)->wSessionKeyOID;
sProcCryptoData.sOutData.prgbBuffer = PpsBlobPlainText->prgbStream;
sProcCryptoData.sOutData.wBufferLength = PpsBlobPlainText->wLen;
LOG_TRANSPORTMSG("Encrypted Data sent to OPTIGA",eInfo);
//Invoke the Decrypt command API from the command library
i4Status = CmdLib_Decrypt(&sProcCryptoData);
if(CMD_LIB_OK != i4Status)
{
LOG_TRANSPORTDBVAL(i4Status,eInfo);
break;
}
PpsBlobPlainText->wLen = sProcCryptoData.sOutData.wRespLength;
//To log the decrypted data
LOG_TRANSPORTDBARY("Decrypted Data", sProcCryptoData.sOutData.prgbBuffer, PpsBlobPlainText->wLen, eInfo);
i4Status = (int32_t) OCP_CL_OK;
}while(FALSE);
return i4Status;
}
/**
* Closes the Crypto layer.
*
* \param[in,out] PpsCL Pointer to #sHardwareCrypto_d structure.
*
*/
void HWCL_Close(sCL_d* PpsCL)
{
if((NULL != PpsCL) && (NULL != PpsCL->phCryptoHdl))
{
OCP_FREE(PpsCL->phCryptoHdl);
PpsCL->phCryptoHdl = NULL;
}
}
#endif //MODULE_ENABLE_DTLS_MUTUAL_AUTH

View File

@@ -0,0 +1,263 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file
*
* \brief This file implements the functionality to form and process DTLS messages for OCP Library.
*
* \addtogroup grMutualAuth
* @{
*/
#include "optiga/dtls/MessageLayer.h"
#ifdef MODULE_ENABLE_DTLS_MUTUAL_AUTH
#define CALL_BACK_OK 0x00000001
/**
* Call back function to allocate memory to the received message from Security Chip.<br>
*
* \param[in,out] PpCBParam Pointer to structure containing information required to allocate memory
* \param[in] psInOutMsg Pointer to sBlob containing the received Handshake message from Security Chip
*
* \retval #CMD_LIB_OK Successful Execution
* \retval #CMD_LIB_ERROR Failure Execution
*/
int32_t CallBack_GetMessage(Void* PpCBParam, const sbBlob_d* psInOutMsg)
{
int32_t i4Status = (int32_t) CMD_LIB_ERROR;
uint32_t dwFragLen;
uint32_t dwTotalLen;
uint32_t dwOffset;
/// @cond hidden
#define PS_CBGETMSG ((sCBGetMsg_d*)PpCBParam)
#define OFFSET_MSG_FRAG_LENGTH 9
#define OFFSET_MSG_TOTAL_LENGTH 1
#define OFFSET_MSG_FRAGMENT_OFFSET 6
/// @endcond
do
{
dwFragLen = Utility_GetUint24(psInOutMsg->prgbStream + OFFSET_MSG_FRAG_LENGTH);
dwTotalLen = Utility_GetUint24(psInOutMsg->prgbStream + OFFSET_MSG_TOTAL_LENGTH);
dwOffset = Utility_GetUint24(psInOutMsg->prgbStream + OFFSET_MSG_FRAGMENT_OFFSET);
//If first time, allocate memory
if(FALSE == PS_CBGETMSG->bRepeatCall)
{
//Allocate memory
PS_CBGETMSG->dwMsgLen = (uint16_t)dwTotalLen + OVERHEAD_LEN;
PS_CBGETMSG->pbActualMsg = (uint8_t*)OCP_MALLOC(dwTotalLen + OVERHEAD_LEN);
if(PS_CBGETMSG->pbActualMsg == NULL)
{
i4Status = (int32_t)OCP_ML_MALLOC_FAILURE;
break;
}
//Set to true indicating memory is already allocated
PS_CBGETMSG->bRepeatCall = TRUE;
OCP_MEMCPY(PS_CBGETMSG->pbActualMsg + (OVERHEAD_LEN - MSG_HEADER_LEN),psInOutMsg->prgbStream,(uint16_t)(dwFragLen + MSG_HEADER_LEN));
//Set fragment offset to zero and fragment len to total len
Utility_SetUint24((PS_CBGETMSG->pbActualMsg + (OVERHEAD_LEN - 3)), dwTotalLen);
}
else
{
//copy data from offset
OCP_MEMCPY(PS_CBGETMSG->pbActualMsg + dwOffset + OVERHEAD_LEN, (psInOutMsg->prgbStream + MSG_HEADER_LEN), (uint16_t)dwFragLen);
}
i4Status = CMD_LIB_OK;
}while(FALSE);
/// @cond hidden
#undef OFFSET_MSG_FRAG_LENGTH
#undef OFFSET_MSG_TOTAL_LENGTH
#undef OFFSET_MSG_FRAGMENT_OFFSET
#undef PS_CBGETMSG
/// @endcond
return i4Status;
}
/**
* Provide Handshake message using Command Library.<br>
* Under some erroneous conditions, error codes from Command Library can also be returned.<br>
*
* \param[in] eMsgType Message type of the handshake message to be received from Security Chip
* \param[in] PpsMessageLayer Pointer to structure containing information required for Message Layer
* \param[out] PpsMessage Pointer to sBlob containing the Handshake message
*
* \retval #OCP_ML_OK Successful Execution
* \retval #OCP_ML_ERROR Failure Execution
* \retval #OCP_ML_INVALID_UNIXTIME Invalid unix time provided by user
*/
int32_t MsgLayer_FormMessage(eMsgType_d eMsgType,const sMessageLayer_d* PpsMessageLayer, sbBlob_d* PpsMessage)
{
int32_t i4Status = (int32_t) OCP_ML_ERROR;
sProcMsgData_d sGMsgVector;
sCallBack_d sCallBack;
sCBGetMsg_d sCBGetMsg;
uMsgParams_d uMsgParams;
do
{
//Null Check
if((NULL == PpsMessageLayer) || (NULL == PpsMessage))
{
i4Status = (int32_t)OCP_ML_NULL_PARAM;
break;
}
//Assign the call back function parameters
sCBGetMsg.bRepeatCall = FALSE;
sCBGetMsg.pbActualMsg = NULL;
sCBGetMsg.dwMsgLen = 0;
//Assign call back function to allocate memory
sCallBack.pfAcceptMessage = CallBack_GetMessage;
sCallBack.fvParams = (Void*) &sCBGetMsg;
//Form the Get message command APDU parameters
sGMsgVector.eParam = eMsgType;
sGMsgVector.wSessionKeyOID = PpsMessageLayer->wSessionID;
sGMsgVector.psCallBack = &sCallBack;
sGMsgVector.psBlobInBuffer = NULL;
//sGMsgVector.puMsgParams = &uMsgParams;
sGMsgVector.puMsgParams = NULL;
//Based on the message type set the message specific data
switch((uint8_t)eMsgType)
{
case eClientHello:
if(NULL != PpsMessageLayer->pfGetUnixTIme)
{
sGMsgVector.puMsgParams = &uMsgParams;
//To use the unix time provided
i4Status = PpsMessageLayer->pfGetUnixTIme(&sGMsgVector.puMsgParams->sMsgParamCH_d.dwUnixTime);
if(CALL_BACK_OK != i4Status)
{
i4Status = (int32_t) OCP_ML_INVALID_UNIXTIME;
break;
}
}
break;
case eClientCertificate:
if(0x0000 != PpsMessageLayer->wOIDDevCertificate)
{
sGMsgVector.puMsgParams = &uMsgParams;
sGMsgVector.puMsgParams->sMsgParamCert_d.wCertOID = PpsMessageLayer->wOIDDevCertificate;
}
break;
default:
//lint -e788 suppress "Default values for return are already set.No more operation required here"
//For other messages there is no message specific data
break;
}
if(((int32_t) OCP_ML_INVALID_UNIXTIME == i4Status) || ((int32_t) OCP_ML_INVALID_CERTTYPE == i4Status))
{
break;
}
//Get the Message using Get Message command from the Security Chip
i4Status = CmdLib_GetMessage(&sGMsgVector);
if(CMD_LIB_OK != i4Status)
{
LOG_TRANSPORTDBVAL(i4Status,eInfo);
break;
}
//Allocated memory is assigned the sBlob
PpsMessage->prgbStream = sCBGetMsg.pbActualMsg;
PpsMessage->wLen = sCBGetMsg.dwMsgLen;
i4Status = (int32_t) OCP_ML_OK ;
}while(FALSE);
return i4Status;
}
/**
* Process Handshake message using Command Library.<br>
* Under some erroneous conditions, error codes from Command Library can also be returned. <br>
*
* \param[in] eMsgType Message type of the handshake message to be send to Security Chip
* \param[in] PpsMessageLayer Pointer to structure containing information required for Message Layer
* \param[in] PpsMessage Pointer to sBlob containing the Handshake message
*
* \retval #OCP_ML_OK Successful Execution
* \retval #OCP_ML_ERROR Failure Execution
*/
int32_t MsgLayer_ProcessMessage(eMsgType_d eMsgType,const sMessageLayer_d* PpsMessageLayer, sbBlob_d* PpsMessage)
{
int32_t i4Status = (int32_t) OCP_ML_ERROR;
sProcMsgData_d sPMsgVector ;
do
{
//Null Check
if((NULL == PpsMessageLayer) || (NULL == PpsMessage) || (NULL == PpsMessage->prgbStream))
{
i4Status = (int32_t)OCP_ML_NULL_PARAM;
break;
}
//Length check for input parameters
if(0 == PpsMessage->wLen)
{
i4Status = (int32_t)OCP_ML_ZERO_LEN;
break;
}
//Assign the required parameter(s) for the Put Message command
sPMsgVector.eParam = eMsgType;
sPMsgVector.psBlobInBuffer = PpsMessage;
sPMsgVector.wSessionKeyOID = PpsMessageLayer->wSessionID;
sPMsgVector.puMsgParams = NULL;
sPMsgVector.psCallBack = NULL;
//Invoke the Put Message command API from the command library to send the message to Security Chip to Process
i4Status = CmdLib_PutMessage(&sPMsgVector);
if(CMD_LIB_OK != i4Status)
{
LOG_TRANSPORTDBVAL(i4Status,eInfo);
break;
}
i4Status = (int32_t) OCP_ML_OK;
}while(FALSE);
#undef PhOCPHandle
return i4Status;
}
/**
* @}
*/
#endif /*MODULE_ENABLE_DTLS_MUTUAL_AUTH*/

1212
external/infineon/optiga/dtls/OCP.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,123 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file
*
* \brief This file implements the Configuration functions for OCP Library.
*
* \addtogroup grMutualAuth
* @{
*/
#include "optiga/dtls/DtlsTransportLayer.h"
#include "optiga/dtls/DtlsHandshakeProtocol.h" //To be put under ifdef
#include "optiga/dtls/DtlsRecordLayer.h"
#include "optiga/dtls/HardwareCrypto.h"
#include "optiga/optiga_dtls.h"
#ifdef MODULE_ENABLE_DTLS_MUTUAL_AUTH
/// @cond hidden
//lint --e{714} suppress "Functions are extern and not reference in header file as
// these function not to be used for external interfaces. Hence suppressed"
Void ConfigHL(fPerformHandshake_d* PpfPerformHandshake,eConfiguration_d PeConfiguration)
{
//Based on input mode assign pointers to PpsAppOCPCntx
switch(PeConfiguration)
{
case eDTLS_12_UDP_HWCRYPTO:
//Assign the Handshake layer function pointer to context data
*PpfPerformHandshake = DtlsHS_Handshake;
break;
case eTLS_12_TCP_HWCRYPTO:
break;
}
}
//lint --e{714} suppress "Functions are extern and not reference in header file as
// these function not to be used for external interfaces. Hence suppressed"
Void ConfigRL(sConfigRL_d* PpsConfigRL,eConfiguration_d PeConfiguration)
{
//Based on input mode assign pointers to psConfigRL
switch(PeConfiguration)
{
case eDTLS_12_UDP_HWCRYPTO:
PpsConfigRL->pfInit = DtlsRL_Init;
PpsConfigRL->pfSend = DtlsRL_Send;
PpsConfigRL->pfRecv = DtlsRL_Recv;
PpsConfigRL->pfClose = DtlsRL_Close;
break;
case eTLS_12_TCP_HWCRYPTO:
break;
}
}
//lint --e{714} suppress "Functions are extern and not reference in header file as
// these function not to be used for external interfaces. Hence suppressed"
Void ConfigTL(sConfigTL_d* PpsConfigTL,eConfiguration_d PeConfiguration)
{
//Based on input mode assign pointers to psConfigTL
switch(PeConfiguration)
{
case eTLS_12_TCP_HWCRYPTO:
break;
case eDTLS_12_UDP_HWCRYPTO:
//Assign function to function pointers
PpsConfigTL->pfInit = DtlsTL_Init;
PpsConfigTL->pfConnect = DtlsTL_Connect;
PpsConfigTL->pfDisconnect = DtlsTL_Disconnect;
PpsConfigTL->pfRecv = DtlsTL_Recv;
PpsConfigTL->pfSend = DtlsTL_Send;
break;
}
}
//lint --e{714} suppress "Functions are extern and not reference in header file as
// these function not to be used for external interfaces. Hence suppressed"
Void ConfigCL(sConfigCL_d* PpsConfigCL,eConfiguration_d PeConfiguration)
{
//Based on input mode assign pointers to psConfigCL
switch(PeConfiguration)
{
case eDTLS_12_UDP_HWCRYPTO:
case eTLS_12_TCP_HWCRYPTO:
PpsConfigCL->pfInit = HWCL_Init;
PpsConfigCL->pfEncrypt = HWCL_Encrypt;
PpsConfigCL->pfDecrypt = HWCL_Decrypt;
PpsConfigCL->pfClose = HWCL_Close;
break;
}
}
/// @endcond
/**
* @}
*/
#endif /*MODULE_ENABLE_DTLS_MUTUAL_AUTH*/

View File

@@ -0,0 +1,39 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file Version.h
*
* \brief This file defines the Host Library version number.
*
*/
#ifndef _VERSION_H_
#define _VERSION_H_
/// Version information of the Host Library
#define VERSION_HOST_LIBRARY "Ver 1.50.1153"
#endif //_VERSION_H_

View File

@@ -0,0 +1,880 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file
*
* \brief This file defines APIs, types and data structures used in the
* Command Library implementation.
*
* \addtogroup grCmdLib
* @{
*/
#ifndef _CMD_LIB_H_
#define _CMD_LIB_H_
#include <stdint.h>
#include "optiga/common/Datatypes.h"
#include "optiga/common/ErrorCodes.h"
#include "optiga/common/AuthLibSettings.h"
#include "optiga/comms/optiga_comms.h"
/****************************************************************************
*
* API Error Codes
*
****************************************************************************/
///Requested operation completed without any error
#define CMD_LIB_OK 0x75E96B01
///Device error, the device error(last error code) is available in the least significant byte e.g. for Invalid OID 0x80010001 is returned.
#define CMD_DEV_ERROR 0x80010000
///An error to indicate that command execution failed.It is possibly that the application on security chip is not open or communication failure has occurred.
#define CMD_DEV_EXEC_ERROR 0x80020000
///Null parameter(s)
#define CMD_LIB_NULL_PARAM 0x80001001
///Invalid or unsupported parameter(s)
#define CMD_LIB_INVALID_PARAM (CMD_LIB_NULL_PARAM + 1)
///Insufficient memory
#define CMD_LIB_INSUFFICIENT_MEMORY (CMD_LIB_NULL_PARAM + 2)
///Length of Input is zero
#define CMD_LIB_LENZERO_ERROR (CMD_LIB_NULL_PARAM + 3)
///Invalid Session ID
#define CMD_LIB_INVALID_SESSIONID (CMD_LIB_NULL_PARAM + 4)
///Invalid Tag
#define CMD_LIB_INVALID_TAG (CMD_LIB_NULL_PARAM + 5)
///Invalid Tag Length
#define CMD_LIB_INVALID_TAGLEN (CMD_LIB_NULL_PARAM + 6)
///Invalid Length
#define CMD_LIB_INVALID_LEN (CMD_LIB_NULL_PARAM + 7)
///Decryption failed
#define CMD_LIB_DECRYPT_FAILURE (CMD_LIB_NULL_PARAM + 8)
///Invalid OID
#define CMD_LIB_INVALID_OID (CMD_LIB_NULL_PARAM + 9)
///Generic error condition
#define CMD_LIB_ERROR 0xF87ECF01
///Length of the hash context information for SHA 256
#define CALC_HASH_SHA256_CONTEXT_SIZE (130)
///Overhead for all hash calculation operations (Tag and Length size (3 bytes) + APDU header (4 bytes))
#define CALC_HASH_FIXED_OVERHEAD_SIZE (0x03 + 0x04)
///Overhead for import or export hash context (Tag and Length size (3 bytes))
#define CALC_HASH_IMPORT_OR_EXPORT_OVERHEAD_SIZE (0x03)
///Overhead for import and export hash context
#define CALC_HASH_IMPORT_AND_EXPORT_OVERHEAD_SIZE (0x06)
/****************************************************************************
*
* Common data structure used across all functions.
*
****************************************************************************/
/**
* \brief Structure to receive the response of the device for a command.
*/
typedef struct sCmdResponse_d
{
///The length of the buffer
uint16_t wBufferLength;
///Pointer to the buffer to copy the response
uint8_t *prgbBuffer;
///Actual length of the response
uint16_t wRespLength;
}sCmdResponse_d;
/**
* \brief Function to send a command and receive response for the command.
*/
typedef int32_t (*pFTransceive)(const void* ctx,const uint8_t *PprgbWriteBuffer, const uint16_t *PpwWriteBufferLen, uint8_t *PprgbReadBuffer, uint16_t *PpwReadBufferLen);
/****************************************************************************
*
* Definitions related to OpenApplication and CloseApplication commands.
*
****************************************************************************/
/**
* \brief Enumerations to open the application on security chip.
*/
typedef enum eOpenType_d
{
///Initialise a clean application context
eInit = 0x00
}eOpenType_d;
/**
* \brief Structure to specify open application command parameters.
*/
typedef struct sOpenApp_d
{
///Type of option for Open application
eOpenType_d eOpenType;
}sOpenApp_d;
/**
* \brief Opens the Security Chip Application.
*/
LIBRARY_EXPORTS int32_t CmdLib_OpenApplication(const sOpenApp_d* PpsOpenApp);
/// @cond hidden
LIBRARY_EXPORTS void CmdLib_SetOptigaCommsContext(const optiga_comms_t *p_input_optiga_comms);
/// @endcond
/****************************************************************************
*
* Definitions related to GetDataObject and SetDataObject commands.
*
****************************************************************************/
/**
* \brief Enumeration to specify data or metadata.
*/
typedef enum eDataOrMedata_d
{
///Read or write data
eDATA,
///Read or write metadata
eMETA_DATA
}eDataOrMedata_d;
/**
* \brief Enumeration to specify write option.
*/
typedef enum eWriteOption_d
{
///Perform write operation
eWRITE,
///Perform erase and write operation
eERASE_AND_WRITE
}eWriteOption_d;
/**
* \brief Structure to specify GetDataObject command parameters.
*/
typedef struct sGetData_d
{
///OID of data object
uint16_t wOID;
///Offset within the data object
uint16_t wOffset;
///Number of data bytes to read
uint16_t wLength;
///To read data or metadata
eDataOrMedata_d eDataOrMdata;
}sGetData_d;
/**
* \brief Structure to specify SetDataObject command parameters.
*/
typedef struct sSetData_d
{
///OID of data object
uint16_t wOID;
///Offset within the data object
uint16_t wOffset;
///Number of data bytes to write
uint16_t wLength;
///Data bytes to be written
uint8_t *prgbData;
///To write data or metadata
eDataOrMedata_d eDataOrMdata;
///Write option
eWriteOption_d eWriteOption;
}sSetData_d;
#ifdef MODULE_ENABLE_READ_WRITE
/**
* \brief Reads the specified data object by issuing GetDataObject command.
*/
LIBRARY_EXPORTS int32_t CmdLib_GetDataObject(const sGetData_d *PpsGDVector, sCmdResponse_d *PpsResponse);
/**
* \brief Writes to the specified data object by issuing SetDataObject command.
*/
LIBRARY_EXPORTS int32_t CmdLib_SetDataObject(const sSetData_d *PpsSDVector);
/**
* \brief Reads maximum communication buffer size supported by the security chip.
*/
LIBRARY_EXPORTS uint16_t CmdLib_GetMaxCommsBufferSize(Void);
#endif
/****************************************************************************
*
* Definitions related to authentication commands.
*
****************************************************************************/
///Challenge minimum length
#define CHALLENGE_MIN_LEN 0x08
///Challenge maximum length
#define CHALLENGE_MAX_LEN 0x100
/**
* \brief Enumeration to specify an authentication scheme.
*/
typedef enum eAuthScheme_d
{
///The ECDSA signature scheme as specified within FIPS 186-3 (SHA256)
eECDSA = 0x91,
///DTLS Client scheme with cipher suite as DTLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
eDTLSClient = 0x99
}eAuthScheme_d;
/**
* \brief Structure to specify authentication command parameters.
*/
typedef struct sAuthMsg_d
{
///Challenge length
uint16_t wRndLength;
///Challenge
uint8_t *prgbRnd;
///Authentication scheme
eAuthScheme_d eAuthScheme;
///Private key
uint16_t wOIDDevPrivKey;
}sAuthMsg_d;
/**
* \brief Structure to specify authentication Scheme parameters.
*/
typedef struct sAuthScheme_d
{
///OID of Device Private key
uint16_t wDevicePrivKey;
///OID of Session Key
uint16_t wSessionKeyId;
///Authentication scheme
eAuthScheme_d eAuthScheme;
}sAuthScheme_d;
/**
* \brief Enumeration to specify the type of the random number
*/
typedef enum eRngType_d
{
///True random number
eTRNG = 0x00,
///Deterministic random number
eDRNG = 0x01,
}eRngType_d;
/**
* \brief Structure to specify option to generate random number
*/
typedef struct sRngOptions_d
{
///Type of Random number
eRngType_d eRngType;
///Length of the random number to be generated
uint16_t wRandomDataLen;
}sRngOptions_d;
/**
* \brief Gets the signature generated by Security Chip.
*/
LIBRARY_EXPORTS int32_t CmdLib_GetSignature(const sAuthMsg_d *PpsAuthMsg, sCmdResponse_d *PpsResponse);
/**
* \brief Gets the true random bytes generated by Security Chip.
*/
LIBRARY_EXPORTS int32_t CmdLib_GetRandom(const sRngOptions_d *PpsRng, sCmdResponse_d *PpsResponse);
/**
* \brief Sets the Authentication Scheme by issuing SetAuthScheme command to Security Chip.
*/
LIBRARY_EXPORTS int32_t CmdLib_SetAuthScheme(const sAuthScheme_d *PpsAuthVector);
/**
* \brief Enumeration to specify Hashing algorithm.
*/
typedef enum eHashAlg_d
{
///SHA256 for Hashing
eSHA256 = 0xE2
}eHashAlg_d;
/**
* \brief Enumeration to specify Hashing Sequence.
*/
typedef enum eHashSequence_d
{
///Start hashing
eStartHash = 0x00,
///Start and Finalize hashing
eStartFinalizeHash = 0x01,
///Continue hashing
eContinueHash = 0x02,
///Finalize hashing
eFinalizeHash = 0x03,
///Terminate hashing
eTerminateHash = 0x04,
///Get Intermediate hash
eIntermediateHash = 0x05
}eHashSequence_d;
/**
* \brief Enumeration to specify Hashing data type.
*/
typedef enum eDataType_d
{
///Data stream
eDataStream = 0x00,
///OID contents
eOIDData = 0x01
}eDataType_d;
/**
* \brief Structure to specify OID information.
*/
typedef struct sOIDInfo_d
{
///OID of data object
uint16_t wOID;
///Offset within the data object
uint16_t wOffset;
///Number of data bytes starting from the offset
uint16_t wLength;
}sOIDInfo_d;
/**
* \brief Enumeration to specify the action to be performed with the context.
*/
typedef enum eContextAction_d
{
///Context data is not used
eUnused = 0x00,
///Import hash context to perform the hash
eImport = 0x06,
///Export the current active hash context
eExport = 0x07,
///Import the provided hash context and export back the hash context after hashing
eImportExport = 0x67
}eContextAction_d;
/**
* \brief Structure to specify the information for context information.
*/
typedef struct sContextInfo_d
{
///Action on the input context
eContextAction_d eContextAction;
///Pointer to memory , to copy to/from context data
uint8_t* pbContextData;
///Length of the context while importing/ Length of memory while exporting context
uint16_t dwContextLen;
}sContextInfo_d;
/**
* \brief Structure to specify parameters for Hash generation.
*/
typedef struct sCalcHash_d
{
///Hashing Algorithm
eHashAlg_d eHashAlg;
///Hashing sequence
eHashSequence_d eHashSequence;
///Type of data for hashing
eDataType_d eHashDataType;
///Data stream blob for hashing
sbBlob_d sDataStream;
///Object data for hashing
sOIDInfo_d sOIDData;
///Output Hash
sCmdResponse_d sOutHash;
///Context Information
sContextInfo_d sContextInfo;
}sCalcHash_d;
/**
* \brief Structure to specify hash information.
*/
typedef struct sHashinfo
{
///Hash Algorithm type
eHashAlg_d eHashAlgo;
///Hash Length
uint8_t bHashLen;
///Hash context data
uint16_t wHashCntx;
}sHashinfo_d;
/**
* \brief Enumeration for supported Signing scheme.
*/
typedef enum eSignScheme_d
{
///ECDSA FIPS 186-3 w/o hash
eECDSA_FIPS_186_3_WITHOUT_HASH = 0x11
}eSignScheme_d;
/**
* \brief Enumeration for supported algorithm identifier.
*/
typedef enum eAlgId_d
{
///Elliptic curve key on NIST P256 curve
eECC_NIST_P256 = 0x03,
///Elliptic curve key on NIST P384 curve
eECC_NIST_P384 = 0x04
}eAlgId_d;
/**
* \brief Structure to specify public key for verify hash
*/
typedef struct sPubKeyInput_d
{
///Algorithm identifier
eAlgId_d eAlgId;
///Data stream containing public key
sbBlob_d sDataStream;
}sPubKeyInput_d;
/**
* \brief Structure to specify parameters for Signature verification.
*/
typedef struct sVerifyOption_d
{
///Signing scheme
eSignScheme_d eSignScheme;
///Source of the public key
eDataType_d eVerifyDataType;
///Data stream blob for hashing
sPubKeyInput_d sPubKeyInput;
///OID of data object
uint16_t wOIDPubKey;
}sVerifyOption_d;
/**
* \brief Structure to return key pair as output.
*/
typedef struct sOutKeyPair_d
{
///Blob pointing to memory to store public key
sbBlob_d sPublicKey;
///Blob pointing to memory to store private key
sbBlob_d sPrivateKey;
}sOutKeyPair_d;
/**
* \brief Enumeration to specify the action on key pair.
*/
typedef enum eKeyExport_d
{
///Stores only the private key in the OID and exports the public key
eStorePrivKeyOnly = 0x01,
///Exports both public and private key as the output
eExportKeyPair = 0x07
}eKeyExport_d;
/**
* \brief Enumeration to specify supported key usage.
*/
typedef enum eKeyUsage_d
{
///The key is used for authentication
eAuthentication = 0x01,
///The key is used for encryption
eEncryption = 0x02,
///The key is used for host firmware update
eHostFwUpdate = 0x04,
///The key is used for device management
eDevMgmt = 0x08,
///The key is used for signature
eSign = 0x10,
///The key agreement
eKeyAgreement = 0x20
}eKeyUsage_d;
/**
* \brief Structure to specify parameters for Key Pair Generation.
*/
typedef struct sKeyPairOption_d
{
///Algorithm identifier of the key to be generated
eAlgId_d eAlgId;
///Option to export/store keys
eKeyExport_d eKeyExport;
///OID of the private key/session context to be generated
uint16_t wOIDPrivKey;
///Key Usage
eKeyUsage_d eKeyUsage;
}sKeyPairOption_d;
/**
* \brief Structure to specify parameters for signature generation.
*/
typedef struct sCalcSignOptions_d
{
///Signing scheme
eSignScheme_d eSignScheme;
///OID of the signature key
uint16_t wOIDSignKey;
///Digest to be signed
sbBlob_d sDigestToSign;
}sCalcSignOptions_d;
/**
* \brief Enumeration to specify supported key agreement primitives
*/
typedef enum eKeyAgreementType_d
{
///Elliptic Curve Diffie-Hellman shared secret agreement according to NIST SP-800 56A
eECDH_NISTSP80056A = 0x01
}eKeyAgreementType_d;
/**
* \brief Structure to specify parameters for shared secret calculation.
*/
typedef struct sCalcSSecOptions_d
{
///Key agreement algorithm
eKeyAgreementType_d eKeyAgreementType;
///Algorithm identifier of the public key
eAlgId_d ePubKeyAlgId;
///OID of the private key/session context for shared secret calculation
uint16_t wOIDPrivKey;
///OID of the session context to store the calculated secret
uint16_t wOIDSharedSecret;
///Public key for shared secret calculation
sbBlob_d sPubKey;
}sCalcSSecOptions_d;
/**
* \brief Enumeration to specify supported key derivation method
*/
typedef enum eKeyDerivationMethod_d
{
///IETF 5246 TLS PRF SHA256
eTLS_PRF_SHA256 = 0x01
}eKeyDerivationMethod_d;
/**
* \brief Structure to specify parameters for derive key generation.
*/
typedef struct sDeriveKeyOptions_d
{
///Key derivation method
eKeyDerivationMethod_d eKDM;
///OID of Shared Secret to derive the new secret from
uint16_t wOIDSharedSecret;
///The length of the key to be derived
uint16_t wDerivedKeyLen;
///OID to store the Derived key
uint16_t wOIDDerivedKey;
///Seed
sbBlob_d sSeed;
}sDeriveKeyOptions_d;
#ifdef MODULE_ENABLE_TOOLBOX
/**
* \brief Calculates the hash on input data by issuing CalcHash command to Security Chip.
*/
LIBRARY_EXPORTS int32_t CmdLib_CalcHash(sCalcHash_d* PpsCalcHash);
/**
* \brief Verify the signature on digest by issuing VerifySign command to Security Chip.
*/
LIBRARY_EXPORTS int32_t CmdLib_VerifySign(const sVerifyOption_d* PpsVerifySign,const sbBlob_d * PpsDigest,const sbBlob_d * PpsSignature);
/**
* \brief Generate a key pair by issuing GenKeyPair command to Security Chip.
*/
LIBRARY_EXPORTS int32_t CmdLib_GenerateKeyPair(const sKeyPairOption_d* PpsKeyPairOption,sOutKeyPair_d* PpsOutKeyPair);
/**
* \brief Calculate signature on a digest by issuing CalcSign command to the Security Chip.
*/
LIBRARY_EXPORTS int32_t CmdLib_CalculateSign(const sCalcSignOptions_d *PpsCalcSign,sbBlob_d *PpsSignature);
/**
* \brief Calculate shared secret by issuing CalcSSec command to the Security Chip.
*/
LIBRARY_EXPORTS int32_t CmdLib_CalculateSharedSecret(const sCalcSSecOptions_d *PpsCalcSSec,sbBlob_d *PpsSecret);
/**
* \brief Derive session key by issuing DeriveKey command to the Security Chip.
*/
LIBRARY_EXPORTS int32_t CmdLib_DeriveKey(const sDeriveKeyOptions_d *PpsDeriveKey,sbBlob_d *PpsKey);
#endif/*MODULE_ENABLE_TOOLBOX*/
/****************************************************************************
*
* Definitions related to (D)TLS commands.
*
****************************************************************************/
///Length of APDU header
#define LEN_APDUHEADER 0x04
///Number of bytes in Session ID field
#define BYTES_SESSIONID 0x02
///bits per byte
#define BITS_PER_BYTE 0x08
///Tag Encoding length
#define LEN_TAG_ENCODING 0x03
///Additional bytes for Encryption/Decryption
#define ADDITIONALBYTES_ENCDEC 10
///Overhead for all uplink/downlink messages
#define OVERHEAD_UPDOWNLINK (LEN_APDUHEADER + BYTES_SESSIONID + LEN_TAG_ENCODING + ADDITIONALBYTES_ENCDEC)
//Overhead for Encrypt/Decrypt response
#define OVERHEAD_ENCDEC_RESPONSE (LEN_APDUHEADER + LEN_TAG_ENCODING)
/**
* \brief Enumeration to specify the type of message.
*/
typedef enum eMsgType_d
{
//Client Side Message type
///Client Hello
eClientHello = 0x01,
///Client Hello with Cookie
eClientHelloWithCookie = 0x03,
///Client Certificate
eClientCertificate = 0x0B,
///Client Key Exchange
eClientKeyExchange = 0x10,
///Certificate Verify
eCertificateVerify = 0x0F,
///Client Finished
eClientFinished = 0x14,
//Server Side Message type
///Hello Verify Request
eHelloVerifyRequest = 0x03,
///Server Hello
eServerHello = 0x02,
///Server Certificate
eServerCertificate = 0x0B,
///Server Key Exchange
eServerKeyExchange = 0x0C,
///Certificate Request
eCertificateRequest = 0x0D,
///Server Hello Done
eServerHelloDone = 0x0E,
///Server Finished
eServerFinished = 0x14,
///Change cipher spec
eChangeCipherSpec = 0x13,
///Close session
eCloseSession = 0x71
}eMsgType_d;
/**
* \brief Union to specify message specific parameters
*/
typedef union uMsgParams_d
{
///Client Hello Params
struct sMsgParamCH_d
{
///Unix Time
uint32_t dwUnixTime;
}sMsgParamCH_d;
///Certificate Params
struct sMsgParamCert_d
{
///Certificate OID
uint16_t wCertOID;
}sMsgParamCert_d;
}uMsgParams_d;
///Callback to Caller to accept the message
typedef int32_t (*fAcceptMessage)(Void*,const sbBlob_d*);
/**
* \brief Structure to specify Call back parameters for Get Message.
*/
typedef struct sCallBack_d
{
///Callback to Caller to accept the message
fAcceptMessage pfAcceptMessage;
///Params for Call back
Void* fvParams;
}sCallBack_d;
/**
* \brief Structure to specify parameters for (D)TLS handshake messages.
*/
typedef struct sProcMsgData_d
{
///Pointer to Input Buffer memory
sbBlob_d* psBlobInBuffer;
///Type of Message
eMsgType_d eParam;
///Session Key OID
uint16_t wSessionKeyOID;
///Message related parameters
uMsgParams_d* puMsgParams;
///Pointer to a structure containing Callback function and parameter pointer to Caller to accept the message
sCallBack_d *psCallBack;
}sProcMsgData_d;
/**
* \brief Structure to specify ProcUpLink/ProcDownLink command parameters.
*/
typedef struct sProcCryptoData_d
{
///Contains data to be encrypted/decrypted.This should contain enough memory to accommodate APDU header, data formatting and the data for encryption/decryption
sbBlob_d sInData;
///Actual length of data to be encrypted/decrypted
uint16_t wInDataLength;
///Session Key OID
uint16_t wSessionKeyOID;
///Holds the output data after encryption/decryption
sCmdResponse_d sOutData;
}sProcCryptoData_d;
#ifdef MODULE_ENABLE_DTLS_MUTUAL_AUTH
/**
* \brief Generates Uplink message by issuing ProcUpLink command to Security Chip.
*/
LIBRARY_EXPORTS int32_t CmdLib_GetMessage(const sProcMsgData_d *PpsGMsgVector);
/**
* \brief Process Authentication message by issuing ProcDownLink command to Security Chip.
*/
LIBRARY_EXPORTS int32_t CmdLib_PutMessage(const sProcMsgData_d *PpsPMsgVector);
/**
* \brief Encrypts data by issuing ProcUpLink command to Security Chip.
*/
LIBRARY_EXPORTS int32_t CmdLib_Encrypt(sProcCryptoData_d *PpsEncVector);
/**
* \brief Decrypts data by issuing ProcDownLink command to Security Chip.
*/
LIBRARY_EXPORTS int32_t CmdLib_Decrypt(sProcCryptoData_d *PpsDecVector);
/**
* \brief Closes the Security Chip session as indicated by the Session Reference Id.
*/
LIBRARY_EXPORTS int32_t CmdLib_CloseSession(uint16_t PwSessionRefId);
#endif /* MODULE_ENABLE_DTLS_MUTUAL_AUTH*/
#endif //_CMD_LIB_H_
/**
* @}
*/

View File

@@ -0,0 +1,91 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file
*
* \brief This file is defines the compilation switches to build code with required features.
*
* \addtogroup grMutualAuth
* @{
*/
#ifndef _AUTH_LIB_SETTINGS_H_
#define _AUTH_LIB_SETTINGS_H_
/*
To enable a user in choosing required feature set, compilation switches are provided to build the code.
1.FEATURE_ONEWAY_AUTH : One Way authentication feature is enabled.
2.FEATURE_DTLS_MUTUAL_AUTH : Mutual authentication feature is enabled.
3.FEATURE_TOOLBOX : Tool box feature is enabled
4.By default all features are enabled.
A user can define more switches in the following way and add it before the default #else directive
//Sample definition for new compile time switch
#ifdef NEW_REQUIRED_FEATURES
#define MODULE_X
#define MODULE_Y
#define MODULE_Z
#endif
*/
//If only One Way Authentication feature required
#ifdef FEATURE_ONEWAY_AUTH
#define MODULE_ENABLE_READ_WRITE
#define MODULE_ENABLE_ONE_WAY_AUTH
#define FEATURE_ENABLED
#endif
//If only Mutual Authentication feature required
#ifdef FEATURE_DTLS_MUTUAL_AUTH
#define MODULE_ENABLE_READ_WRITE
#define MODULE_ENABLE_DTLS_MUTUAL_AUTH
#define FEATURE_ENABLED
#endif
#ifdef FEATURE_TOOLBOX
#define MODULE_ENABLE_TOOLBOX
#define FEATURE_ENABLED
#endif
//By Default all are enabled
#ifndef FEATURE_ENABLED
#define MODULE_ENABLE_READ_WRITE
#define MODULE_ENABLE_ONE_WAY_AUTH
// #define MODULE_ENABLE_DTLS_MUTUAL_AUTH
#define MODULE_ENABLE_TOOLBOX
#endif
#ifdef OPTIMIZE_CODE
#define OPTIMIZE_CODE(x) #ifndef x
#define OPTIMIZE_CODE_ENDS(x) #endif
#else
#define OPTIMIZE_CODE(x)
#define OPTIMIZE_CODE_ENDS(x)
#endif
#endif /* _AUTH_LIB_SETTINGS_H_*/
/**
* @}
*/

View File

@@ -0,0 +1,140 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
*
* \file
*
* \brief This file contains the type definitions for the fundamental data types.
*
*
*
*/
#ifndef _DATATYPES_H_
#define _DATATYPES_H_
/******************************************************************************
* required includes
* Setup common include order for the used types and definitions
******************************************************************************/
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
/******************************************************************************
* DataTypes.h
******************************************************************************/
/******************************************************************************
* defines
******************************************************************************/
/// @cond hidden
#ifndef _OPTIGA_EXPORTS_DLLEXPORT_H_
#define _OPTIGA_EXPORTS_DLLEXPORT_H_
#if defined(WIN32) || defined(_WIN32)
#ifdef OPTIGA_LIB_EXPORTS
#define LIBRARY_EXPORTS __declspec(dllexport)
#elif defined(OPTIGA_LIB_EXCLUDE_IMPORT)
#define LIBRARY_EXPORTS
#else
#define LIBRARY_EXPORTS __declspec(dllimport)
#endif // OPTIGA_LIB_EXPORTS
#else
#define LIBRARY_EXPORTS
#endif //WIN32
#endif /*_OPTIGA_EXPORTS_DLLEXPORT_H_*/
/// @endcond
/// Definition for false
#ifndef FALSE
#define FALSE 0
#endif
/// Definition for true
#ifndef TRUE
#define TRUE 1
#endif
/******************************************************************************
* fundamental typedefs
******************************************************************************/
/// Typedef for one byte integer
typedef char char_t;
/// Typedef for native byte pointer
typedef uint8_t* puint8_t;
/// Typedef for a 4 byte unsigned integer pointer
typedef uint32_t* puint32_t;
/// Typedef for unsigned word pointer
typedef uint16_t* puint16_t ;
/// Typedef for a void
typedef void Void;
/// Typedef for a double word
typedef double double_t;
/// Typedef for a float
typedef float float_t;
/// Typedef for a boolean
typedef uint8_t bool_t;
/// Typedef for Handle
typedef Void* hdl_t;
/// typedef for host library status
typedef uint16_t host_lib_status_t;
/// typedef for OPTIGA host library status (will be updated to different data type in the future to keep in sync with other modules)
typedef int32_t optiga_lib_status_t;
/**
* \brief Structure to specify a byte stream consisting of length and data
* pointer.
*/
typedef struct sbBlob_d
{
/// Length of the byte stream
uint16_t wLen;
/// Pointer to byte array which contains the data stream
uint8_t *prgbStream;
} sbBlob_d;
/// typedef for application event handler
typedef void (*app_event_handler_t)(void* upper_layer_ctx, host_lib_status_t event);
#ifndef _STATIC_H
#define _STATIC_H static
#endif
#endif /* __DATATYPES_H__ */

View File

@@ -0,0 +1,153 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file
*
* \brief This file defines the error codes.
*
*
*
*/
#ifndef _ERRORCODES_H_
#define _ERRORCODES_H_
/******************************************************************************
* required includes
* Setup common include order for the used types and definitions
******************************************************************************/
/******************************************************************************
* ErrorCodes.h
******************************************************************************/
/******************************************************************************
* defines
******************************************************************************/
/// Communication success
#define E_COMMS_SUCCESS 0x00000000
/// Error code if protocol exit timeout has occurred
#define E_COMMS_TIMEOUT_OCCURRED 0x80000003
/// Error code if soft reset is not supported by slave
#define E_COMMS_SOFT_RESET_NOT_SUPPORTED 0x80000005
/// Error code if network layer channel does not mismatch with that of the slave
#define E_COMMS_CHANNEL_NUM_MISMATCH 0x80000006
/// Error code if packet size could not be set
#define E_COMMS_PACKET_SIZE_NOT_SET 0x80000007
/// Error code for invalid key
#define E_COMMS_INVALID_KEY 0x80000008
/// Error code if the input parameter is NULL
#define E_COMMS_PARAMETER_NULL 0x8000000A
/// Error code for uninitialized protocol
#define E_COMMS_PROTOCOL_NOT_INITIALIZED 0x8000000B
/// Error code for wrong reset value
#define E_INVALID_RESET_VALUE 0x8000000C
///Error code for invalid value for a given key
#define E_INVALID_VALUE_FOR_KEY 0x8000000D
/// Error code for if the slave doesn't have any data ready
#define E_COMMS_SLAVE_NODATA 0x8000000E
/// Error code if no channel information is present
#define E_COMMS_NO_CHANNEL_INFORMATION 0x8000000F
/// Error code if APDU is not present
#define E_COMMS_NO_APDU_PRESENT 0x80000010
/// Error code for cold reset not supported
#define E_COMMS_COLD_RESET_NOT_SUPPORTED 0x80000011
/// Error code for partial frame send
#define E_COMMS_PARTIAL_FRAME_SENT 0x80000012
/// Error code for low level I2C write failed
#define E_COMMS_I2C_WRITE_FAILED 0x80000013
/// Error code for low level I2C read failed
#define E_COMMS_I2C_READ_FAILED 0x80000014
/// Error code for buffer size or memory insufficient
#define E_COMMS_INSUFFICIENT_BUF_SIZE 0x80000015
/// Error code when the value of key is not set
#define E_COMMS_KEY_VALUE_NOT_SET 0x80000016
/// Error code for setting a property within a session not allowed
#define E_COMMS_SET_PROPERTY_DENIED 0x80000017
/// Error code for opening the already opened protocol stack
#define E_COMMS_ALREADY_OPEN 0x80000018
/// Error code for frame buffer overflow(at data link layer)
#define E_COMMS_FRAME_BUFFER_OVERFLOW 0x80000019
/// Error code for unsupported functionality
#define E_COMMS_FUNCTION_NOT_SUPPORTED 0x8000001A
/// Error code for invalid channel number
#define E_COMMS_INVALID_CHANNEL_NO 0x8000001B
/// Error code for insufficient memory
#define E_COMMS_INSUFFICIENT_MEMORY 0x8000001C
/// Error code if Nack is received
#define E_COMMS_I2C_NACK_RECEIVED 0x8000001D
/// Error code for I2C Tx/Rx Error
#define E_COMMS_I2C_TXRX_ERROR 0x8000001E
/// Error code for I2C Tx/Rx Error
#define E_COMMS_I2C_TIMEOUT 0x8000001F
/// Error code for I2C Tx/Rx Error
#define E_COMMS_INVALID_REQUEST 0x80000020
/// Error code for communication failure
#define E_COMMS_FAILURE 0xFFFFFFFF
/// Indicates no session available at OPTIGA
#define OPTIGA_LIB_NO_SESSION_AVAILABLE 0x0000
/// OPTIGA Host Library API status - Success
#define OPTIGA_LIB_SUCCESS 0x0000
/// OPTIGA Host Library API status - Busy
#define OPTIGA_LIB_STATUS_BUSY 0x0001
/// OPTIGA Host Library API status - Failure
#define OPTIGA_LIB_ERROR 0xFFFF
#endif /* _ERRORCODES_H_ */

View File

@@ -0,0 +1,362 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
* \file
*
* \brief This file contains a light weight logger.
*
*
* \addtogroup grLogger
* @{
*
*/
#ifndef __LOGGER_H__
#define __LOGGER_H__
#include "optiga/common/Util.h"
#ifdef WIN32
#include <stdio.h>
#endif
/// @cond hidden
/*****************************************************************************
* Defines
*****************************************************************************/
/// Flag for transmit direction
#define TX_DIRECTION 0
/// Flag for reception direction
#define RX_DIRECTION 1
/// Flag to write to console UART
#define CONSOLE_PORT 0
/// Flag to write to cuint UART
#define CUNIT_PORT 1
/// Flag to write to code coverage UART
#define CODE_COVERAGE_PORT 2
//Pointer to writer
typedef int32_t (*pFWriteData)(uint32_t PdwPort, uint8_t* PprgbBuf, uint32_t PdwDataLen);
///This is pointer to log writer
extern pFWriteData pfWriter;
///This function converts Uint8 value to Hex String
void ConvUint8ToHexString (uint8_t* PprgbHexByteArray, uint8_t* PprgbHexString, \
uint32_t dwNoOfBytes, uint8_t PbIsSpaceReq);
///This function converts Uint32 to Hex String
void ConvUint32ToHexString (uint32_t dwVal, uint8_t* PprgbHexString);
///This function converts Uint32 value to Decimal String
void ConvUint32ToDecString (uint32_t dwVal, uint8_t* PprgbDecStr, \
uint8_t bExpStrLen, uint8_t bFillChar);
/*****************************************************************************
* Exposed Logging APIs
*****************************************************************************/
/// Logs a new line
void Util_NewLine(uint32_t PdwUartPort);
/// Logs a string with newline at the end
void Util_LogStringLine(uint32_t PdwUartPort, const char_t *pszString);
/// Logs a string
void Util_LogString(uint32_t PdwUartPort, const char_t *pszString);
//Logs Integer
void Util_LogInt(uint32_t PdwUartPort, const char_t *pszMsg, uint32_t dwValue);
/// Logs a byte array
void Util_LogArray(uint8_t* prgbBuf, uint16_t wLen, bool_t fDirection, bool_t fDumpPacketAnalysis);
/// Print an array in hex format
void Util_DumpHex(uint8_t* prgbBuf, uint16_t wLen);
//Print on console port with new line
#define CONSOLE_LOGSTRINGLINE(pszString) Util_LogStringLine(CONSOLE_PORT,pszString);
//Print on console port
#define CONSOLE_LOGSTRING(pszString) Util_LogString(CONSOLE_PORT,pszString);
//Print on console port
#define CONSOLE_LOGINTEGER(pszString,value) Util_LogInt(CONSOLE_PORT,pszString,value);
//Print on Cunit port
#define CUNIT_LOGSTRING(pszString) Util_LogString(CUNIT_PORT,pszString);
//Print on coverage port
#define COVERAGE_LOGSTRING(pszString,dwLen) pfWriter(CODE_COVERAGE_PORT,pszString,dwLen);
/*****************************************************************************
* Level based logging Exposed APIs
*****************************************************************************/
/// @endcond
/**
* \brief Structure to Logger.
*/
typedef struct sLogger_d
{
///Handle to instance of writer
uint32_t* pHdl;
///Log Writer
hdl_t phfWriter;//This to be replaced by actual type
}sLogger_d;
#ifdef ENABLE_LOG
//This is second write
typedef int32_t (*pFWriteData2)(void* Hdl, uint8_t* PprgbBuf, uint32_t PdwDataLen);
//This is the arguement to be passed to pfWriter.It refers to the handle to writer context/structure.
extern void* pHandle;
//This is second log writer
extern pFWriteData2 pfWriter2;
///Delimiter to indicate "Seperator Open"
#define DELIMITER_OPEN "["
///Delimiter to indicate "Seperator Close"
#define DELIMITER_CLOSE "]"
///Format to print time as [hh:mm:ss][level][type] :message newline
#define LOG_FORMAT "[%s]%-4s%-2s:%s%s"
///Log message Level
///This indicates message is an Information
#define LOGGER_LEVEL_INFO DELIMITER_OPEN"Info"DELIMITER_CLOSE
///This indicates message is a Warning
#define LOGGER_LEVEL_WARNING DELIMITER_OPEN"Warn"DELIMITER_CLOSE
///This indicates message is an Error
#define LOGGER_LEVEL_ERROR DELIMITER_OPEN"Erro"DELIMITER_CLOSE
///Log message Type
///This indicates message is logged from Handshake Layer
#define LOGGER_TYPE_HANDSHAKE DELIMITER_OPEN"HS"DELIMITER_CLOSE
///This indicates message is logged from Record Layer
#define LOGGER_TYPE_RECORDLAYER DELIMITER_OPEN"RL"DELIMITER_CLOSE
///This indicates message is logged from Transport Layer
#define LOGGER_TYPE_TRANSPORTLAYER DELIMITER_OPEN"TL"DELIMITER_CLOSE
/**
* \brief This structure represents Log Level Types
*/
typedef enum eLogLevel {
///Information
eInfo = 1,
///Warning
eWarning = 2,
///Error
eError = 3,
}eLogLevel;
/**
* \brief This structure represents Log Layer Types
*/
typedef enum eLogLayer {
///Handshake
eHS = 1,
///Record
eRL = 2,
///Transport
eTL = 3,
}eLogLayer;
/**
* \brief This structure contains state of logging
*/
typedef enum eSetState {
///Enable Logging
eEnable = 0x01,
///Disable Logging
eDisable = 0x02,
//Invalid
eInvalid = 0xFF
}eSetState;
/**
* \brief Returns the current state of Logging level.
*/
eSetState Util_GetLogLevelState(eLogLevel level);
/**
* \brief Sets the state of the Logging Level.
*/
void Util_SetLogLevelState(eLogLevel type,eSetState value);
/**
* \brief Returns the current state of the Logging Layer.
*/
eSetState Util_GetLogLayerState(eLogLayer layer);
/**
* \brief Sets the state of the Logging Layer.
*/
void Util_SetLogLayerState(eLogLayer layer,eSetState value);
/**
* \brief Sets the Log Writer and handle.
*/
void Util_SetLogWriter(pFWriteData2 writer,void* pHdl);
/**
* \brief Logs a message with type and level information.
*/
void Util_LogMessage(char* message, eLogLayer layer, eLogLevel level);
/**
* \brief Logs a 4 byte debug value with type and level information.
*/
void Util_LogDebugVal(uint32_t dwDBValue, eLogLayer layer, eLogLevel level);
/**
* \brief Logs a message with type,level information and also the content of the buffer.
*/
void Util_LogMsgArray(char* pzMsg, uint8_t* PrgbBuffer, uint16_t wLen, eLogLayer eLayer, eLogLevel eLevel);
#endif
///Define ENABLE_LOG to enable logging
#ifdef ENABLE_LOG
///Disable Layer during runtime
#define DISABLE_LOGGING_LAYER(layer) Util_SetLogLayerState(layer,eDisable)
///Enable Layer during runtime
#define ENABLE_LOGGING_LAYER(layer) Util_SetLogLayerState(layer,eEnable)
///Get Layer State
#define GET_LOGGING_LAYER(layer) Util_GetLogLayerState(layer)
///Disable Level during runtime
#define DISABLE_LOGGING_LEVEL(level) Util_SetLogLevelState(level,eDisable)
///Enable Level during runtime
#define ENABLE_LOGGING_LEVEL(level) Util_SetLogLevelState(level,eEnable)
///Get Level State
#define GET_LOGGING_LEVEL(level) Util_GetLogLevelState(level)
#else
/// @cond hidden
#define DISABLE_LOGGING_LAYER(layer)
#define ENABLE_LOGGING_LAYER(layer)
#define GET_LOGGING_LAYER(layer)
#define DISABLE_LOGGING_LEVEL(level)
#define ENABLE_LOGGING_LEVEL(level)
#define GET_LOGGING_LEVEL(level)
/// @endcond
#endif
/// @cond hidden
#ifdef _OCPDEBUG_WIN32
#define DEBUG_PRINT(msg) printf("%s",msg);
#else
#define DEBUG_PRINT(msg)
#endif
/// @endcond
///Define ENABLE_LOG and ENABLE_HANDSHAKETYPE to enable Handshake layer logging.
///ENABLE_LOG enable logs at top level and logging will not wok if not defined.
#if !defined ENABLE_HANDSHAKETYPE || !defined ENABLE_LOG
/// @cond hidden
#define LOG_HANDSHAKEMSG(msg,level) DEBUG_PRINT("HANDSHAKETYPE Undefined\n")
#define LOG_HANDSHAKEDBVAL(val,level) DEBUG_PRINT("HANDSHAKETYPE Undefined\n")
/// @endcond
#else
///Log Handshake Message
#define LOG_HANDSHAKEMSG(msg,level) \
{ \
if(eEnable==Util_GetLogLayerState(eHS)) \
Util_LogMessage(msg,eHS,level); \
else{DEBUG_PRINT("Handshake Layer Disabled\n");} \
}
///Logs Handshake layer 4 byte debug value
#define LOG_HANDSHAKEDBVAL(val,level) \
{ \
if(eEnable==Util_GetLogLayerState(eHS)) \
Util_LogDebugVal(val,eHS,level); \
else{DEBUG_PRINT("Handshake Layer Disabled\n");} \
}
#endif
///Define ENABLE_LOG and ENABLE_RECORDLAYERTYPE to enable Record layer logging.
///ENABLE_LOG enable logs at top level and logging will not wok if not defined.
#if !defined ENABLE_RECORDLAYERTYPE || !defined ENABLE_LOG
/// @cond hidden
#define LOG_RECORDLAYERMSG(msg,level) DEBUG_PRINT("RECORDLAYERTYPE Undefined\n")
#define LOG_RECORDLAYERDBVAL(val,level) DEBUG_PRINT("RECORDLAYERTYPE Undefined\n")
/// @endcond
#else
///Log Record Header Message
#define LOG_RECORDLAYERMSG(msg,level) \
{ \
if(eEnable==Util_GetLogLayerState(eRL)) \
Util_LogMessage(msg,eRL,level); \
else{DEBUG_PRINT("Record Layer Disabled\n");} \
}
///Logs record layer 4 byte debug value
#define LOG_RECORDLAYERDBVAL(val,level) \
{ \
if(eEnable==Util_GetLogLayerState(eRL)) \
Util_LogDebugVal(val,eRL,level); \
else{DEBUG_PRINT("Record Layer Disabled\n");} \
}
#endif
///Define ENABLE_LOG and ENABLE_TRANSPORTTYPE to enable Transport Layer logging.
///ENABLE_LOG enable logs at top level and logging will not wok if not defined.
#if !defined ENABLE_TRANSPORTTYPE || !defined ENABLE_LOG
/// @cond hidden
#define LOG_TRANSPORTMSG(msg,level) DEBUG_PRINT("TRANSPORTTYPE Undefined\n")
#define LOG_TRANSPORTDBVAL(val,level) DEBUG_PRINT("TRANSPORTTYPE Undefined\n")
#define LOG_TRANSPORTDBARY(Msg, buffer, wLen, level) DEBUG_PRINT("TRANSPORTTYPE Undefined\n")
/// @endcond
#else
///Log Transport layer Message
#define LOG_TRANSPORTMSG(msg,level) \
{ \
if(eEnable==Util_GetLogLayerState(eTL)) \
Util_LogMessage(msg,eTL,level); \
else{DEBUG_PRINT("Transport Layer Disabled\n");} \
}
///Logs Transport layer 4 byte debug value
#define LOG_TRANSPORTDBVAL(val,level) \
{ \
if(eEnable==Util_GetLogLayerState(eTL)) \
Util_LogDebugVal(val,eTL,level); \
else{DEBUG_PRINT("Transport Layer Disabled\n");} \
}
///Logs Transport layer Array value
#define LOG_TRANSPORTDBARY(Msg, buffer, wLen, level) \
{ \
if(eEnable==Util_GetLogLayerState(eTL)) \
Util_LogMsgArray(Msg, buffer, wLen, eTL, level); \
else{DEBUG_PRINT("Transport Layer Disabled\n");} \
}
#endif
#ifdef ENABLE_LOG
///Enable the logger handle
#define LOG_SETWRITER(writer,hdl) Util_SetLogWriter((pFWriteData2)writer,hdl);
#else
/// @cond hidden
#define LOG_SETWRITER(writer,hdl) DEBUG_PRINT("Logger is Disabled\n")
/// @endcond
#endif
#endif //__LOGGER_H__
/**
* @}
*/

View File

@@ -0,0 +1,53 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file
*
* \brief This file defines the memory management related macros.
*
*
* \addtogroup grMutualAuth
*
*/
#ifndef _MEMMGMT_H_
#define _MEMMGMT_H_
///Malloc function to allocate the heap memory
#define OCP_MALLOC(size) malloc(size)
///Malloc function to allocate the heap memory
#define OCP_CALLOC(block,blocksize) calloc(block,blocksize)
///To free the allocated memory
#define OCP_FREE(node) free(node)
///To copy the data from source to destination
#define OCP_MEMCPY(dst,src,size) memcpy(dst,src,size)
///To copy the data from source to destination
#define OCP_MEMSET(src,val,size) memset(src,val,size)
#endif /* _MEMMGMT_H_ */

View File

@@ -0,0 +1,153 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file
*
* \brief This file contains utility functions
*
*
*
*/
#ifndef _UTIL_H_
#define _UTIL_H_
#include "optiga/common/Datatypes.h"
///Greater than
#define GREATER_THAN 0x00000001
///Lesser than
#define LESSER_THAN 0x00000002
///Equal
#define EQUAL 0x00000000
/// Default Low bound value value
#define DEFAULT_LOWBOUND_DOUBLEWORD 0x00000000
/// Mask double word value
#define MASK_DOUBLE_WORD 0xFFFFFFFF
///Word bit size
#define WORD_SIZE 32
///Successful Execution
#define UTIL_SUCCESS 0x00000000
///Execution Failure
#define UTIL_ERROR 0xFFFFFFFF
///Least significant bit set to high
#define LEAST_SIGNIFICANT_BIT_HIGH 0x00000001
///Least significant bit set to high
#define MOST_SIGNIFICANT_BIT_HIGH 0x80000000
/**
* \brief structure to store the record sequence number
*/
typedef struct sUint64
{
///Higher 32 bit of the record sequence number
uint32_t dwHigherByte;
///Lower 32 bit of the record sequence number
uint32_t dwLowerByte;
}sUint64;
/**
* \brief The function compares two uint64 data type.<br>
*/
int32_t CompareUint64(const sUint64 *PpsSrc1, const sUint64 *PpsSrc2);
/**
* \brief Calculates the difference between the two uint64 data.<br>
*/
int32_t SubtractUint64(const sUint64 *PpsMinuend, const sUint64 *PpsSubtrahend,sUint64 *PpsDifference);
/**
* \brief Adds two uint64 data.<br>
*/
int32_t AddUint64(const sUint64 *PpsSrc1, const sUint64 *PpsSrc2,sUint64 *PpsDest);
/**
* \brief Increments uint64 data.<br>
*/
int32_t IncrementUint64(sUint64 *PpsSrc1);
/**
* \brief Converts byte array to uint64.<br>
*/
int32_t GetUint64(sUint64 *PpsOut,const uint8_t* pbVal,uint16_t wLen);
/**
* \brief To Slide the window by shift count.<br>
*/
int32_t ShiftLeftUint64(sUint64 *PpsWindow, sUint64 PsShiftCount, uint8_t PWindowSize, uint8_t PbMaxWindowSize);
/**
* \brief To set a bit in the sUnit64 data.<br>
*/
int32_t Utility_SetBitUint64(sUint64* PprgbData, uint8_t bWindowSize, uint8_t bBitPosition);
/**
* \brief Prepares uint16 [Big endian] type value from the buffer.<br>
*/
uint16_t Utility_GetUint16 (const uint8_t* PprgbData);
/**
* \brief Prepares uint32 [Big endian] type value from the buffer .<br>
*/
uint32_t Utility_GetUint32 (const uint8_t* PprgbData);
/**
* \brief Copies 2 bytes of uint16 type value to the buffer<br>
*/
void Utility_SetUint16 (puint8_t PprgbData,uint16_t PwValue);
/**
* \brief Prepares uint24 [Big endian] type value from the buffer .<br>
*/
uint32_t Utility_GetUint24 (const uint8_t* PprgbData);
/**
* \brief Copies LSB 3 bytes of uint32 [Big endian] type value to the buffer and store.<br>
*/
void Utility_SetUint24 (uint8_t* PprgbData,uint32_t Pdwvalue);
/**
* \brief Copies LSB 4 bytes of uint32 [Big endian] type value to the buffer and store.<br>
*/
void Utility_SetUint32 (uint8_t* PprgbData,uint32_t Pdwvalue);
/**
* \brief Copies the data from source buffer to destination buffer.<br>
*/
void Utility_Memmove(puint8_t PprgbDestBuf, const puint8_t PprgbSrcBuf, uint16_t PwLength);
#endif //_UTIL_H_

View File

@@ -0,0 +1,104 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file
*
* \brief This file implements optiga comms abstraction layer for IFX I2C Protocol.
*
* \addtogroup grOptigaComms
* @{
*/
#ifndef _OPTIGA_COMMS_H_
#define _OPTIGA_COMMS_H_
/**********************************************************************************************************************
* HEADER FILES
*********************************************************************************************************************/
#include "optiga/common/Datatypes.h"
/**********************************************************************************************************************
* MACROS
*********************************************************************************************************************/
/// Succesfull execution
#define OPTIGA_COMMS_SUCCESS 0x0000
/// Error in execution
#define OPTIGA_COMMS_ERROR 0x0001
/// Busy, doing operation
#define OPTIGA_COMMS_BUSY 0x0002
/**********************************************************************************************************************
* DATA STRUCTURES
*********************************************************************************************************************/
/** @brief optiga comms structure */
typedef struct optiga_comms
{
/// Comms structure pointer
void* comms_ctx;
/// Upper layer contect
void* upper_layer_ctx;
/// Upper layer handler
app_event_handler_t upper_layer_handler;
/// Optiga comms state
uint8_t state;
}optiga_comms_t;
extern optiga_comms_t optiga_comms;
/**********************************************************************************************************************
* API Prototypes
*********************************************************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Opens the communication channel with OPTIGA.
*/
LIBRARY_EXPORTS host_lib_status_t optiga_comms_open(optiga_comms_t *p_ctx);
/**
* \brief Resets the OPTIGA.
*/
LIBRARY_EXPORTS host_lib_status_t optiga_comms_reset(optiga_comms_t *p_ctx,uint8_t reset_type);
/**
* \brief Sends and receives the APDU.
*/
LIBRARY_EXPORTS host_lib_status_t optiga_comms_transceive(optiga_comms_t *p_ctx,const uint8_t* p_data,
const uint16_t* p_data_length,
uint8_t* p_buffer, uint16_t* p_buffer_len);
/**
* \brief Closes the communication channel with OPTIGA.
*/
LIBRARY_EXPORTS host_lib_status_t optiga_comms_close(optiga_comms_t *p_ctx);
/**
* @}
*/
#endif /*_OPTIGA_COMMS_H_*/

View File

@@ -0,0 +1,88 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file AlertProtocol.h
*
* \brief This file defines APIs, types and data structures used in the
* (D)TLS Alert implementation.
*
* \addtogroup grMutualAuth
* @{
*/
#ifndef __ALERT_H__
#define __ALERT_H__
#include "optiga/dtls/OcpCommon.h"
#include "optiga/dtls/OcpCommonIncludes.h"
#ifdef MODULE_ENABLE_DTLS_MUTUAL_AUTH
/****************************************************************************
*
* API Error Codes
*
****************************************************************************/
/// Successful execution
#define OCP_AL_OK 0x74281527
/// Failure in execution
#define OCP_AL_ERROR 0xFC468021
///Null Parameter(s)
#define OCP_AL_NULL_PARAM BASE_ERROR_ALERT
///Length of input is zero
#define OCP_AL_LENZERO_ERROR (BASE_ERROR_ALERT + 1)
///Fatal error
#define OCP_AL_FATAL_ERROR (BASE_ERROR_ALERT + 2)
///Warning error
#define OCP_AL_WARNING_ERROR (BASE_ERROR_ALERT + 3)
/**
* \brief Process the Alert Messages.
*/
int32_t Alert_ProcessMsg(const sbBlob_d* PpsAlertMsg,int32_t* Ppi4ErrorCode);
/**
* \brief Sends Alert based on the internal error code via the Record Layer.
*/
void Alert_Send(sConfigRL_d *PpsConfigRL,int32_t Pi4ErrorCode);
///Macro to Send Alert
#ifndef DISABLE_ALERT
#define SEND_ALERT(RLHdl,error) Alert_Send(RLHdl,error);
#else
#define SEND_ALERT(RLHdl,error)
#endif
#endif /* MODULE_ENABLE_DTLS_MUTUAL_AUTH */
#endif //__ALERT_H__
/**
* @}
*/

View File

@@ -0,0 +1,93 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file
*
* \brief This file defines the error code layering.
*
* \addtogroup grMutualAuth
* @{
*/
#ifndef _BASEERRORCODE_H_
#define _BASEERRORCODE_H_
/*
The following defines the Error code layering for a 4 byte error code.
Each byte is represented as XX, where X being a single nibble.
|8X|XX|XX|XX|
| | | |---->Error Codes
| | |------->Layer
| |---------->Unused
|------------->80
*/
/// Base Error Code
#define ERROR_CODE_BASE 0x80000000
///Base Error code for Comms
#define BASE_ERROR_COMMS (ERROR_CODE_BASE | 0x00000000)
///Base Error code for Command Lib
#define BASE_ERROR_CMDLIB (ERROR_CODE_BASE | 0x00000100)
///Base Error code for Integration Lib
#define BASE_ERROR_INTLIB (ERROR_CODE_BASE | 0x00000200)
///Base Error code for Crypto Lib
#define BASE_ERROR_CRYPTOLIB (ERROR_CODE_BASE | 0x00000300)
///Base Error code for Alert
#define BASE_ERROR_ALERT (ERROR_CODE_BASE | 0x00000500)
///Base Error code for Handshake Layer
#define BASE_ERROR_HANDSHAKELAYER (ERROR_CODE_BASE | 0x00000600)
///Base Error code for Transport Layer
#define BASE_ERROR_TRANSPORTLAYER (ERROR_CODE_BASE | 0x00000700)
///Base Error code for OCP
#define BASE_ERROR_OCPLAYER (ERROR_CODE_BASE | 0x00000800)
///Base Error code for Record Layer
#define BASE_ERROR_RECORDLAYER (ERROR_CODE_BASE | 0x00000900)
///Base Error code for Windowing
#define BASE_ERROR_WINDOW (ERROR_CODE_BASE | 0x00000A00)
///Base Error code for Message Layer
#define BASE_ERROR_MESSAGELAYER (ERROR_CODE_BASE | 0x00000B00)
///Base Error code for Flight Handler
#define BASE_ERROR_FLIGHT (ERROR_CODE_BASE | 0x00000C00)
///Base Error code for Crypto Layer
#define BASE_ERROR_CRYPTO_LAYER (ERROR_CODE_BASE | 0x00000D00)
///Base Error code UDP
#define BASE_ERROR_UDP (ERROR_CODE_BASE | 0x00000E00)
#endif //_BASEERRORCODE_H_
/**
* @}
*/

View File

@@ -0,0 +1,199 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file DtlsFlighthandler.h
*
* \brief This file defines APIs, types and data structures used in the
* DTLS Flight handlers implementation.
*
* \addtogroup grMutualAuth
* @{
*/
#ifndef __DTLSFH_H__
#define __DTLSFH_H__
#include "optiga/dtls/MessageLayer.h"
#include "optiga/dtls/DtlsHandshakeProtocol.h"
#include "optiga/dtls/AlertProtocol.h"
#include "optiga/optiga_dtls.h"
#include "optiga/dtls/DtlsRecordLayer.h"
#ifdef MODULE_ENABLE_DTLS_MUTUAL_AUTH
/// @cond hidden
#define DEV_ERROR_CODE_MASK 0xFFFFFF00
#define DEV_ERROR_LSBCODE_MASK 0xFF
/// @endcond
/****************************************************************************
*
* API Error Codes
*
****************************************************************************/
/// Successful execution
#define OCP_FL_OK 0x7569412
/// Failure in execution
#define OCP_FL_ERROR 0xF4358417
///Null Parameter(s)
#define OCP_FL_NULL_PARAM BASE_ERROR_FLIGHT
///Flight not listed
#define OCP_FL_NOT_LISTED (OCP_FL_NULL_PARAM + 1)
///State of Flight is old
#define OCP_FL_STATE_OLD (OCP_FL_NULL_PARAM + 2)
///Message with invalid sequence number
#define OCP_FL_INVALID_MSG_SEQNUM (OCP_FL_NULL_PARAM + 3)
///Message doesn't belong to a flight
#define OCP_FL_MSG_NOT_IN_FLIGHT (OCP_FL_NULL_PARAM + 4)
///Message sequence number is not in expected sequence
#define OCP_FL_MSG_OPT_MSG_ERROR (OCP_FL_NULL_PARAM + 5)
///Message received again
#define OCP_MSG_RXAGAIN (OCP_FL_NULL_PARAM + 6)
///Flight messages being received
#define OCP_FL_RXING (OCP_FL_NULL_PARAM + 7)
///Flight processing is past the current flight
#define OCP_FL_DONE (OCP_FL_NULL_PARAM + 8)
///Node for a message is not available in the list
#define OCP_FL_MSG_NODE_NOT_AVAIL (OCP_FL_NULL_PARAM + 9)
///Node for a message is available in the list
#define OCP_FL_MSG_NODE_AVAIL (OCP_FL_NULL_PARAM + 10)
///Message is completely received
#define OCP_FL_MSG_RECEIVED (OCP_FL_NULL_PARAM + 11)
///Message completion check error
#define OCP_FL_MSG_ERROR (OCP_FL_NULL_PARAM + 12)
///Malloc failure
#define OCP_FL_MALLOC_FAILURE (OCP_FL_NULL_PARAM + 13)
///Message sending to Security chip failed
#define OCP_FL_SEND_MSG_TO_OPTIGA_ERROR (OCP_FL_NULL_PARAM + 14)
///Sending message to server failed
#define OCP_FL_FLIGHTSEND_ERROR (OCP_FL_NULL_PARAM + 15)
///Getting a message from Security chip failed
#define OCP_FL_GET_MSG_FROM_OPTIGA_ERROR (OCP_FL_NULL_PARAM + 16)
///Message Incomplete error
#define OCP_FL_MSG_INCOMPLETE (OCP_FL_NULL_PARAM + 17)
///Message with invalid length
#define OCP_FL_INVALID_MSG_LENGTH (OCP_FL_NULL_PARAM + 18)
///Message received is more than max count
#define OCP_FL_MSG_MAXCOUNT (OCP_FL_NULL_PARAM + 19)
///Message with invalid sequence
#define OCP_FL_INVALID_MSG_SEQ (OCP_FL_NULL_PARAM + 20)
///Message with invalid LENGTH
#define OCP_FL_INVALID_PROCFLIGHT (OCP_FL_NULL_PARAM + 21)
///Message with invalid message type
#define OCP_FL_MSG_NOT_LISTED (OCP_FL_NULL_PARAM + 22)
///Message to be ignored
#define OCP_FL_MSG_IGNORE (OCP_FL_NULL_PARAM + 23)
///Internal Error
#define OCP_FL_INT_ERROR (OCP_FL_NULL_PARAM + 24)
///Invalid Handshake Error
#define OCP_FL_HS_ERROR (OCP_FL_NULL_PARAM + 25)
/**
* \brief Checks whether the received message belongs to the expected flight.<br>
*/
int32_t DtlsHS_MsgCheck(uint8_t PbLastProcFlight, const sbBlob_d* PpsBlobMessage, const sMsgLyr_d* PpsMessageLayer);
/**
* \brief Initializes flight node.
*/
int32_t DtlsHS_FlightNodeInit(sFlightDetails_d* PpsFlightNode, uint8_t PbLastProcFlight);
/**
* \brief Gets the Flight type for the corresponding message type.<br>
*/
int32_t DtlsHS_GetFlightID(uint8_t PbMsgType, uint8_t* PpFlightID);
/**
* \brief Searches the look-up table and returns the message descriptors of a flight.<br>
*/
void DtlsHS_GetFlightMsgInfo(uint8_t PeFlightID, uint16_t** PpwMessageList);
/**
* \brief Validates the sequence number of message/ fragment received of flight 2.<br>
*/
int32_t DtlsHS_Flight2CheckMsgSeqNum(uint8_t PbRxMsgID, uint16_t PwRxMsgSeqNum, const sMsgInfo_d *PpsMessageList);
/**
* \brief Flight one handler to process flight 1 messages.
*/
int32_t DtlsHS_Flight1Handler(uint8_t PbLastProcFlight, sFlightStats_d* PpThisFlight, sMsgLyr_d* PpsMessageLayer);
/**
* \brief Flight two handler to process flight 2 messages.
*/
int32_t DtlsHS_Flight2Handler(uint8_t PbLastProcFlight, sFlightStats_d* PpThisFlight, sMsgLyr_d* PpsMessageLayer);
/**
* \brief Flight three handler to process flight 3 messages.
*/
int32_t DtlsHS_Flight3Handler(uint8_t PbLastProcFlight, sFlightStats_d* PpThisFlight, sMsgLyr_d* PpsMessageLayer);
/**
* \brief Flight four handler to process flight 4 messages.
*/
int32_t DtlsHS_Flight4Handler(uint8_t PbLastProcFlight, sFlightStats_d* PpThisFlight, sMsgLyr_d* PpsMessageLayer);
/**
* \brief Flight five handler to process flight 5 messages.
*/
int32_t DtlsHS_Flight5Handler(uint8_t PbLastProcFlight, sFlightStats_d* PpThisFlight, sMsgLyr_d* PpsMessageLayer);
/**
* \brief Flight six handler to process flight 6 messages.
*/
int32_t DtlsHS_Flight6Handler(uint8_t PbLastProcFlight, sFlightStats_d* PpThisFlight, sMsgLyr_d* PpsMessageLayer);
#endif /* MODULE_ENABLE_DTLS_MUTUAL_AUTH*/
#endif //__DTLSFH_H__
/**
* @}
*/

View File

@@ -0,0 +1,364 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file
*
* \brief This file defines APIs, types and data structures used in the
* DTLS Handshake protocol.
*
* \addtogroup grMutualAuth
* @{
*/
#ifndef __DTLSHS_H__
#define __DTLSHS_H__
#include "optiga/common/Util.h"
#include "optiga/dtls/OcpCommon.h"
#include "optiga/dtls/MessageLayer.h"
#ifdef MODULE_ENABLE_DTLS_MUTUAL_AUTH
/****************************************************************************
*
* API Error Codes
*
****************************************************************************/
///Invalid Fragment size
#define OCP_HL_INVALID_FRAGMENT_SIZE (BASE_ERROR_HANDSHAKELAYER + 2)
///Invalid Current offset
#define OCP_HL_INVALID_OFFSET_LEN (BASE_ERROR_HANDSHAKELAYER + 3)
///Insufficient memory
#define OCP_HL_INSUFFICIENT_MEMORY (BASE_ERROR_HANDSHAKELAYER + 4)
///Invalid Length
#define OCP_HL_INVALID_LENGTH (BASE_ERROR_HANDSHAKELAYER + 5)
///Fragment Length mismatch
#define OCP_HL_LEN_MISMATCH (BASE_ERROR_HANDSHAKELAYER + 6)
///Total Length mismatch
#define OCP_HL_TOTALLEN_MISMATCH (BASE_ERROR_HANDSHAKELAYER + 7)
///Invalid message type
#define OCP_HL_INVALID_MSGTYPE (BASE_ERROR_HANDSHAKELAYER + 8)
///Previous flight message received
#define OCP_HL_RETRANSMISSION (BASE_ERROR_HANDSHAKELAYER + 9)
///Future flight message received
#define OCP_HL_CONTINUE (BASE_ERROR_HANDSHAKELAYER + 10)
///Future flight message received
#define OCP_HL_TIMEOUT (BASE_ERROR_HANDSHAKELAYER + 11)
///Malloc failure
#define OCP_HL_MALLOC_FAILURE (BASE_ERROR_HANDSHAKELAYER + 12)
///Ignore the Record
#define OCP_HL_IGNORE_RECORD (BASE_ERROR_HANDSHAKELAYER + 13)
///Buffer overflow
#define OCP_HL_BUFFER_OVERFLOW (BASE_ERROR_HANDSHAKELAYER + 14)
///Invalid sequence
#define OCP_HL_INVALID_SEQUENCE (BASE_ERROR_HANDSHAKELAYER + 15)
///Invalid Hello request message
#define OCP_HL_INVALID_HRMSG (BASE_ERROR_HANDSHAKELAYER + 16)
/****************************************************************************
*
* Common data structure used across all functions.
*
****************************************************************************/
///Maximum value of message type
#define MAX_MSG_TYPE_VALUE 20
/**
* \brief Structure to hold fragmentation data
*/
typedef struct sFragmentMsg_d
{
///Complete Message
sbBlob_d* psCompleteMsg;
///Fragment Size
uint16_t wFragmentSize;
///Message fragment
sbBlob_d* psMsgFrag;
///Current offset in complete message
uint16_t wCurrentOffset;
///Remaining length to be fragmented
uint16_t wRemainingLen;
}sFragmentMsg_d;
/**
* \brief Structure to hold header information
*/
typedef struct sMsgHeader_d
{
///Specifies message type
uint8_t bMsgType;
///Total length of the handshake message
uint32_t dwTotalLength;
///Message sequence
uint16_t wMsgSequence;
///Specifies the offset of fragment data in actual message
uint32_t dwFragmentOffset;
///Message fragment
uint32_t dwFragmentLength;
///Flight to which the message belongs
eFlight_d eFlight;
///Indicate memory is already Allocated
bool_t fMemoryAllocated;
}sMsgHeader_d;
/**
* \brief Status of Message in the buffer
*/
typedef enum eMsgState_d
{
///Message is partial
ePartial = 0x01,
///Message is complete
eComplete = 0x02,
//Message is processed/returned
eProcessed = 0x03,
//Message receiving again
eReReceiving = 0x04
}eMsgState_d;
/**
* \brief Enum values for server message type
*/
typedef enum eServerMessage_d
{
//Server Side Message type
///Server Hello message
eServer_Hello = 2,
///Hello Verify Request
eHello_Verify_Request = 3,
///Server request message
eServer_Certificate = 11,
///Server key Exchange
eServer_Key_Exchange = 12,
///Certificate request message
eServer_Certificate_Request = 13,
///Server hello done message
eServer_Hello_Done = 14,
///Server finished message
eServer_Finished = 20
}eServerMessage_d;
/**
* \brief This structure maps message type to the flight number
*/
typedef struct sFlightMapTable_d
{
///Message type
uint8_t bMsgType;
///Flight number
eFlight_d FlightNum;
}sFlightMapTable_d;
/// MAcro to update the flight or message state
#define UPDATE_FSTATE(X,Y) (X=Y)
/**
* \brief Structure to hold message fragment in buffer
*/
typedef struct sMsg_d
{
///Message type
uint8_t bMsgType;
///Message sequence
uint16_t wMsgSequence;
///Complete Message Holder
uint8_t* psMsgHolder;
//Message Length
uint32_t dwMsgLength;
//Fragments info
uint8_t* psMsgMapPtr;
///State of the Message
eMsgState_d eMsgState;
///Max Msg reception count
uint8_t bMsgCount;
///Pointer to next message
struct sMsg_d* psNext;
}sMsgInfo_d;
/**
* \brief Flight States
*/
typedef enum eFlightState_d
{
///Initialize state where flight node is created
efInit = 0,
///State where message will be receiving or sent to/from Host
efReady,
///State where flight is completely received and buffered
efReceived,
///State where flight is received again
efReReceive,
///Message is processed by security chip
efProcessed,
///Message is formed by security chip and sent out
efTransmitted,
///Message is retransmitted
efReTransmit,
///Completion of flight handling
efDone
}eFlightState_d;
/**
* \brief Enum values for message type in the flight
*/
typedef enum eOptionalFlag_d
{
///Mandatory message in the flight
eMandatory = 0,
///Optional message in the flight
eOptional = 1,
}eOptionalFlag_d;
/**
* \brief Structure to hold the Flight status
*/
typedef struct sFlightStats_d
{
///Current Flight state
uint8_t bFlightState;
///Pointer to structure #sMsgInfo_d
sMsgInfo_d *psMessageList;
}sFlightStats_d;
/**
* \brief Structure to hold the information required for Message Layer.
*/
typedef struct sMsgLyr_d
{
///Optional Message List
uint8_t rgbOptMsgList[5];
///(D)TLS Session ID
uint16_t wSessionID;
///Maximum PMTU
uint16_t wMaxPmtu;
///Receive Message Sequence Number
uint32_t dwRMsgSeqNum;
///Record Layer
sConfigRL_d* psConfigRL;
///Certificate Type used for Authentication
uint16_t wOIDDevCertificate;
///Callback function pointer to get unixtime
fGetUnixTime_d pfGetUnixTIme;
///Message/Fragment
sbBlob_d sMsg;
///Message/Fragment from the transport layer
sbBlob_d sTLMsg;
///Flight received
eFlight_d eFlight;
} sMsgLyr_d;
///Macro to check for mandatory message
#define IsMandatory(x) ((x & 0xFF00) ? 0: 1)
///Macro to check for optional message
#define IsOptional(x) ((x & 0xFF00) ? 1: 0)
///Macro to get the Flight number
#define FLIGHTID(x) (x & 0xFF)
/**
* \brief Flight handler function pointer
*/
typedef int32_t (*fFlightHandler)(uint8_t PbLastProcFlight, sFlightStats_d* PpThisFlight, sMsgLyr_d* PpsMessageLayer);
/**
* \brief DTLS Spec reference table
*/
typedef struct sFlightTable_d
{
///Lower byte - Flight ID, Upper byte - eOptional/ eMandatory
uint16_t wFlightDesc;
///Lower byte - Message ID, Upper byte - eOptional/ eMandatory
uint16_t wMsgTypes[6];
/// Flight Handler
fFlightHandler pFlightHndlr;
}sFlightTable_d;
/**
* \brief Structure to hold information of a Flight
*/
typedef struct sFlightDetails_d
{
///Flight Descriptor
uint16_t wFlightDecp;
///Flight handler
fFlightHandler pFlightHndlr;
///Structure containing flight status
sFlightStats_d sFlightStats;
///Pointer to the next flight node
struct sFlightDetails_d* psNext;
}sFlightDetails_d;
///Table to map number of msg in a send flight and its flight handler
extern const sFlightTable_d rgsSFlightInfo[];
///Table to map number of msg in a send flight and its flight handler
extern const sFlightTable_d rgsRFlightInfo[];
/****************************************************************************
*
* Definitions related to (D)TLS commands.
*
****************************************************************************/
/**
* \brief Prepares Handshake message header
*/
int32_t DtlsHS_PrepareMsgHeader(uint8_t* PpbMsgHeader, const sMsgInfo_d *sMsgInfo);
/**
* \brief Performs (D)TLS handshake
*/
int32_t DtlsHS_Handshake(sHandshake_d* PphHandshake);
/**
* \brief Sends a message to the server.
*/
int32_t DtlsHS_FSendMessage(const sMsgInfo_d* PpsMsgPtr, const sMsgLyr_d* PpsMessageLayer);
/**
* \brief Process and validates Handshake message header.<br>
*/
int32_t DtlsHS_ProcHeader(sbBlob_d PsBlobMessage);
#endif /* MODULE_ENABLE_DTLS_MUTUAL_AUTH*/
#endif //__DTLSHS_H__
/**
* @}
*/

View File

@@ -0,0 +1,204 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file DtlsRecordLayer.h
*
* \brief This file contains structures and prototypes of record layer functionalities for DTLS.
* \addtogroup grOCP
* @{
*
*/
#ifndef __DTLSRECORDLAYER_H__
#define __DTLSRECORDLAYER_H__
#include "optiga/dtls/DtlsWindowing.h"
#include "optiga/dtls/OcpRecordLayer.h"
#include "optiga/dtls/MessageLayer.h"
#include "optiga/dtls/OcpCommonIncludes.h"
#ifdef MODULE_ENABLE_DTLS_MUTUAL_AUTH
///Failure in execution and record already received
#define OCP_RL_WINDOW_IGNORE BASE_ERROR_WINDOW
///Valid record is received and window is updated and moved
#define OCP_RL_WINDOW_UPDATED (BASE_ERROR_WINDOW + 1)
///Valid record is received and window is updated
#define OCP_RL_WINDOW_MOVED (BASE_ERROR_WINDOW + 2)
///Window overflow
#define OCP_RL_SEQUENCE_OVERFLOW (BASE_ERROR_WINDOW + 3)
///Encryption/Decryption enabled flag
#define ENC_DEC_ENABLED 0xB5
///Encryption/Decryption disabled flag
#define ENC_DEC_DISABLED 0x6A
/// @cond hidden
///Record Header offset for Content Type
#define OFFSET_RL_CONTENTTYPE (0)
///Record Header offset for Protocol Version
#define OFFSET_RL_PROT_VERSION (OFFSET_RL_CONTENTTYPE + 1) //1
///Record Header offset for Epoch
#define OFFSET_RL_EPOCH (OFFSET_RL_PROT_VERSION + 2) //3
///Record Header offset Sequence Number
#define OFFSET_RL_SEQUENCE (OFFSET_RL_EPOCH + 2) //5
///Record Header offset for Fragment Length
#define OFFSET_RL_FRAG_LENGTH (OFFSET_RL_SEQUENCE + 6) //11
///Record Header offset for Start of Fragment
#define OFFSET_RL_FRAGMENT (OFFSET_RL_FRAG_LENGTH + 2) //13
///Record Header length
#define LENGTH_RL_HEADER (OFFSET_RL_FRAGMENT)
///Record Header length of sequence number bytes
#define LENGTH_RL_SEQUENCE 6
///Flag to indicate change cipher spec is received
#define CCS_RECORD_RECV 0x01
///Flag to indicate change cipher spec is not received
#define CCS_RECORD_NOTRECV 0x00
/// @endcond
/**
* \brief Structure for Record Layer (D)TLS.
*/
typedef struct sRecordLayer_d
{
///Server epoch Number
uint16_t wServerEpoch;
///Server Sequence Number
sUint64 sServerSeqNumber;
///(D)TLS Version Information
uint16_t wTlsVersionInfo;
///Client epoch Number
uint16_t wClientEpoch;
///Client Next epoch Number
uint16_t wClientNextEpoch;
///Client Sequence Number
sUint64 sClientSeqNumber;
///Client Sequence Number for the next Epoch
sUint64 sClientNextSeqNumber;
///Flag whether record to be encrypted/decrypted while send/recv.
uint8_t bEncDecFlag;
///Pointer to callback to validate record
int32_t (*fEncDecRecord)(const sCL_d*, const sbBlob_d*, sbBlob_d*, uint16_t);
///Argument to be passed to callback, if any
sCL_d* pEncDecArgs;
///Window
sWindow_d* psWindow;
///Window for next epoch
sWindow_d* psNextWindow;
///Session Key OID
uint16_t wSessionKeyOID;
///Indicates if the record received is encrypted or not
uint8_t *pbDec;
///Indicates if the record received is Change cipher spec
uint8_t *pbRecvCCSRecord;
} sRecordLayer_d;
/**
* \brief Structure for Record contents.
*/
typedef struct sRecordData_d
{
///Content Type
uint8_t bContentType;
///Actual message in the record
sbBlob_d *psBlobInOutMsg;
///Information of record
//uint32_t dwRecordInfo;
///Indicates if memory needs to be allocated or not
uint8_t bMemoryAllocated;
}sRecordData_d;
/**
* \brief Structure to hold the information required for Encrypt and Decrypt message call back to encrypt the data.
*/
//typedef struct sCBEncDecMsg_d
//{
// //Length of data to be encrypted/decrypted
// uint16_t wInDataLength;
//
// ///Session Key OID
// uint16_t wSessionKeyOID;
//
//}sCBEncDecMsg_d;
/**
* \brief Structure to hold the information required change the server epoch state.
*/
typedef struct sCBStateTrn_d
{
///Handle to Record layer structure
hdl_t phRLHdl;
}sCBStateTrn_d;
/**
* \brief Initialise DTLS Record Layer.
*/
int32_t DtlsRL_Init(sRL_d* psRL);
/**
* \brief Adds record header and send data over transport layer.
*/
int32_t DtlsRL_Send(sRL_d* psRecordLayer,uint8_t* pbData,uint16_t wDataLen);
/**
* \brief Receives a record over transport layer, performs window check and remove the record header.
*/
int32_t DtlsRL_Recv(sRL_d* psRecordLayer,uint8_t* pbBuffer,uint16_t* pwLen);
/**
* \brief Frees memory held by dtls record layer.
*/
void DtlsRL_Close(sRL_d* psRL);
/**
* \brief Slides the window to highest set sequence number.
*/
void Dtls_SlideWindow(const sRL_d* PpsRecordLayer, eAuthState_d PeAuthState);
#endif /* MODULE_ENABLE_DTLS_MUTUAL_AUTH */
#endif //__DTLSRECORDLAYER_H__
/**
* @}
*/

View File

@@ -0,0 +1,79 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file
*
* \brief This file defines APIs, types and data structures used in the
* DTLS Transport Layer.
*
* \addtogroup grOCP
* @{
*/
#ifndef __DTLSTL_H__
#define __DTLSTL_H__
#include "optiga/pal/pal_socket.h"
#include "optiga/dtls/OcpTransportLayer.h"
#include "optiga/dtls/OcpCommonIncludes.h"
#ifdef MODULE_ENABLE_DTLS_MUTUAL_AUTH
/**
* \brief This function initializes transport layer communication structure.
*/
int32_t DtlsTL_Init(sTL_d* PpsTL);
/**
* \brief This function creates client port.
*/
int32_t DtlsTL_Connect(sTL_d* PpsTL);
/**
* \brief This function transmits the data to the server from which the data
* was received.
*/
int32_t DtlsTL_Send(const sTL_d* PpsTL,uint8_t* PpbBuffer,uint16_t PwLen);
/**
* \brief This function receives the data from the server.
*/
int32_t DtlsTL_Recv(const sTL_d* PpsTL,uint8_t* PpbBuffer,uint16_t* PpwLen);
/**
* \brief This function closes the UDP communication and releases all the resources.
*/
void DtlsTL_Disconnect(sTL_d* PpsTL);
#endif /* MODULE_ENABLE_DTLS_MUTUAL_AUTH */
#endif //__DTLSTL_H__
/**
* @}
*/

View File

@@ -0,0 +1,85 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file
*
* \brief This file implements the APIs, types and data structures used in the
* for DTLS Windowing.
*
* \addtogroup grMutualAuth
* @{
*/
#ifndef _H_DTLS_WINDOWING_H_
#define _H_DTLS_WINDOWING_H_
#include <stdint.h>
#include "optiga/common/Util.h"
#include "optiga/dtls/OcpCommonIncludes.h"
#ifdef MODULE_ENABLE_DTLS_MUTUAL_AUTH
/**
* \brief Structure for DTLS Windowing.
*/
typedef struct sWindow_d
{
///Sequence number
sUint64 sRecvSeqNumber;
///Higher Bound of window
sUint64 sHigherBound;
///Lower bound of window
sUint64 sLowerBound;
///Size of window, value valid through 32 to 64
uint8_t bWindowSize;
///Window Frame
sUint64 sWindowFrame;
///Pointer to callback to validate record
int32_t (*fValidateRecord)(const void*);
///Argument to be passed to callback, if any
void* pValidateArgs;
}sWindow_d;
/**
* \brief Structure for Sliding Windowing.
*/
typedef struct sSlideWindow_d
{
///Sequence number
sUint64 sClientSeqNumber;
///Pointer to DTLS windowing structure
sWindow_d* psWindow;
}sSlideWindow_d;
/**
* \brief Performs record replay detection and rejects the duplicated records.
*/
int32_t DtlsCheckReplay(sWindow_d *PpsWindow);
#endif /* MODULE_ENABLE_DTLS_MUTUAL_AUTH*/
#endif //_H_DTLS_WINDOWING_H_
/**
* @}
*/

View File

@@ -0,0 +1,75 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file HardwareCrypto.h
*
* \brief This file contains structures and prototypes of hardware crypto layer.
* \addtogroup grMutualAuth
* @{
*
*/
#ifndef __HWCRYPTO_H__
#define __HWCRYPTO_H__
#include "optiga/dtls/OcpCryptoLayer.h"
#include "optiga/common/MemoryMgmt.h"
/**
* \brief Structure for Hardware Crypto.
*/
typedef struct sHardwareCrypto_d
{
/// Session OID
uint16_t wSessionKeyOID;
}sHardwareCrypto_d;
/**
* \brief Initialises the Hardware Crypto Layer.
*/
int32_t HWCL_Init(sCL_d* PpsCL, const void* PpParam);
/**
* \brief Encrypts the input plain text using Security chip.
*/
int32_t HWCL_Encrypt(const sCL_d* PpsCL, const sbBlob_d* PpsBlobPlainText,sbBlob_d* PpsBlobCipherText,uint16_t PwLen);
/**
* \brief Decrypts the input cipher text using Security chip.
*/
int32_t HWCL_Decrypt(const sCL_d* PpsCL,const sbBlob_d* PpsBlobCipherText,sbBlob_d* PpsBlobPlainText,uint16_t PwLen);
/**
* \brief Closes the Crypto layer.
*/
void HWCL_Close(sCL_d* PpsCL);
#endif //__HWCRYPTO_H__
/**
* @}
*/

View File

@@ -0,0 +1,156 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file
*
* \brief This file defines APIs, types and data structures used in the
* (D)TLS Message Layer implementation.
*
* \addtogroup grMutualAuth
* @{
*/
#ifndef __MSGLAYER_H__
#define __MSGLAYER_H__
#include <stdio.h>
#include "optiga/dtls/DtlsHandshakeProtocol.h"
#include "optiga/common/Datatypes.h"
#include "optiga/dtls/OcpCommon.h"
#include "optiga/cmd/CommandLib.h"
#ifdef MODULE_ENABLE_DTLS_MUTUAL_AUTH
/****************************************************************************
*
* API Error Codes
*
****************************************************************************/
/// Successful execution
#define OCP_ML_OK 0x75268512
/// Failure in execution
#define OCP_ML_ERROR 0xF4350158
///Null Parameter(s)
#define OCP_ML_NULL_PARAM BASE_ERROR_MESSAGELAYER
///Zero Length input parameter(s)
#define OCP_ML_ZERO_LEN (BASE_ERROR_MESSAGELAYER + 1)
///Insufficient memory
#define OCP_ML_INSUFFICIENT_MEMORY (BASE_ERROR_MESSAGELAYER + 2)
///Invalid unix time
#define OCP_ML_INVALID_UNIXTIME (BASE_ERROR_MESSAGELAYER + 3)
///Invalid certificate type
#define OCP_ML_INVALID_CERTTYPE (BASE_ERROR_MESSAGELAYER + 4)
///Invalid certificate type
#define OCP_ML_MALLOC_FAILURE (BASE_ERROR_MESSAGELAYER + 5)
/****************************************************************************
*
* Definitions related to (D)TLS commands.
*
****************************************************************************/
/// @cond hidden
///Timeout expired
#define OCP_ML_TIMEOUT (OCP_ML_NULL_PARAM + 3)
///Length of Handshake message header
#define MSG_HEADER_LEN 12
///Over head length for command library
#define OVERHEAD_LEN 21 //APDU (4) + Message header len(12) + Tag enconding len(5)
//Macro to validate the time out
#define TIMEELAPSED(bStartTime,bTimeout) (((uint32_t)(pal_os_timer_get_time_in_milliseconds() - bStartTime) < (uint32_t)(bTimeout*1000))?TRUE:FALSE)
/// @endcond
/****************************************************************************
*
* Common data structures used across all functions.
*
****************************************************************************/
/**
* \brief Structure to hold the information required for Get message call back to allocate memory.
*/
typedef struct sCBGetMsg_d
{
///Indicate to allocate memory only for first time
uint8_t bRepeatCall;
///Pointer to the allocated memory where the message is stored
uint8_t* pbActualMsg;
///Size of the allocated memory
uint16_t dwMsgLen;
}sCBGetMsg_d;
/**
* \brief Structure to hold the information required for Message Layer.
*/
typedef struct sMessageLayer_d
{
///(D)TLS Session ID
uint16_t wSessionID;
///Maximum PMTU
uint16_t wMaxPmtu;
///Record Layer
sConfigRL_d* psConfigRL;
///Certificate Type used for Authentication
uint16_t wOIDDevCertificate;
///Callback function pointer to get unixtime
fGetUnixTime_d pfGetUnixTIme;
} sMessageLayer_d;
/**
* \brief Provide Handshake message using Command Library.<br>
*/
int32_t MsgLayer_FormMessage(eMsgType_d eMsgType,const sMessageLayer_d* PpsMessageLayer, sbBlob_d* PpsMessage);
/**
* \brief Process Handshake message using Command Library.<br>
*/
int32_t MsgLayer_ProcessMessage(eMsgType_d eMsgType,const sMessageLayer_d* PpsMessageLayer, sbBlob_d* PpsMessage);
/**
* \brief Encrypt the Data using Command Library.<br>
*/
int32_t MsgLayer_EncryptMessage(const sbBlob_d* PpsBlobPlainMsg, sbBlob_d* PpsBlobCipherMsg, uint16_t PwInDataLen, uint16_t PwSessionKeyOID);
/**
* \brief Decrypt the Data using Command Library.<br>
*/
int32_t MsgLayer_DecryptMessage(const sbBlob_d* PpsBlobCipherMsg, sbBlob_d* PpsBlobPlainMsg, uint16_t PwInDataLen, uint16_t PwSessionKeyOID);
#endif /* MODULE_ENABLE_DTLS_MUTUAL_AUTH*/
#endif //__MSGLAYER_H__
/**
* @}
*/

View File

@@ -0,0 +1,178 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file
*
* \brief This file defines APIs, types and data structures used in the
* OCP configurations.
*
* \addtogroup grMutualAuth
* @{
*/
#ifndef __OCPCOMMON_H__
#define __OCPCOMMON_H__
#include "optiga/common/Datatypes.h"
#include "optiga/dtls/OcpRecordLayer.h"
#include "optiga/common/MemoryMgmt.h"
#include "optiga/dtls/OcpCommonIncludes.h"
#include "optiga/pal/pal_os_timer.h"
/// Successful execution
#define OCP_HL_OK 0x75236512
/// Failure in execution
#define OCP_HL_ERROR 0XF3CA3154
///Null Parameter(s)
#define OCP_HL_NULL_PARAM BASE_ERROR_HANDSHAKELAYER
///Length of input is zero
#define OCP_HL_LENZERO_ERROR (BASE_ERROR_HANDSHAKELAYER + 1)
///Maximum PMTU value
#define MAX_PMTU 1500
///Minimum PMTU Value
#define MIN_PMTU 296
///Buffer size to hold the received data
#define TLBUFFER_SIZE 1500
///Overhead length for encrypted message
#define ENCRYPTED_APP_OVERHEAD (UDP_RECORD_OVERHEAD + EXPLICIT_NOUNCE_LENGTH + MAC_LENGTH )
///Macro to get the Maximum length of the Application data which can be sent
#define MAX_APP_DATALEN(PhAppOCPCtx) ((((sAppOCPCtx_d*)PhAppOCPCtx)->sHandshake.wMaxPmtu) - ENCRYPTED_APP_OVERHEAD)
/****************************************************************************
*
* Common data structure used across all functions.
*
****************************************************************************/
///Function pointer to get the unix time
typedef int32_t (*fGetUnixTime_d)(uint32_t*);
/**
* \brief Enumeration to specify the mode of operation of OCP
*/
typedef enum eMode_d
{
///Client
eClient = 0x24,
///Server
eServer = 0x81
}eMode_d;
/**
* \brief Enumeration to specify the Protocol version
*/
typedef enum eProtVersion_d
{
///DTLS 1.2
eDTLS_1_2,
///TLS 1.2
eTLS_1_2
}eProtVersion_d;
/**
* \brief Enum for Mutual Authentication states
*/
typedef enum eAuthState_d
{
//Authentication parameters initialized
eAuthInitialised,
//Authentication started
eAuthStarted,
//Authentication is completed
eAuthCompleted,
//Authentication session is closed
eAuthSessionClosed
}eAuthState_d;
/**
* \brief Structure containing Handshake related data.
*/
typedef struct sHandshake_d
{
///Mode of operation,Client/Server
eMode_d eMode;
///Maximum PMTU
uint16_t wMaxPmtu;
///Pointer to Record Layer
sConfigRL_d* psConfigRL;
///Pointer to Logger
sLogger_d phLogger;
///To indicate fatal alert
bool_t fFatalError;
//Indicates status of Mutual Authentication
eAuthState_d eAuthState;
///Handle to OCP
hdl_t PhAppOCPCtx;
///Session OID
uint16_t wSessionOID;
///Certificate Type used for Authentication
uint16_t wOIDDevCertificate;
///Private key used for authentication
uint16_t wOIDDevPrivKey;
///Callback function pointer to get unixtime
fGetUnixTime_d pfGetUnixTIme;
}sHandshake_d;
/**
* \brief Enum for Flights
*/
typedef enum eFlight_d
{
///Flight 0
eFlight0 = 0,
///Flight 1
eFlight1 = 1,
///Flight 2
eFlight2 = 2,
///Flight 3
eFlight3 = 3,
///Flight 4
eFlight4 = 4,
///Flight 5
eFlight5 = 5,
///Flight 6
eFlight6 = 6,
///Default
eDefault
}eFlight_d;
///Function pointer to perform Handshake
typedef int32_t (*fPerformHandshake_d)(sHandshake_d*);
#endif //__OCPCOMMON_H__
/**
* @}
*/

View File

@@ -0,0 +1,43 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file
*
* \brief This file includes the commonly used header files.
*
* \addtogroup grMutualAuth
* @{
*/
#ifndef _COMMONCONFIG_H_
#define _COMMONCONFIG_H_
#include "optiga/common/AuthLibSettings.h"
#include "optiga/dtls/BaseErrorCodes.h"
#include "optiga/Version.h"
#endif //_COMMONCONFIG_H_
/**
* @}
*/

View File

@@ -0,0 +1,114 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file
*
* \brief This file defines APIs, types and data structures used in the
* OCP Crypto Layer.
*
* \addtogroup grMutualAuth
* @{
*/
#ifndef __OCPCRYPTOLAYER_H__
#define __OCPCRYPTOLAYER_H__
#include "optiga/common/Datatypes.h"
#include "optiga/common/Logger.h"
#include "optiga/dtls/OcpCommonIncludes.h"
/****************************************************************************
*
* Common data structure used across all functions.
*
****************************************************************************/
/// Failure in execution
#define OCP_CL_ERROR 0x51667F82
///Successful Execution
#define OCP_CL_OK 0x4C36F247
///Null paramter
#define OCP_CL_NULL_PARAM BASE_ERROR_CRYPTO_LAYER
///Malloc Failure in Crypto
#define OCP_CL_MALLOC_FAILURE (BASE_ERROR_CRYPTO_LAYER + 1)
///Zero Length Failure
#define OCP_CL_ZERO_LEN (BASE_ERROR_CRYPTO_LAYER + 2)
///Insufficient memory
#define OCP_CL_INSUFFICIENT_MEMORY (BASE_ERROR_CRYPTO_LAYER + 3)
/**
* \brief Structure containing Crypto Layer information.
*/
typedef struct sCL_d
{
///Handle to Crypto
hdl_t phCryptoHdl;
//Pointer to Logger
sLogger_d sLogger;
}sCL_d;
///Function pointer to Initialize Record Layer.
typedef int32_t (*fCLInit)(sCL_d* psCL, const void*);
///Function pointer for Record Layer Send
typedef int32_t (*fCLEncrypt)(const sCL_d* psCL, const sbBlob_d* PpsBlobPlainText,sbBlob_d* PpsBlobCipherText,uint16_t wLen);
///Function pointer for Record Layer Receive
typedef int32_t (*fCLDecrypt)(const sCL_d* psCL, const sbBlob_d* PpsBlobCipherText,sbBlob_d* PpsBlobPlainText,uint16_t wLen);
///Function pointer to close Record Layer
typedef void (*fCLClose)(sCL_d* psCL);
/**
* \brief Structure to configure Crypto Layer.
*/
typedef struct sConfigCL_d
{
///Function pointer to Init Crypto layer
fCLInit pfInit;
///Function pointer to Close Crypto layer
fCLClose pfClose;
///Function pointer to Encrypt data via Crypto layer
fCLEncrypt pfEncrypt;
///Function pointer to Decrypt data via Crypto layer
fCLDecrypt pfDecrypt;
///Crypto Handle
sCL_d sCL;
}sConfigCL_d;
#endif //__OCPCRYPTOLAYER_H__
/**
* @}
*/

View File

@@ -0,0 +1,190 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file
*
* \brief This file defines APIs, types and data structures used in the
* OCP Record Layer.
*
* \addtogroup grMutualAuth
* @{
*/
#ifndef __OCPRECORDLAYER_H__
#define __OCPRECORDLAYER_H__
#include "optiga/dtls/OcpTransportLayer.h"
#include "optiga/dtls/OcpCryptoLayer.h"
#include "optiga/common/Logger.h"
/// Failure in execution
#define OCP_RL_ERROR 0x55667F82
/// Internal status for success.
#define OCP_RL_OK 0x297D9015
///Invalid record length
#define OCP_RL_INVALID_RECORD_LENGTH BASE_ERROR_RECORDLAYER
///Invalid record content type
#define OCP_RL_INVALID_CONTENTTYPE (BASE_ERROR_RECORDLAYER + 1)
///Invalid decrypt payload lenght
#define OCP_RL_INVALID_DEC_PAYLOAD_LEN (BASE_ERROR_RECORDLAYER + 2)
///Invalid protocol version
#define OCP_RL_INVALID_PROTOCOL_VERSION (BASE_ERROR_RECORDLAYER + 3)
///Incorrect epoch
#define OCP_RL_INCORRECT_EPOCH (BASE_ERROR_RECORDLAYER + 4)
///Record length mismatch
#define OCP_RL_RECORD_LEN_MISMATCH (BASE_ERROR_RECORDLAYER + 5)
///Bad record
#define OCP_RL_BAD_RECORD (BASE_ERROR_RECORDLAYER + 6)
/// No data
#define OCP_RL_NO_DATA (BASE_ERROR_RECORDLAYER + 7)
/// Data length is greater than PMTU
#define OCP_RL_LEN_GREATER_PMTU (BASE_ERROR_RECORDLAYER + 8)
///Invalid record instance
#define OCP_RL_INVALID_INSTANCE (BASE_ERROR_RECORDLAYER + 9)
///Alert record received
#define OCP_RL_ALERT_RECEIVED (BASE_ERROR_RECORDLAYER + 10)
///Alert record received
#define OCP_RL_APPDATA_RECEIVED (BASE_ERROR_RECORDLAYER + 11)
///Malloc Failure
#define OCP_RL_MALLOC_FAILURE (BASE_ERROR_RECORDLAYER + 12)
///Cipher Spec Content Spec
#define CONTENTTYPE_CIPHER_SPEC 0x14
///Alert Content Spec
#define CONTENTTYPE_ALERT 0x15
///Handshake Content Spec
#define CONTENTTYPE_HANDSHAKE 0x16
///Application Data Content Spec
#define CONTENTTYPE_APP_DATA 0x17
///UDP REcord overhead length
#define UDP_RECORD_OVERHEAD 41 //20(IP Header) + 8(UDP Header) + 13(RL Header)
///Length of the MAC generated for encrypted message
#define MAC_LENGTH 8
///Length of Explicit Nounce
#define EXPLICIT_NOUNCE_LENGTH 8
/****************************************************************************
*
* Common data structure used across all functions.
*
****************************************************************************/
/**
* \brief Structure containing Record Layer information.
*/
typedef struct sRL_d
{
///Handle to Record layer structure sRecordLayer_d
hdl_t phRLHdl;
///Pointer to Configured TL
sConfigTL_d* psConfigTL;
///Pointer to Configured Crypto
sConfigCL_d* psConfigCL;
///Structure that holds logger parameters
sLogger_d sLogger;
///Indicates if memory needs to be allocated or not
uint8_t bMemoryAllocated;
///Content Type
uint8_t bContentType;
///Indicate Multiple record received
uint8_t bMultipleRecord;
///Indicates if the send flight is retransmitted
bool_t fRetransmit;
///Indicates if the record received is encrypted or not
uint8_t bDecRecord;
///Indicates if the record received is Change cipher spec
uint8_t bRecvCCSRecord;
///pointer to a Next record
uint8_t* pNextRecord;
///Pointer to callback to change the server epoch state
Void (*fServerStateTrn)(const void*);
}sRL_d;
///Function pointer to Initialize Record Layer.
typedef int32_t (*fRLInit)(sRL_d* psRL);
///Function pointer for Record Layer Send
typedef int32_t (*fRLSend)(sRL_d* psRL, uint8_t* pbBuffer,uint16_t wLen);
///Function pointer for Record Layer Receive
typedef int32_t (*fRLRecv)(sRL_d* psRL,uint8_t* pbBuffer,uint16_t* pwLen);
///Function pointer to close Record Layer
typedef void (*fRLClose)(sRL_d* psRL);
/**
* \brief Structure to configure Record Layer.
*/
typedef struct sConfigRL_d
{
///Function pointer to Init RL
fRLInit pfInit;
///Function pointer to CloseRL
fRLClose pfClose;
///Function pointer to Send via RL
fRLSend pfSend;
///Function pointer to Receive via RL
fRLRecv pfRecv;
///Record Layer
sRL_d sRL;
}sConfigRL_d;
#endif //__OCPRECORDLAYER_H__
/**
* @}
*/

View File

@@ -0,0 +1,159 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file
*
* \brief This file defines APIs, types and data structures used in the
* OCP Transport Layer.
*
* \addtogroup grMutualAuth
* @{
*/
#ifndef __OCPTRANSPORTLAYER_H__
#define __OCPTRANSPORTLAYER_H__
#include "optiga/common/Datatypes.h"
#include "optiga/common/Logger.h"
#include "optiga/dtls/OcpCommonIncludes.h"
///General error
#define OCP_TL_ERROR 0xF1267AB3
///Successful execution
#define OCP_TL_OK 0x72309781
///Null Parameter(S)
#define OCP_TL_NULL_PARAM BASE_ERROR_TRANSPORTLAYER
///Null Parameter(S)
#define OCP_TL_BINDING_FAILURE (BASE_ERROR_TRANSPORTLAYER + 1)
///NO Data received
#define OCP_TL_NO_DATA (BASE_ERROR_TRANSPORTLAYER + 2)
///Malloc failure
#define OCP_TL_MALLOC_FAILURE (BASE_ERROR_TRANSPORTLAYER + 3)
/****************************************************************************
*
* Common data structure used across all functions.
*
****************************************************************************/
/**
* \brief Enumeration to represent transport layer communication state
*/
typedef enum eConnectionState_d
{
///Connected to network
eConnected = 0x01,
///Disconnected from network
eDisconnected = 0x02
}eConnectionState_d;
/**
* \brief This structure contains Ethernet communication data
*/
typedef enum eReceiveCall_d
{
///Blocking Ethernet call
eBlocking = 0x10,
///Non Blocking Ethernet call
eNonBlocking = 0x20
}eReceiveCall_d;
/**
* \brief Structure holding Transport Layer Information.
*/
typedef struct sTL_d
{
///Handle to transport layer
hdl_t phTLHdl;
///Port Number
uint16_t wPort;
///IP Address
char_t* pzIpAddress;
///Transport Layer Timeout
uint16_t wTimeout;
///Connection state
eConnectionState_d eIsConnected;
///Call type Blocking or NonBlocking
eReceiveCall_d eCallType;
//Structure that holds logger parameters
sLogger_d sLogger;
}sTL_d;
///Function pointer for Transport Layer Init.
typedef int32_t (*fTLInit)(sTL_d* psTL);
///Function pointer for Transport Layer Connect.
typedef int32_t (*fTLConnect)(sTL_d* psTL);
///Function pointer for Transport Layer Disconnect
typedef void (*fTLDisconnect)(sTL_d* psTL);
///Function pointer for Transport Layer Send
typedef int32_t (*fTLSend)(const sTL_d* psTL,uint8_t* pbBuffer,uint16_t wLen);
///Function pointer for Transport Layer Receive
typedef int32_t (*fTLRecv)(const sTL_d* psTL,uint8_t* pbBuffer,uint16_t* pwLen);
/**
* \brief Structure to configure Transport Layer.
*/
typedef struct sConfigTL_d
{
///Function pointer to Init via TL
fTLInit pfInit;
///Function pointer to Send via TL
fTLSend pfSend;
///Function pointer to Receive via TL
fTLRecv pfRecv;
///Function pointer to Connect to TL
fTLConnect pfConnect;
///Function pointer to Disconnect from TL
fTLDisconnect pfDisconnect;
///Transport Layer
sTL_d sTL;
}sConfigTL_d;
#endif //__OCPTRANSPORTLAYER_H__
/**
* @}
*/

View File

@@ -0,0 +1,67 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file
*
* \brief This file contains a UDP error codes.
*
*
* \addtogroup grMutualAuth
* @{
*
*/
#ifndef _UDPERRCODES_H_
#define _UDPERRCODES_H_
///Failure to allocate memory
#define E_COMMS_UDP_ALLOCATE_FAILURE 0x80000100
///Binding failure to a port
#define E_COMMS_UDP_BINDING_FAILURE 0x80000101
///No data present to send
#define E_COMMS_UDP_NO_DATA_TO_SEND 0x80000102
///No data received from the target
#define E_COMMS_UDP_NO_DATA_RECEIVED 0x80000103
///Failure to route the UDP packet
#define E_COMMS_UDP_ROUTING_FAILURE 0x80000104
///Failure to deallocate the memory
#define E_COMMS_UDP_DEALLOCATION_FAILURE 0x80000105
///Copy to the buffer failure
#define E_COMMS_UDP_COPY_BUFFER_FAILURE 0x80000106
///UDP connect failure
#define E_COMMS_UDP_CONNECT_FAILURE 0x80000107
#endif /* _UDPERRCODES_H_ */
/**
* @}
*/

View File

@@ -0,0 +1,104 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file ifx_i2c.h
*
* \brief This file defines the API prototype for IFX I2C protocol v1.65 wrapper.
*
* \addtogroup grIFXI2C
* @{
*/
#ifndef _IFXI2C_H_
#define _IFXI2C_H_
#ifdef __cplusplus
extern "C" {
#endif
/***********************************************************************************************************************
* HEADER FILES
**********************************************************************************************************************/
#include "optiga/common/Datatypes.h"
#include "optiga/ifx_i2c/ifx_i2c_config.h"
/***********************************************************************************************************************
* MACROS
***********************************************************************************************************************/
/***********************************************************************************************************************
* ENUMS
***********************************************************************************************************************/
/** @brief IFX I2C Reset types */
typedef enum ifx_i2c_reset_type
{
/// Cold reset. Both reset pin and vdd pin are toggled low and then high
IFX_I2C_COLD_RESET = 0U,
/// Soft reset. 0x0000 is written to IFX-I2C Soft reset register
IFX_I2C_SOFT_RESET = 1U,
/// Warm reset. Only reset pin is toggled low and then high
IFX_I2C_WARM_RESET = 2U
} ifx_i2c_reset_type_t;
/***********************************************************************************************************************
* DATA STRUCTURES
***********************************************************************************************************************/
/***********************************************************************************************************************
* API PROTOTYPES
**********************************************************************************************************************/
/**
* \brief Initializes the IFX I2C protocol stack for a given context.
*/
host_lib_status_t ifx_i2c_open(ifx_i2c_context_t *p_ctx);
/**
* \brief Resets the I2C slave.
*/
host_lib_status_t ifx_i2c_reset(ifx_i2c_context_t *p_ctx, ifx_i2c_reset_type_t reset_type);
/**
* \brief Sends a command and receives a response for the command.
*/
host_lib_status_t ifx_i2c_transceive(ifx_i2c_context_t *p_ctx,const uint8_t* p_data, const uint16_t* p_data_length,
uint8_t* p_buffer, uint16_t* p_buffer_len);
/**
* \brief Closes the IFX I2C protocol stack for a given context.
*/
host_lib_status_t ifx_i2c_close(ifx_i2c_context_t *p_ctx);
/**
* \brief Sets the slave address of the target device.
*/
host_lib_status_t ifx_i2c_set_slave_address(ifx_i2c_context_t *p_ctx, uint8_t slave_address, uint8_t persistent);
#ifdef __cplusplus
}
#endif
#endif /* _IFXI2C_H_ */
/**
* @}
**/

View File

@@ -0,0 +1,312 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file ifx_i2c_config.h
*
* \brief This file defines the structures and macros for the Infineon I2C Protocol.
*
* \addtogroup grIFXI2C
* @{
*/
#ifndef _IFX_I2C_CONFIG_H_
#define _IFX_I2C_CONFIG_H_
#ifdef __cplusplus
extern "C" {
#endif
/***********************************************************************************************************************
* HEADER FILES
**********************************************************************************************************************/
// Protocol Stack Includes
#include <stdint.h>
#include "optiga/pal/pal_i2c.h"
#include "optiga/pal/pal_gpio.h"
#include "optiga/pal/pal_os_timer.h"
/***********************************************************************************************************************
* MACROS
**********************************************************************************************************************/
/** @brief I2C slave address of the Infineon device */
#define IFX_I2C_BASE_ADDR (0x30)
/** @brief Physical Layer: polling interval in microseconds */
#define PL_POLLING_INVERVAL_US (1000)
/** @brief Physical layer: maximal attempts */
#define PL_POLLING_MAX_CNT (200)
/** @brief Physical Layer: data register polling interval in microseconds */
#define PL_DATA_POLLING_INVERVAL_US (5000)
/** @brief Physical Layer: guard time interval in microseconds */
#define PL_GUARD_TIME_INTERVAL_US (50)
/** @brief Data link layer: maximum frame size */
#ifndef DL_MAX_FRAME_SIZE
#define DL_MAX_FRAME_SIZE (300)
#endif
/** @brief Data link layer: header size */
#define DL_HEADER_SIZE (5)
/** @brief Data link layer: maximum number of retries in case of transmission error */
#define DL_TRANS_REPEAT (3)
/** @brief Data link layer: Trans timeout in milliseconds*/
#define PL_TRANS_TIMEOUT_MS (10)
/** @brief Transport layer: Maximum exit timeout in seconds */
#define TL_MAX_EXIT_TIMEOUT (6)
/** @brief Reset low time for GPIO pin toggling */
#define RESET_LOW_TIME_MSEC (2000)
/** @brief Start up time */
#define STARTUP_TIME_MSEC (12000)
/** @brief Protocol Stack: Status codes for success */
#define IFX_I2C_STACK_SUCCESS (0x00)
/** @brief Protocol Stack: Status codes for error */
#define IFX_I2C_STACK_ERROR (0x01)
/** @brief Protocol Stack: Status codes busy */
#define IFX_I2C_STACK_BUSY (0x02)
/** @brief Protocol Stack: Memory insufficient */
#define IFX_I2C_STACK_MEM_ERROR (0x03)
/** @brief Protocol Stack: Fatal error. Used internal to IFX I2C Stack */
#define IFX_I2C_FATAL_ERROR (0x04)
/** @brief Offset of Datalink header in tx_frame_buffer */
#define IFX_I2C_DL_HEADER_OFFSET (0)
/** @brief Offset of Transport header in tx_frame_buffer */
#define IFX_I2C_TL_HEADER_OFFSET (IFX_I2C_DL_HEADER_OFFSET+3)
/** @brief Protocol Stack debug switch for physical layer (set to 0 or 1) */
#define IFX_I2C_LOG_PL 0
/** @brief Protocol Stack debug switch for data link layer (set to 0 or 1) */
#define IFX_I2C_LOG_DL 0
/** @brief Protocol Stack debug switch for transport layer (set to 0 or 1) */
#define IFX_I2C_LOG_TL 0
/** @brief Log ID number for physical layer */
#define IFX_I2C_LOG_ID_PL 0x00
/** @brief Log ID number for data link layer */
#define IFX_I2C_LOG_ID_DL 0x01
/** @brief Log ID number for transport layer */
#define IFX_I2C_LOG_ID_TL 0x02
/** @brief Log ID number for platform abstraction layer */
#define IFX_I2C_LOG_ID_PAL 0x04
/***********************************************************************************************************************
* ENUMS
***********************************************************************************************************************/
/***********************************************************************************************************************
* DATA STRUCTURES
***********************************************************************************************************************/
struct ifx_i2c_context;
/** @brief Event handler function prototype */
typedef void (*ifx_i2c_event_handler_t)(struct ifx_i2c_context* ctx, host_lib_status_t event, const uint8_t* data, uint16_t data_len);
/** @brief Physical layer structure */
typedef struct ifx_i2c_pl
{
// Physical Layer low level interface variables
/// Physical layer buffer
uint8_t buffer[DL_MAX_FRAME_SIZE+1];
/// Tx length
uint16_t buffer_tx_len;
/// Rx length
uint16_t buffer_rx_len;
/// Action on register, read/write
uint8_t register_action;
/// i2c read/i2c write
uint8_t i2c_cmd;
/// Retry counter
uint16_t retry_counter;
// Physical Layer high level interface variables
/// Action of frame. Tx/Rx
uint8_t frame_action;
/// Frame state
uint8_t frame_state ;
/// Pointer to data to be sent
uint8_t * p_tx_frame;
/// Length of data to be sent
uint16_t tx_frame_len;
// Upper layer handler
ifx_i2c_event_handler_t upper_layer_event_handler;
// Physical Layer negotiation/soft reset variables
/// Negotiation state
uint8_t negotiate_state;
/// Soft reset requested
uint8_t request_soft_reset;
} ifx_i2c_pl_t;
/** @brief Datalink layer structure */
typedef struct ifx_i2c_dl
{
// Data Link layer internal state variables
/// Datalink layer state
uint8_t state;
/// Tx sequence number
uint8_t tx_seq_nr;
// Rx sequence number
uint8_t rx_seq_nr;
/// Indicate only Rx required
uint8_t action_rx_only;
/// Retransmit counter
uint8_t retransmit_counter;
/// Error occured
uint8_t error;
/// Resynced
uint8_t resynced;
/// Timeout value
uint32_t data_poll_timeout;
/// Transmit buffer size
uint16_t tx_buffer_size;
/// Receive buffer size
uint16_t rx_buffer_size;
/// Pointer to main transmit buffers
uint8_t* p_tx_frame_buffer;
/// Pointer to main receive buffers
uint8_t* p_rx_frame_buffer;
///Start time of sending frame
uint32_t frame_start_time;
// Upper layer Event handler
ifx_i2c_event_handler_t upper_layer_event_handler;
} ifx_i2c_dl_t;
/** @brief Transport layer structure */
typedef struct ifx_i2c_tl
{
// Transport Layer state and buffer
/// Transport layer state
uint8_t state;
/// Pointer to packet provided by user
uint8_t* p_actual_packet;
/// Total received data
uint16_t total_recv_length;
/// Actual length of user provided packet
uint16_t actual_packet_length;
/// Offset till which data is sent from p_actual_packet
uint16_t packet_offset;
/// Maximum length of packet at transport layer
uint16_t max_packet_length;
/// Pointer to user provided receive buffer
uint8_t* p_recv_packet_buffer;
/// Length of receive buffer
uint16_t* p_recv_packet_buffer_length;
/// Start time of the transport layer API
uint32_t api_start_time;
///Chaining error coutn from slave
uint8_t chaining_error_count;
///Chaining error count for master
uint8_t master_chaining_error_count;
///State to check last chaining state
uint8_t previous_chaining;
/// transmission done
uint8_t transmission_completed;
/// Error event state
uint8_t error_event;
/// Upper layer event handler
ifx_i2c_event_handler_t upper_layer_event_handler;
} ifx_i2c_tl_t;
/** @brief IFX I2C context structure */
typedef struct ifx_i2c_context
{
/// I2C Slave address
uint8_t slave_address;
/// Frequency of i2c master
uint16_t frequency;
/// Data link layer frame size
uint16_t frame_size;
/// Pointer to pal gpio context for vdd
pal_gpio_t* p_slave_vdd_pin;
/// Pointer to pal gpio context for reset
pal_gpio_t* p_slave_reset_pin;
/// Pointer to pal i2c context
pal_i2c_t* p_pal_i2c_ctx;
/// Upper layer event handler
app_event_handler_t upper_layer_event_handler;
/// Upper layer context
void* p_upper_layer_ctx;
/// Pointer to upper layer rx buffer
uint8_t* p_upper_layer_rx_buffer;
/// Pointer to length of upper layer rx buffer
uint16_t* p_upper_layer_rx_buffer_len;
/// Protocol variables
/// ifx i2c wrapper apis state
uint8_t state;
/// ifx i2c wrapper api status
uint8_t status;
/// reset states
uint8_t reset_state;
/// type of reset
uint8_t reset_type;
/// init pal
uint8_t do_pal_init;
/// Transport layer context
ifx_i2c_tl_t tl;
/// Datalink layer context
ifx_i2c_dl_t dl;
/// Physical layer context
ifx_i2c_pl_t pl;
/// IFX I2C tx frame of max length
uint8_t tx_frame_buffer[DL_MAX_FRAME_SIZE];
/// IFX I2C rx frame of max length
uint8_t rx_frame_buffer[DL_MAX_FRAME_SIZE];
} ifx_i2c_context_t;
/***********************************************************************************************************************
* GLOBAL
***********************************************************************************************************************/
/** @brief IFX I2C Instance */
extern ifx_i2c_context_t ifx_i2c_context_0;
/***********************************************************************************************************************
* LOCAL ROUTINES
***********************************************************************************************************************/
/***********************************************************************************************************************
* API PROTOTYPES
**********************************************************************************************************************/
/**
* @}
**/
#ifdef __cplusplus
}
#endif
#endif /* _IFX_I2C_CONFIG_H_ */

View File

@@ -0,0 +1,117 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file ifx_i2c_data_link_layer.h
*
* \brief This file defines the API prototype for data link layer of the Infineon I2C Protocol Stack library.
*
* \addtogroup grIFXI2C
* @{
*/
#ifndef _IFX_I2C_DATA_LINK_LAYER_H_
#define _IFX_I2C_DATA_LINK_LAYER_H_
#ifdef __cplusplus
extern "C" {
#endif
/***********************************************************************************************************************
* HEADER FILES
**********************************************************************************************************************/
#include "optiga/ifx_i2c/ifx_i2c_config.h"
/***********************************************************************************************************************
* MACROS
**********************************************************************************************************************/
/** @brief Error event propagated to upper layer */
#define IFX_I2C_DL_EVENT_ERROR (0x01)
/** @brief Transmit success event propagated to upper layer (bit field 1) */
#define IFX_I2C_DL_EVENT_TX_SUCCESS (0x02)
/** @brief Receive success event propagated to upper layer (bit field 3)*/
#define IFX_I2C_DL_EVENT_RX_SUCCESS (0x04)
/***********************************************************************************************************************
* ENUMS
**********************************************************************************************************************/
/***********************************************************************************************************************
* DATA STRUCTURES
***********************************************************************************************************************/
/***********************************************************************************************************************
* API PROTOTYPES
**********************************************************************************************************************/
/**
* @brief Function for initializing the module.
*
* Function initializes and enables the module and registers
* an event handler to receive events from this module.
* @attention This function must be called before using the module.
*
* @param[in,out] p_ctx Pointer to ifx i2c context.
* @param[in] handler Function pointer to the event handler of the upper layer.
*
* @retval IFX_I2C_STACK_SUCCESS If initialization was successful.
* @retval IFX_I2C_STACK_ERROR If the module is already initialized.
*/
host_lib_status_t ifx_i2c_dl_init(ifx_i2c_context_t *p_ctx,ifx_i2c_event_handler_t handler);
/**
* @brief Function for sending a frame.
*
* Asynchronous function to send a frame. The function returns immediately.
* One of the following events is propagated to the event handler registered
* with @ref ifx_i2c_dl_init.
*
* @param[in,out] p_ctx Pointer to ifx i2c context.
* @param[in] frame_len Frame length.
*
* @retval IFX_I2C_STACK_SUCCESS If function was successful.
* @retval IFX_I2C_STACK_ERROR If the module is busy.
*/
host_lib_status_t ifx_i2c_dl_send_frame(ifx_i2c_context_t *p_ctx,uint16_t frame_len);
/**
* @brief Function for receiving a frame.
*
* Asynchronous function to receive a frame. The function returns immediately.
* One of the following events is propagated to the event handler registered
* with @ref ifx_i2c_dl_init.
*
* @param[in,out] p_ctx Pointer to ifx i2c context.
*
* @retval IFX_I2C_STACK_SUCCESS If function was successful.
* @retval IFX_I2C_STACK_ERROR If the module is busy.
*/
host_lib_status_t ifx_i2c_dl_receive_frame(ifx_i2c_context_t *p_ctx);
#ifdef __cplusplus
}
#endif
#endif /* _IFX_I2C_DATA_LINK_LAYER_H_ */
/**
* @}
**/

View File

@@ -0,0 +1,123 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file ifx_i2c_physical_layer.h
*
* \brief This file defines the API prototype for physical layer of the Infineon I2C Protocol Stack library.
*
* \addtogroup grIFXI2C
* @{
*/
#ifndef _IFX_I2C_PHYSICAL_LAYER_H_
#define _IFX_I2C_PHYSICAL_LAYER_H_
#ifdef __cplusplus
extern "C" {
#endif
/***********************************************************************************************************************
* HEADER FILES
**********************************************************************************************************************/
#include "optiga/ifx_i2c/ifx_i2c_config.h"
/***********************************************************************************************************************
* MACROS
**********************************************************************************************************************/
/***********************************************************************************************************************
* ENUMS
**********************************************************************************************************************/
/***********************************************************************************************************************
* DATA STRUCTURES
***********************************************************************************************************************/
/***********************************************************************************************************************
* API PROTOTYPES
**********************************************************************************************************************/
/**
* @brief Function for initializing the module.
*
* Function initializes and enables the module and registers
* an event handler to receive events from this module.
* @attention This function must be called before using the module.
*
* @param[in,out] p_ctx Pointer to ifx i2c context.
* @param[in] handler Function pointer to the event handler of the upper layer.
*
* @retval IFX_I2C_STACK_SUCCESS If initialization was successful.
* @retval IFX_I2C_STACK_ERROR If the module is already initialized.
*/
host_lib_status_t ifx_i2c_pl_init(ifx_i2c_context_t *p_ctx,ifx_i2c_event_handler_t handler);
/**
* @brief Function for sending a frame.
*
* Asynchronous function to send a frame. The function returns immediately.
* One of the following events is propagated to the event handler registered
* with @ref ifx_i2c_pl_init
*
* @param[in,out] p_ctx Pointer to ifx i2c context.
* @param[in] p_frame Buffer containing the frame.
* @param[in] frame_len Frame length.
*
* @retval IFX_I2C_STACK_SUCCESS If function was successful.
* @retval IFX_I2C_STACK_ERROR If the module is busy.
*/
host_lib_status_t ifx_i2c_pl_send_frame(ifx_i2c_context_t *p_ctx,uint8_t* p_frame, uint16_t frame_len);
/**
* @brief Function for receiving a frame.
*
* Asynchronous function to receive a frame. The function returns immediately.
* One of the following events is propagated to the event handler registered
* with @ref ifx_i2c_pl_init
*
* @param[in] p_ctx Pointer to ifx i2c context.
*
* @retval IFX_I2C_STACK_SUCCESS If function was successful.
* @retval IFX_I2C_STACK_ERROR If the module is busy.
*/
host_lib_status_t ifx_i2c_pl_receive_frame(ifx_i2c_context_t *p_ctx);
/**
* @brief Function for setting slave address.
*
* Synchronous function to set slave address.
*
* @param[in] p_ctx Pointer to ifx i2c context.
*\param[in] slave_address Holds new slave address[7 Bit] to be set.
* \param[in] storage_type Storage type.
*
* @retval IFX_I2C_STACK_SUCCESS If function was successful.
* @retval IFX_I2C_STACK_ERROR If setting slave address fails.
*/
host_lib_status_t ifx_i2c_pl_write_slave_address(ifx_i2c_context_t *p_ctx, uint8_t slave_address, uint8_t storage_type);
/**
* @}
**/
#ifdef __cplusplus
}
#endif
#endif /* _IFX_I2C_PHYSICAL_LAYER_H_ */

View File

@@ -0,0 +1,98 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file ifx_i2c_transport_layer.h
*
* \brief This file defines the API prototype for transport layer of the Infineon I2C Protocol Stack library.
*
* \addtogroup grIFXI2C
* @{
*/
#ifndef _IFX_I2C_TRANSPORT_LAYER_H_
#define _IFX_I2C_TRANSPORT_LAYER_H_
#ifdef __cplusplus
extern "C" {
#endif
/***********************************************************************************************************************
* HEADER FILES
**********************************************************************************************************************/
#include "optiga/ifx_i2c/ifx_i2c_config.h"
#include "optiga/pal/pal_os_timer.h"
/***********************************************************************************************************************
* MACROS
**********************************************************************************************************************/
/***********************************************************************************************************************
* ENUMS
**********************************************************************************************************************/
/***********************************************************************************************************************
* DATA STRUCTURES
***********************************************************************************************************************/
/***********************************************************************************************************************
* API PROTOTYPES
**********************************************************************************************************************/
/**
* @brief Function for initializing the module.
*
* Function initializes and enables the module and registers
* an event handler to receive events from this module.
* @attention This function must be called before using the module.
*
* @param[in,out] p_ctx Pointer to ifx i2c context.
* @param[in] handler Function pointer to the event handler of the upper layer.
*
* @retval IFX_I2C_STACK_SUCCESS If initialization was successful.
* @retval IFX_I2C_STACK_ERROR If the module is already initialized.
*/
host_lib_status_t ifx_i2c_tl_init(ifx_i2c_context_t *p_ctx,ifx_i2c_event_handler_t handler);
/**
* @brief Function to transmit and receive a packet.
*
* Asynchronous function to send and receive a packet.
* The function returns immediately. One of the following events is
* propagated to the event handler registered with @ref ifx_i2c_tl_init
*
* @param[in,out] p_ctx Pointer to ifx i2c context.
* @param[in] p_packet Buffer containing the packet header.
* @param[in] packet_len Packet header length.
* @param[in] p_recv_packet Buffer containing the packet payload.
* @param[in] recv_packet_len Packet payload length.
*
* @retval IFX_I2C_STACK_SUCCESS If function was successful.
* @retval IFX_I2C_STACK_ERROR If the module is busy.
*/
host_lib_status_t ifx_i2c_tl_transceive(ifx_i2c_context_t *p_ctx,uint8_t* p_packet, uint16_t packet_len,
uint8_t* p_recv_packet, uint16_t* recv_packet_len);
/**
* @}
**/
#ifdef __cplusplus
}
#endif
#endif /* IFX_I2C_TRANSPORT_LAYER_H__ */

View File

@@ -0,0 +1,544 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
* \file
*
* \brief This file implements the prototype declarations of OPTIGA Crypt.
*
* \addtogroup grOptigaCrypt
* @{
*/
#ifndef _OPTIGA_CRYPT_H_
#define _OPTIGA_CRYPT_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "optiga/common/Datatypes.h"
#include "optiga/cmd/CommandLib.h"
/**
* OPTIGA crypt module return values
*/
///OPTIGA crypt API execution is successful
#define OPTIGA_CRYPT_SUCCESS (0x0000)
///OPTIGA crypt module in busy state
#define OPTIGA_CRYPT_BUSY (0x0001)
///OPTIGA crypt API failed
#define OPTIGA_CRYPT_ERROR (0x0402)
///OPTIGA crypt API called with invalid inputs
#define OPTIGA_CRYPT_ERROR_INVALID_INPUT (0x0403)
///OPTIGA crypt API called with insufficient memory buffer
#define OPTIGA_CRYPT_ERROR_MEMORY_INSUFFICIENT (0x0404)
///OPTIGA crypt API called when, a request of same instance is already in service
#define OPTIGA_CRYPT_ERROR_INSTANCE_IN_USE (0x0405)
/**
* \brief Typedef for Key IDs
* The KEY_STORE_ID_xxx holds only private key
*
* The SESSION_ID_xxx can hold private key, premaster secret(ECDH) and master secret(PRF).
* But only one at a time.
*/
typedef enum optiga_key_id
{
/// Key from key store (non-volatile)
OPTIGA_KEY_STORE_ID_E0F0 = 0xE0F0,
/// Key from key store (non-volatile)
OPTIGA_KEY_STORE_ID_E0F1 = 0xE0F1,
/// Key from key store (non-volatile)
OPTIGA_KEY_STORE_ID_E0F2 = 0xE0F2,
/// Key from key store (non-volatile)
OPTIGA_KEY_STORE_ID_E0F3 = 0xE0F3,
/// Key from Session context id 1 (volatile)
OPTIGA_SESSION_ID_E100 = 0xE100,
/// Key from Session context id 2 (volatile)
OPTIGA_SESSION_ID_E101 = 0xE101,
/// Key from Session context id 3 (volatile)
OPTIGA_SESSION_ID_E102 = 0xE102,
/// Key from Session context id 4 (volatile)
OPTIGA_SESSION_ID_E103 = 0xE103,
} optiga_key_id_t;
/**
* OPTIGA Random Generation types
*/
typedef enum optiga_rng_types
{
/// Generate Random data using TRNG
OPTIGA_RNG_TYPE_TRNG = 0x00,
/// Generate Random data using DRNG
OPTIGA_RNG_TYPE_DRNG = 0x01,
} optiga_rng_types_t;
typedef enum optiga_ecc_curve
{
//TBD: values to be aligned as per the specification
///
OPTIGA_ECC_NIST_P_256 = 0x03,
///
OPTIGA_ECC_NIST_P_384 = 0x04,
} optiga_ecc_curve_t;
typedef enum optiga_key_usage
{
/// This enables the private key for the signature generation as part of authentication commands
OPTIGA_KEY_USAGE_AUTHENTICATION = 0x01,
/// This enables the private key for the signature generation
OPTIGA_KEY_USAGE_SIGN = 0x10,
/// This enables the private key for key agreement (e.g. ecdh operations)
OPTIGA_KEY_USAGE_KEY_AGREEMENT = 0x20,
} optiga_key_usage_t;
/**
* \brief To specify the hash context information.
*/
typedef struct optiga_hash_context
{
///buffer to hold the context data
uint8_t * context_buffer;
///context length
uint16_t context_buffer_length;
///hashing algorithm
uint8_t hash_algo;
} optiga_hash_context_t;
/**
* \brief Specifies the hashing algorithm type in OPTIGA.
*/
typedef enum optiga_hash_type
{
/// Hash algorithm type SHA256
OPTIGA_HASH_TYPE_SHA_256 = 0xE2
} optiga_hash_type_t;
/** @brief Data is provided by host*/
#define OPTIGA_CRYPT_HOST_DATA (0x01)
/** @brief Data in internal to optiga OID */
#define OPTIGA_CRYPT_OID_DATA (0x00)
/**
* \brief To specify the data coming from the host for hashing.
*/
typedef struct hash_data_from_host
{
/// data for hashing
const uint8_t * buffer;
/// data length for hashing
uint32_t length;
} hash_data_from_host_t;
/**
* \brief To specify the data object for hashing.
*/
typedef struct hash_data_in_optiga
{
///OID of data object
uint16_t oid;
///Offset within the data object
uint16_t offset;
///Number of data bytes starting from the offset
uint16_t length;
} hash_data_in_optiga_t;
/**
* \brief To specifiy the Public Key details (key, size and algorithm)
*/
typedef struct public_key_from_host
{
/// Public Key
uint8_t * public_key;
/// Length of public key
uint16_t length;
/// Public key algorithm
uint8_t curve;
} public_key_from_host_t;
/**
* \brief To specify the OID which holds the shared secret.
*/
typedef struct key_from_opitga
{
///
uint16_t key_oid;
} optiga_shared_secret_t;
/**
* @brief Generates a random number.
*
* Generates the requested random stream of data for the user provided length.<br>
*
*
*<b>Pre Conditions:</b>
* - The application on OPTIGA must be opened using optiga_util_open_application before using this API.<br>
*
*<b>API Details:</b>
* - Invokes optiga_cmd_get_random API, based on the input arguments to retrieve random data .<br>
*<br>
*
*<b>Notes:</b>
* - Error codes from lower layers will be returned as it is.<br>
* - The maximum value of the <b>random_data_length</b> parameter is size of buffer <b>random_data</b>.
* In case the value is greater than buffer size, memory corruption can occur.<br>
*
* \param[in] rng_type Type of random data generator.
* - The input must be from optiga_rng_type.
* - Argument check for rng_type is not done since OPTIGA will provide an error for invalid rng_type.
* \param[in,out] random_data Pointer to the buffer into which random data is stored, must not be NULL.
* \param[in] random_data_length Length of random data to be generated.
* - Range should be 8 - 256 bytes.
* - Length validation is not done, since OPTIGA will provide an error for invalid random_data_length.
*
* \retval OPTIGA_CRYPT_SUCCESS Successful invocation of optiga cmd module
* \retval OPTIGA_CRYPT_ERROR_INVALID_INPUT Wrong Input arguments provided
* \retval OPTIGA_CRYPT_ERROR_INSTANCE_IN_USE Same instance with ongoing request servicing is used
* \retval OPTIGA_DEVICE_ERROR Command execution failure in OPTIGA and the LSB indicates the error code.(Refer Solution Reference Manual)
*/
LIBRARY_EXPORTS optiga_lib_status_t optiga_crypt_random(optiga_rng_types_t rng_type,
uint8_t * random_data,
uint16_t random_data_length);
/**
*
* @brief Initializes a hash context.
*
* Sets up a hash context and exports it.<br>
*
*<b>Pre Conditions:</b>
* - The application on OPTIGA must be opened using optiga_util_open_application before using this API.<br>
*
*<b>API Details:</b><br>
* - Initializes a new hash context.<br>
* - Exports the hash context to caller.<br>
*
*<b>Notes:</b><br>
* - Error codes from lower layer will be returned as it is.<br>
* - User must save the output hash context for further usage as OPTIGA does not store it internally.<br>
*
*<br>
* \param[inout] hash_ctx Pointer to optiga_hash_context_t to store the hash context from OPTIGA
* - The input <b>hash_algo</b> in <b>hash_ctx</b> must be from optiga_hash_type.
*
* \retval OPTIGA_CRYPT_SUCCESS Successful invocation of optiga cmd module
* \retval OPTIGA_CRYPT_ERROR_INVALID_INPUT Wrong Input arguments provided
* \retval OPTIGA_CRYPT_ERROR_INSTANCE_IN_USE Same instance with ongoing request servicing is used
* \retval OPTIGA_DEVICE_ERROR Command execution failure in OPTIGA and the LSB indicates the error code.(Refer Solution Reference Manual)
*/
LIBRARY_EXPORTS optiga_lib_status_t optiga_crypt_hash_start(optiga_hash_context_t * hash_ctx);
/**
*
* @brief Updates a hash context with the input data.
*
* Updates hashing for the given data and hash context then export the updated hash context.<br>
*
*
*<b>Pre Conditions:</b>
* - The application on OPTIGA must be opened using optiga_util_open_application before using this API.<br>
* - optiga_hash_context_t from optiga_crypt_hash_start or optiga_crypt_hash_update must be available.
*
*<b>API Details:</b><br>
* - Update the input hash context.<br>
* - Exports the hash context to caller.<br>
*
*<b>Notes:</b><br>
* - Error codes from lower layer will be returned as it is.<br>
* - User must save the output hash context for further usage as OPTIGA does not store it internally.<br>
*
*<br>
* \param[in] hash_ctx Pointer to optiga_hash_context_t containing hash context from OPTIGA, must not be NULL
* \param[in] source_of_data_to_hash Data from host / Data in optiga. Must be one of the below
* - OPTIGA_CRYPT_HOST_DATA,if source of data is from Host.
* - OPTIGA_CRYPT_OID_DATA,if the source of data is from OPITGA.
* \param[in] data_to_hash Data for hashing either in hash_data_from_host or in hash_data_in_optiga
*
* \retval OPTIGA_CRYPT_SUCCESS Successful invocation of optiga cmd module
* \retval OPTIGA_CRYPT_ERROR_INVALID_INPUT Wrong Input arguments provided
* \retval OPTIGA_CRYPT_ERROR_INSTANCE_IN_USE Same instance with ongoing request servicing is used
* \retval OPTIGA_DEVICE_ERROR Command execution failure in OPTIGA and the LSB indicates the error code.(Refer Solution Reference Manual)
*/
LIBRARY_EXPORTS optiga_lib_status_t optiga_crypt_hash_update(optiga_hash_context_t * hash_ctx,
uint8_t source_of_data_to_hash,
void * data_to_hash);
/**
*
* @brief Finalizes and exports the hash output.
*
* Finalizes the hash context and returns hash as output.<br>
*
*<b>Pre Conditions:</b>
* - The application on OPTIGA must be opened using optiga_util_open_application before using this API.<br>
* - optiga_hash_context_t from optiga_crypt_hash_start or optiga_crypt_hash_update must be available.
*
*<b>API Details:</b><br>
* - Finalize the hash from the input hash context
* - Exports the finalized hash.
*
*<b>Notes:</b><br>
* - Error codes from lower layer will be returned as it is.<br>
* - hash context is not updated by this API. This can be used later to fulfill intermediate hash use-cases<br>
* - User must save the output hash context for further usage as OPTIGA does not store it internally.<br>
*
*<br>
* \param[in] hash_ctx Pointer to optiga_hash_context_t containing hash context from OPTIGA, must not be NULL
* \param[inout] hash_output Output Hash
*
* \retval OPTIGA_CRYPT_SUCCESS Successful invocation of optiga cmd module
* \retval OPTIGA_CRYPT_ERROR_INVALID_INPUT Wrong Input arguments provided
* \retval OPTIGA_CRYPT_ERROR_INSTANCE_IN_USE Same instance with ongoing request servicing is used
* \retval OPTIGA_DEVICE_ERROR Command execution failure in OPTIGA and the LSB indicates the error code.(Refer Solution Reference Manual)
*/
LIBRARY_EXPORTS optiga_lib_status_t optiga_crypt_hash_finalize(optiga_hash_context_t * hash_ctx,
uint8_t * hash_output);
/**
*
* @brief Generates an key pair based on ECC curves.
*
* Generates an ECC key-pair based on the type of the key.<br>
*
*
*<b>Pre Conditions:</b>
* - The application on OPTIGA must be opened using optiga_util_open_application before using this API.<br>
*
*<b>API Details:</b>
* - Generate an ECC key pair using OPTIGA.<br>
* - If export is requested, Exports the private key else stores it in the input private key OID.<br>
* - Exports the public key always.<br>
*<br>
*
*<b>Notes:</b>
* - Error codes from lower layers will be returned as it is.<br>
*
* \param[in] curve_id ECC curve id.
* \param[in] key_usage Key usage defined by optiga_key_usage_t.
* - Values from optiga_key_usage can be logically ORed and passed.<br>
* - It is ignored if export_private_key is FALSE (0).
* \param[in] export_private_key TRUE (1) - Exports both private key and public key to the host.<br>
* FALSE (0) - Exports only public key to the host. The input key_usage is ignored.
* \param[in] private_key Buffer to store private key or private key OID of OPTIGA, must not be NULL.
* - If export_private_key is TRUE, assign pointer to a buffer to store private key.
* - The size of the buffer must be sufficient enough to accommodate the key type and additional DER encoding formats.
* - If export_private_key is FALSE, assign pointer to variable of type optiga_key_id_t.
* \param[in,out] public_key Buffer to store public key, must not be NULL.
* \param[in] public_key_length Initially set as length of public_key, later updated as actual length of public_key.
*
* \retval OPTIGA_CRYPT_SUCCESS Successful invocation of optiga cmd module
* \retval OPTIGA_CRYPT_ERROR_INVALID_INPUT Wrong Input arguments provided
* \retval OPTIGA_CRYPT_ERROR_INSTANCE_IN_USE Same instance with ongoing request servicing is used
* \retval OPTIGA_DEVICE_ERROR Command execution failure in OPTIGA and the LSB indicates the error code.(Refer Solution Reference Manual)
*/
LIBRARY_EXPORTS optiga_lib_status_t optiga_crypt_ecc_generate_keypair(optiga_ecc_curve_t curve_id,
uint8_t key_usage,
bool_t export_private_key,
void * private_key,
uint8_t * public_key,
uint16_t * public_key_length);
/**
*
* @brief Generates a signature for the given digest.
*
* Generates a signature for the given digest using private key stored in OPTIGA.<br>
*
*
*<b>Pre Conditions:</b>
* - The application on OPTIGA must be opened using optiga_util_open_application before using this API.<br>.
*
*<b>API Details:</b>
* - Generated signature for the input digest.<br>
* - Exports the generated signature.<br>
*<br>
*
*<b>Notes:</b>
* - Error codes from lower layers will be returned as it is.<br>
*
* \param[in] digest Digest on which signature is generated.
* \param[in] digest_length Length of the input digest.
* \param[in] private_key Private key OID to generate signature.
* \param[in,out] signature Generated signature, must not be NULL.
* - The size of the buffer must be sufficient enough to accommodate the additional DER encoding formatting for R and S components of signature.
* \param[in] signature_length Length of signature.Intial value set as length of buffer, later updated as the actual length of generated signature.
*
* \retval OPTIGA_CRYPT_SUCCESS Successful invocation of optiga cmd module
* \retval OPTIGA_CRYPT_ERROR_INVALID_INPUT Wrong Input arguments provided
* \retval OPTIGA_CRYPT_ERROR_INSTANCE_IN_USE Same instance with ongoing request servicing is used
* \retval OPTIGA_DEVICE_ERROR Command execution failure in OPTIGA and the LSB indicates the error code.(Refer Solution Reference Manual)
*/
LIBRARY_EXPORTS optiga_lib_status_t optiga_crypt_ecdsa_sign(uint8_t * digest,
uint8_t digest_length,
optiga_key_id_t private_key,
uint8_t * signature,
uint16_t * signature_length);
/**
*
* @brief Verifies the signature over the given digest.
*
* Verifies the signature over a given digest provided with the input data.<br>
*
*<b>Pre Conditions:</b>
* - The application on OPTIGA must be opened using optiga_util_open_application.<br>
*
*<b>API Details:</b>
* - Verifies the signature over the given provided with the input data using public key.
*
*<b>Notes:</b>
* - Error codes from lower layers will be returned as it is to the application.<br>
*
* \param[in] digest Pointer to a given digest buffer, must not be NULL.
* \param[in] digest_length Length of digest
* \param[in] signature Pointer to a given signature buffer, must not be NULL.
* \param[in] signature_length Length of signature
* \param[in] public_key_source_type Public key from host / public key of certificate OID from OPTIGA. Value must be one of the below
* - OPTIGA_CRYPT_OID_DATA, if the public key is to used from the certificate data object from OPTIGA.
* - OPTIGA_CRYPT_HOST_DATA, if the public key is provided by host.
* \param[in] public_key Public key from host / public key of certificate OID. Value must be one of the below
* - For certificate OID, pointer OID value must be passed.
* - For Public key from host, pointer to public_key_from_host_t instance.
*
* \retval OPTIGA_CRYPT_SUCCESS Successful invocation of optiga cmd module
* \retval OPTIGA_CRYPT_ERROR_INVALID_INPUT Wrong Input arguments provided
* \retval OPTIGA_CRYPT_ERROR_INSTANCE_IN_USE Same instance with ongoing request servicing is used
* \retval OPTIGA_DEVICE_ERROR Command execution failure in OPTIGA and the LSB indicates the error code.(Refer Solution Reference Manual)
*/
LIBRARY_EXPORTS optiga_lib_status_t optiga_crypt_ecdsa_verify(uint8_t * digest,
uint8_t digest_length,
uint8_t * signature,
uint16_t signature_length,
uint8_t public_key_source_type,
void * public_key);
/**
* @brief Calculates the shared secret using ECDH algorithm.
*
* Calculates the shared secret using ECDH algorithm.<br>
*
*
*<b>Pre Conditions:</b>
* - The application on OPTIGA must be opened using optiga_util_open_application.<br>
* - There must be a secret available in the "session context / data object OID" provided as input parameter.<br>
*
*<b>API Details:</b>
* - Calculates the shared secret based on input private key object ID and public key.<br>
* - Based on user request(export_to_host), the shared secret can either be exported to the host or be stored in the acquired session object ID.<br>
*<br>
*
*<b>Notes:</b>
* - Error codes from lower layers will be returned as it is.<br>
* - The buffer size for shared secret should be appropriately provided by the user
* - If the user provides <b>private_key</b> as session based and <b>export_to_host</b> as FALSE,<br>
* then the shared secret generated will overwrite the private key stored in the session object ID
*
* \param[in] private_key Object ID of the private key stored in OPTIGA.<br>
* - Possible values are from the optiga_key_id_t <br>
* - Argument check for private_key is not done since OPTIGA will provide an error for invalid private_key.
* \param[in] public_key Pointer to the public key structure for shared secret generation with its properties, must not be NULL.<br>
* - Provide the inputs according to the structure type public_key_from_host_t
* \param[in] export_to_host TRUE (1) - Exports the generated shared secret to Host. <br>
* FALSE (0) - Stores the generated shared secret into the session object ID acquired by the instance.
* \param[in,out] shared_secret Pointer to the shared secret buffer, only if <b>export_to_host</b> is TRUE. <br>
* Otherwise supply NULL as input.
*
* \retval OPTIGA_CRYPT_SUCCESS Successful invocation of optiga cmd module
* \retval OPTIGA_CRYPT_ERROR_INVALID_INPUT Wrong Input arguments provided
* \retval OPTIGA_CRYPT_ERROR_INSTANCE_IN_USE Same instance with ongoing request servicing is used
* \retval OPTIGA_DEVICE_ERROR Command execution failure in OPTIGA and the LSB indicates the error code.(Refer Solution Reference Manual)
*/
LIBRARY_EXPORTS optiga_lib_status_t optiga_crypt_ecdh(optiga_key_id_t private_key,
public_key_from_host_t * public_key,
bool_t export_to_host,
uint8_t * shared_secret);
/**
* @brief Derives a key.
*
* Derives a key using the secret stored in OPTIGA.<br>
*
*<b>Pre Conditions:</b>
* - The application on OPTIGA must be opened using optiga_util_open_application.<br>
* - There must be a secret available in the "session context / data object OID" provided as input parameter.<br>
* - An instance of optiga_crypt_t must be created using the optiga_crypt_create API.
*
*<b>API Details:</b>
* - Derives a key using the secret stored in OPTIGA.
* - Provides the options to store the derived key into OPTIGA session context or export to the host.
* - It invokes the callback handler of the instance, when it is asynchronously completed.
*
*<b>Notes:</b>
* - At present, the minimum length of the output derived key is 16.
* - Error codes from lower layers will be returned as it is to the application.<br>
*
* \param[in] secret Object ID of the secret stored in OPTIGA.
* - OPTIGA_KEY_ID_SESSION_BASED from optiga_key_id_t, indicates the secret is available.
* in the session context acquired by the instance.
* - or any OPTIGA data object ID(16 bit OID) which holds the secret.
* \param[in] label Pointer to the label, can be NULL if not applicable.
* \param[in] label_length Length of the label.
* \param[in] seed Valid pointer to the seed, must not be NULL.
* \param[in] seed_length Length of the seed.
* \param[in] derived_key_length Length of derived key.
* \param[in] export_to_host TRUE (1) - Exports the derived key to Host. <br>
* FALSE (0) - Stores the derived key into the session object ID acquired by the instance.
* \param[in,out] derived_key Pointer to the valid buffer with a minimum size of derived_key_length,
* in case of exporting the key to host(<b>export_to_host= TRUE</b>). Otherwise set to NULL.
*
* \retval OPTIGA_CRYPT_SUCCESS Successful invocation of optiga cmd module
* \retval OPTIGA_CRYPT_ERROR_INVALID_INPUT Wrong Input arguments provided
* \retval OPTIGA_CRYPT_ERROR_INSTANCE_IN_USE Same instance with ongoing request servicing is used
* \retval OPTIGA_DEVICE_ERROR Command execution failure in OPTIGA and the LSB indicates the error code.(Refer Solution Reference Manual)
*/
LIBRARY_EXPORTS optiga_lib_status_t optiga_crypt_tls_prf_sha256(uint16_t secret,
uint8_t * label,
uint16_t label_length,
uint8_t * seed,
uint16_t seed_length,
uint16_t derived_key_length,
bool_t export_to_host,
uint8_t * derived_key);
#ifdef __cplusplus
}
#endif
#endif //_OPTIGA_CRYPT_H_
/**
* @}
*/

View File

@@ -0,0 +1,210 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file
*
* \brief This file defines APIs, types and data structures used in the
* OCP implementation.
*
* \addtogroup grOCP
* @{
*/
#ifndef __OCP_H__
#define __OCP_H__
/// @cond hidden
#ifndef _OPTIGA_EXPORTS_DLLEXPORT_H_
#define _OPTIGA_EXPORTS_DLLEXPORT_H_
#if defined(WIN32) || defined(_WIN32)
#ifdef OPTIGA_LIB_EXPORTS
#define LIBRARY_EXPORTS __declspec(dllexport)
#else
#define LIBRARY_EXPORTS __declspec(dllimport)
#endif // OPTIGA_LIB_EXPORTS
#else
#define LIBRARY_EXPORTS
#endif //WIN32
#endif /*_OPTIGA_EXPORTS_DLLEXPORT_H_*/
/// @endcond
#include "optiga/common/Datatypes.h"
#include "optiga/dtls/OcpCommon.h"
#include "optiga/dtls/OcpCommonIncludes.h"
#ifdef MODULE_ENABLE_DTLS_MUTUAL_AUTH
/****************************************************************************
*
* API Error Codes
*
****************************************************************************/
/// Successful execution
#define OCP_LIB_OK 0x75282512
/// Failure in execution
#define OCP_LIB_ERROR 0xF3053159
/// Null Parameter(s)
#define OCP_LIB_NULL_PARAM BASE_ERROR_OCPLAYER
/// Unsupported Configuration
#define OCP_LIB_UNSUPPORTED_CONFIG (BASE_ERROR_OCPLAYER + 1)
/// Connection already exists
#define OCP_LIB_CONNECTION_ALREADY_EXISTS (BASE_ERROR_OCPLAYER + 2)
/// Session ID not available
#define OCP_LIB_SESSIONID_UNAVAILABLE (BASE_ERROR_OCPLAYER + 3)
/// Memory Allocation failure
#define OCP_LIB_MALLOC_FAILURE (BASE_ERROR_OCPLAYER + 4)
/// Unsupported PMTU Value
#define OCP_LIB_UNSUPPORTED_PMTU (BASE_ERROR_OCPLAYER + 5)
/// Unsupported Mode
#define OCP_LIB_UNSUPPORTED_MODE (BASE_ERROR_OCPLAYER + 6)
///Authentication not done
#define OCP_LIB_AUTHENTICATION_NOTDONE (BASE_ERROR_OCPLAYER + 7)
///Data Length is greater than the maximum length
#define OCP_LIB_INVALID_LEN (BASE_ERROR_OCPLAYER + 8)
///Data Length is equal to zero
#define OCP_LIB_LENZERO_ERROR (BASE_ERROR_OCPLAYER + 9)
///Memory is not sufficient
#define OCP_LIB_INSUFFICIENT_MEMORY (BASE_ERROR_OCPLAYER + 10)
///Invalid timeout value
#define OCP_LIB_INVALID_TIMEOUT (BASE_ERROR_OCPLAYER + 11)
///Timeout occured
#define OCP_LIB_TIMEOUT (BASE_ERROR_OCPLAYER + 12)
///requested operation not allowed
#define OCP_LIB_OPERATION_NOT_ALLOWED (BASE_ERROR_OCPLAYER + 13)
///Decryption failure
#define OCP_LIB_DECRYPT_FAILURE (BASE_ERROR_OCPLAYER + 14)
///No renegotiation supported
#define OCP_LIB_NO_RENEGOTIATE (BASE_ERROR_OCPLAYER + 15)
/****************************************************************************
*
* Common data structure used across all functions.
*
****************************************************************************/
/**
* \brief Enumeration for supported OCP Configurations
*/
typedef enum eConfiguration_d
{
///DTLS 1.2 protocol over UDP using Hardware crypto
eDTLS_12_UDP_HWCRYPTO = 0x85,
///TLS 1.2 protocol over TCP using Hardware crypto
eTLS_12_TCP_HWCRYPTO = 0x49
}eConfiguration_d;
/**
* \brief Structure to that hold network related information
*/
typedef struct sNetworkParams_d
{
///Port Number
uint16_t wPort;
///IP Address
char_t* pzIpAddress;
///Network Pmtu
uint16_t wMaxPmtu;
}sNetworkParams_d;
/**
* \brief Structure to Configure OCP Library
*/
typedef struct sConfigOCP_d
{
///Callback function pointer to get Unix time
fGetUnixTime_d pfGetUnixTIme;
///Network connection structure
sNetworkParams_d sNetworkParams;
///Mode of operation
eMode_d eMode;
///Configuration of mode
eConfiguration_d eConfiguration;
///Logger
sLogger_d sLogger;
///Certificate OID
uint16_t wOIDDevCertificate;
///Private key OID
uint16_t wOIDDevPrivKey;
}sAppOCPConfig_d;
/**
* \brief Initializes the OCP Library.
*/
LIBRARY_EXPORTS int32_t OCP_Init(const sAppOCPConfig_d* PpsAppOCPConfig,hdl_t* PphAppOCPCtx);
/**
* \brief Connect to server and performs a Handshake.
*/
LIBRARY_EXPORTS int32_t OCP_Connect(const hdl_t PhAppOCPCtx);
/**
* \brief Sends Application data.
*/
LIBRARY_EXPORTS int32_t OCP_Send(const hdl_t PhAppOCPCtx,const uint8_t* PpbData,uint16_t PwLen);
/**
* \brief Receives Application data.
*/
LIBRARY_EXPORTS int32_t OCP_Receive(const hdl_t PhAppOCPCtx,uint8_t* PpbData,uint16_t* PpwLen, uint16_t PwTimeout);
/**
* \brief Disconnects from server.
*/
LIBRARY_EXPORTS int32_t OCP_Disconnect(hdl_t PhAppOCPCtx);
#endif /* MODULE_ENABLE_DTLS_MUTUAL_AUTH*/
#endif //__OCP_H__
/**
* @}
*/

View File

@@ -0,0 +1,323 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
* \file
*
* \brief This file defines APIs, types and data structures used in the OPTIGA UTIL module.
*
* \addtogroup grOptigaUtil
* @{
*/
#ifndef _H_OPTIGA_UTIL_H_
#define _H_OPTIGA_UTIL_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "optiga/common/Datatypes.h"
#include "optiga/cmd/CommandLib.h"
#include "optiga/common/AuthLibSettings.h"
///Requested operation completed without any error
#define INT_LIB_OK 0x75AB1C02
///Null parameter(s)
#define INT_LIB_NULL_PARAM 0x80002001
///Invalid data in response
#define INT_LIB_INVALID_RESPONSE (INT_LIB_NULL_PARAM + 1)
///Invalid access condition
#define INT_LIB_INVALID_AC (INT_LIB_NULL_PARAM + 2)
///Length of input is zero
#define INT_LIB_ZEROLEN_ERROR (INT_LIB_NULL_PARAM + 3)
///Invalid or unsupported parameter(s)
#define INT_LIB_INVALID_PARAM (INT_LIB_NULL_PARAM + 4)
///Invalid Length
#define INT_LIB_INVALID_LENGTH (INT_LIB_NULL_PARAM + 5)
///Malloc Failures
#define INT_LIB_MALLOC_FAILURE (INT_LIB_NULL_PARAM + 6)
///General error
#define INT_LIB_ERROR 0xFE5A5502
/// Option to only write the data object
#define OPTIGA_UTIL_WRITE_ONLY (0x00)
/// Option to erase and write the data object
#define OPTIGA_UTIL_ERASE_AND_WRITE (0x40)
/**
* OPTIGA util module return values
*/
///OPTIGA util API execution is successful
#define OPTIGA_UTIL_SUCCESS (0x0000)
///OPTIGA util module in busy state
#define OPTIGA_UTIL_BUSY (0x0001)
///OPTIGA util API failed
#define OPTIGA_UTIL_ERROR (0x0302)
///OPTIGA util API called with invalid inputs
#define OPTIGA_UTIL_ERROR_INVALID_INPUT (0x0303)
///OPTIGA util API called with insufficient memory buffer
#define OPTIGA_UTIL_ERROR_MEMORY_INSUFFICIENT (0x0304)
///OPTIGA util API called when, a request of same instance is already in service
#define OPTIGA_UTIL_ERROR_INSTANCE_IN_USE (0x0305)
/**
* \brief Typedef for OIDs
*/
typedef enum eOID_d
{
/// Global Life Cycle State
eLCS_G = 0xE0C0,
/// Global Security Status
eSECURITY_STATUS_G = 0xE0C1,
/// Coprocessor UID
eCOPROCESSOR_UID = 0xE0C2,
/// Global Life Cycle State
eSLEEP_MODE_ACTIVATION_DELAY = 0xE0C3,
/// Current limitation
eCURRENT_LIMITATION = 0xE0C4,
/// Security Event Counter
eSECURITY_EVENT_COUNTER = 0xE0C5,
/// Device Public Key Certificate issued by IFX
eDEVICE_PUBKEY_CERT_IFX = 0xE0E0,
/// Project-Specific device Public Key Certificate
eDEVICE_PUBKEY_CERT_PRJSPC_1 = 0xE0E1,
/// Project-Specific device Public Key Certificate
eDEVICE_PUBKEY_CERT_PRJSPC_2 = 0xE0E2,
/// Project-Specific device Public Key Certificate
eDEVICE_PUBKEY_CERT_PRJSPC_3 = 0xE0E3,
/// First Device Private Key
eFIRST_DEVICE_PRIKEY_1 = 0xE0F0,
/// First Device Private Key
eFIRST_DEVICE_PRIKEY_2 = 0xE0F1,
/// First Device Private Key
eFIRST_DEVICE_PRIKEY_3 = 0xE0F2,
/// First Device Private Key
eFIRST_DEVICE_PRIKEY_4 = 0xE0F3,
/// Application Life Cycle Status
eLCS_A = 0xF1C0,
/// Application Security Status
eSECURITY_STATUS_A = 0xF1C1,
/// Error codes
eERROR_CODES = 0xF1C2
} eOID_d;
/**
* @brief Initializes the communication with optiga.
*
* Initializes the communication with OPTIGA for the given instance. <br>
*
*<b>Pre Conditions:</b>
*
*<b>API Details:</b>
* - Initiate open application command to optiga.<br>
*<br>
*
*<b>Notes:</b><br>
* Initialisation flow example:
*
* optiga_comms_t optiga_comms = {(void*)&ifx_i2c_context_0, NULL, NULL, 0};
*
* static int32_t optiga_init(void)
* {
* int32_t status = (int32_t) OPTIGA_LIB_ERROR;
*
* do
* {
* status = optiga_util_open_application(&optiga_comms);
* if(OPTIGA_LIB_SUCCESS != status)
* {
* // optiga_util_open_application() failed
* break;
* }
*
* status = OPTIGA_LIB_SUCCESS;
* } while(0);
*
* return status;
* }
*
* \param[in] p_comms Pointer to the communication parameters initialised before
* - Error codes from lower layer will be returned as it is.<br>
*
* \retval OPTIGA_LIB_SUCCESS Successful invocation of optiga cmd module
* \retval OPTIGA_LIB_ERROR Error during function execurition
* \retval OPTIGA_DEVICE_ERROR Command execution failure in OPTIGA and the LSB indicates the error code.(Refer Solution Reference Manual)
*/
LIBRARY_EXPORTS optiga_lib_status_t optiga_util_open_application(optiga_comms_t* p_comms);
/**
* @brief Reads data from optiga.
*
* Retrieves the requested data that is stored from the user provided data object.<br>
*
*
*<b>Pre Conditions:</b>
* - The application on OPTIGA must be opened using optiga_util_open_application before using this API.<br>
*
*<b>API Details:</b>
* - Invokes optiga_cmd_get_data_object API, based on the input arguments to read the data from the data object.<br>
*<br>
*
*<b>Notes:</b>
* - Error codes from lower layers will be returned as it is.<br>
* - The maximum value of the <b>*bytes_to_read</b> parameter is size of buffer <b>p_buffer</b>. In case the value is greater than buffer size, memory corruption can occur.<br>
* - <b>*bytes_to_read</b> parameter is set to 0, in case any errors occurs while retrieving the data. initially contains the value of the user provided data length to be read. When the data is successfully retrieved, this value is updated with actual data length retrieved.<br>
* In case of any errors, the value is set to 0.<br>
*
* \param[in] optiga_oid OID of data object
* - It should be a valid data object, otherwise OPTIGA returns an error.<br>
* \param[in] offset Offset from within data object
* - It must be valid offset from within data object, otherwise OPTIGA returns an error.<br>
* \param[in,out] buffer Valid pointer to the buffer to which data is read
* \param[in,out] bytes_to_read Valid pointer to the length of data to be read from data object
* - When the data is successfully retrieved, it is updated with actual data length retrieved
*
* \retval OPTIGA_UTIL_SUCCESS Successful invocation of optiga cmd module
* \retval OPTIGA_UTIL_ERROR_INVALID_INPUT Wrong Input arguments provided
* \retval OPTIGA_DEVICE_ERROR Command execution failure in OPTIGA and the LSB indicates the error code.(Refer Solution Reference Manual)
*/
LIBRARY_EXPORTS optiga_lib_status_t optiga_util_read_data(uint16_t optiga_oid,
uint16_t offset,
uint8_t * buffer,
uint16_t * bytes_to_read);
/**
* @brief Reads metadata of a data object from optiga.
*
* Reads the metadata of the user provided data object.<br>
*
*<b>Pre Conditions:</b>
* - The application on OPTIGA must be opened using optiga_util_open_application before using this API.<br>
*
*<b>API Details:</b>
* - Invokes optiga_cmd_get_data_object API, based on the input arguments to read the metadata from the data object.<br>
*<br>
*
*<b>Notes:</b>
* - Error codes from lower layers will be returned as it is.<br>
* - The metadata returned will be in TLV format.<br>
* - The maximum value of the <b>*bytes_to_read</b> parameter is size of buffer <b>p_buffer</b>. In case the value is greater than buffer size, memory corruption can occur.<br>
*
* \param[in] optiga_oid OID of data object
* - It should be a valid data object, otherwise OPTIGA returns an error.<br>
* \param[in,out] buffer Valid pointer to the buffer to which metadata is read
* \param[in,out] bytes_to_read Valid pointer to the length of metadata to be read from data object
* - When the metadata is successfully retrieved, it is updated with actual metadata length retrieved
*
* \retval OPTIGA_UTIL_SUCCESS Successful invocation of optiga cmd module
* \retval OPTIGA_UTIL_ERROR_INVALID_INPUT Wrong Input arguments provided
* \retval OPTIGA_UTIL_ERROR_INSTANCE_IN_USE Same instance with ongoing request servicing used
* \retval OPTIGA_DEVICE_ERROR Command execution failure in OPTIGA and the LSB indicates the error code.(Refer Solution Reference Manual)
*/
LIBRARY_EXPORTS optiga_lib_status_t optiga_util_read_metadata(uint16_t optiga_oid,
uint8_t * buffer,
uint16_t * bytes_to_read);
/**
* @brief Writes data to optiga.
*
* Writes the data provided by the user into the specified data object.<br>
*
*<b>Pre Conditions:</b>
* - The application on OPTIGA must be opened using optiga_util_open_application before using this API.<br>
*
*<b>API Details:</b>
* - Invokes optiga_cmd_set_data_object API, based on the input arguments to write the data to the data object.<br>
*<br>
*
*<b>Notes:</b>
* - Error codes from lower layers will be returned as it is.<br>
* - The maximum value of the <b>bytes_to_write parameter</b> is size of buffer <b>p_buffer</b>. In case the value is greater than buffer size, incorrect values can get written into the data object in OPTIGA.<br>
* - In case the write_type provided is other than <b>erase and write(0x00)</b> or <b>write only(0x40)</b>, the function returns OPTIGA_UTIL_ERROR.<br>
*
* \param[in] optiga_oid OID of data object
* - It should be a valid data object, otherwise OPTIGA returns an error.<br>
* \param[in] write_type Type of the write operation. Can be OPTIGA_UTIL_ERASE_AND_WRITE or OPTIGA_UTIL_WRITE_ONLY
* \param[in] offset Offset from within data object
* - It must be valid offset from within data object, otherwise OPTIGA returns an error.<br>
* \param[in,out] buffer Valid pointer to the buffer with user data to write
* \param[in] bytes_to_write Length of data to be written
*
* \retval OPTIGA_UTIL_SUCCESS Successful invocation of optiga cmd module
* \retval OPTIGA_UTIL_ERROR_INVALID_INPUT Wrong Input arguments provided
* \retval OPTIGA_UTIL_ERROR_INSTANCE_IN_USE Same instance with ongoing request servicing used
* \retval OPTIGA_CMD_ERROR_MEMORY_INSUFFICIENT Length of the buffer to copy the metadata is less than actual length of metadata
* \retval OPTIGA_DEVICE_ERROR Command execution failure in OPTIGA and the LSB indicates the error code.(Refer Solution Reference Manual)
*/
LIBRARY_EXPORTS optiga_lib_status_t optiga_util_write_data(uint16_t optiga_oid,
uint8_t write_type,
uint16_t offset,
uint8_t * buffer,
uint16_t bytes_to_write);
/**
* @brief Writes metadata for the user provided data object.
*
* Writes metadata for the user provided data object.
*
*<b>Pre Conditions:</b>
* - The application on OPTIGA must be opened using optiga_util_open_application before using this API.<br>
*
*<b>API Details:</b>
* - Invokes optiga_cmd_set_data_object API, based on the input arguments to write metadata to the data object.<br>
*<br>
*
*<b>Notes:</b>
* - Error codes from lower layers will be returned as it is.<br>
* - The maximum value of the <b>bytes_to_write</b> parameter is size of buffer <b>p_buffer</b>.
* In case the value is greater than buffer size, incorrect values can get written into the meta data of the data object in OPTIGA.<br>
* - The metadata to be written must be in TLV format <br>
*
* \param[in] optiga_oid OID of data object
* - It should be a valid data object, otherwise OPTIGA returns an error.<br>
* \param[in,out] buffer Valid pointer to the buffer with metadata to write
* \param[in] bytes_to_write Length of metadata to be written
*
* \retval OPTIGA_UTIL_SUCCESS Successful invocation of optiga cmd module
* \retval OPTIGA_UTIL_ERROR_INVALID_INPUT Wrong Input arguments provided
* \retval OPTIGA_UTIL_ERROR_INSTANCE_IN_USE Same instance with ongoing request servicing used
* \retval OPTIGA_DEVICE_ERROR Command execution failure in OPTIGA and the LSB indicates the error code.(Refer Solution Reference Manual)
*/
LIBRARY_EXPORTS optiga_lib_status_t optiga_util_write_metadata(uint16_t optiga_oid,
uint8_t * buffer,
uint8_t bytes_to_write);
#ifdef __cplusplus
}
#endif
#endif //_H_OPTIGA_UTIL_H_
/**
* @}
*/

View File

@@ -0,0 +1,74 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file
*
* \brief This file implements the prototype declarations of platform abstraction layer
*
* \addtogroup grPAL
* @{
*/
#ifndef _PAL_H_
#define _PAL_H_
/**********************************************************************************************************************
* HEADER FILES
*********************************************************************************************************************/
#include "optiga/common/Datatypes.h"
/**********************************************************************************************************************
* pal.h
*********************************************************************************************************************/
/**********************************************************************************************************************
* MACROS
*********************************************************************************************************************/
/// PAL API execution is successful
#define PAL_STATUS_SUCCESS (0x0000)
/// PAL API execution failed
#define PAL_STATUS_FAILURE (0x0001)
/// PAL I2C is busy
#define PAL_STATUS_I2C_BUSY (0x0002)
/**********************************************************************************************************************
* ENUMS
*********************************************************************************************************************/
/**
* \brief PAL return status.
*/
typedef uint16_t pal_status_t;
/**********************************************************************************************************************
* API Prototypes
*********************************************************************************************************************/
#endif /* _PAL_H_ */
/**
* @}
*/

View File

@@ -0,0 +1,93 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file
*
* \brief This file implements the prototype declarations of pal gpio
*
* \addtogroup grPAL
* @{
*/
#ifndef _PAL_GPIO_H_
#define _PAL_GPIO_H_
/**********************************************************************************************************************
* HEADER FILES
*********************************************************************************************************************/
#include "optiga/pal/pal.h"
/**********************************************************************************************************************
* MACROS
*********************************************************************************************************************/
/**********************************************************************************************************************
* ENUMS
*********************************************************************************************************************/
/**********************************************************************************************************************
* DATA STRUCTURES
*********************************************************************************************************************/
/**
* \brief Structure defines the PAL GPIO configuration.
*/
typedef struct pal_gpio
{
/// Pointer to gpio platform specific context/structure
void* p_gpio_hw;
} pal_gpio_t;
/**********************************************************************************************************************
* API Prototypes
*********************************************************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Sets the gpio pin to high state.
*/
void pal_gpio_set_high(const pal_gpio_t* p_gpio_context);
/**
* \brief Sets the gpio pin to Low state.
*/
void pal_gpio_set_low(const pal_gpio_t* p_gpio_context);
#ifdef __cplusplus
}
#endif
#endif /* _PAL_GPIO_H_ */
/**
* @}
*/

View File

@@ -0,0 +1,107 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file
*
* \brief This file implements the prototype declarations of pal i2c
*
* \addtogroup grPAL
* @{
*/
#ifndef _PAL_I2C_H_
#define _PAL_I2C_H_
/**********************************************************************************************************************
* HEADER FILES
*********************************************************************************************************************/
#include "optiga/pal/pal.h"
/**********************************************************************************************************************
* MACROS
*********************************************************************************************************************/
/// Event returned when I2C master completes execution
#define PAL_I2C_EVENT_SUCCESS (0x0000)
/// Event returned when I2C master operation fails
#define PAL_I2C_EVENT_ERROR (0x0001)
/// Event returned when lower level I2C bus is busy
#define PAL_I2C_EVENT_BUSY (0x0002)
/**********************************************************************************************************************
* ENUMS
*********************************************************************************************************************/
/**********************************************************************************************************************
* DATA STRUCTURES
*********************************************************************************************************************/
/** @brief PAL I2C context structure */
typedef struct pal_i2c
{
/// Pointer to I2C master platform specific context
void* p_i2c_hw_config;
/// I2C slave address
uint8_t slave_address;
/// Pointer to store the callers context information
void* upper_layer_ctx;
/// Pointer to store the callers handler
void* upper_layer_event_handler;
} pal_i2c_t;
/**********************************************************************************************************************
* API Prototypes
*********************************************************************************************************************/
/**
* @brief Initializes the I2C master.
*/
pal_status_t pal_i2c_init(const pal_i2c_t* p_i2c_context);
/**
* @brief Sets the I2C Master bitrate
*/
pal_status_t pal_i2c_set_bitrate(const pal_i2c_t* p_i2c_context, uint16_t bitrate);
//Dileep: "write on I2C bus" --> "write to I2C bus"
/**
* @brief Writes on I2C bus.
*/
pal_status_t pal_i2c_write(pal_i2c_t* p_i2c_context, uint8_t* p_data , uint16_t length);
/**
* @brief Reads from I2C bus.
*/
pal_status_t pal_i2c_read(pal_i2c_t* p_i2c_context, uint8_t* p_data , uint16_t length);
/**
* @brief De-initializes the I2C master.
*/
pal_status_t pal_i2c_deinit(const pal_i2c_t* p_i2c_context);
#endif /* _PAL_I2C_H_ */
/**
* @}
*/

View File

@@ -0,0 +1,64 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file
*
* \brief This file implements the platform abstraction layer extern declarations for ifx i2c.
*
* \addtogroup grPAL
* @{
*/
#ifndef _PAL_IFX_I2C_CONFIG_H_
#define _PAL_IFX_I2C_CONFIG_H_
/**********************************************************************************************************************
* HEADER FILES
*********************************************************************************************************************/
#include "optiga/pal/pal.h"
#include "optiga/pal/pal_i2c.h"
#include "optiga/pal/pal_gpio.h"
/**********************************************************************************************************************
* MACROS
*********************************************************************************************************************/
/**********************************************************************************************************************
* ENUMS
*********************************************************************************************************************/
/**********************************************************************************************************************
* PAL extern definitions for IFX I2C
*********************************************************************************************************************/
extern pal_i2c_t optiga_pal_i2c_context_0;
extern pal_gpio_t optiga_vdd_0;
extern pal_gpio_t optiga_reset_0;
#endif /* _PAL_IFX_I2C_CONFIG_H_ */
/**
* @}
*/

View File

@@ -0,0 +1,79 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
* \file
*
* \brief This file implements the prototype declarations of pal os event
*
* \addtogroup grPAL
* @{
*/
#ifndef _PAL_OS_EVENT_H_
#define _PAL_OS_EVENT_H_
/**********************************************************************************************************************
* HEADER FILES
*********************************************************************************************************************/
#include "optiga/common/Datatypes.h"
#include "optiga/pal/pal.h"
/**********************************************************************************************************************
* MACROS
*********************************************************************************************************************/
/**********************************************************************************************************************
* ENUMS
*********************************************************************************************************************/
/**********************************************************************************************************************
* PAL extern definitions
*********************************************************************************************************************/
/**
* @brief typedef for Callback function when timer elapses.
*/
typedef void (*register_callback)(void*);
#ifdef PAL_OS_HAS_EVENT_INIT
/**
* @brief Platform specific event init function.
*/
pal_status_t pal_os_event_init(void);
#endif
/**
* @brief Callback registration function to trigger once when timer expires.
*/
void pal_os_event_register_callback_oneshot(register_callback callback, void* callback_args, uint32_t time_us);
#endif //_PAL_OS_EVENT_H_
/**
* @}
*/

View File

@@ -0,0 +1,78 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file pal_os_lock.h
*
* \brief This file provides the prototype declarations of PAL OS lock functionalities
*
* \addtogroup grPAL
* @{
*/
#ifndef _PAL_OS_LOCK_H_
#define _PAL_OS_LOCK_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "pal.h"
/**
* @brief Acquires a lock.
*
*<b>Pre-conditions:</b>
* None.<br>
*
*<b>API Details:</b>
* - Acquires the lock.<br>
*<br>
*
*
*/
pal_status_t pal_os_lock_acquire(void);
/**
* @brief Releases the lock.
*
*<b>Pre-conditions:</b>
* None.<br>
*
*<b>API Details:</b>
* - Releases the lock.<br>
*<br>
*
*
*/
void pal_os_lock_release(void);
#ifdef __cplusplus
}
#endif
#endif //_PAL_OS_LOCK_H_
/**
* @}
*/

View File

@@ -0,0 +1,77 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file
*
* \brief This file implements the prototype declarations of pal os random functionalities
*
* \addtogroup grPAL
* @{
*/
#ifndef _PAL_OS_RANDOM_H_
#define _PAL_OS_RANDOM_H_
/**********************************************************************************************************************
* HEADER FILES
*********************************************************************************************************************/
#include "pal.h"
/**********************************************************************************************************************
* MACROS
*********************************************************************************************************************/
/**********************************************************************************************************************
* ENUMS
*********************************************************************************************************************/
/**********************************************************************************************************************
* DATA STRUCTURES
*********************************************************************************************************************/
/**********************************************************************************************************************
* API Prototypes
*********************************************************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Gets the random counter value.
*/
uint32_t pal_os_random_get_counter(void);
#ifdef __cplusplus
}
#endif
#endif /* _PAL_OS_RANDOM_H_ */
/**
* @}
*/

View File

@@ -0,0 +1,90 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file
*
* \brief This file implements the prototype declarations of pal os timer functionalities.
*
* \addtogroup grPAL
* @{
*/
#ifndef _PAL_OS_TIMER_H_
#define _PAL_OS_TIMER_H_
/**********************************************************************************************************************
* HEADER FILES
*********************************************************************************************************************/
#include "optiga/pal/pal.h"
/*********************************************************************************************************************
* pal_os_timer.h
*********************************************************************************************************************/
/**********************************************************************************************************************
* MACROS
*********************************************************************************************************************/
/**********************************************************************************************************************
* ENUMS
*********************************************************************************************************************/
/**********************************************************************************************************************
* DATA STRUCTURES
*********************************************************************************************************************/
/**********************************************************************************************************************
* API Prototypes
*********************************************************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Gets tick count value in milliseconds
*/
uint32_t pal_os_timer_get_time_in_milliseconds(void);
/**
* @brief Waits or delay until the supplied milliseconds
*/
void pal_os_timer_delay_in_milliseconds(uint16_t milliseconds);
#ifdef __cplusplus
}
#endif
#endif /* _PAL_OS_TIMER_H_ */
/**
* @}
*/

View File

@@ -0,0 +1,198 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file
*
* \brief This file implements the prototype declarations of pal socket functionalities
* \addtogroup grPAL
* @{
*/
#ifndef _PAL_SOCKET_H_
#define _PAL_SOCKET_H_
/**********************************************************************************************************************
* HEADER FILES
*********************************************************************************************************************/
#ifdef MODULE_ENABLE_DTLS_MUTUAL_AUTH
#ifndef WIN32
#include "optiga/common/Datatypes.h"
#include "udp.h"
#include "inet.h"
#else
#include <winsock2.h>
#include "optiga/common/Datatypes.h"
#endif
#include "optiga/common/ErrorCodes.h"
#include "optiga/dtls/UDPErrorCodes.h"
/// @cond hidden
/**********************************************************************************************************************
* MACROS
*********************************************************************************************************************/
#ifndef WIN32
#define IPAddressParse(pzIpAddress, psIPAddress) (inet_aton(pzIpAddress, psIPAddress))
#else
#define IPAddressParse(pzIpAddress, psIPAddress) (1)
#endif
/// @endcond
/**********************************************************************************************************************
* ENUMS
*********************************************************************************************************************/
/**********************************************************************************************************************
* DATA STRUCTURES
*********************************************************************************************************************/
#ifndef WIN32
/**
* \brief Pointer type definition of pal socket receive event callback
*/
typedef void (*pal_socket_event_listener)(void *arg, struct udp_pcb *pcb, struct pbuf *p,
ip_addr_t *addr, u16_t port);
#endif
/**
* \brief This structure contains socket communication data
*/
typedef enum eRecvMode_d
{
eBlock = 0x10,
eNonBlock = 0x20
}eRecvMode_d;
/**
* \brief This structure contains socket communication data
*/
#ifndef WIN32
typedef struct pal_socket
{
///UDP structure Tx
struct udp_pcb *pcbTx;
///UDP structure Rx
struct udp_pcb *pcbRx;
//Received IP address
ip_addr_t sIPAddress;
///Function pointer to hold receive callback
pal_socket_event_listener pfListen;
///Port for UDP communication
uint16_t wPort;
///Transport Layer Timeout
uint16_t wTimeout;
///Enumeration to indicate Blocking or Non blocking
uint8_t bMode;
} pal_socket_t;
#else
typedef struct pal_socket
{
///Received IP address
char* sIPAddress;
///Port for UDP communication
uint16_t wPort;
///Pointer to the socket for Receiving
SOCKET SocketHdl;
///IPv4 Socket address for Receiving
SOCKADDR_IN sSocketAddrIn;
///Transport Layer Timeout
uint16_t wTimeout;
///Enumeration to indicate Blocking or Non blocking
uint8_t bMode;
} pal_socket_t;
#endif
/**********************************************************************************************************************
* API Prototypes
*********************************************************************************************************************/
/**
* \brief Assign IP address
*/
#ifndef WIN32
int32_t pal_socket_assign_ip_address(const char* p_ip_address,void *p_input_ip_address);
#else
int32_t pal_socket_assign_ip_address(const char_t* p_ip_address,char** p_input_ip_address);
#endif
/**
* \brief Initializes the socket communication structure
*/
int32_t pal_socket_init(pal_socket_t* p_socket);
/**
* \brief Creates server port and bind
*/
int32_t pal_socket_open(pal_socket_t* p_socket,
uint16_t port);
/**
* \brief Creates a client port and connect
*/
int32_t pal_socket_connect(pal_socket_t* p_socket,
uint16_t port);
/**
* \brief Receive data from the client
*/
int32_t pal_socket_listen(pal_socket_t* p_socket, uint8_t *p_data,
uint32_t *p_length);
/**
* \brief Sends the data to the the client
*/
int32_t pal_socket_send(const pal_socket_t* p_socket, uint8_t *p_data,
uint32_t length);
/**
* \brief Closes the socket communication and release the udp port
*/
void pal_socket_close(pal_socket_t* p_socket);
#endif
#endif //_PAL_SOCKET_H_
/**
* @}
*/

View File

@@ -0,0 +1,237 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
* \file
*
* \brief This file implements
*
* \addtogroup grOptigaUtil
* @{
*/
#include "optiga/optiga_util.h"
#include "optiga/comms/optiga_comms.h"
#include "optiga/cmd/CommandLib.h"
#include "optiga/pal/pal_os_timer.h"
///Length of metadata
#define LENGTH_METADATA 0x1C
volatile static host_lib_status_t optiga_comms_status;
#ifdef MODULE_ENABLE_READ_WRITE
static void __optiga_util_comms_event_handler(void* upper_layer_ctx, host_lib_status_t event)
{
optiga_comms_status = event;
}
optiga_lib_status_t optiga_util_open_application(optiga_comms_t* p_comms)
{
optiga_lib_status_t status = OPTIGA_LIB_ERROR;
sOpenApp_d sOpenApp;
do {
// OPTIGA(TM) Initialization phase
//Invoke optiga_comms_open to initialize the IFX I2C Protocol and security chip
optiga_comms_status = OPTIGA_COMMS_BUSY;
p_comms->upper_layer_handler = __optiga_util_comms_event_handler;
status = optiga_comms_open(p_comms);
if(E_COMMS_SUCCESS != status)
{
status = OPTIGA_LIB_ERROR;
break;
}
//Wait until IFX I2C initialization is complete
while(optiga_comms_status == OPTIGA_COMMS_BUSY)
{
pal_os_timer_delay_in_milliseconds(1);
}
if((OPTIGA_COMMS_SUCCESS != status) || (optiga_comms_status == OPTIGA_COMMS_ERROR))
{
status = OPTIGA_LIB_ERROR;
break;
}
//Set OPTIGA comms context in Command library before invoking the use case APIs or command library APIs
//This context will be used by command library to communicate with OPTIGA using IFX I2C Protocol.
CmdLib_SetOptigaCommsContext(p_comms);
//Open the application in Security Chip
sOpenApp.eOpenType = eInit;
status = CmdLib_OpenApplication(&sOpenApp);
if(CMD_LIB_OK == status)
{
status = OPTIGA_LIB_SUCCESS;
}
} while(FALSE);
return status;
}
optiga_lib_status_t optiga_util_read_data(uint16_t optiga_oid, uint16_t offset,
uint8_t * p_buffer, uint16_t* buffer_size)
{
int32_t status = (int32_t)OPTIGA_LIB_ERROR;
sGetData_d cmd_params;
sCmdResponse_d cmd_resp;
do
{
if((NULL == p_buffer) || (NULL == buffer_size) || (0 == *buffer_size))
{
status = (int32_t)OPTIGA_LIB_ERROR;
break;
}
cmd_params.wOID = optiga_oid;
cmd_params.wLength = *buffer_size;
cmd_params.wOffset = offset;
cmd_params.eDataOrMdata = eDATA;
cmd_resp.prgbBuffer = p_buffer;
cmd_resp.wBufferLength = *buffer_size;
cmd_resp.wRespLength = 0;
status = CmdLib_GetDataObject(&cmd_params,&cmd_resp);
if(CMD_LIB_OK != status)
{
break;
}
*buffer_size = cmd_resp.wRespLength;
status = OPTIGA_LIB_SUCCESS;
}while(FALSE);
return status;
}
optiga_lib_status_t optiga_util_read_metadata(uint16_t optiga_oid, uint8_t * p_buffer, uint16_t* buffer_size)
{
int32_t status = (int32_t)OPTIGA_LIB_ERROR;
sGetData_d cmd_params;
sCmdResponse_d cmd_resp;
uint16_t buffer_limit = *buffer_size;
do
{
if((NULL == p_buffer) || (NULL == buffer_size) || (0 == *buffer_size))
{
status = (int32_t)OPTIGA_LIB_ERROR;
break;
}
//Get metadata of OID
cmd_params.wOID = optiga_oid;
cmd_params.wLength = LENGTH_METADATA;
cmd_params.wOffset = 0;
cmd_params.eDataOrMdata = eMETA_DATA;
cmd_resp.prgbBuffer = p_buffer;
cmd_resp.wBufferLength = buffer_limit;
cmd_resp.wRespLength = 0;
status = CmdLib_GetDataObject(&cmd_params,&cmd_resp);
if(CMD_LIB_OK != status)
{
break;
}
*buffer_size = cmd_resp.wRespLength;
status = OPTIGA_LIB_SUCCESS;
}while(FALSE);
return status;
}
optiga_lib_status_t optiga_util_write_data(uint16_t optiga_oid, uint8_t write_type, uint16_t offset, uint8_t * p_buffer, uint16_t buffer_size)
{
int32_t status = (int32_t)OPTIGA_LIB_ERROR;
sSetData_d sd_params;
do
{
if((NULL == p_buffer) || (0x00 == buffer_size))
{
break;
}
if ((OPTIGA_UTIL_WRITE_ONLY != write_type) && (OPTIGA_UTIL_ERASE_AND_WRITE != write_type))
{
status = OPTIGA_UTIL_ERROR_INVALID_INPUT;
break;
}
sd_params.wOID = optiga_oid;
sd_params.wOffset = offset;
sd_params.eDataOrMdata = eDATA;
if (OPTIGA_UTIL_ERASE_AND_WRITE == write_type)
{
sd_params.eWriteOption = eERASE_AND_WRITE;
}
else
{
sd_params.eWriteOption = eWRITE;
}
sd_params.prgbData = p_buffer;
sd_params.wLength = buffer_size;
status = CmdLib_SetDataObject(&sd_params);
if(CMD_LIB_OK != status)
{
break;
}
status = OPTIGA_LIB_SUCCESS;
}while(FALSE);
return status;
}
optiga_lib_status_t optiga_util_write_metadata(uint16_t optiga_oid, uint8_t * p_buffer, uint8_t buffer_size)
{
int32_t status = (int32_t)OPTIGA_LIB_ERROR;
sSetData_d sd_params;
sd_params.wOID = optiga_oid;
sd_params.wOffset = 0;
sd_params.eDataOrMdata = eMETA_DATA;
sd_params.eWriteOption = eWRITE;
sd_params.prgbData = p_buffer;
sd_params.wLength = buffer_size;
status = CmdLib_SetDataObject(&sd_params);
if(CMD_LIB_OK != status)
{
return status;
}
return OPTIGA_LIB_SUCCESS;
}
#endif // MODULE_ENABLE_READ_WRITE

31
external/infineon/pal/nrf5x/README.md vendored Normal file
View File

@@ -0,0 +1,31 @@
# General
All projects built with the nrf5x PAL need to set `DL_MAX_FRAME_SIZE=250` via
a global define, because the nrf5x doesn't support the default frame size.
To use the PAL together with other I2C devices and be able to run it also on a BLE Shield2Go
make a global define `IFX_2GO_SUPPORT`.
# Nordic SDK `nrf_crypto` backend
To use the OPTIGA with the `nrf_crypto` API the Nordic SDK needs to be modified
according to the following steps.
Locate the folder <NRF_SDK>/components/libraries/crypto/. In each file listed in
the following table locate the include statement section starting with the
comment `// Include all backends`.
Append the corresponding OPTIGA backend header file include statement at the end
of each respective include block.
|File |Include statement to append |
|----------------------------|-----------------------------------|
|`nrf_crypto_ecc_backend.h` |`#include "optiga_backend_ecc.h"` |
|`nrf_crypto_ecdh_backend.h` |`#include "optiga_backend_ecdh.h"` |
|`nrf_crypto_ecdsa_backend.h`|`#include "optiga_backend_ecdsa.h"`|
|`nrf_crypto_rng_backend.h` |`#include "optiga_backend_rng.h"` |
# Memory Allocation
The library allocates memory on the heap. To ensure correct operation the heap
must be sufficiently large, e.g. 8,192 Bytes.

138
external/infineon/pal/nrf5x/pal_gpio.c vendored Normal file
View File

@@ -0,0 +1,138 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file
*
* \brief This file implements the platform abstraction layer APIs for gpio.
*
* \addtogroup grPAL
* @{
*/
/**********************************************************************************************************************
* HEADER FILES
*********************************************************************************************************************/
#include "optiga/pal/pal_gpio.h"
#include "optiga/pal/pal_ifx_i2c_config.h"
#include "nrf_gpio.h"
#include "pal_pin_config.h"
/**********************************************************************************************************************
* MACROS
*********************************************************************************************************************/
/**********************************************************************************************************************
* LOCAL DATA
*********************************************************************************************************************/
/**********************************************************************************************************************
* LOCAL ROUTINES
*********************************************************************************************************************/
void setup_nrf_gpio(uint32_t pin)
{
// don't touch pin config for unused pins
if (pin == OPTIGA_PIN_UNUSED) {
return;
}
// remove our flags to allow nrf_gpio_* functions to work
const uint32_t pin_nr = pin & ~OPTIGA_PIN_ALL_MASKS;
// Init pin direction
nrf_gpio_cfg_output(pin_nr);
// Set pin to initial state
nrf_gpio_pin_write(pin_nr, pin & OPTIGA_PIN_INITIAL_VAL_MASK);
}
void write_nrf_gpio(uint32_t pin, bool value)
{
// Skip pins marked for one time init or unused
if ((pin == OPTIGA_PIN_UNUSED) || (pin & OPTIGA_PIN_ONE_TIME_INIT_MASK)) {
return;
}
// remove our flags to allow nrf_gpio_* functions to work
const uint32_t pin_nr = pin & ~OPTIGA_PIN_ALL_MASKS;
nrf_gpio_pin_write(pin_nr, value);
}
/**********************************************************************************************************************
* API IMPLEMENTATION
*********************************************************************************************************************/
pal_status_t pal_gpio_init(const pal_gpio_t * p_gpio_context)
{
const uint32_t vdd_pin = (uint32_t)(optiga_vdd_0.p_gpio_hw);
const uint32_t rst_pin = (uint32_t)(optiga_reset_0.p_gpio_hw);
setup_nrf_gpio(vdd_pin);
setup_nrf_gpio(rst_pin);
return PAL_STATUS_SUCCESS;
}
/**
* Sets the gpio pin to high state
*
* <b>API Details:</b>
* The API sets the pin high, only if the pin is assigned to a valid gpio context.<br>
* Otherwise the API returns without any failure status.<br>
*
*\param[in] p_gpio_context Pointer to pal layer gpio context
*
*
*/
void pal_gpio_set_high(const pal_gpio_t* p_gpio_context)
{
if (p_gpio_context != NULL)
{
write_nrf_gpio((uint32_t)(p_gpio_context->p_gpio_hw), true);
}
}
/**
* Sets the gpio pin to low state
*
* <b>API Details:</b>
* The API set the pin low, only if the pin is assigned to a valid gpio context.<br>
* Otherwise the API returns without any failure status.<br>
*
*\param[in] p_gpio_context Pointer to pal layer gpio context
*
*/
void pal_gpio_set_low(const pal_gpio_t* p_gpio_context)
{
if (p_gpio_context != NULL)
{
write_nrf_gpio((uint32_t)(p_gpio_context->p_gpio_hw), false);
}
}
/**
* @}
*/

360
external/infineon/pal/nrf5x/pal_i2c.c vendored Normal file
View File

@@ -0,0 +1,360 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file
*
* \brief This file implements the platform abstraction layer(pal) APIs for I2C.
*
* \addtogroup grPAL
* @{
*/
/**********************************************************************************************************************
* HEADER FILES
*********************************************************************************************************************/
#include "optiga/pal/pal_i2c.h"
#include "optiga/ifx_i2c/ifx_i2c.h"
#include "nrf_twi_mngr.h"
#include "pal_pin_config.h"
#include <stdbool.h>
/// @cond hidden
/**********************************************************************************************************************
* MACROS
*********************************************************************************************************************/
#define PAL_I2C_MASTER_MAX_BITRATE (400)
/** @brief I2C driver instance */
#define TWI_INSTANCE_ID 0
/** @brief Maximal number of pending I2C transactions */
#define MAX_PENDING_TRANSACTIONS 5
/*********************************************************************************************************************
* LOCAL DATA
*********************************************************************************************************************/
/* Pointer to the current pal i2c context */
static pal_i2c_t * gp_pal_i2c_current_ctx;
/** @brief Definition of TWI manager instance */
#ifndef IFX_2GO_SUPPORT
NRF_TWI_MNGR_DEF(m_app_twi, MAX_PENDING_TRANSACTIONS, TWI_INSTANCE_ID);
#else
nrf_twi_mngr_t m_app_twi;
#endif
/** @brief Definition of TWI manager transfer instance */
static nrf_twi_mngr_transfer_t m_transfer;
/** @brief Definition of TWI manager transaction instance */
static nrf_twi_mngr_transaction_t m_transaction;
static bool initialized = false;
/**********************************************************************************************************************
* LOCAL ROUTINES
*********************************************************************************************************************/
/**
* Pal I2C event handler function to invoke the registered upper layer callback<br>
*
*<b>API Details:</b>
* - This function implements the platform specific i2c event handling mechanism<br>
* - It calls the registered upper layer function after completion of the I2C read/write operations<br>
* - The respective event status are explained below.
* - #PAL_I2C_EVENT_ERROR when I2C fails due to low level failures(NACK/I2C protocol errors)
* - #PAL_I2C_EVENT_SUCCESS when operation is successfully completed
*
* \param[in] p_pal_i2c_ctx Pointer to the pal i2c context #pal_i2c_t
* \param[in] event Status of the event reported after read/write completion or due to I2C errors
*
*/
static void app_twi_callback(ret_code_t result, void * p_user_data)
{
app_event_handler_t upper_layer_handler;
//lint --e{611} suppress "void* function pointer is type casted to app_event_handler_t type"
upper_layer_handler = (app_event_handler_t)gp_pal_i2c_current_ctx->upper_layer_event_handler;
if (result == NRF_SUCCESS)
{
upper_layer_handler(gp_pal_i2c_current_ctx->upper_layer_ctx, PAL_I2C_EVENT_SUCCESS);
}
else
{
upper_layer_handler(gp_pal_i2c_current_ctx->upper_layer_ctx, PAL_I2C_EVENT_ERROR);
}
}
/// @endcond
/**********************************************************************************************************************
* API IMPLEMENTATION
*********************************************************************************************************************/
/**
* API to initialize the i2c master with the given context.
* <br>
*
*<b>API Details:</b>
* - The platform specific initialization of I2C master has to be implemented as part of this API, if required.<br>
* - If the target platform does not demand explicit initialization of i2c master
* (Example: If the platform driver takes care of init after the reset), it would not be required to implement.<br>
* - The implementation must take care the following scenarios depending upon the target platform selected.
* - The implementation must handle the acquiring and releasing of the I2C bus before initializing the I2C master to
* avoid interrupting the ongoing slave I2C transactions using the same I2C master.
* - If the I2C bus is in busy state, the API must not initialize and return #PAL_STATUS_I2C_BUSY status.
* - Repeated initialization must be taken care with respect to the platform requirements. (Example: Multiple users/applications
* sharing the same I2C master resource)
*
*<b>User Input:</b><br>
* - The input #pal_i2c_t p_i2c_context must not be NULL.<br>
*
* \param[in] p_i2c_context Pal i2c context to be initialized
*
* \retval #PAL_STATUS_SUCCESS Returns when the I2C master init it successfull
* \retval #PAL_STATUS_FAILURE Returns when the I2C init fails.
*/
pal_status_t pal_i2c_init(const pal_i2c_t* p_i2c_context)
{
#ifndef IFX_2GO_SUPPORT
nrf_drv_twi_config_t const config = {
.scl = OPTIGA_PIN_I2C_SCL,
.sda = OPTIGA_PIN_I2C_SDA,
.frequency = NRF_DRV_TWI_FREQ_400K,
.interrupt_priority = APP_IRQ_PRIORITY_LOWEST,
.clear_bus_init = false
};
#else
#include "ifx_2go_common.h"
nrf_drv_twi_config_t const config = {
.scl = ifx_2go_pin_config()->scl,
.sda = ifx_2go_pin_config()->sda,
.frequency = NRF_TWI_FREQ_400K,
.interrupt_priority = APP_IRQ_PRIORITY_LOWEST,
.clear_bus_init = false
};
#endif
if(initialized)
{
nrf_twi_mngr_uninit(&m_app_twi);
}
// Initialize I2C driver
if (nrf_twi_mngr_init(&m_app_twi, &config) != NRF_SUCCESS)
{
return PAL_STATUS_FAILURE;
}
initialized = true;
return PAL_STATUS_SUCCESS;
}
/**
* API to de-initialize the I2C master with the specified context.
* <br>
*
*<b>API Details:</b>
* - The platform specific de-initialization of I2C master has to be implemented as part of this API, if required.<br>
* - If the target platform does not demand explicit de-initialization of i2c master
* (Example: If the platform driver takes care of init after the reset), it would not be required to implement.<br>
* - The implementation must take care the following scenarios depending upon the target platform selected.
* - The implementation must handle the acquiring and releasing of the I2C bus before de-initializing the I2C master to
* avoid interrupting the ongoing slave I2C transactions using the same I2C master.
* - If the I2C bus is in busy state, the API must not de-initialize and return #PAL_STATUS_I2C_BUSY status.
* - This API must ensure that multiple users/applications sharing the same I2C master resource is not impacted.
*
*<b>User Input:</b><br>
* - The input #pal_i2c_t p_i2c_context must not be NULL.<br>
*
* \param[in] p_i2c_context I2C context to be de-initialized
*
* \retval #PAL_STATUS_SUCCESS Returns when the I2C master de-init it successfull
* \retval #PAL_STATUS_FAILURE Returns when the I2C de-init fails.
*/
pal_status_t pal_i2c_deinit(const pal_i2c_t* p_i2c_context)
{
if(initialized) {
nrf_twi_mngr_uninit(&m_app_twi);
}
initialized = false;
return PAL_STATUS_SUCCESS;
}
/**
* Platform abstraction layer API to write the data to I2C slave.
* <br>
* <br>
* \image html pal_i2c_write.png "pal_i2c_write()" width=20cm
*
*
*<b>API Details:</b>
* - The API attempts to write if the I2C bus is free, else it returns busy status #PAL_STATUS_I2C_BUSY<br>
* - The bus is released only after the completion of transmission or after completion of error handling.<br>
* - The API invokes the upper layer handler with the respective event status as explained below.
* - #PAL_I2C_EVENT_BUSY when I2C bus in busy state
* - #PAL_I2C_EVENT_ERROR when API fails
* - #PAL_I2C_EVENT_SUCCESS when operation is successfully completed asynchronously
*<br>
*
*<b>User Input:</b><br>
* - The input #pal_i2c_t p_i2c_context must not be NULL.<br>
* - The upper_layer_event_handler must be initialized in the p_i2c_context before invoking the API.<br>
*
*<b>Notes:</b><br>
* - Otherwise the below implementation has to be updated to handle different bitrates based on the input context.<br>
* - The caller of this API must take care of the guard time based on the slave's requirement.<br>
*
* \param[in] p_i2c_context Pointer to the pal I2C context #pal_i2c_t
* \param[in] p_data Pointer to the data to be written
* \param[in] length Length of the data to be written
*
* \retval #PAL_STATUS_SUCCESS Returns when the I2C write is invoked successfully
* \retval #PAL_STATUS_FAILURE Returns when the I2C write fails.
* \retval #PAL_STATUS_I2C_BUSY Returns when the I2C bus is busy.
*/
pal_status_t pal_i2c_write(pal_i2c_t* p_i2c_context,uint8_t* p_data , uint16_t length)
{
gp_pal_i2c_current_ctx = p_i2c_context;
m_transfer.p_data = p_data;
m_transfer.length = length;
m_transfer.operation = NRF_TWI_MNGR_WRITE_OP(IFX_I2C_BASE_ADDR);
m_transfer.flags = 0;
m_transaction.callback = app_twi_callback;
m_transaction.number_of_transfers = 1;
m_transaction.p_required_twi_cfg = NULL;
m_transaction.p_transfers = &m_transfer;
m_transaction.p_user_data = (void*) PAL_STATUS_SUCCESS;
if (nrf_twi_mngr_schedule(&m_app_twi, &m_transaction) != NRF_SUCCESS)
{
app_twi_callback(NRF_ERROR_BUSY, 0);
}
return PAL_STATUS_SUCCESS;
}
/**
* Platform abstraction layer API to read the data from I2C slave.
* <br>
* <br>
* \image html pal_i2c_read.png "pal_i2c_read()" width=20cm
*
*<b>API Details:</b>
* - The API attempts to read if the I2C bus is free, else it returns busy status #PAL_STATUS_I2C_BUSY<br>
* - The bus is released only after the completion of reception or after completion of error handling.<br>
* - The API invokes the upper layer handler with the respective event status as explained below.
* - #PAL_I2C_EVENT_BUSY when I2C bus in busy state
* - #PAL_I2C_EVENT_ERROR when API fails
* - #PAL_I2C_EVENT_SUCCESS when operation is successfully completed asynchronously
*<br>
*
*<b>User Input:</b><br>
* - The input #pal_i2c_t p_i2c_context must not be NULL.<br>
* - The upper_layer_event_handler must be initialized in the p_i2c_context before invoking the API.<br>
*
*<b>Notes:</b><br>
* - Otherwise the below implementation has to be updated to handle different bitrates based on the input context.<br>
* - The caller of this API must take care of the guard time based on the slave's requirement.<br>
*
* \param[in] p_i2c_context pointer to the PAL i2c context #pal_i2c_t
* \param[in] p_data Pointer to the data buffer to store the read data
* \param[in] length Length of the data to be read
*
* \retval #PAL_STATUS_SUCCESS Returns when the I2C read is invoked successfully
* \retval #PAL_STATUS_FAILURE Returns when the I2C read fails.
* \retval #PAL_STATUS_I2C_BUSY Returns when the I2C bus is busy.
*/
pal_status_t pal_i2c_read(pal_i2c_t* p_i2c_context , uint8_t* p_data , uint16_t length)
{
gp_pal_i2c_current_ctx = p_i2c_context;
m_transfer.p_data = p_data;
m_transfer.length = length;
m_transfer.operation = NRF_TWI_MNGR_READ_OP(IFX_I2C_BASE_ADDR);
m_transfer.flags = 0;
m_transaction.callback = app_twi_callback;
m_transaction.number_of_transfers = 1;
m_transaction.p_required_twi_cfg = 0;
m_transaction.p_transfers = &m_transfer;
m_transaction.p_user_data = (void*) PAL_STATUS_SUCCESS;
if (nrf_twi_mngr_schedule(&m_app_twi, &m_transaction) != NRF_SUCCESS)
{
app_twi_callback(NRF_ERROR_BUSY, 0);
}
return PAL_STATUS_SUCCESS;
}
/**
* Platform abstraction layer API to set the bitrate/speed(KHz) of I2C master.
* <br>
*
*<b>API Details:</b>
* - Sets the bitrate of I2C master if the I2C bus is free, else it returns busy status #PAL_STATUS_I2C_BUSY<br>
* - The bus is released after the setting the bitrate.<br>
* - This API must take care of setting the bitrate to I2C master's maximum supported value.
* - Eg. In XMC4500, the maximum supported bitrate is 400 KHz. If the supplied bitrate is greater than 400KHz, the API will
* set the I2C master's bitrate to 400KHz.
* - Use the #PAL_I2C_MASTER_MAX_BITRATE macro to specify the maximum supported bitrate value for the target platform.
* - If upper_layer_event_handler is initialized, the upper layer handler is invoked with the respective event
* status listed below.
* - #PAL_I2C_EVENT_BUSY when I2C bus in busy state
* - #PAL_I2C_EVENT_ERROR when API fails to set the bit rate
* - #PAL_I2C_EVENT_SUCCESS when operation is successful
*<br>
*
*<b>User Input:</b><br>
* - The input #pal_i2c_t p_i2c_context must not be NULL.<br>
*
* \param[in] p_i2c_context Pointer to the pal i2c context
* \param[in] bitrate Bitrate to be used by i2c master in KHz
*
* \retval #PAL_STATUS_SUCCESS Returns when the setting of bitrate is successfully completed
* \retval #PAL_STATUS_FAILURE Returns when the setting of bitrate fails.
* \retval #PAL_STATUS_I2C_BUSY Returns when the I2C bus is busy.
*/
pal_status_t pal_i2c_set_bitrate(const pal_i2c_t* p_i2c_context , uint16_t bitrate)
{
// Bitrate is fixed to the maximum frequency on this platform (400K)
return PAL_STATUS_SUCCESS;
}
#ifdef IFX_2GO_SUPPORT
pal_status_t pal_i2c_set_instance(nrf_twi_mngr_t* twi_inst)
{
m_app_twi = *twi_inst;
}
#endif/*IFX_2GO_SUPPORT*/
/**
* @}
*/

View File

@@ -0,0 +1,89 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file
*
* \brief This file implements platform abstraction layer configurations for ifx i2c protocol.
*
* \addtogroup grPAL
* @{
*/
/**********************************************************************************************************************
* HEADER FILES
*********************************************************************************************************************/
#include "stdlib.h"
#include "stdio.h"
#include "optiga/pal/pal_gpio.h"
#include "optiga/pal/pal_i2c.h"
#include "optiga/ifx_i2c/ifx_i2c_config.h"
#include "pal_pin_config.h"
/*********************************************************************************************************************
* pal ifx i2c instance
*********************************************************************************************************************/
/**
* \brief PAL I2C configuration for OPTIGA.
*/
pal_i2c_t optiga_pal_i2c_context_0 =
{
/// Pointer to I2C master platform specific context
NULL,
/// Slave address
IFX_I2C_BASE_ADDR,
/// Upper layer context
NULL,
/// Callback event handler
NULL
};
/*********************************************************************************************************************
* PAL GPIO configurations defined for nrf52 development boards PCA10040 and PCA10056 with the Trust X Shield and
* Trust M 2Go board plugged in.
*********************************************************************************************************************/
/**
* \brief PAL vdd pin configuration for OPTIGA.
*/
pal_gpio_t optiga_vdd_0 =
{
// Platform specific GPIO context for the pin used to toggle Vdd.
// Casting the uint32_t to a void* is possible, because nrf52 is a 32Bit platform
(void*) OPTIGA_PIN_VDD
};
/**
* \brief PAL reset pin configuration for OPTIGA.
*/
pal_gpio_t optiga_reset_0 =
{
// Platform specific GPIO context for the pin used to toggle Reset.
// Casting the uint32_t to a void* is possible, because nrf52 is a 32Bit platform
(void*) OPTIGA_PIN_RST
};
/**
* @}
*/

211
external/infineon/pal/nrf5x/pal_os.c vendored Normal file
View File

@@ -0,0 +1,211 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file
*
* \brief This file implements the platform abstraction layer APIs for os event/scheduler.
*
* \addtogroup grPAL
* @{
*/
/**********************************************************************************************************************
* HEADER FILES
*********************************************************************************************************************/
#include <stdbool.h>
#include "stdlib.h"
#include "stdio.h"
#include "optiga/pal/pal_os_event.h"
#include "nrf_rtc.h"
#include "nrf_drv_rtc.h"
#include "nrf_delay.h"
#include "nrf_pwr_mgmt.h"
/**********************************************************************************************************************
* MACROS
*********************************************************************************************************************/
/*********************************************************************************************************************
* LOCAL DATA
*********************************************************************************************************************/
/// @cond hidden
/// Callback function when timer elapses
static volatile register_callback callback_registered = NULL;
/// Pointer to store upper layer callback context (For example: Ifx i2c context)
static void * callback_ctx;
/// Flag to indicate to the delay function when the timer has elapsed
static volatile bool timer_elapsed = false;
/// Flag to indicate if the the RTC was already initialized, re-init. causes an NRF_ERROR
static bool m_rtc2_is_initialized = false;
static const nrf_drv_rtc_t rtc2 = NRF_DRV_RTC_INSTANCE(2);
static nrf_drv_rtc_config_t m_rtc2_config = NRF_DRV_RTC_DEFAULT_CONFIG;
#define RTC_CLOCK_FREQUENCY 32768
// Set the prescaler to approximately get 0.25 ms intervals
// 32768Hz/8 = 4096 Hz -> 0.2441us
// it's a 24bit counter, so it will overflow every ~68min
#define RTC_PRESCALER 8
#define RTC_TICK_FREQ (RTC_CLOCK_FREQUENCY/RTC_PRESCALER)
/**
* Timer callback handler.
*
* This get called from the TIMER elapse event.<br>
* Once the timer expires, the registered callback funtion gets called from the timer event handler, if
* the call back is not NULL.<br>
*
*\param[in] args Callback argument
*
*/
static void ifx_rtc_handler(nrf_drv_rtc_int_type_t int_type)
{
volatile register_callback callback;
(void)nrf_drv_rtc_cc_disable(&rtc2, int_type);
switch(int_type)
{
case NRF_DRV_RTC_INT_COMPARE0:
// handler for register_callback_oneshot
if (callback_registered != NULL)
{
callback = callback_registered;
callback_registered = NULL;
callback(callback_ctx);
}
break;
case NRF_DRV_RTC_INT_COMPARE1:
// handler for delay_in_milliseconds
timer_elapsed = true;
break;
default:
// Do nothing
break;
}
}
/// @endcond
void pal_os_event_init()
{
if (m_rtc2_is_initialized == true)
{
return;
}
// set prescaler so that a tick is approximately 1ms
m_rtc2_config.prescaler = RTC_PRESCALER;
// Initialize the RTC2 driver instance
APP_ERROR_CHECK(nrf_drv_rtc_init(&rtc2, &m_rtc2_config, ifx_rtc_handler));
// Power on RTC instance
nrf_drv_rtc_enable(&rtc2);
m_rtc2_is_initialized = true;
}
/**
* Platform specific event call back registration function to trigger once when timer expires.
* <br>
*
* <b>API Details:</b>
* This function registers the callback function supplied by the caller.<br>
* It triggers a timer with the supplied time interval in microseconds.<br>
* Once the timer expires, the registered callback function gets called.<br>
*
* \param[in] callback Callback function pointer
* \param[in] callback_args Callback arguments
* \param[in] time_us time in micro seconds to trigger the call back
*
*/
void pal_os_event_register_callback_oneshot(register_callback callback,
void* callback_args,
uint32_t time_us)
{
callback_registered = callback;
callback_ctx = callback_args;
// parentheses are set this way to avoid overflow when multiplying time_us with something
uint32_t future_ticks = (time_us/(1000*1000/RTC_TICK_FREQ));
// we can't reliably set an interrupt less than two ticks ahead, as per NRF52832 datasheet, p. 245
// do busy waiting instead
if(future_ticks < 2) {
nrf_delay_us(time_us);
ifx_rtc_handler(NRF_DRV_RTC_INT_COMPARE0);
return;
}
// add current tick value
future_ticks += nrf_drv_rtc_counter_get(&rtc2);
// Set the compare register to trigger approximately at time_us
APP_ERROR_CHECK(nrf_drv_rtc_cc_set(&rtc2, NRF_DRV_RTC_INT_COMPARE0, future_ticks, true));
}
/**
* Get the current time in milliseconds<br>
*
*
* \retval uint32_t time in milliseconds
*/
uint32_t pal_os_timer_get_time_in_milliseconds(void)
{
return nrf_drv_rtc_counter_get(&rtc2)*1000/RTC_TICK_FREQ;
}
/**
* Function to wait or delay until the given milliseconds time
*
* \param[in] milliseconds Delay value in milliseconds
*
*/
void pal_os_timer_delay_in_milliseconds(uint16_t milliseconds)
{
timer_elapsed = false;
uint32_t future_ticks = milliseconds*(RTC_TICK_FREQ/1000);
// we can't reliably set an interrupt less than two ticks ahead, as per NRF52832 datasheet, p. 245
// do busy waiting instead
if(future_ticks < 2) {
nrf_delay_ms(milliseconds);
return;
}
// add current tick value
future_ticks += nrf_drv_rtc_counter_get(&rtc2);
// Set the compare register to trigger in approximately milliseconds
APP_ERROR_CHECK(nrf_drv_rtc_cc_set(&rtc2, NRF_DRV_RTC_INT_COMPARE1, future_ticks, true));
while(!timer_elapsed)
{
nrf_pwr_mgmt_run();
}
timer_elapsed = false;
}
/**
* @}
*/

View File

@@ -0,0 +1,64 @@
/**
* MIT License
*
* Copyright (c) 2018 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
*
* \file pal_os_lock.c
*
* \brief This file implements the platform abstraction layer APIs for os locks (e.g. semaphore).
*
* \addtogroup grPAL
* @{
*/
#include "optiga/pal/pal_os_lock.h"
#include "nrf_atomic.h"
#include "nrf_pwr_mgmt.h"
/**
* @brief PAL OS lock structure. Might be extended if needed
*/
typedef struct pal_os_lock
{
nrf_atomic_flag_t lock;
} pal_os_lock_t;
static volatile pal_os_lock_t pal_os_lock = {.lock = 0};
pal_status_t pal_os_lock_acquire(void)
{
// wait until previous value was false, this indicates the lock was free and we own it now.
while(nrf_atomic_flag_set_fetch(&pal_os_lock.lock)) {
nrf_pwr_mgmt_run();
}
return PAL_STATUS_SUCCESS;
}
void pal_os_lock_release(void)
{
(void)nrf_atomic_flag_clear(&pal_os_lock.lock);
}
/**
* @}
*/

View File

@@ -0,0 +1,112 @@
/**
* \copyright
* MIT License
*
* Copyright (c) 2019 Infineon Technologies AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*
* \endcopyright
*
* \author Infineon Technologies AG
*
* \file pal_pin_config.h
*
* \brief This file defines the pins the OPTIGA is connected to.
*
* \addtogroup grPAL
*
* @{
*/
#ifndef _OPTIGA_PIN_CONFIG_H_
#define _OPTIGA_PIN_CONFIG_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "boards.h"
#include <stdint.h>
// To select a pin configuration set its define to '1' and all others to '0'
// Trust X Shield
// OPTIGA as 2Go board on the TrustX shield, e.g. TrustX2Go and TrustM2Go
#define OPTIGA_PIN_CONFIG_2GO 0
// OPTIGA soldered on the TrustX shield
#define OPTIGA_PIN_CONFIG_TRUSTX_SHIELD 0
// MY IOT ADAPTER
// Product Link: https://www.infineon.com/cms/en/product/evaluation-boards/my-iot-adapter/
// OPTIGA as 2Go board on MY IOT ADAPTER Slot 1
#define OPTIGA_PIN_CONFIG_MYIOT_SLOT1 0
// OPTIGA as 2Go board on MY IOT ADAPTER Slot 2 or 3
#define OPTIGA_PIN_CONFIG_MYIOT_SLOT2_3 1
/*
* The following defines pack additional information into the highest bits of
* a void*. This is safe, because on nrf52 the pin description uses less than 8 bit
* and a void* has 32 bits on this platform.
*/
/** @brief set a pin to this value to mark it as unused and it will not be initialised */
#define OPTIGA_PIN_UNUSED UINT32_C(0xFFFFFFFF)
#define OPTIGA_PIN_INITIAL_VAL_MASK (UINT32_C(1) << 31)
/** @brief defines the initial state of the pin */
#define OPTIGA_PIN_INITIAL_VAL_HIGH OPTIGA_PIN_INITIAL_VAL_MASK
#define OPTIGA_PIN_INITIAL_VAL_LOW 0
#define OPTIGA_PIN_ONE_TIME_INIT_MASK (UINT32_C(1) << 30)
/** @brief If this flag is set, the pin will be initialised with the specified value, but not used */
#define OPTIGA_PIN_ONE_TIME_INIT OPTIGA_PIN_ONE_TIME_INIT_MASK
#define OPTIGA_PIN_ALL_MASKS (OPTIGA_PIN_INITIAL_VAL_MASK | OPTIGA_PIN_ONE_TIME_INIT_MASK)
#if OPTIGA_PIN_CONFIG_2GO == 1
#define OPTIGA_PIN_VDD (ARDUINO_9_PIN | OPTIGA_PIN_INITIAL_VAL_LOW | OPTIGA_PIN_ONE_TIME_INIT)
#define OPTIGA_PIN_RST (ARDUINO_7_PIN | OPTIGA_PIN_INITIAL_VAL_LOW)
#elif OPTIGA_PIN_CONFIG_TRUSTX_SHIELD == 1
#define OPTIGA_PIN_VDD (ARDUINO_9_PIN | OPTIGA_PIN_INITIAL_VAL_HIGH)
#define OPTIGA_PIN_RST (ARDUINO_7_PIN | OPTIGA_PIN_INITIAL_VAL_LOW)
#elif OPTIGA_PIN_CONFIG_MYIOT_SLOT1 == 1
#define OPTIGA_PIN_RST (ARDUINO_10_PIN | OPTIGA_PIN_INITIAL_VAL_LOW)
#define OPTIGA_PIN_VDD OPTIGA_PIN_UNUSED
#elif OPTIGA_PIN_CONFIG_MYIOT_SLOT2_3 == 1
#define OPTIGA_PIN_RST (ARDUINO_5_PIN | OPTIGA_PIN_INITIAL_VAL_LOW)
#define OPTIGA_PIN_VDD OPTIGA_PIN_UNUSED
#else
#error "No pin configuration selected"
#endif
/** @brief PIN for I2C SCL to Infineon OPTIGA Trust X device */
#define OPTIGA_PIN_I2C_SCL (ARDUINO_SCL_PIN)
/** @brief PIN for I2C SDA to Infineon OPTIGA Trust X device */
#define OPTIGA_PIN_I2C_SDA (ARDUINO_SDA_PIN)
#ifdef __cplusplus
}
#endif
#endif /*_OPTIGA_PIN_CONFIG_H_*/
/**
* @}
*/