Skip to content

Commit

Permalink
implement profile 7
Browse files Browse the repository at this point in the history
  • Loading branch information
zariiii9003 committed Nov 19, 2024
1 parent 971d62a commit cc64088
Show file tree
Hide file tree
Showing 7 changed files with 369 additions and 2 deletions.
7 changes: 6 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ python_add_library(p05
MODULE
${CMAKE_SOURCE_DIR}/src/e2e/p05.c
${PY_ABI_OPTIONS})
python_add_library(p07
MODULE
${CMAKE_SOURCE_DIR}/src/e2e/p07.c
${PY_ABI_OPTIONS})

# Add libraries
add_library(crclib STATIC ${CMAKE_SOURCE_DIR}/src/e2e/crclib.c)
Expand All @@ -49,5 +53,6 @@ target_link_libraries(p01 PRIVATE crclib)
target_link_libraries(p02 PRIVATE crclib)
target_link_libraries(p04 PRIVATE crclib util)
target_link_libraries(p05 PRIVATE crclib util)
target_link_libraries(p07 PRIVATE crclib util)

install(TARGETS crc p01 p02 p04 p05 LIBRARY DESTINATION e2e)
install(TARGETS crc p01 p02 p04 p05 p07 LIBRARY DESTINATION e2e)
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ The documentation is available [here](https://autosar-e2e.readthedocs.io/en/late
This library provides fast C implementations of the E2E CRC algorithms and E2E profiles.

Currently, all relevant CRC algorithms are available in module `e2e.crc`
but only E2E profiles 1, 2, 4 and 5 are available.
but only E2E profiles 1, 2, 4, 5 and 7 are available.
If you provide example data for the other profiles I would try to implement them, too.

## Installation
Expand Down
6 changes: 6 additions & 0 deletions doc/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ Profile 05
.. autofunction:: e2e.p05.e2e_p05_protect
.. autofunction:: e2e.p05.e2e_p05_check

Profile 07
""""""""""

.. autofunction:: e2e.p07.e2e_p07_protect
.. autofunction:: e2e.p07.e2e_p07_check

CRC Functions
^^^^^^^^^^^^^

Expand Down
2 changes: 2 additions & 0 deletions src/e2e/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
"p02",
"p04",
"p05",
"p07",
]

from e2e import crc as crc
from e2e import p01 as p01
from e2e import p02 as p02
from e2e import p04 as p04
from e2e import p05 as p05
from e2e import p07 as p07
from e2e._version import __version__
247 changes: 247 additions & 0 deletions src/e2e/p07.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
/* SPDX-FileCopyrightText: 2022-present Artur Drogunow <[email protected]>
#
# SPDX-License-Identifier: MIT */

#define PY_SSIZE_T_CLEAN
#include <Python.h>

#include <stdbool.h>
#include <stdint.h>

#include "crclib.h"
#include "util.h"

#define P07LENGTH_POS 8u
#define P07LENGTH_LEN 4u
#define P07COUNTER_POS 12u
#define P07COUNTER_LEN 4u
#define P07DATAID_POS 16u
#define P07DATAID_LEN 4u
#define P07CRC_POS 0u
#define P07CRC_LEN 8u

#define P07HEADER_LEN (P07CRC_LEN+P07LENGTH_LEN+P07COUNTER_LEN+P07DATAID_LEN)

uint64_t compute_p07_crc(uint8_t *data_ptr,
uint32_t length,
uint32_t offset)
{
uint64_t crc;

// bytes before crc bytes
uint32_t crc_offset = (uint32_t)(offset + P07CRC_POS);
crc = Crc_CalculateCRC64(data_ptr, crc_offset, CRC64_INITIAL_VALUE, true);

// bytes after crc bytes, if any
if (offset + P07CRC_POS + P07CRC_LEN < length){
uint32_t second_part_offset = offset + P07CRC_POS + P07CRC_LEN;
uint8_t *second_part_ptr = data_ptr + second_part_offset;
uint32_t second_part_len = length - (uint32_t)(offset + P07CRC_POS + P07CRC_LEN);
crc = Crc_CalculateCRC64(second_part_ptr, second_part_len, crc, false);
}
return crc;
}

PyDoc_STRVAR(e2e_p07_protect_doc,
"e2e_p07_protect(data: bytearray, length: int, data_id: int, *, offset: int = 0, increment_counter: bool = True) -> None \n"
"Calculate CRC inplace according to AUTOSAR E2E Profile 7. \n"
"\n"
":param bytearray data: \n"
" Mutable `bytes-like object <https://docs.python.org/3/glossary.html#term-bytes-like-object>`_.\n"
":param int length: \n"
" Number of data bytes which are considered for CRC calculation. `length` must fulfill \n"
" the following condition: ``20 <= length <= len(data)`` \n"
":param int data_id: \n"
" A unique identifier which is used to protect against masquerading. The `data_id` is a 32bit unsigned integer. \n"
":param int offset: \n"
" Byte offset of the E2E header. \n"
":param bool increment_counter: \n"
" If `True` the counter will be incremented before calculating the CRC. \n");

static PyObject *
py_e2e_p07_protect(PyObject *module,
PyObject *args,
PyObject *kwargs)
{
Py_buffer data;
unsigned long length;
unsigned long data_id;
unsigned long offset = 0;
int increment = true;

static char *kwlist[] = {
"data",
"length",
"data_id",
"offset",
"increment_counter",
NULL};

if (!PyArg_ParseTupleAndKeywords(args, kwargs, "y*kk|$kp:e2e_p07_protect",
kwlist, &data, &length, &data_id, &offset, &increment))
{
return NULL;
}
if (data.readonly)
{
PyErr_SetString(PyExc_ValueError, "\"data\" must be mutable. Use a bytearray or any object that implements the buffer protocol.");
goto error;
}
if (data.len < P07HEADER_LEN)
{
PyErr_SetString(PyExc_ValueError, "The length of bytearray \"data\" must be greater than or equal to 20.");
goto error;
}
if (length < P07HEADER_LEN || length > data.len)
{
PyErr_SetString(PyExc_ValueError, "Parameter \"length\" must fulfill the following condition: 20 <= length <= len(data).");
goto error;
}
if (offset > data.len - P07HEADER_LEN)
{
PyErr_SetString(PyExc_ValueError, "Argument \"offset\" invalid.");
goto error;
}

uint8_t *data_ptr = (uint8_t *)data.buf;

// write length
uint32_to_bigendian(data_ptr + offset + P07LENGTH_POS, length);

// increment counter
if (increment) {
uint32_t counter = bigendian_to_uint32(data_ptr + offset + P07COUNTER_POS);
counter += 1;
uint32_to_bigendian(data_ptr + offset + P07COUNTER_POS, counter);
}

// write data_id
uint32_to_bigendian(data_ptr + offset + P07DATAID_POS, data_id);

// calculate CRC
uint64_t crc = compute_p07_crc(data_ptr, length, offset);
uint64_to_bigendian(data_ptr + offset + P07CRC_POS, crc);

PyBuffer_Release(&data);

Py_RETURN_NONE;

error:
PyBuffer_Release(&data);
return NULL;
}

PyDoc_STRVAR(e2e_p07_check_doc,
"e2e_p07_check(data: bytes, length: int, data_id: int, *, offset: int = 0) -> bool \n"
"Return ``True`` if CRC is correct according to AUTOSAR E2E Profile 7. \n"
"\n"
":param data: \n"
" `bytes-like object <https://docs.python.org/3/glossary.html#term-bytes-like-object>`_. \n"
":param length: \n"
" Data byte count over which the CRC must be calculated. `length` must fulfill \n"
" the following condition: ``20 <= length <= len(data)`` \n"
":param int data_id: \n"
" A unique identifier which is used to protect against masquerading. The `data_id` is a 32bit unsigned integer. \n"
":param int offset: \n"
" Byte offset of the E2E header. \n"
":return:\n"
" `True` if CRC is valid, otherwise return `False`");

static PyObject *
py_e2e_p07_check(PyObject *module,
PyObject *args,
PyObject *kwargs)
{
Py_buffer data;
unsigned long length;
unsigned long data_id;
unsigned long offset = 0;

static char *kwlist[] = {
"data",
"length",
"data_id",
"offset",
NULL};

if (!PyArg_ParseTupleAndKeywords(args, kwargs, "y*kk|$k:e2e_p07_check",
kwlist, &data, &length, &data_id, &offset))
{
return NULL;
}
if (data.len < P07HEADER_LEN)
{
PyErr_SetString(PyExc_ValueError, "The length of bytearray \"data\" must be greater or equal to 20.");
goto error;
}
if (length < P07HEADER_LEN || length > data.len)
{
PyErr_SetString(PyExc_ValueError, "Parameter \"length\" must fulfill the following condition: 20 <= length <= len(data).");
goto error;
}
if (offset > data.len - P07HEADER_LEN)
{
PyErr_SetString(PyExc_ValueError, "Argument \"offset\" invalid.");
goto error;
}

uint8_t *data_ptr = (uint8_t *)data.buf;

// read length
uint32_t length_actual = bigendian_to_uint32(data_ptr + offset + P07LENGTH_POS);

// read data_id
uint32_t data_id_actual = bigendian_to_uint32(data_ptr + offset + P07DATAID_POS);

// read crc
uint64_t crc_actual = bigendian_to_uint64(data_ptr + offset + P07CRC_POS);

// calculate CRC
uint64_t crc = compute_p07_crc(data_ptr, length, offset);

PyBuffer_Release(&data);

if ((length_actual == length) && (data_id_actual == data_id) && (crc_actual == crc))
{
Py_RETURN_TRUE;
}
else
{
Py_RETURN_FALSE;
}

error:
PyBuffer_Release(&data);
return NULL;
}

static struct PyMethodDef methods[] = {
{"e2e_p07_protect",
(PyCFunction)py_e2e_p07_protect,
METH_VARARGS | METH_KEYWORDS,
e2e_p07_protect_doc},
{"e2e_p07_check",
(PyCFunction)py_e2e_p07_check,
METH_VARARGS | METH_KEYWORDS,
e2e_p07_check_doc},
{NULL} // sentinel
};

static PyModuleDef module = {
PyModuleDef_HEAD_INIT,
.m_name = "e2e.p07",
.m_doc = "",
.m_size = -1,
.m_methods = methods};

PyMODINIT_FUNC PyInit_p07(void)
{

PyObject *module_p;
module_p = PyModule_Create(&module);

if (module_p == NULL)
return (NULL);

return (module_p);
}
11 changes: 11 additions & 0 deletions src/e2e/p07.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
def e2e_p07_protect(
data: bytearray,
length: int,
data_id: int,
*,
offset: int = 0,
increment_counter: bool = True,
) -> None: ...
def e2e_p07_check(
data: bytes, length: int, data_id: int, *, offset: int = 0
) -> bool: ...
Loading

0 comments on commit cc64088

Please sign in to comment.