* .

* wip

* wip

* wip

* wip

* tag=True does not do anything because it is default

* attach, detach...

* gov

* deps

* fix

* wip

* .

* wip

* wip

* checks

* wip

* .

* verifier

* verifier

* plug stuff in

* fmt

* .

* wip

* fix

* rest

* move test

* fix

* tweaks

* cmake

* cmake_fix

* schema

* Update include/ccf/common_auth_policies.h

Co-authored-by: Eddy Ashton <ashton.eddy@gmail.com>

* feedback

* span span span

* .

* Turn off colours in the governance test

Co-authored-by: Eddy Ashton <ashton.eddy@gmail.com>
This commit is contained in:
Amaury Chamayou 2022-10-18 11:01:54 +01:00 коммит произвёл GitHub
Родитель 1dd0f69b45
Коммит 1bbf8886f3
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
113 изменённых файлов: 50802 добавлений и 13 удалений

57
3rdparty/exported/QCBOR/.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,57 @@
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
# Compiled binaries
qcbortest
qcbormin

20
3rdparty/exported/QCBOR/.travis.yml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,20 @@
os:
- linux
language: c
compiler:
- gcc
env:
sudo: false
addons:
apt:
packages:
- make
install:
- make
script:
- ./qcbortest

19
3rdparty/exported/QCBOR/CMakeLists.txt поставляемый Normal file
Просмотреть файл

@ -0,0 +1,19 @@
cmake_minimum_required(VERSION 3.10.2)
project(qcbor
DESCRIPTION "QCBOR"
LANGUAGES C
VERSION 1.0.0)
set(CMAKE_C_FLAGS "-pedantic -Wall -O3 -ffunction-sections")
set(SOURCE
src/ieee754.c
src/qcbor_decode.c
src/qcbor_encode.c
src/qcbor_err_to_str.c
src/UsefulBuf.c
)
add_library(qcbor ${SOURCE})
target_include_directories(qcbor PUBLIC inc)

101
3rdparty/exported/QCBOR/Makefile поставляемый Normal file
Просмотреть файл

@ -0,0 +1,101 @@
# Makefile -- UNIX-style make for qcbor as a lib and command line test
#
# Copyright (c) 2018-2021, Laurence Lundblade. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
# See BSD-3-Clause license in README.md
#
# The math library is needed for floating-point support. To
# avoid need for it #define QCBOR_DISABLE_FLOAT_HW_USE
LIBS=-lm
# The QCBOR makefile uses a minimum of compiler flags so that it will
# work out-of-the-box with a wide variety of compilers. For example,
# some compilers error out on some of the warnings flags gcc supports.
# The $(CMD_LINE) variable allows passing in extra flags. This is
# used on the stringent build script that is in
# https://github.com/laurencelundblade/qdv. This script is used
# before pushes to master (though not yet through and automated build
# process)
CFLAGS=$(CMD_LINE) -I inc -I test -Os -fPIC
QCBOR_OBJ=src/UsefulBuf.o src/qcbor_encode.o src/qcbor_decode.o src/ieee754.o src/qcbor_err_to_str.o
TEST_OBJ=test/UsefulBuf_Tests.o test/qcbor_encode_tests.o \
test/qcbor_decode_tests.o test/run_tests.o \
test/float_tests.o test/half_to_double_from_rfc7049.o example.o ub-example.o
.PHONY: all so install uninstall clean
all: qcbortest libqcbor.a
so: libqcbor.so
qcbortest: libqcbor.a $(TEST_OBJ) cmd_line_main.o
$(CC) -o $@ $^ libqcbor.a $(LIBS)
libqcbor.a: $(QCBOR_OBJ)
ar -r $@ $^
# The shared library is not made by default because of platform
# variability For example MacOS and Linux behave differently and some
# IoT OS's don't support them at all.
libqcbor.so: $(QCBOR_OBJ)
$(CC) -shared $^ $(CFLAGS) -o $@
PUBLIC_INTERFACE=inc/qcbor/UsefulBuf.h inc/qcbor/qcbor_private.h inc/qcbor/qcbor_common.h inc/qcbor/qcbor_encode.h inc/qcbor/qcbor_decode.h inc/qcbor/qcbor_spiffy_decode.h
src/UsefulBuf.o: inc/qcbor/UsefulBuf.h
src/qcbor_decode.o: inc/qcbor/UsefulBuf.h inc/qcbor/qcbor_private.h inc/qcbor/qcbor_common.h inc/qcbor/qcbor_decode.h inc/qcbor/qcbor_spiffy_decode.h src/ieee754.h
src/qcbor_encode.o: inc/qcbor/UsefulBuf.h inc/qcbor/qcbor_private.h inc/qcbor/qcbor_common.h inc/qcbor/qcbor_encode.h src/ieee754.h
src/iee754.o: src/ieee754.h
src/qcbor_err_to_str.o: inc/qcbor/qcbor_common.h
example.o: $(PUBLIC_INTERFACE)
ub-example.o: $(PUBLIC_INTERFACE)
test/run_tests.o: test/UsefulBuf_Tests.h test/float_tests.h test/run_tests.h test/qcbor_encode_tests.h test/qcbor_decode_tests.h inc/qcbor/qcbor_private.h
test/UsefulBuf_Tests.o: test/UsefulBuf_Tests.h inc/qcbor/UsefulBuf.h
test/qcbor_encode_tests.o: test/qcbor_encode_tests.h $(PUBLIC_INTERFACE)
test/qcbor_decode_tests.o: test/qcbor_decode_tests.h $(PUBLIC_INTERFACE)
test/float_tests.o: test/float_tests.h test/half_to_double_from_rfc7049.h $(PUBLIC_INTERFACE)
test/half_to_double_from_rfc7049.o: test/half_to_double_from_rfc7049.h
cmd_line_main.o: test/run_tests.h $(PUBLIC_INTERFACE)
ifeq ($(PREFIX),)
PREFIX := /usr/local
endif
install: libqcbor.a $(PUBLIC_INTERFACE)
install -d $(DESTDIR)$(PREFIX)/lib/
install -m 644 libqcbor.a $(DESTDIR)$(PREFIX)/lib/
install -d $(DESTDIR)$(PREFIX)/include/qcbor
install -m 644 inc/qcbor/qcbor.h $(DESTDIR)$(PREFIX)/include/qcbor
install -m 644 inc/qcbor/qcbor_private.h $(DESTDIR)$(PREFIX)/include/qcbor
install -m 644 inc/qcbor/qcbor_common.h $(DESTDIR)$(PREFIX)/include/qcbor
install -m 644 inc/qcbor/qcbor_decode.h $(DESTDIR)$(PREFIX)/include/qcbor
install -m 644 inc/qcbor/qcbor_spiffy_decode.h $(DESTDIR)$(PREFIX)/include/qcbor
install -m 644 inc/qcbor/qcbor_encode.h $(DESTDIR)$(PREFIX)/include/qcbor
install -m 644 inc/qcbor/UsefulBuf.h $(DESTDIR)$(PREFIX)/include/qcbor
install_so: libqcbor.so
install -m 755 libqcbor.so $(DESTDIR)$(PREFIX)/lib/libqcbor.so.1.0.0
ln -sf libqcbor.so.1 $(DESTDIR)$(PREFIX)/lib/libqcbor.so
ln -sf libqcbor.so.1.0.0 $(DESTDIR)$(PREFIX)/lib/libqcbor.so.1
uninstall: libqcbor.a $(PUBLIC_INTERFACE)
$(RM) -d $(DESTDIR)$(PREFIX)/include/qcbor/*
$(RM) -d $(DESTDIR)$(PREFIX)/include/qcbor/
$(RM) $(addprefix $(DESTDIR)$(PREFIX)/lib/, \
libqcbor.a libqcbor.so libqcbor.so.1 libqcbor.so.1.0.0)
clean:
rm -f $(QCBOR_OBJ) $(TEST_OBJ) libqcbor.a cmd_line_main.o libqcbor.a libqcbor.so qcbormin qcbortest

942
3rdparty/exported/QCBOR/QCBOR.xcodeproj/project.pbxproj поставляемый Normal file
Просмотреть файл

@ -0,0 +1,942 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 50;
objects = {
/* Begin PBXBuildFile section */
0FA9BEB7216CE6CA00BA646B /* qcbor_decode_tests.c in Sources */ = {isa = PBXBuildFile; fileRef = 0FA9BEB5216CE6CA00BA646B /* qcbor_decode_tests.c */; };
0FA9BEBA216DC7AD00BA646B /* qcbor_encode_tests.c in Sources */ = {isa = PBXBuildFile; fileRef = 0FA9BEB8216DC7AD00BA646B /* qcbor_encode_tests.c */; };
0FA9BEBD216DE31700BA646B /* UsefulBuf_Tests.c in Sources */ = {isa = PBXBuildFile; fileRef = 0FA9BEBC216DE31700BA646B /* UsefulBuf_Tests.c */; };
E73B57592161CA690080D658 /* ieee754.c in Sources */ = {isa = PBXBuildFile; fileRef = E73B57582161CA690080D658 /* ieee754.c */; };
E73B575E2161CA7C0080D658 /* float_tests.c in Sources */ = {isa = PBXBuildFile; fileRef = E73B575A2161CA7C0080D658 /* float_tests.c */; };
E73B575F2161CA7C0080D658 /* half_to_double_from_rfc7049.c in Sources */ = {isa = PBXBuildFile; fileRef = E73B575D2161CA7C0080D658 /* half_to_double_from_rfc7049.c */; };
E73B57652161F8F80080D658 /* run_tests.c in Sources */ = {isa = PBXBuildFile; fileRef = E73B57632161F8F70080D658 /* run_tests.c */; };
E743D0F324AD08020017899F /* example.c in Sources */ = {isa = PBXBuildFile; fileRef = E743D0E124AC516D0017899F /* example.c */; };
E743D10B24DD4EF50017899F /* qcbor_encode.c in Sources */ = {isa = PBXBuildFile; fileRef = E776E08C214AE07400E67947 /* qcbor_encode.c */; };
E743D10C24DD4EF50017899F /* ieee754.c in Sources */ = {isa = PBXBuildFile; fileRef = E73B57582161CA690080D658 /* ieee754.c */; };
E743D10D24DD4EF50017899F /* half_to_double_from_rfc7049.c in Sources */ = {isa = PBXBuildFile; fileRef = E73B575D2161CA7C0080D658 /* half_to_double_from_rfc7049.c */; };
E743D10E24DD4EF50017899F /* run_tests.c in Sources */ = {isa = PBXBuildFile; fileRef = E73B57632161F8F70080D658 /* run_tests.c */; };
E743D10F24DD4EF50017899F /* qcbor_decode.c in Sources */ = {isa = PBXBuildFile; fileRef = E776E08E214AE07500E67947 /* qcbor_decode.c */; };
E743D11024DD4EF50017899F /* float_tests.c in Sources */ = {isa = PBXBuildFile; fileRef = E73B575A2161CA7C0080D658 /* float_tests.c */; };
E743D11124DD4EF50017899F /* qcbor_decode_tests.c in Sources */ = {isa = PBXBuildFile; fileRef = 0FA9BEB5216CE6CA00BA646B /* qcbor_decode_tests.c */; };
E743D11224DD4EF50017899F /* UsefulBuf.c in Sources */ = {isa = PBXBuildFile; fileRef = E776E08D214AE07500E67947 /* UsefulBuf.c */; };
E743D11324DD4EF50017899F /* qcbor_encode_tests.c in Sources */ = {isa = PBXBuildFile; fileRef = 0FA9BEB8216DC7AD00BA646B /* qcbor_encode_tests.c */; };
E743D11424DD4EF50017899F /* cmd_line_main.c in Sources */ = {isa = PBXBuildFile; fileRef = E776E096214AE0C700E67947 /* cmd_line_main.c */; };
E743D11524DD4EF50017899F /* UsefulBuf_Tests.c in Sources */ = {isa = PBXBuildFile; fileRef = 0FA9BEBC216DE31700BA646B /* UsefulBuf_Tests.c */; };
E743D11C24DD51340017899F /* example.c in Sources */ = {isa = PBXBuildFile; fileRef = E743D0E124AC516D0017899F /* example.c */; };
E743D11D24DD51350017899F /* example.c in Sources */ = {isa = PBXBuildFile; fileRef = E743D0E124AC516D0017899F /* example.c */; };
E743D12024DE05CC0017899F /* qcbor_encode.c in Sources */ = {isa = PBXBuildFile; fileRef = E776E08C214AE07400E67947 /* qcbor_encode.c */; };
E743D12124DE05CC0017899F /* ieee754.c in Sources */ = {isa = PBXBuildFile; fileRef = E73B57582161CA690080D658 /* ieee754.c */; };
E743D12224DE05CC0017899F /* half_to_double_from_rfc7049.c in Sources */ = {isa = PBXBuildFile; fileRef = E73B575D2161CA7C0080D658 /* half_to_double_from_rfc7049.c */; };
E743D12324DE05CC0017899F /* run_tests.c in Sources */ = {isa = PBXBuildFile; fileRef = E73B57632161F8F70080D658 /* run_tests.c */; };
E743D12424DE05CC0017899F /* qcbor_decode.c in Sources */ = {isa = PBXBuildFile; fileRef = E776E08E214AE07500E67947 /* qcbor_decode.c */; };
E743D12524DE05CC0017899F /* float_tests.c in Sources */ = {isa = PBXBuildFile; fileRef = E73B575A2161CA7C0080D658 /* float_tests.c */; };
E743D12624DE05CC0017899F /* qcbor_decode_tests.c in Sources */ = {isa = PBXBuildFile; fileRef = 0FA9BEB5216CE6CA00BA646B /* qcbor_decode_tests.c */; };
E743D12724DE05CC0017899F /* UsefulBuf.c in Sources */ = {isa = PBXBuildFile; fileRef = E776E08D214AE07500E67947 /* UsefulBuf.c */; };
E743D12824DE05CC0017899F /* qcbor_encode_tests.c in Sources */ = {isa = PBXBuildFile; fileRef = 0FA9BEB8216DC7AD00BA646B /* qcbor_encode_tests.c */; };
E743D12924DE05CC0017899F /* cmd_line_main.c in Sources */ = {isa = PBXBuildFile; fileRef = E776E096214AE0C700E67947 /* cmd_line_main.c */; };
E743D12A24DE05CC0017899F /* example.c in Sources */ = {isa = PBXBuildFile; fileRef = E743D0E124AC516D0017899F /* example.c */; };
E743D12B24DE05CC0017899F /* UsefulBuf_Tests.c in Sources */ = {isa = PBXBuildFile; fileRef = 0FA9BEBC216DE31700BA646B /* UsefulBuf_Tests.c */; };
E772021723B52C02006E966E /* qcbor_encode.c in Sources */ = {isa = PBXBuildFile; fileRef = E776E08C214AE07400E67947 /* qcbor_encode.c */; };
E772021823B52C02006E966E /* ieee754.c in Sources */ = {isa = PBXBuildFile; fileRef = E73B57582161CA690080D658 /* ieee754.c */; };
E772021923B52C02006E966E /* half_to_double_from_rfc7049.c in Sources */ = {isa = PBXBuildFile; fileRef = E73B575D2161CA7C0080D658 /* half_to_double_from_rfc7049.c */; };
E772021A23B52C02006E966E /* run_tests.c in Sources */ = {isa = PBXBuildFile; fileRef = E73B57632161F8F70080D658 /* run_tests.c */; };
E772021B23B52C02006E966E /* qcbor_decode.c in Sources */ = {isa = PBXBuildFile; fileRef = E776E08E214AE07500E67947 /* qcbor_decode.c */; };
E772021C23B52C02006E966E /* float_tests.c in Sources */ = {isa = PBXBuildFile; fileRef = E73B575A2161CA7C0080D658 /* float_tests.c */; };
E772021D23B52C02006E966E /* qcbor_decode_tests.c in Sources */ = {isa = PBXBuildFile; fileRef = 0FA9BEB5216CE6CA00BA646B /* qcbor_decode_tests.c */; };
E772021E23B52C02006E966E /* UsefulBuf.c in Sources */ = {isa = PBXBuildFile; fileRef = E776E08D214AE07500E67947 /* UsefulBuf.c */; };
E772021F23B52C02006E966E /* qcbor_encode_tests.c in Sources */ = {isa = PBXBuildFile; fileRef = 0FA9BEB8216DC7AD00BA646B /* qcbor_encode_tests.c */; };
E772022023B52C02006E966E /* cmd_line_main.c in Sources */ = {isa = PBXBuildFile; fileRef = E776E096214AE0C700E67947 /* cmd_line_main.c */; };
E772022123B52C02006E966E /* UsefulBuf_Tests.c in Sources */ = {isa = PBXBuildFile; fileRef = 0FA9BEBC216DE31700BA646B /* UsefulBuf_Tests.c */; };
E776E08F214AE07500E67947 /* qcbor_encode.c in Sources */ = {isa = PBXBuildFile; fileRef = E776E08C214AE07400E67947 /* qcbor_encode.c */; };
E776E090214AE07500E67947 /* UsefulBuf.c in Sources */ = {isa = PBXBuildFile; fileRef = E776E08D214AE07500E67947 /* UsefulBuf.c */; };
E776E091214AE07500E67947 /* qcbor_decode.c in Sources */ = {isa = PBXBuildFile; fileRef = E776E08E214AE07500E67947 /* qcbor_decode.c */; };
E776E097214AE0C700E67947 /* cmd_line_main.c in Sources */ = {isa = PBXBuildFile; fileRef = E776E096214AE0C700E67947 /* cmd_line_main.c */; };
E7864766252CE63100A0C11B /* qcbor_err_to_str.c in Sources */ = {isa = PBXBuildFile; fileRef = E7864765252CE63100A0C11B /* qcbor_err_to_str.c */; };
E7C960B92800A09E00FB537C /* ub-example.c in Sources */ = {isa = PBXBuildFile; fileRef = E7C960B82800A09E00FB537C /* ub-example.c */; };
E7FDBF04256C969D007138A8 /* qcbor_encode.c in Sources */ = {isa = PBXBuildFile; fileRef = E776E08C214AE07400E67947 /* qcbor_encode.c */; };
E7FDBF05256C969D007138A8 /* ieee754.c in Sources */ = {isa = PBXBuildFile; fileRef = E73B57582161CA690080D658 /* ieee754.c */; };
E7FDBF06256C969D007138A8 /* qcbor_err_to_str.c in Sources */ = {isa = PBXBuildFile; fileRef = E7864765252CE63100A0C11B /* qcbor_err_to_str.c */; };
E7FDBF07256C969D007138A8 /* half_to_double_from_rfc7049.c in Sources */ = {isa = PBXBuildFile; fileRef = E73B575D2161CA7C0080D658 /* half_to_double_from_rfc7049.c */; };
E7FDBF08256C969D007138A8 /* run_tests.c in Sources */ = {isa = PBXBuildFile; fileRef = E73B57632161F8F70080D658 /* run_tests.c */; };
E7FDBF09256C969D007138A8 /* qcbor_decode.c in Sources */ = {isa = PBXBuildFile; fileRef = E776E08E214AE07500E67947 /* qcbor_decode.c */; };
E7FDBF0A256C969D007138A8 /* float_tests.c in Sources */ = {isa = PBXBuildFile; fileRef = E73B575A2161CA7C0080D658 /* float_tests.c */; };
E7FDBF0B256C969D007138A8 /* qcbor_decode_tests.c in Sources */ = {isa = PBXBuildFile; fileRef = 0FA9BEB5216CE6CA00BA646B /* qcbor_decode_tests.c */; };
E7FDBF0C256C969D007138A8 /* UsefulBuf.c in Sources */ = {isa = PBXBuildFile; fileRef = E776E08D214AE07500E67947 /* UsefulBuf.c */; };
E7FDBF0D256C969D007138A8 /* qcbor_encode_tests.c in Sources */ = {isa = PBXBuildFile; fileRef = 0FA9BEB8216DC7AD00BA646B /* qcbor_encode_tests.c */; };
E7FDBF0E256C969D007138A8 /* cmd_line_main.c in Sources */ = {isa = PBXBuildFile; fileRef = E776E096214AE0C700E67947 /* cmd_line_main.c */; };
E7FDBF0F256C969D007138A8 /* example.c in Sources */ = {isa = PBXBuildFile; fileRef = E743D0E124AC516D0017899F /* example.c */; };
E7FDBF10256C969D007138A8 /* UsefulBuf_Tests.c in Sources */ = {isa = PBXBuildFile; fileRef = 0FA9BEBC216DE31700BA646B /* UsefulBuf_Tests.c */; };
E7FDBF1A257A6C1F007138A8 /* qcbor_encode.c in Sources */ = {isa = PBXBuildFile; fileRef = E776E08C214AE07400E67947 /* qcbor_encode.c */; };
E7FDBF1B257A6C1F007138A8 /* ieee754.c in Sources */ = {isa = PBXBuildFile; fileRef = E73B57582161CA690080D658 /* ieee754.c */; };
E7FDBF1C257A6C1F007138A8 /* qcbor_err_to_str.c in Sources */ = {isa = PBXBuildFile; fileRef = E7864765252CE63100A0C11B /* qcbor_err_to_str.c */; };
E7FDBF1D257A6C1F007138A8 /* half_to_double_from_rfc7049.c in Sources */ = {isa = PBXBuildFile; fileRef = E73B575D2161CA7C0080D658 /* half_to_double_from_rfc7049.c */; };
E7FDBF1E257A6C1F007138A8 /* run_tests.c in Sources */ = {isa = PBXBuildFile; fileRef = E73B57632161F8F70080D658 /* run_tests.c */; };
E7FDBF1F257A6C1F007138A8 /* qcbor_decode.c in Sources */ = {isa = PBXBuildFile; fileRef = E776E08E214AE07500E67947 /* qcbor_decode.c */; };
E7FDBF20257A6C1F007138A8 /* float_tests.c in Sources */ = {isa = PBXBuildFile; fileRef = E73B575A2161CA7C0080D658 /* float_tests.c */; };
E7FDBF21257A6C1F007138A8 /* qcbor_decode_tests.c in Sources */ = {isa = PBXBuildFile; fileRef = 0FA9BEB5216CE6CA00BA646B /* qcbor_decode_tests.c */; };
E7FDBF22257A6C1F007138A8 /* UsefulBuf.c in Sources */ = {isa = PBXBuildFile; fileRef = E776E08D214AE07500E67947 /* UsefulBuf.c */; };
E7FDBF23257A6C1F007138A8 /* qcbor_encode_tests.c in Sources */ = {isa = PBXBuildFile; fileRef = 0FA9BEB8216DC7AD00BA646B /* qcbor_encode_tests.c */; };
E7FDBF24257A6C1F007138A8 /* cmd_line_main.c in Sources */ = {isa = PBXBuildFile; fileRef = E776E096214AE0C700E67947 /* cmd_line_main.c */; };
E7FDBF25257A6C1F007138A8 /* example.c in Sources */ = {isa = PBXBuildFile; fileRef = E743D0E124AC516D0017899F /* example.c */; };
E7FDBF26257A6C1F007138A8 /* UsefulBuf_Tests.c in Sources */ = {isa = PBXBuildFile; fileRef = 0FA9BEBC216DE31700BA646B /* UsefulBuf_Tests.c */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
E743D11724DD4EF50017899F /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
E743D12D24DE05CC0017899F /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
E772022323B52C02006E966E /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
E776E07A214ADF7F00E67947 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
E7FDBF12256C969D007138A8 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
E7FDBF28257A6C1F007138A8 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
0F8BADA722EF40FC008B6513 /* not_well_formed_cbor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = not_well_formed_cbor.h; path = test/not_well_formed_cbor.h; sourceTree = "<group>"; };
0FA9BEB5216CE6CA00BA646B /* qcbor_decode_tests.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.c; name = qcbor_decode_tests.c; path = test/qcbor_decode_tests.c; sourceTree = "<group>"; tabWidth = 3; };
0FA9BEB6216CE6CA00BA646B /* qcbor_decode_tests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = qcbor_decode_tests.h; path = test/qcbor_decode_tests.h; sourceTree = "<group>"; };
0FA9BEB8216DC7AD00BA646B /* qcbor_encode_tests.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.c; name = qcbor_encode_tests.c; path = test/qcbor_encode_tests.c; sourceTree = "<group>"; tabWidth = 3; };
0FA9BEB9216DC7AD00BA646B /* qcbor_encode_tests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = qcbor_encode_tests.h; path = test/qcbor_encode_tests.h; sourceTree = "<group>"; };
0FA9BEBB216DE31700BA646B /* UsefulBuf_Tests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UsefulBuf_Tests.h; path = test/UsefulBuf_Tests.h; sourceTree = "<group>"; };
0FA9BEBC216DE31700BA646B /* UsefulBuf_Tests.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.c; name = UsefulBuf_Tests.c; path = test/UsefulBuf_Tests.c; sourceTree = "<group>"; tabWidth = 3; };
E73B57572161CA680080D658 /* ieee754.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ieee754.h; path = src/ieee754.h; sourceTree = "<group>"; };
E73B57582161CA690080D658 /* ieee754.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ieee754.c; path = src/ieee754.c; sourceTree = "<group>"; };
E73B575A2161CA7C0080D658 /* float_tests.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.c; name = float_tests.c; path = test/float_tests.c; sourceTree = "<group>"; tabWidth = 3; };
E73B575B2161CA7C0080D658 /* half_to_double_from_rfc7049.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = half_to_double_from_rfc7049.h; path = test/half_to_double_from_rfc7049.h; sourceTree = "<group>"; };
E73B575C2161CA7C0080D658 /* float_tests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = float_tests.h; path = test/float_tests.h; sourceTree = "<group>"; };
E73B575D2161CA7C0080D658 /* half_to_double_from_rfc7049.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = half_to_double_from_rfc7049.c; path = test/half_to_double_from_rfc7049.c; sourceTree = "<group>"; };
E73B57632161F8F70080D658 /* run_tests.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.c; name = run_tests.c; path = test/run_tests.c; sourceTree = "<group>"; tabWidth = 3; };
E73B57642161F8F80080D658 /* run_tests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = run_tests.h; path = test/run_tests.h; sourceTree = "<group>"; };
E743D0E124AC516D0017899F /* example.c */ = {isa = PBXFileReference; indentWidth = 3; lastKnownFileType = sourcecode.c.c; path = example.c; sourceTree = "<group>"; tabWidth = 3; };
E743D0F224AC54600017899F /* example.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = example.h; sourceTree = "<group>"; };
E743D10824CEDE2D0017899F /* qcbor_spiffy_decode.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.h; name = qcbor_spiffy_decode.h; path = inc/qcbor/qcbor_spiffy_decode.h; sourceTree = "<group>"; tabWidth = 3; };
E743D11B24DD4EF50017899F /* QCBOR_Disable_HW_Float */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = QCBOR_Disable_HW_Float; sourceTree = BUILT_PRODUCTS_DIR; };
E743D13124DE05CC0017899F /* QCBOR_Disable_Preferred_Float */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = QCBOR_Disable_Preferred_Float; sourceTree = BUILT_PRODUCTS_DIR; };
E743D132251014E60017899F /* Tagging.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = Tagging.md; path = doc/Tagging.md; sourceTree = "<group>"; };
E74BF411245D6713002CE8E8 /* UsefulBuf.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.h; name = UsefulBuf.h; path = inc/qcbor/UsefulBuf.h; sourceTree = "<group>"; tabWidth = 3; };
E772022723B52C02006E966E /* QCBOR_Disable_Exp_Mantissa */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = QCBOR_Disable_Exp_Mantissa; sourceTree = BUILT_PRODUCTS_DIR; };
E776E07C214ADF7F00E67947 /* QCBOR */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = QCBOR; sourceTree = BUILT_PRODUCTS_DIR; };
E776E08C214AE07400E67947 /* qcbor_encode.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.c; name = qcbor_encode.c; path = src/qcbor_encode.c; sourceTree = "<group>"; tabWidth = 3; };
E776E08D214AE07500E67947 /* UsefulBuf.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.c; name = UsefulBuf.c; path = src/UsefulBuf.c; sourceTree = "<group>"; tabWidth = 3; };
E776E08E214AE07500E67947 /* qcbor_decode.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.c; name = qcbor_decode.c; path = src/qcbor_decode.c; sourceTree = "<group>"; tabWidth = 3; };
E776E094214AE09700E67947 /* UsefulBuf.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.h; name = UsefulBuf.h; path = inc/UsefulBuf.h; sourceTree = "<group>"; tabWidth = 3; };
E776E096214AE0C700E67947 /* cmd_line_main.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.c; path = cmd_line_main.c; sourceTree = "<group>"; tabWidth = 3; };
E776E161214EE19C00E67947 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
E7864765252CE63100A0C11B /* qcbor_err_to_str.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = qcbor_err_to_str.c; path = src/qcbor_err_to_str.c; sourceTree = "<group>"; };
E78C91DE240C90C100F4CECE /* qcbor_decode.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.h; name = qcbor_decode.h; path = inc/qcbor/qcbor_decode.h; sourceTree = "<group>"; tabWidth = 3; };
E78C91DF240C90C100F4CECE /* qcbor_common.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.h; name = qcbor_common.h; path = inc/qcbor/qcbor_common.h; sourceTree = "<group>"; tabWidth = 3; };
E78C91E0240C90C100F4CECE /* qcbor_private.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.h; name = qcbor_private.h; path = inc/qcbor/qcbor_private.h; sourceTree = "<group>"; tabWidth = 3; };
E78C91E1240C90C100F4CECE /* qcbor_encode.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 3; lastKnownFileType = sourcecode.c.h; name = qcbor_encode.h; path = inc/qcbor/qcbor_encode.h; sourceTree = "<group>"; tabWidth = 3; };
E7C960B72800A09E00FB537C /* ub-example.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ub-example.h"; sourceTree = "<group>"; };
E7C960B82800A09E00FB537C /* ub-example.c */ = {isa = PBXFileReference; indentWidth = 3; lastKnownFileType = sourcecode.c.c; path = "ub-example.c"; sourceTree = "<group>"; tabWidth = 3; };
E7FDBF16256C969D007138A8 /* QCBOR_Disable_Indef */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = QCBOR_Disable_Indef; sourceTree = BUILT_PRODUCTS_DIR; };
E7FDBF2C257A6C1F007138A8 /* QCBOR_Disable_Indef_array */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = QCBOR_Disable_Indef_array; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
E743D11624DD4EF50017899F /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
E743D12C24DE05CC0017899F /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
E772022223B52C02006E966E /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
E776E079214ADF7F00E67947 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
E7FDBF11256C969D007138A8 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
E7FDBF27257A6C1F007138A8 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
E743D0E024AC51470017899F /* example */ = {
isa = PBXGroup;
children = (
E743D0F224AC54600017899F /* example.h */,
E743D0E124AC516D0017899F /* example.c */,
E7C960B72800A09E00FB537C /* ub-example.h */,
E7C960B82800A09E00FB537C /* ub-example.c */,
);
name = example;
sourceTree = "<group>";
};
E776E073214ADF7F00E67947 = {
isa = PBXGroup;
children = (
E776E161214EE19C00E67947 /* README.md */,
E743D132251014E60017899F /* Tagging.md */,
E776E096214AE0C700E67947 /* cmd_line_main.c */,
E776E092214AE07C00E67947 /* inc */,
E776E08B214AE06600E67947 /* src */,
E776E095214AE0B600E67947 /* test */,
E743D0E024AC51470017899F /* example */,
E776E07D214ADF7F00E67947 /* Products */,
);
sourceTree = "<group>";
};
E776E07D214ADF7F00E67947 /* Products */ = {
isa = PBXGroup;
children = (
E776E07C214ADF7F00E67947 /* QCBOR */,
E772022723B52C02006E966E /* QCBOR_Disable_Exp_Mantissa */,
E743D11B24DD4EF50017899F /* QCBOR_Disable_HW_Float */,
E743D13124DE05CC0017899F /* QCBOR_Disable_Preferred_Float */,
E7FDBF16256C969D007138A8 /* QCBOR_Disable_Indef */,
E7FDBF2C257A6C1F007138A8 /* QCBOR_Disable_Indef_array */,
);
name = Products;
sourceTree = "<group>";
};
E776E08B214AE06600E67947 /* src */ = {
isa = PBXGroup;
children = (
E776E08C214AE07400E67947 /* qcbor_encode.c */,
E776E08E214AE07500E67947 /* qcbor_decode.c */,
E776E08D214AE07500E67947 /* UsefulBuf.c */,
E73B57582161CA690080D658 /* ieee754.c */,
E73B57572161CA680080D658 /* ieee754.h */,
E7864765252CE63100A0C11B /* qcbor_err_to_str.c */,
);
name = src;
sourceTree = "<group>";
};
E776E092214AE07C00E67947 /* inc */ = {
isa = PBXGroup;
children = (
E743D10824CEDE2D0017899F /* qcbor_spiffy_decode.h */,
E74BF411245D6713002CE8E8 /* UsefulBuf.h */,
E78C91DF240C90C100F4CECE /* qcbor_common.h */,
E78C91DE240C90C100F4CECE /* qcbor_decode.h */,
E78C91E1240C90C100F4CECE /* qcbor_encode.h */,
E78C91E0240C90C100F4CECE /* qcbor_private.h */,
E776E094214AE09700E67947 /* UsefulBuf.h */,
);
name = inc;
sourceTree = "<group>";
};
E776E095214AE0B600E67947 /* test */ = {
isa = PBXGroup;
children = (
E73B57632161F8F70080D658 /* run_tests.c */,
E73B57642161F8F80080D658 /* run_tests.h */,
0FA9BEBC216DE31700BA646B /* UsefulBuf_Tests.c */,
0FA9BEBB216DE31700BA646B /* UsefulBuf_Tests.h */,
0FA9BEB8216DC7AD00BA646B /* qcbor_encode_tests.c */,
0FA9BEB9216DC7AD00BA646B /* qcbor_encode_tests.h */,
0FA9BEB5216CE6CA00BA646B /* qcbor_decode_tests.c */,
0FA9BEB6216CE6CA00BA646B /* qcbor_decode_tests.h */,
E73B575A2161CA7C0080D658 /* float_tests.c */,
E73B575C2161CA7C0080D658 /* float_tests.h */,
E73B575D2161CA7C0080D658 /* half_to_double_from_rfc7049.c */,
E73B575B2161CA7C0080D658 /* half_to_double_from_rfc7049.h */,
0F8BADA722EF40FC008B6513 /* not_well_formed_cbor.h */,
);
name = test;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
E743D10924DD4EF50017899F /* QCBOR_Disable_HW_Float */ = {
isa = PBXNativeTarget;
buildConfigurationList = E743D11824DD4EF50017899F /* Build configuration list for PBXNativeTarget "QCBOR_Disable_HW_Float" */;
buildPhases = (
E743D10A24DD4EF50017899F /* Sources */,
E743D11624DD4EF50017899F /* Frameworks */,
E743D11724DD4EF50017899F /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = QCBOR_Disable_HW_Float;
productName = QCBOR;
productReference = E743D11B24DD4EF50017899F /* QCBOR_Disable_HW_Float */;
productType = "com.apple.product-type.tool";
};
E743D11E24DE05CC0017899F /* QCBOR_Disable_Preferred_Float */ = {
isa = PBXNativeTarget;
buildConfigurationList = E743D12E24DE05CC0017899F /* Build configuration list for PBXNativeTarget "QCBOR_Disable_Preferred_Float" */;
buildPhases = (
E743D11F24DE05CC0017899F /* Sources */,
E743D12C24DE05CC0017899F /* Frameworks */,
E743D12D24DE05CC0017899F /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = QCBOR_Disable_Preferred_Float;
productName = QCBOR;
productReference = E743D13124DE05CC0017899F /* QCBOR_Disable_Preferred_Float */;
productType = "com.apple.product-type.tool";
};
E772021523B52C02006E966E /* QCBOR_Disable_Exp_Mantissa */ = {
isa = PBXNativeTarget;
buildConfigurationList = E772022423B52C02006E966E /* Build configuration list for PBXNativeTarget "QCBOR_Disable_Exp_Mantissa" */;
buildPhases = (
E772021623B52C02006E966E /* Sources */,
E772022223B52C02006E966E /* Frameworks */,
E772022323B52C02006E966E /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = QCBOR_Disable_Exp_Mantissa;
productName = QCBOR;
productReference = E772022723B52C02006E966E /* QCBOR_Disable_Exp_Mantissa */;
productType = "com.apple.product-type.tool";
};
E776E07B214ADF7F00E67947 /* QCBOR */ = {
isa = PBXNativeTarget;
buildConfigurationList = E776E083214ADF7F00E67947 /* Build configuration list for PBXNativeTarget "QCBOR" */;
buildPhases = (
E776E078214ADF7F00E67947 /* Sources */,
E776E079214ADF7F00E67947 /* Frameworks */,
E776E07A214ADF7F00E67947 /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = QCBOR;
productName = QCBOR;
productReference = E776E07C214ADF7F00E67947 /* QCBOR */;
productType = "com.apple.product-type.tool";
};
E7FDBF02256C969D007138A8 /* QCBOR_Disable_Indef */ = {
isa = PBXNativeTarget;
buildConfigurationList = E7FDBF13256C969D007138A8 /* Build configuration list for PBXNativeTarget "QCBOR_Disable_Indef" */;
buildPhases = (
E7FDBF03256C969D007138A8 /* Sources */,
E7FDBF11256C969D007138A8 /* Frameworks */,
E7FDBF12256C969D007138A8 /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = QCBOR_Disable_Indef;
productName = QCBOR;
productReference = E7FDBF16256C969D007138A8 /* QCBOR_Disable_Indef */;
productType = "com.apple.product-type.tool";
};
E7FDBF18257A6C1F007138A8 /* QCBOR_Disable_Indef_array */ = {
isa = PBXNativeTarget;
buildConfigurationList = E7FDBF29257A6C1F007138A8 /* Build configuration list for PBXNativeTarget "QCBOR_Disable_Indef_array" */;
buildPhases = (
E7FDBF19257A6C1F007138A8 /* Sources */,
E7FDBF27257A6C1F007138A8 /* Frameworks */,
E7FDBF28257A6C1F007138A8 /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = QCBOR_Disable_Indef_array;
productName = QCBOR;
productReference = E7FDBF2C257A6C1F007138A8 /* QCBOR_Disable_Indef_array */;
productType = "com.apple.product-type.tool";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
E776E074214ADF7F00E67947 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1150;
ORGANIZATIONNAME = "Laurence Lundblade";
TargetAttributes = {
E776E07B214ADF7F00E67947 = {
CreatedOnToolsVersion = 9.4.1;
};
};
};
buildConfigurationList = E776E077214ADF7F00E67947 /* Build configuration list for PBXProject "QCBOR" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = E776E073214ADF7F00E67947;
productRefGroup = E776E07D214ADF7F00E67947 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
E776E07B214ADF7F00E67947 /* QCBOR */,
E772021523B52C02006E966E /* QCBOR_Disable_Exp_Mantissa */,
E743D10924DD4EF50017899F /* QCBOR_Disable_HW_Float */,
E743D11E24DE05CC0017899F /* QCBOR_Disable_Preferred_Float */,
E7FDBF02256C969D007138A8 /* QCBOR_Disable_Indef */,
E7FDBF18257A6C1F007138A8 /* QCBOR_Disable_Indef_array */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
E743D10A24DD4EF50017899F /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
E743D10B24DD4EF50017899F /* qcbor_encode.c in Sources */,
E743D10C24DD4EF50017899F /* ieee754.c in Sources */,
E743D10D24DD4EF50017899F /* half_to_double_from_rfc7049.c in Sources */,
E743D10E24DD4EF50017899F /* run_tests.c in Sources */,
E743D10F24DD4EF50017899F /* qcbor_decode.c in Sources */,
E743D11024DD4EF50017899F /* float_tests.c in Sources */,
E743D11124DD4EF50017899F /* qcbor_decode_tests.c in Sources */,
E743D11224DD4EF50017899F /* UsefulBuf.c in Sources */,
E743D11324DD4EF50017899F /* qcbor_encode_tests.c in Sources */,
E743D11424DD4EF50017899F /* cmd_line_main.c in Sources */,
E743D11D24DD51350017899F /* example.c in Sources */,
E743D11524DD4EF50017899F /* UsefulBuf_Tests.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
E743D11F24DE05CC0017899F /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
E743D12024DE05CC0017899F /* qcbor_encode.c in Sources */,
E743D12124DE05CC0017899F /* ieee754.c in Sources */,
E743D12224DE05CC0017899F /* half_to_double_from_rfc7049.c in Sources */,
E743D12324DE05CC0017899F /* run_tests.c in Sources */,
E743D12424DE05CC0017899F /* qcbor_decode.c in Sources */,
E743D12524DE05CC0017899F /* float_tests.c in Sources */,
E743D12624DE05CC0017899F /* qcbor_decode_tests.c in Sources */,
E743D12724DE05CC0017899F /* UsefulBuf.c in Sources */,
E743D12824DE05CC0017899F /* qcbor_encode_tests.c in Sources */,
E743D12924DE05CC0017899F /* cmd_line_main.c in Sources */,
E743D12A24DE05CC0017899F /* example.c in Sources */,
E743D12B24DE05CC0017899F /* UsefulBuf_Tests.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
E772021623B52C02006E966E /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
E772021723B52C02006E966E /* qcbor_encode.c in Sources */,
E772021823B52C02006E966E /* ieee754.c in Sources */,
E772021923B52C02006E966E /* half_to_double_from_rfc7049.c in Sources */,
E772021A23B52C02006E966E /* run_tests.c in Sources */,
E772021B23B52C02006E966E /* qcbor_decode.c in Sources */,
E772021C23B52C02006E966E /* float_tests.c in Sources */,
E772021D23B52C02006E966E /* qcbor_decode_tests.c in Sources */,
E772021E23B52C02006E966E /* UsefulBuf.c in Sources */,
E772021F23B52C02006E966E /* qcbor_encode_tests.c in Sources */,
E772022023B52C02006E966E /* cmd_line_main.c in Sources */,
E743D11C24DD51340017899F /* example.c in Sources */,
E772022123B52C02006E966E /* UsefulBuf_Tests.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
E776E078214ADF7F00E67947 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
E776E08F214AE07500E67947 /* qcbor_encode.c in Sources */,
E73B57592161CA690080D658 /* ieee754.c in Sources */,
E7864766252CE63100A0C11B /* qcbor_err_to_str.c in Sources */,
E73B575F2161CA7C0080D658 /* half_to_double_from_rfc7049.c in Sources */,
E73B57652161F8F80080D658 /* run_tests.c in Sources */,
E776E091214AE07500E67947 /* qcbor_decode.c in Sources */,
E73B575E2161CA7C0080D658 /* float_tests.c in Sources */,
0FA9BEB7216CE6CA00BA646B /* qcbor_decode_tests.c in Sources */,
E776E090214AE07500E67947 /* UsefulBuf.c in Sources */,
0FA9BEBA216DC7AD00BA646B /* qcbor_encode_tests.c in Sources */,
E776E097214AE0C700E67947 /* cmd_line_main.c in Sources */,
E7C960B92800A09E00FB537C /* ub-example.c in Sources */,
E743D0F324AD08020017899F /* example.c in Sources */,
0FA9BEBD216DE31700BA646B /* UsefulBuf_Tests.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
E7FDBF03256C969D007138A8 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
E7FDBF04256C969D007138A8 /* qcbor_encode.c in Sources */,
E7FDBF05256C969D007138A8 /* ieee754.c in Sources */,
E7FDBF06256C969D007138A8 /* qcbor_err_to_str.c in Sources */,
E7FDBF07256C969D007138A8 /* half_to_double_from_rfc7049.c in Sources */,
E7FDBF08256C969D007138A8 /* run_tests.c in Sources */,
E7FDBF09256C969D007138A8 /* qcbor_decode.c in Sources */,
E7FDBF0A256C969D007138A8 /* float_tests.c in Sources */,
E7FDBF0B256C969D007138A8 /* qcbor_decode_tests.c in Sources */,
E7FDBF0C256C969D007138A8 /* UsefulBuf.c in Sources */,
E7FDBF0D256C969D007138A8 /* qcbor_encode_tests.c in Sources */,
E7FDBF0E256C969D007138A8 /* cmd_line_main.c in Sources */,
E7FDBF0F256C969D007138A8 /* example.c in Sources */,
E7FDBF10256C969D007138A8 /* UsefulBuf_Tests.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
E7FDBF19257A6C1F007138A8 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
E7FDBF1A257A6C1F007138A8 /* qcbor_encode.c in Sources */,
E7FDBF1B257A6C1F007138A8 /* ieee754.c in Sources */,
E7FDBF1C257A6C1F007138A8 /* qcbor_err_to_str.c in Sources */,
E7FDBF1D257A6C1F007138A8 /* half_to_double_from_rfc7049.c in Sources */,
E7FDBF1E257A6C1F007138A8 /* run_tests.c in Sources */,
E7FDBF1F257A6C1F007138A8 /* qcbor_decode.c in Sources */,
E7FDBF20257A6C1F007138A8 /* float_tests.c in Sources */,
E7FDBF21257A6C1F007138A8 /* qcbor_decode_tests.c in Sources */,
E7FDBF22257A6C1F007138A8 /* UsefulBuf.c in Sources */,
E7FDBF23257A6C1F007138A8 /* qcbor_encode_tests.c in Sources */,
E7FDBF24257A6C1F007138A8 /* cmd_line_main.c in Sources */,
E7FDBF25257A6C1F007138A8 /* example.c in Sources */,
E7FDBF26257A6C1F007138A8 /* UsefulBuf_Tests.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
E743D11924DD4EF50017899F /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_UNDEFINED_BEHAVIOR_SANITIZER_INTEGER = YES;
CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES;
CODE_SIGN_STYLE = Automatic;
GCC_OPTIMIZATION_LEVEL = 0;
"GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = QCBOR_DISABLE_FLOAT_HW_USE;
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
GCC_WARN_PEDANTIC = YES;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
E743D11A24DD4EF50017899F /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_UNDEFINED_BEHAVIOR_SANITIZER_INTEGER = YES;
CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES;
CODE_SIGN_STYLE = Automatic;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
GCC_WARN_PEDANTIC = YES;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
E743D12F24DE05CC0017899F /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_UNDEFINED_BEHAVIOR_SANITIZER_INTEGER = YES;
CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES;
CODE_SIGN_STYLE = Automatic;
GCC_OPTIMIZATION_LEVEL = 0;
"GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = QCBOR_DISABLE_PREFERRED_FLOAT;
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
GCC_WARN_PEDANTIC = YES;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
E743D13024DE05CC0017899F /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_UNDEFINED_BEHAVIOR_SANITIZER_INTEGER = YES;
CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES;
CODE_SIGN_STYLE = Automatic;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
GCC_WARN_PEDANTIC = YES;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
E772022523B52C02006E966E /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_UNDEFINED_BEHAVIOR_SANITIZER_INTEGER = YES;
CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES;
CODE_SIGN_STYLE = Automatic;
GCC_OPTIMIZATION_LEVEL = 0;
"GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA;
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
GCC_WARN_PEDANTIC = YES;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
E772022623B52C02006E966E /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_UNDEFINED_BEHAVIOR_SANITIZER_INTEGER = YES;
CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES;
CODE_SIGN_STYLE = Automatic;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
GCC_WARN_PEDANTIC = YES;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
E776E081214ADF7F00E67947 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_SHADOW = YES;
GCC_WARN_SIGN_COMPARE = YES;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_LABEL = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
"HEADER_SEARCH_PATHS[arch=*]" = inc;
MACOSX_DEPLOYMENT_TARGET = 10.13;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
};
name = Debug;
};
E776E082214ADF7F00E67947 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_SHADOW = YES;
GCC_WARN_SIGN_COMPARE = YES;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_LABEL = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
"HEADER_SEARCH_PATHS[arch=*]" = inc;
MACOSX_DEPLOYMENT_TARGET = 10.13;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
};
name = Release;
};
E776E084214ADF7F00E67947 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_UNDEFINED_BEHAVIOR_SANITIZER_INTEGER = YES;
CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES;
CODE_SIGN_STYLE = Automatic;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
GCC_WARN_PEDANTIC = YES;
"HEADER_SEARCH_PATHS[arch=*]" = inc;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
E776E085214ADF7F00E67947 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_UNDEFINED_BEHAVIOR_SANITIZER_INTEGER = YES;
CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES;
CODE_SIGN_STYLE = Automatic;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
GCC_WARN_PEDANTIC = YES;
"HEADER_SEARCH_PATHS[arch=*]" = inc;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
E7FDBF14256C969D007138A8 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_UNDEFINED_BEHAVIOR_SANITIZER_INTEGER = YES;
CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES;
CODE_SIGN_STYLE = Automatic;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS;
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
GCC_WARN_PEDANTIC = YES;
"HEADER_SEARCH_PATHS[arch=*]" = inc;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
E7FDBF15256C969D007138A8 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_UNDEFINED_BEHAVIOR_SANITIZER_INTEGER = YES;
CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES;
CODE_SIGN_STYLE = Automatic;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
GCC_WARN_PEDANTIC = YES;
"HEADER_SEARCH_PATHS[arch=*]" = inc;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
E7FDBF2A257A6C1F007138A8 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_UNDEFINED_BEHAVIOR_SANITIZER_INTEGER = YES;
CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES;
CODE_SIGN_STYLE = Automatic;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS;
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
GCC_WARN_PEDANTIC = YES;
"HEADER_SEARCH_PATHS[arch=*]" = inc;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
E7FDBF2B257A6C1F007138A8 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_UNDEFINED_BEHAVIOR_SANITIZER_INTEGER = YES;
CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES;
CODE_SIGN_STYLE = Automatic;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
GCC_WARN_PEDANTIC = YES;
"HEADER_SEARCH_PATHS[arch=*]" = inc;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
E743D11824DD4EF50017899F /* Build configuration list for PBXNativeTarget "QCBOR_Disable_HW_Float" */ = {
isa = XCConfigurationList;
buildConfigurations = (
E743D11924DD4EF50017899F /* Debug */,
E743D11A24DD4EF50017899F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
E743D12E24DE05CC0017899F /* Build configuration list for PBXNativeTarget "QCBOR_Disable_Preferred_Float" */ = {
isa = XCConfigurationList;
buildConfigurations = (
E743D12F24DE05CC0017899F /* Debug */,
E743D13024DE05CC0017899F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
E772022423B52C02006E966E /* Build configuration list for PBXNativeTarget "QCBOR_Disable_Exp_Mantissa" */ = {
isa = XCConfigurationList;
buildConfigurations = (
E772022523B52C02006E966E /* Debug */,
E772022623B52C02006E966E /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
E776E077214ADF7F00E67947 /* Build configuration list for PBXProject "QCBOR" */ = {
isa = XCConfigurationList;
buildConfigurations = (
E776E081214ADF7F00E67947 /* Debug */,
E776E082214ADF7F00E67947 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
E776E083214ADF7F00E67947 /* Build configuration list for PBXNativeTarget "QCBOR" */ = {
isa = XCConfigurationList;
buildConfigurations = (
E776E084214ADF7F00E67947 /* Debug */,
E776E085214ADF7F00E67947 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
E7FDBF13256C969D007138A8 /* Build configuration list for PBXNativeTarget "QCBOR_Disable_Indef" */ = {
isa = XCConfigurationList;
buildConfigurations = (
E7FDBF14256C969D007138A8 /* Debug */,
E7FDBF15256C969D007138A8 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
E7FDBF29257A6C1F007138A8 /* Build configuration list for PBXNativeTarget "QCBOR_Disable_Indef_array" */ = {
isa = XCConfigurationList;
buildConfigurations = (
E7FDBF2A257A6C1F007138A8 /* Debug */,
E7FDBF2B257A6C1F007138A8 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = E776E074214ADF7F00E67947 /* Project object */;
}

507
3rdparty/exported/QCBOR/README.md поставляемый Normal file
Просмотреть файл

@ -0,0 +1,507 @@
![QCBOR Logo](https://github.com/laurencelundblade/qdv/blob/master/logo.png?raw=true)
**QCBOR** is a powerful, commercial-quality CBOR encoder/decoder that
implements these RFCs:
* [RFC8949](https://tools.ietf.org/html/rfc8949) The CBOR Standard. (Everything
except sorting of encoded maps)
* [RFC7049](https://tools.ietf.org/html/rfc7049) The previous CBOR standard.
Replaced by RFC 8949.
* [RFC8742](https://tools.ietf.org/html/rfc8742) CBOR Sequences
* [RFC8943](https://tools.ietf.org/html/rfc8943) CBOR Dates
## QCBOR Characteristics
**Implemented in C with minimal dependency** – Dependent only
on C99, <stdint.h>, <stddef.h>, <stdbool.h> and <string.h> making
it highly portable. <math.h> and <fenv.h> are used too, but their
use can disabled. No #ifdefs or compiler options need to be set for
QCBOR to run correctly.
**Focused on C / native data representation** – Careful conversion of
CBOR data types in to C data types, handling over and
underflow, strict typing and such so the caller doesn't have to
worry so much about this and so code using QCBOR passes static
analyzers easier. Simpler code because there is no support for
encoding/decoding to/from JSON, pretty printing, diagnostic
notation... Only encoding from native C representations and decoding
to native C representations is supported.
**Small simple memory model** – Malloc is not needed. The encode
context is 176 bytes, decode context is 312 bytes and the
description of decoded data item is 56 bytes. Stack use is light and
there is no recursion. The caller supplies the memory to hold the
encoded CBOR and encode/decode contexts so caller has full control
of memory usage making it good for embedded implementations that
have to run in small fixed memory.
**Easy decoding of maps** – The "spiffy decode" functions allow
fetching map items directly by label. Detection of duplicate map
items is automatically performed. This makes decoding of complex
protocols much simpler, say when compared to TinyCBOR.
**Supports most of RFC 8949** – With some size limits, all data types
and formats in the specification are supported. Map sorting is main
CBOR feature that is not supported. The same decoding API supports
both definite and indefinite-length map and array decoding. Decoding
indefinite length strings is supported but requires a string
allocator be set up. Encoding of indefinite length strings is
planned, but not yet supported.
**Extensible and general** – Provides a way to handle data types that
are not directly supported.
**Secure coding style** – Uses a construct called UsefulBuf as a
discipline for very safe coding and handling of binary data.
**Small code size** – In the smallest configuration the object
code is less than 4KB on 64-bit x86 CPUs. The design is such that
object code for QCBOR APIs not used is not referenced.
**Clear documented public interface** – The public interface is
separated from the implementation. It can be put to use without
reading the source.
**Comprehensive test suite** – Easy to verify on a new platform or OS
with the test suite. The test suite dependencies are minimal and the
same as the library's.
## Spiffy Decode
These are functions to decode particular data types. They are an
alternative to and built on top of QCBORDecode_GetNext(). They do type
checking and in some cases sophisticated type conversion.
Spiffy decode supports easier map and array decoding. A map can be
descended into with QCBORDecode_EnterMap(). When a map has been
entered, members can be retrieved by label. Detection of duplicate
map labels, an error, is automatically performed.
An internal error state is maintained. This simplifies the decode
implementation as an error check is only needed at the end of the
decode, rather than on every function.
An outcome is that decoding implementations are simple and involve
many fewer lines of code. They also tend to parallel the encoding
implementations as seen in the following example.
/* Encode */
QCBOREncode_Init(&EncodeCtx, Buffer);
QCBOREncode_OpenMap(&EncodeCtx);
QCBOREncode_AddTextToMap(&EncodeCtx, "Manufacturer", pE->Manufacturer);
QCBOREncode_AddInt64ToMap(&EncodeCtx, "Displacement", pE->uDisplacement);
QCBOREncode_AddInt64ToMap(&EncodeCtx, "Horsepower", pE->uHorsePower);
QCBOREncode_CloseMap(&EncodeCtx);
uErr = QCBOREncode_Finish(&EncodeCtx, &EncodedEngine);
/* Decode */
QCBORDecode_Init(&DecodeCtx, EncodedEngine, QCBOR_DECODE_MODE_NORMAL);
QCBORDecode_EnterMap(&DecodeCtx);
QCBORDecode_GetTextStringInMapSZ(&DecodeCtx, "Manufacturer", &(pE->Manufacturer));
QCBORDecode_GetInt64InMapSZ(&DecodeCtx, "Displacement", &(pE->uDisplacement));
QCBORDecode_GetInt64InMapSZ(&DecodeCtx, "Horsepower", &(pE->uHorsePower));
QCBORDecode_ExitMap(&DecodeCtx);
uErr = QCBORDecode_Finish(&DecodeCtx);
The spiffy decode functions will handle definite and indefinite length
maps and arrays without the caller having to do anything. This
includes mixed definite and indefinte maps and arrays. (Some work
remains to support map searching with indefinite length strings.)
## Comparison to TinyCBOR
TinyCBOR is a popular widely used implementation. Like QCBOR,
it is a solid, well-maintained commercial quality implementation. This
section is for folks trying to understand the difference in
the approach between QCBOR and TinyCBOR.
TinyCBOR's API is more minimalist and closer to the CBOR
encoding mechanics than QCBOR's. QCBOR's API is at a somewhat higher
level of abstraction.
QCBOR really does implement just about everything described in
RFC 8949. The main part missing is sorting of maps when encoding.
TinyCBOR implements a smaller part of the standard.
No detailed code size comparison has been made, but in a spot check
that encodes and decodes a single integer shows QCBOR about 25%
larger. QCBOR encoding is actually smaller, but QCBOR decoding is
larger. This includes the code to call the library, which is about the
same for both libraries, and the code linked from the libraries. QCBOR
is a bit more powerful, so you get value for the extra code brought
in, especially when decoding more complex protocols.
QCBOR tracks encoding and decoding errors internally so the caller
doesn't have to check the return code of every call to an encode or
decode function. In many cases the error check is only needed as the
last step or an encode or decode. TinyCBOR requires an error check on
each call.
QCBOR provides a substantial feature that allows searching for data
items in a map by label. It works for integer and text string labels
(and at some point byte-string labels). This includes detection of
items with duplicate labels. This makes the code for decoding CBOR
simpler, similar to the encoding code and easier to read. TinyCBOR
supports search by string, but no integer, nor duplicate detection.
QCBOR provides explicit support many of the registered CBOR tags. For
example, QCBOR supports big numbers and decimal fractions including
their conversion to floats, uint64_t and such.
Generally, QCBOR supports safe conversion of most CBOR number formats
into number formats supported in C. For example, a data item can be
fetched and converted to a C uint64_t whether the input CBOR is an
unsigned 64-bit integer, signed 64-bit integer, floating-point number,
big number, decimal fraction or a big float. The conversion is
performed with full proper error detection of overflow and underflow.
QCBOR has a special feature for decoding byte-string wrapped CBOR. It
treats this similar to entering an array with one item. This is
particularly use for CBOR protocols like COSE that make use of
byte-string wrapping. The implementation of these protocols is
simpler and uses less memory.
QCBOR's test suite is written in the same portable C that QCBOR is
where TinyCBOR requires Qt for its test. QCBOR's test suite is
designed to be able to run on small embedded devices the same as
QCBOR.
## Code Status
The current version is v1.1, a small feature addition and bug fix
release over QCBOR 1.0.
Code has been stable for over a year. The last major change was in
fall of 2020.
QCBOR was originally developed by Qualcomm. It was [open sourced
through CAF](https://source.codeaurora.org/quic/QCBOR/QCBOR/) with a
permissive Linux license, September 2018 (thanks Qualcomm!).
## Building
There is a simple makefile for the UNIX style command line binary that
compiles everything to run the tests.
These eleven files, the contents of the src and inc directories, make
up the entire implementation.
* inc
* UsefulBuf.h
* qcbor_private.h
* qcbor_common.h
* qcbor_encode.h
* qcbor_decode.h
* qcbor_spiffy_decode.h
* src
* UsefulBuf.c
* qcbor_encode.c
* qcbor_decode.c
* ieee754.h
* ieee754.c
For most use cases you should just be able to add them to your
project. Hopefully the easy portability of this implementation makes
this work straight away, whatever your development environment is.
The test directory includes the tests that are nearly as portable as
the main implementation. If your development environment doesn't
support UNIX style command line and make, you should be able to make a
simple project and add the test files to it. Then just call
RunTests() to invoke them all.
While this code will run fine without configuration, there are several
C pre processor macros that can be #defined in order to:
* use a more efficient implementation
* to reduce code size
* to improve performance (a little)
* remove features to reduce code size
See the comment sections on "Configuration" in inc/UsefulBuf.h and
the pre processor defines that start with QCBOR_DISABLE_XXX.
### Floating Point Support & Configuration
By default, all QCBOR floating-point features are enabled:
* Encoding and decoding of basic float types, single and double-precision
* Encoding and decoding of half-precision with conversion to/from single
and double-precision
* Preferred serialization of floating-point
* Floating point dates
* Methods that can convert big numbers, decimal fractions and other numbers
to/from floating-point
If full floating-point is not needed, the following #defines can be
used to reduce object code size and dependency.
See discussion in qcbor_encode.h for other details.
### #define QCBOR_DISABLE_FLOAT_HW_USE
This removes dependency on:
* Floating-point hardware and floating-point instructions
* `<math.h>` and `<fenv.h>`
* The math library (libm, -lm)
For most limited environments, this removes enough floating-point
dependencies to be able to compile and run QCBOR.
Note that this does not remove use of the types double and float from
QCBOR, but it limits QCBOR's use of them to converting the encoded
byte stream to them and copying them. Converting and copying them
usually don't require any hardware, libraries or includes. The C
compiler takes care of it on its own.
QCBOR uses its own implementation of half-precision float-pointing
that doesn't depend on math libraries. It uses masks and shifts
instead. Thus, even with this define, half-precision encoding and
decoding works.
When this is defined, the QCBOR functionality lost is minimal and only
for decoding:
* Decoding floating-point format dates are not handled
* There is no conversion between floats and integers when decoding. For
example, QCBORDecode_GetUInt64ConvertAll() will be unable to convert
to and from float-point.
* Floats will be unconverted to double when decoding.
No interfaces are disabled or removed with this define. If input that
requires floating-point conversion or functions are called that
request floating-point conversion, an error code like
`QCBOR_ERR_HW_FLOAT_DISABLED` will be returned.
This saves only a small amount of object code. The primary purpose for
defining this is to remove dependency on floating point hardware and
libraries.
#### #define QCBOR_DISABLE_PREFERRED_FLOAT
This eliminates support for half-precision
and CBOR preferred serialization by disabling
QCBOR's shift and mask based implementation of
half-precision floating-point.
With this defined, single and double-precision floating-point
numbers can still be encoded and decoded. Conversion
of floating-point to and from integers, big numbers and
such is also supported. Floating-point dates are still
supported.
The primary reason to define this is to save object code.
Roughly 900 bytes are saved, though about half of this
can be saved just by not calling any functions that
encode floating-point numbers.
#### #define USEFULBUF_DISABLE_ALL_FLOAT
This eliminates floating point support completely (along with related function
headers). This is useful if the compiler options deny the usage of floating
point operations completely, and the usage soft floating point ABI is not
possible.
#### Compiler options
Compilers support a number of options that control
which float-point related code is generated. For example,
it is usually possible to give options to the compiler to avoid all
floating-point hardware and instructions, to use software
and replacement libraries instead. These are usually
bigger and slower, but these options may still be useful
in getting QCBOR to run in some environments in
combination with `QCBOR_DISABLE_FLOAT_HW_USE`.
In particular, `-mfloat-abi=soft`, disables use of
hardware instructions for the float and double
types in C for some architectures.
## Code Size
These are approximate sizes on a 64-bit x86 CPU with the -Os optimization.
| | smallest | largest |
|---------------|----------|---------|
| encode only | 850 | 2100 |
| decode only | 2000 | 13300 |
| combined | 2850 | 15500 |
From the table above, one can see that the amount of code pulled in
from the QCBOR library varies a lot, ranging from 1KB to 15KB. The
main factor is in this is the number of QCBOR functions called and
which ones they are. QCBOR is constructed with less internal
interdependency so only code necessary for the called functions is
brought in.
Encoding is simpler and smaller. An encode-only implementation may
bring in only 1KB of code.
Encoding of floating-point brings in a little more code as does
encoding of tagged types and encoding of bstr wrapping.
Basic decoding using QCBORDecode_GetNext() brings in 3KB.
Use of the supplied MemPool by calling QCBORDecode_SetMemPool() to
setup to decode indefinite-length strings adds 0.5KB.
Basic use of spiffy decode to brings in about 3KB. Using more spiffy
decode functions, such as those for tagged types bstr wrapping brings
in more code.
Finally, use of all of the integer conversion functions will bring in
about 5KB, though you can use the simpler ones like
QCBORDecode_GetInt64() without bringing in very much code.
In addition to using fewer QCBOR functions, the following are some
ways to make the code smaller.
The gcc compiler output is usually smaller than llvm because stack
guards are off by default (be sure you actually have gcc and not llvm
installed to be invoked by the gcc command). You can also turn off
stack gaurds with llvm. It is safe to turn off stack gaurds with this
code because Usefulbuf provides similar defenses and this code was
carefully written to be defensive.
If QCBOR is installed as a shared library, then of course only one
copy of the code is in memory no matter how many applications use it.
### Disabling Features
Here's the list of all features that can be disabled to save object
code. The amount saved is an approximation.
| #define | Saves |
| ----------------------------------------| ------|
| QCBOR_DISABLE_ENCODE_USAGE_GUARDS | 150 |
| QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS | 400 |
| QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS | 200 |
| QCBOR_DISABLE_UNCOMMON_TAGS | 100 |
| QCBOR_DISABLE_EXP_AND_MANTISSA | 400 |
| QCBOR_DISABLE_PREFERRED_FLOAT | 900 |
| QCBOR_DISABLE_FLOAT_HW_USE | 50 |
| USEFULBUF_DISABLE_ALL_FLOAT | 950 |
QCBOR_DISABLE_ENCODE_USAGE_GUARDS affects encoding only. It doesn't
disable any encoding features, just some error checking. Disable it
when you are confident that an encoding implementation is complete and
correct.
Indefinite lengths are a feature of CBOR that makes encoding simpler
and the decoding more complex. They allow the encoder to not have to
know the length of a string, map or array when they start encoding
it. Their main use is when encoding has to be done on a very
constrained device. Conversely when decoding on a very constrained
device, it is good to prohibit use of indefinite lengths so the
decoder can be smaller.
The QCBOR decode API processes both definite and indefinite lengths
with the same API, except to decode indefinite-length strings a
storage allocator must be configured.
To reduce the size of the decoder define
QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS particularly if you are not
configuring a storage allocator.
Further reduction can be by defining
QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS which will result in an error
when an indefinite-length map or array arrives for decoding.
QCBOR_DISABLE_UNCOMMON_TAGS disables the decoding of explicit tags for
base 64, regex, UUID and MIME data. This just disabled the automatic
recognition of these from a major type 6 tag.
QCBOR_DISABLE_EXP_AND_MANTISSA disables the decoding of decimal
fractions and big floats.
See the discussion above on floating-point.
### Size of spiffy decode
When creating a decode implementation, there is a choice of whether
or not to use spiffy decode features or to just use
QCBORDecode_GetNext().
The implementation using spiffy decode will be simpler resulting in
the calling code being smaller, but the amount of code brought in
from the QCBOR library will be larger. Basic use of spiffy decode
brings in about 2KB of object code. If object code size is not a
concern, then it is probably better to use spiffy decode because it
is less work, there is less complexity and less testing to worry
about.
If code size is a concern, then use of QCBORDecode_GetNext() will
probably result in smaller overall code size for simpler CBOR
protocols. However, if the CBOR protocol is complex then use of
spiffy decode may reduce overall code size. An example of a complex
protocol is one that involves decoding a lot of maps or maps that
have many data items in them. The overall code may be smaller
because the general purpose spiffy decode map processor is the one
used for all the maps.
## Other Software Using QCBOR
* [t_cose](https://github.com/laurencelundblade/t_cose) implements enough of
[COSE, RFC 8152](https://tools.ietf.org/html/rfc8152) to support
[CBOR Web Token (CWT)](https://tools.ietf.org/html/rfc8392) and
[Entity Attestation Token (EAT)](https://tools.ietf.org/html/draft-ietf-rats-eat-06).
Specifically it supports signing and verification of the COSE_Sign1 message.
* [ctoken](https://github.com/laurencelundblade/ctoken) is an implementation of
EAT and CWT.
## Credits
* Ganesh Kanike for porting to QSEE
* Mark Bapst for sponsorship and release as open source by Qualcomm
* Sachin Sharma for release through CAF
* Tamas Ban for porting to TF-M and 32-bit ARM
* Michael Eckel for Makefile improvements
* Jan Jongboom for indefinite length encoding
* Peter Uiterwijk for error strings and other
* Michael Richarson for CI set up and fixing some compiler warnings
* Máté Tóth-Pál for float-point disabling and other
* Dave Thaler for portability to Windows
## Copyright and License
QCBOR is available under what is essentially the 3-Clause BSD License.
Files created inside Qualcomm and open-sourced through CAF (The Code
Aurora Forum) have a slightly modified 3-Clause BSD License. The
modification additionally disclaims NON-INFRINGEMENT.
Files created after release to CAF use the standard 3-Clause BSD
License with no modification. These files have the SPDX license
identifier, "SPDX-License-Identifier: BSD-3-Clause" in them.
### BSD-3-Clause license
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
### Copyright for this README
Copyright (c) 2018-2021, Laurence Lundblade. All rights reserved.
Copyright (c) 2021, Arm Limited. All rights reserved.

27
3rdparty/exported/QCBOR/SECURITY.md поставляемый Normal file
Просмотреть файл

@ -0,0 +1,27 @@
# Security Policy
## Reporting a Vulnerability
Please report security vulnerabilities by sending email to lgl@island-resort.com.
Please include "QCBOR SECURITY" in the subject line.
In most cases the vulnerability should not be reported by filing an issue in GitHub as this
will publically disclose the issue before a fix is available.
Laurence Lundblade maintains this code and will respond in a day or two with an initial
evaluation.
Security fixes will be prioritized over other work.
Vulnerabilities will be fixed promptly, but some may be more complex than others
and take longer. If the fix is quick, it will usually be turned around in a
few days.
## Availability of Fixes
When the fix has been created, it will be privately verified with the party that reported it.
Only after the fix has been verified and the reporter has had a chance to integrate the fix,
will it be made available as a public commit in GitHub.
If the reporter doesn't respond or can't integrate the fix, it will be made public after 30 days.

1
3rdparty/exported/QCBOR/UsefulBuf.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
#include "qcbor/UsefulBuf.h"

46
3rdparty/exported/QCBOR/cmd_line_main.c поставляемый Normal file
Просмотреть файл

@ -0,0 +1,46 @@
/*==============================================================================
cmd_line_mainc.c -- Runs tests for QCBOR encoder / decoder
Copyright (c) 2018-2020, Laurence Lundblade. All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
See BSD-3-Clause license in README.md
Created on 9/13/18
=============================================================================*/
#include <stdio.h>
#include "run_tests.h"
#include "example.h"
#include "ub-example.h"
/*
This is an implementation of OutputStringCB built using stdio. If
you don't have stdio, replaces this.
*/
static void fputs_wrapper(const char *szString, void *pOutCtx, int bNewLine)
{
fputs(szString, (FILE *)pOutCtx);
if(bNewLine) {
fputs("\n", pOutCtx);
}
}
int main(int argc, const char * argv[])
{
(void)argc; // Avoid unused parameter error
RunQCborExample();
RunUsefulBufExample();
// This call prints out sizes of data structures to remind us
// to keep them small.
PrintSizesQCBOR(&fputs_wrapper, stdout);
// This runs all the tests
return RunTestsQCBOR(argv+1, &fputs_wrapper, stdout, NULL);
}

4
3rdparty/exported/QCBOR/doc/DocReadMe.txt поставляемый Normal file
Просмотреть файл

@ -0,0 +1,4 @@
Most documentation is in the header files in ../inc/qcbor/.
The files here are additional articles.
There is cross-referencing between these articles and the header files.

237
3rdparty/exported/QCBOR/doc/Tagging.md поставляемый Normal file
Просмотреть файл

@ -0,0 +1,237 @@
@anchor CBORTags
# Types and Tagging in CBOR
## New Types
CBOR provides a means for defining new data types beyond the primitive
types like integers and strings. These new types can be the simple
association of some further semantics with a primitive type or they
can be large complex aggregations.
The explicit means for identifying these new types as called tagging.
It uses a simple unsigned integer known as the tag number to indicate
that the following CBOR is of that type. Officially speaking, a "tag"
is made up of exactly a tag number and tag content. The tag content
is exactly a single data item, but note that a single data item can be
a map or an array which contains further nested maps and arrays and
thus arbitrarily complex.
The tag numbers can be up to UINT64_MAX, so there are a lot of them.
Some defined in standards and registered in the IANA CBOR Tag
Registry. A very large range is available for proprietary tags.
## Are Tags "Optional"?
The description of tags in
[RFC 7049] (https://tools.ietf.org/html/rfc7049) and in some other
places can lead one to think they are optional prefixes that can be
ignored at times. This is not true.
As stated above, a tag is exactly a tag number and a single data item
that is the tag content. Its purpose in the encoded CBOR is to
indicate something is of a data type. Ignoring it would be like
ignoring a typedef or struct in C.
However, it is common in CBOR-based protocols to use the format,
semantics or definition of the tag content without it actually being a
*tag*. One can think of this as *borrowing* the tag content or implied
type information.
For example, [RFC 8392] (https://tools.ietf.org/html/rfc8392) which
defines a CBOR Web Token, a CWT, says that the NumericDate field is
represented as a CBOR numeric date described as tag 1 in the CBOR
standard, but with the tag number 1 omitted from the encoding. A
NumericDate is thus not a tag. It just borrows the content format and
semantics from tag 1.
This borrowing of the content makes a lot of sense for data items that
are labeled members of a map where the type of the data can be easily
inferred by the label and the full use of a tag with a tag number
would be redundant.
There is another way that tags are "optional". RFC 8392 serves again
as an example. A CWT is officially defined as a COSE-secured map
containing a bunch of claims where each claim is a labeled data
item. This COSE-secured map-of-claims is the definition of a *CWT* and
stands on its own as the definition of a protocol message. One can say
that some protocol message is a *CWT* without ever mention the word
tag or the *CWT Tag*.
Then RFC 8392 goes on to define a *CWT Tag* as a tag with tag number
of 61 and tag content being a *CWT*. The content format definition
comes first and stands on it's own.
To recap, the tags defined in RFC 7049 such as the date formats define
the content type of the tag only in the context of the tag itself. To
use the content formats outside of the tag, the content format must be
borrowed. By contrast some definitions first define the content
format in an independent way, then they define a tag to enclose that
particular content format. A CWT is of the later sort.
Finally, every CBOR protocol should explicitly spell out how it is
using each tag, borrowing tag content and such. If the protocol you
are trying to implement doesn't, ask the designer. Generally,
protocols designs should not allow for some data item to optional be
either a tag or to be the borrowed tag content. While allowing this
tag optionality is a form of Postel's law, "be liberal in what you
accept", current wisdom is somewhat the opposite.
## Types and Tags in QCBOR
QCBOR explicitly supports all the tags defined in
[RFC 7049] (https://tools.ietf.org/html/rfc7049). It has specific APIs
and data structures for encoding and decoding them.
These APIs and structures can support either the full and proper tag
form or the borrowed content form that is not a tag.
The original QCBOR APIs for encoding tags did not allow for encoding
the borrowed content format. They only support the proper tag
format. With spiffy decode, a second set of APIs was added that takes
and argument to indicate whether the proper tag should be output or
just the borrowed content format should be output. The first set are
the "AddXxxx" functions and the second the "AddTXxxx" functions.
When decoding with QCBORDecode_GetNext(), the non-spiffy decode API,
the proper tag form is automatically recognized by the tag number and
decoded into QCBORItem. This decoding API however cannot recognize
borrowed content format. The caller must tell QCBOR when borrowed
content format is expected.
The spiffy decode APIs for the particular tags are the way the caller
tells QCBOR to expect borrowed content format. These spiffy decode
APIs can also decode the proper tag as well. When asked to decode a
proper tag and the input CBOR is not, it is a decode validity
error. These APIs take an argument which says whether to expect the
proper tag or just the borrowed content. They can also be told to
allow either to "be liberal in what you accept", but this is not
recommended.
## Nested Tags
CBOR tags are an enclosing or encapsulating format. When one tag
encloses another, the enclosed tag is the content for the enclosing
tag.
Encoding nested tags is easy with QCBOREncode_AddTag(). Just call it
several times before calling the functions to encode the tag content.
When QCBOR decodes tags it does so by first completely processing the
built-in tags that it knows how to process. It returns that processed
item.
If tags occur that QCBOR doesn't know how to process, it will return
the tag content as a @ref QCBORItem and list the tags that
encapsulate. The caller then has the information it needs to process
tag that QCBOR did not.
Nesting of tags is certainly used in CBOR protocols, but deep nesting
is less common so QCBOR has an implementation limit of 4 levels of tag
encapsulation on some tag content. (This can be increased by changing
QCBOR_MAX_TAGS_PER_ITEM, but it will increase stack memory use by
increasing the size of a QCBORItem).
QCBOR also saves memory by mapping the tag values larger than
UINT16_MAX, so the tags have to fetched through an accessor function.
When decoding with QCBORDecode_GetNext(), the encapsulating tags are
listed in the QCBORItem returned. When decoding with spiffy decoding
functions the tags encapsulating the last-decoded item are saved in
the decode context and have to be fetched with
QCBORDecode_GetNthTagOfLast().
## Tags for Encapsulated CBOR
Tag 24 and 63 deserve special mention. The content of these tags is a
byte string containing encoded CBOR. The content of tag 24 is a single
CBOR data item and the content of tag 63 is a CBOR sequence, more than
one data item. Said another way, with tag 24 you can have deeply
nested complex structures, but the if you do the one data item must be
either a map or an array or a tag that defined to be complex and
nested. With tag 63, the content can be a sequence of integers not
held together in a map or array. Tag 63 is defined in
[RFC 8742] (https://tools.ietf.org/html/rfc8742).
The point of encapsulating CBOR this way is often so it can be
cryptographically signed. It works well with off-the-shelf encoders
and decoders to sign and verify CBOR this way because the decoder can
just get the byte string that it needs to hash in a normal way, then
feed the content back into another instance of the CBOR decoder.
It is also a way to break up complex CBOR structures so they can be
decoded in layers. Usually, with CBOR one error will render the whole
structure un-decodable because there is little redundancy in the
encoding. By nesting like this, an error in the wrapped CBOR will not
cause decoding error in the wrapping CBOR.
QCBOR can be asked to treat these two tags as nesting like maps and
arrays are nesting with the spiffy decode
QCBORDecode_EnterBstrWrapped() decoding function. It is kind of like
entering an array with one item, but with the difference that the end
is defined by the end of the byte string not the end of the array.
These tags work like others in that they can be the proper tag or they
can be the borrowed content. The QCBOR API supports this as any other
tag.
Finally, the payload and protected headers of COSE are worth
mentioning here. Neither are officially tag 24 or 63 though they look
like it and QCBORs decode APIs can be used on them.
The protected headers are a CBOR byte string that always contains
encoded CBOR. It could have been described as tag 24 borrowed content.
The payload is always a byte string, but only sometimes contains
encoded CBOR. It never could have been defined as tag 24. When the
payload is known to contain CBOR, like the case of a CWT, then QCBOR's
QCBORDecode_EnterBstrWrapped() can be used to decode it.
## Tags that Can be Ignored
There are a few specially defined tags that can actually be
ignored. These are the following:
21 Hint that content should be base64url encoded
22 Hint that content should be base64 encoded
23 Hint that content should be base16 encoded
57799 Tag that serves as a CBOR magic number
The content format for all these tags is that it can be any valid
CBOR. Decoding of these tags doesn't have to check the content format.
Tag 55799 is not really for consumption by the CBOR decoder. Rather it
is for file format checkers and such. The other tags are just hints
in how to process the content. They don't really create new data types
with new semantics.
Other than these four, just about every other tag defined thus far
requires the content to be of a specific type and results in a new
data type that a protocol decoder must understand.
## Standard Tags and the Tags Registry
Tags used in CBOR protocols should at least be registered in the
[IANA CBOR Tags Registry] (https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml).
A small number of tags (0-23), are full IETF standards. Further, tags
24-255 require published documentation, but are not full IETF
standards. Beyond tag 255, the tags are first come first served.
There is no range for private use, so any tag used in a CBOR protocol
should be registered. The range of tag values is very large to
accommodate this.
As described above, It is common to use data types from the registry
in a CBOR protocol without the explicit tag, so in a way the registry
is a registry of data types.
## See Also
See @ref Tags-Overview and @ref Tag-Usage.

56
3rdparty/exported/QCBOR/doc/TimeTag1FAQ.md поставляемый Normal file
Просмотреть файл

@ -0,0 +1,56 @@
# Tag 1 Implementators FAQ
+-------------------------------+---------------------+------------------------+
| | 1 second resolution | microsecond resolution |
+-------------------------------+---------------------+------------------------+
| Recent Human Time Scale | 32-bit unsigned | double |
| 1970 - 2106 | | |
+-------------------------------+---------------------+------------------------+
| Recent Human Past | 32-bit negative | double |
| 1834 - 1970 | | |
+-------------------------------+---------------------+------------------------+
| Universal Scale, Now & Future | 64-bit unsigned | double |
| 1970 - 500 billion years | | |
+-------------------------------+---------------------+------------------------+
| Universal Scale, Past | 64-bit negative | double |
| 500 billion years ago - 1969 | | |
+-------------------------------+---------------------+------------------------+
Q: I just want to implement the minimum, what should I do?
A: You should support 64-bit unsigned encoding. This will cover just about every use case because it works from 1970 until over 500 billion years in the future and 1 second resolution is enough for most human activity. The earth is only 4.5 billion years old. Note that time values up to 2106 will be encoded as 32-bit integers even though 64-bit integers are supported because only 32-bits are needed to count seconds up to the year 2106.
Q: Im implementing on an 8-bit CPU and 64-bit integers are really a problem.
A: You can support just 32-bit integers, but they will stop working in 2106.
Q: Why 2106 and not 2038?
A: Because CBOR encodes positive and negative integers with different major types and thus is able to use the full 32-bits for positive integers.
Q: What if I need time values before 1970?
A: Implement 64 or 32-bit negative time values, but note that there is no clear standard for this as POSIX and UTC time are not defined for this time period. If your implementation assumes every days is 86,400 seconds and follow the rules for leap years, you should have accuracy to within hours, if not minutes.
Q: Is Tag 1 better than Tag 0 for time values?
A: In a lot of ways it is, because it is just a simple integer. It takes up a lot less space. It is a lot simpler to parse. Most OSs have the ability to turn POSIX time into a structure of month, day, year, hour, minute and second. Note however that POSIX time has a discontinuity of about once every year for leap second adjustment.
Q: What is a leap second?
A: It actually takes the earth about 1 year and 1 second to revolve around the sun, so 1 extra second has to be added almost every year. UTC Time handles this by counting the seconds from 0-60 (not 0-59) in the last minute of the year. This standard uses POSIX time which can be said to handle this by the clock stopping for 1 second in the last minute of the year.
Q: Do I have to implement floating point time?
A: No. There are not many use cases that need it. However, for maximal interoperability, it is good to support it.
Q: When should I use floating point?
A: Only if you need time resolution greater than one second. There is no benefit otherwise. 64-bit time can represent time +/-500 billion years in the same number of bits, so floating point time is unnecessary for very large times scales.
Q: What resolution do I get with floating point?
A: It varies over the years. For 1970 to 1971 you get almost nanosecond accuracy. For the current century, 2000-2099, you get microsecond accuracy. 285 million years from now, it will be less than a second and the 64-bit unsigned representation will have more resolution. This is because a double only has 52 bits of resolution.
Q: Should I implement single or double floating point?
A: If you are going to use floating point you should always implement double. Single has no advantage over 32-bit integers. It provides less range and less precision. It has only 23 bits of resolution. It is of course good to support decoding of single in case someone sends you one, but there no point to ever sending a tag 1 encoded time value as a single.
Q: Can I disallow floating point time in the definition of my protocol?
A: Yes. This is a good idea if you do not need resolution less than one second. It will make implementations simpler and more compact. Note that while most CPUs do support IEEE 754 floating point, particularly small ones do not.
Q: What if Im transmitting thousands of time stamps and space is a problem?
A: If you want to maintain 1 second resolution, there is really no more compact way to transmit time than tag 1 with 32-bit or 64-bit integer. If you wish reduce resolution, use a different time, perhaps one that counts days rather than seconds.

384
3rdparty/exported/QCBOR/example.c поставляемый Normal file
Просмотреть файл

@ -0,0 +1,384 @@
/* =========================================================================
example.c -- Example code for QCBOR
Copyright (c) 2020-2021, Laurence Lundblade. All rights reserved.
Copyright (c) 2021, Arm Limited. All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
See BSD-3-Clause license in README.md
Created on 6/30/2020
========================================================================== */
#include <stdio.h>
#include "example.h"
#include "qcbor/qcbor_encode.h"
#include "qcbor/qcbor_decode.h"
#include "qcbor/qcbor_spiffy_decode.h"
/**
* This is a simple example of encoding and decoding some CBOR from
* and to a C structure.
*
* This also includes a comparison between the original structure
* and the one decoded from the CBOR to confirm correctness.
*/
#define MAX_CYLINDERS 16
/**
* The data structure representing a car engine that is encoded and
* decoded in this example.
*/
typedef struct
{
UsefulBufC Manufacturer;
int64_t uDisplacement;
int64_t uHorsePower;
#ifndef USEFULBUF_DISABLE_ALL_FLOAT
double dDesignedCompresion;
#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
int64_t uNumCylinders;
bool bTurboCharged;
#ifndef USEFULBUF_DISABLE_ALL_FLOAT
struct {
double dMeasuredCompression;
} cylinders[MAX_CYLINDERS];
#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
} CarEngine;
/**
* @brief Initialize the Engine data structure with values to encode.
*
* @param[out] pE The Engine structure to fill in
*/
void EngineInit(CarEngine *pE)
{
pE->Manufacturer = UsefulBuf_FROM_SZ_LITERAL("Porsche");
pE->uDisplacement = 3296;
pE->uHorsePower = 210;
#ifndef USEFULBUF_DISABLE_ALL_FLOAT
pE->dDesignedCompresion = 9.1;
#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
pE->uNumCylinders = 6;
pE->bTurboCharged = false;
#ifndef USEFULBUF_DISABLE_ALL_FLOAT
pE->cylinders[0].dMeasuredCompression = 9.0;
pE->cylinders[1].dMeasuredCompression = 9.2;
pE->cylinders[2].dMeasuredCompression = 8.9;
pE->cylinders[3].dMeasuredCompression = 8.9;
pE->cylinders[4].dMeasuredCompression = 9.1;
pE->cylinders[5].dMeasuredCompression = 9.0;
#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
}
/**
* @brief Compare two Engine structure for equality.
*
* @param[in] pE1 First Engine to compare.
* @param[in] pE2 Second Engine to compare.
*
* @retval Return @c true if the two Engine data structures are exactly the
* same.
*/
static bool EngineCompare(const CarEngine *pE1, const CarEngine *pE2)
{
if(pE1->uNumCylinders != pE2->uNumCylinders) {
return false;
}
if(pE1->bTurboCharged != pE2->bTurboCharged) {
return false;
}
if(pE1->uDisplacement != pE2->uDisplacement) {
return false;
}
if(pE1->uHorsePower != pE2->uHorsePower) {
return false;
}
#ifndef USEFULBUF_DISABLE_ALL_FLOAT
if(pE1->dDesignedCompresion != pE2->dDesignedCompresion) {
return false;
}
for(int64_t i = 0; i < pE2->uNumCylinders; i++) {
if(pE1->cylinders[i].dMeasuredCompression !=
pE2->cylinders[i].dMeasuredCompression) {
return false;
}
}
#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
if(UsefulBuf_Compare(pE1->Manufacturer, pE2->Manufacturer)) {
return false;
}
return true;
}
/**
* @brief Encode an initialized CarEngine data structure in CBOR.
*
* @param[in] pEngine The data structure to encode.
* @param[in] Buffer Pointer and length of buffer to output to.
*
* @return The pointer and length of the encoded CBOR or
* @ref NULLUsefulBufC on error.
*
* This encodes the input structure \c pEngine as a CBOR map of
* label-value pairs. An array of float is one of the items in the
* map.
*
* This uses the UsefulBuf convention of passing in a non-const empty
* buffer to be filled in and returning a filled in const buffer. The
* buffer to write into is given as a pointer and length in a
* UsefulBuf. The buffer returned with the encoded CBOR is a
* UsefulBufC also a pointer and length. In this implementation the
* pointer to the returned data is exactly the same as that of the
* empty buffer. The returned length will be smaller than or equal to
* that of the empty buffer. This gives correct const-ness for the
* buffer passed in and the data returned.
*
* @c Buffer must be big enough to hold the output. If it is not @ref
* NULLUsefulBufC will be returned. @ref NULLUsefulBufC will be
* returned for any other encoding errors.
*
* This can be called with @c Buffer set to @ref SizeCalculateUsefulBuf
* in which case the size of the encoded engine will be calculated,
* but no actual encoded CBOR will be output. The calculated size is
* in @c .len of the returned @ref UsefulBufC.
*/
UsefulBufC EncodeEngine(const CarEngine *pEngine, UsefulBuf Buffer)
{
/* Set up the encoding context with the output buffer */
QCBOREncodeContext EncodeCtx;
QCBOREncode_Init(&EncodeCtx, Buffer);
/* Proceed to output all the items, letting the internal error
* tracking do its work */
QCBOREncode_OpenMap(&EncodeCtx);
QCBOREncode_AddTextToMap(&EncodeCtx, "Manufacturer", pEngine->Manufacturer);
QCBOREncode_AddInt64ToMap(&EncodeCtx, "NumCylinders", pEngine->uNumCylinders);
QCBOREncode_AddInt64ToMap(&EncodeCtx, "Displacement", pEngine->uDisplacement);
QCBOREncode_AddInt64ToMap(&EncodeCtx, "Horsepower", pEngine->uHorsePower);
#ifndef USEFULBUF_DISABLE_ALL_FLOAT
QCBOREncode_AddDoubleToMap(&EncodeCtx, "DesignedCompression", pEngine->dDesignedCompresion);
#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
QCBOREncode_OpenArrayInMap(&EncodeCtx, "Cylinders");
#ifndef USEFULBUF_DISABLE_ALL_FLOAT
for(int64_t i = 0 ; i < pEngine->uNumCylinders; i++) {
QCBOREncode_AddDouble(&EncodeCtx,
pEngine->cylinders[i].dMeasuredCompression);
}
#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
QCBOREncode_CloseArray(&EncodeCtx);
QCBOREncode_AddBoolToMap(&EncodeCtx, "Turbo", pEngine->bTurboCharged);
QCBOREncode_CloseMap(&EncodeCtx);
/* Get the pointer and length of the encoded output. If there was
* any encoding error, it will be returned here */
UsefulBufC EncodedCBOR;
QCBORError uErr;
uErr = QCBOREncode_Finish(&EncodeCtx, &EncodedCBOR);
if(uErr != QCBOR_SUCCESS) {
return NULLUsefulBufC;
} else {
return EncodedCBOR;
}
}
/**
* Error results when decoding an Engine data structure.
*/
typedef enum {
EngineSuccess,
CBORNotWellFormed,
TooManyCylinders,
EngineProtocolerror,
WrongNumberOfCylinders
} EngineDecodeErrors;
/**
* Convert @ref QCBORError to @ref EngineDecodeErrors.
*/
static EngineDecodeErrors ConvertError(QCBORError uErr)
{
EngineDecodeErrors uReturn;
switch(uErr)
{
case QCBOR_SUCCESS:
uReturn = EngineSuccess;
break;
case QCBOR_ERR_HIT_END:
uReturn = CBORNotWellFormed;
break;
default:
uReturn = EngineProtocolerror;
break;
}
return uReturn;
}
/**
* @brief Simplest engine decode using spiffy decode features.
*
* @param[in] EncodedEngine Pointer and length of CBOR-encoded engine.
* @param[out] pE The structure filled in from the decoding.
*
* @return The decode error or success.
*
* This decodes the CBOR into the engine structure.
*
* As QCBOR automatically supports both definite and indefinite maps
* and arrays, this will decode either.
*
* This uses QCBOR's spiffy decode functions, so the implementation is
* simple and closely parallels the encode implementation in
* EncodeEngineDefiniteLength().
*
* Another way to decode without using spiffy decode functions is to
* use QCBORDecode_GetNext() to traverse the whole tree. This
* requires a more complex implementation, but is faster and will pull
* in less code from the CBOR library. The speed advantage is likely
* of consequence when decoding much much larger CBOR on slow small
* CPUs.
*
* A middle way is to use the spiffy decode
* QCBORDecode_GetItemsInMap(). The implementation has middle
* complexity and uses less CPU.
*/
EngineDecodeErrors DecodeEngineSpiffy(UsefulBufC EncodedEngine, CarEngine *pE)
{
QCBORError uErr;
QCBORDecodeContext DecodeCtx;
/* Let QCBORDecode internal error tracking do its work. */
QCBORDecode_Init(&DecodeCtx, EncodedEngine, QCBOR_DECODE_MODE_NORMAL);
QCBORDecode_EnterMap(&DecodeCtx, NULL);
QCBORDecode_GetTextStringInMapSZ(&DecodeCtx, "Manufacturer", &(pE->Manufacturer));
QCBORDecode_GetInt64InMapSZ(&DecodeCtx, "Displacement", &(pE->uDisplacement));
QCBORDecode_GetInt64InMapSZ(&DecodeCtx, "Horsepower", &(pE->uHorsePower));
#ifndef USEFULBUF_DISABLE_ALL_FLOAT
QCBORDecode_GetDoubleInMapSZ(&DecodeCtx, "DesignedCompression", &(pE->dDesignedCompresion));
#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
QCBORDecode_GetBoolInMapSZ(&DecodeCtx, "Turbo", &(pE->bTurboCharged));
QCBORDecode_GetInt64InMapSZ(&DecodeCtx, "NumCylinders", &(pE->uNumCylinders));
/* Check the internal tracked error now before going on to
* reference any of the decoded data, particularly
* pE->uNumCylinders */
uErr = QCBORDecode_GetError(&DecodeCtx);
if(uErr != QCBOR_SUCCESS) {
goto Done;
}
if(pE->uNumCylinders > MAX_CYLINDERS) {
return TooManyCylinders;
}
QCBORDecode_EnterArrayFromMapSZ(&DecodeCtx, "Cylinders");
#ifndef USEFULBUF_DISABLE_ALL_FLOAT
for(int64_t i = 0; i < pE->uNumCylinders; i++) {
QCBORDecode_GetDouble(&DecodeCtx,
&(pE->cylinders[i].dMeasuredCompression));
}
#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
QCBORDecode_ExitArray(&DecodeCtx);
QCBORDecode_ExitMap(&DecodeCtx);
/* Catch further decoding error here */
uErr = QCBORDecode_Finish(&DecodeCtx);
Done:
return ConvertError(uErr);
}
int32_t RunQCborExample()
{
CarEngine InitialEngine;
CarEngine DecodedEngine;
/* For every buffer used by QCBOR a pointer and a length are always
* carried in a UsefulBuf. This is a secure coding and hygene
* practice to help make sure code never runs off the end of a
* buffer.
*
* UsefulBuf structures are passed as a stack parameter to make the
* code prettier. The object code generated isn't much different
* from passing a pointer parameter and a length parameter.
*
* This macro is equivalent to:
* uint8_t __pBufEngineBuffer[300];
* UsefulBuf EngineBuffer = {__pBufEngineBuffer, 300};
*/
UsefulBuf_MAKE_STACK_UB( EngineBuffer, 300);
/* The pointer in UsefulBuf is not const and used for representing
* a buffer to be written to. For UsefulbufC, the pointer is const
* and is used to represent a buffer that has been written to.
*/
UsefulBufC EncodedEngine;
EngineDecodeErrors uErr;
/* Initialize the structure with some values. */
EngineInit(&InitialEngine);
/* Encode the engine structure. */
EncodedEngine = EncodeEngine(&InitialEngine, EngineBuffer);
if(UsefulBuf_IsNULLC(EncodedEngine)) {
printf("Engine encode failed\n");
goto Done;
}
printf("Example: Definite Length Engine Encoded in %zu bytes\n",
EncodedEngine.len);
/* Decode the CBOR */
uErr = DecodeEngineSpiffy(EncodedEngine, &DecodedEngine);
printf("Example: Spiffy Engine Decode Result: %d\n", uErr);
if(uErr) {
goto Done;
}
/* Check the results */
if(!EngineCompare(&InitialEngine, &DecodedEngine)) {
printf("Example: Spiffy Engine Decode comparison fail\n");
}
/* Further example of how to calculate the encoded size, then allocate */
UsefulBufC EncodedEngineSize;
EncodedEngineSize = EncodeEngine(&InitialEngine, SizeCalculateUsefulBuf);
if(UsefulBuf_IsNULLC(EncodedEngine)) {
printf("Engine encode size calculation failed\n");
goto Done;
}
(void)EncodedEngineSize; /* Supress unsed variable warning */
/* Here malloc could be called to allocate a buffer. Then
* EncodeEngine() can be called a second time to actually
* encode. (The actual code is not live here to avoid a
* dependency on malloc()).
* UsefulBuf MallocedBuffer;
* MallocedBuffer.len = EncodedEngineSize.len;
* MallocedBuffer.ptr = malloc(EncodedEngineSize.len);
* EncodedEngine = EncodeEngine(&InitialEngine, MallocedBuffer);
*/
Done:
printf("\n");
return 0;
}

20
3rdparty/exported/QCBOR/example.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,20 @@
/*==============================================================================
example.h -- QCBOR encode and decode example
Copyright (c) 2020, Laurence Lundblade. All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
See BSD-3-Clause license in README.md
Created on 6/30/20
=============================================================================*/
#ifndef qcborExample_h
#define qcborExample_h
#include <stdint.h>
int32_t RunQCborExample(void);
#endif /* qcborExample_h */

2475
3rdparty/exported/QCBOR/qcbor/UsefulBuf.h поставляемый Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

41
3rdparty/exported/QCBOR/qcbor/qcbor.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,41 @@
/*==============================================================================
Copyright (c) 2016-2018, The Linux Foundation.
Copyright (c) 2018-2020, Laurence Lundblade.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors, nor the name "Laurence Lundblade" may be used to
endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
/**
* @file qcbor.h
*
* Backwards compatibility for includers of qcbor.h (which has been split
* into four include files).
*/
#include "qcbor_encode.h"
#include "qcbor_decode.h"

601
3rdparty/exported/QCBOR/qcbor/qcbor_common.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,601 @@
/*==============================================================================
Copyright (c) 2016-2018, The Linux Foundation.
Copyright (c) 2018-2022, Laurence Lundblade.
Copyright (c) 2021, Arm Limited.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors, nor the name "Laurence Lundblade" may be used to
endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#ifndef qcbor_common_h
#define qcbor_common_h
/**
@file qcbor_common.h
Types and defines common to QCBOR encoding and decoding.
*/
/**
* This define indicates QCBOR v1.1.
*
* There are no backwards compatibiliy issues with QCBOR 1.0.
*
* The only new API is QCBOREncode_OpenBytes() and related.
*/
#define QCBOR_1_1
/**
This define indicates a version of QCBOR that supports spiffy decode,
the decode functions found in qcbor_spiffy_decode.h.
Versions of QCBOR that support spiffy decode are backwards compatible
with previous versions, but there are a few minor exceptions such as
some aspects of tag handling that are different. This define can be
used handle these variances.
*/
#define QCBOR_SPIFFY_DECODE
/* It was originally defined as QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA,
* but this is incosistent with all the other QCBOR_DISABLE_
* #defines, so the name was changed and this was added for backwards
* compatibility
*/
#ifdef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
#define QCBOR_DISABLE_EXP_AND_MANTISSA
#endif
/* If USEFULBUF_DISABLE_ALL_FLOATis defined then define
* QCBOR_DISABLE_FLOAT_HW_USE and QCBOR_DISABLE_PREFERRED_FLOAT
*/
#ifdef USEFULBUF_DISABLE_ALL_FLOAT
#ifndef QCBOR_DISABLE_FLOAT_HW_USE
#define QCBOR_DISABLE_FLOAT_HW_USE
#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
#define QCBOR_DISABLE_PREFERRED_FLOAT
#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
/* Standard CBOR Major type for positive integers of various lengths */
#define CBOR_MAJOR_TYPE_POSITIVE_INT 0
/* Standard CBOR Major type for negative integer of various lengths */
#define CBOR_MAJOR_TYPE_NEGATIVE_INT 1
/* Standard CBOR Major type for an array of arbitrary 8-bit bytes. */
#define CBOR_MAJOR_TYPE_BYTE_STRING 2
/* Standard CBOR Major type for a UTF-8 string. Note this is true 8-bit UTF8
with no encoding and no NULL termination */
#define CBOR_MAJOR_TYPE_TEXT_STRING 3
/* Standard CBOR Major type for an ordered array of other CBOR data items */
#define CBOR_MAJOR_TYPE_ARRAY 4
/* Standard CBOR Major type for CBOR MAP. Maps an array of pairs. The
first item in the pair is the "label" (key, name or identfier) and the second
item is the value. */
#define CBOR_MAJOR_TYPE_MAP 5
/* Standard CBOR major type for a tag number. This creates a CBOR "tag" that
* is the tag number and a data item that follows as the tag content.
*
* Note that this was called an optional tag in RFC 7049, but there's
* not really anything optional about it. It was misleading. It is
* renamed in RFC 8949.
*/
#define CBOR_MAJOR_TYPE_TAG 6
#define CBOR_MAJOR_TYPE_OPTIONAL 6
/* Standard CBOR extra simple types like floats and the values true and false */
#define CBOR_MAJOR_TYPE_SIMPLE 7
/*
These are special values for the AdditionalInfo bits that are part of
the first byte. Mostly they encode the length of the data item.
*/
#define LEN_IS_ONE_BYTE 24
#define LEN_IS_TWO_BYTES 25
#define LEN_IS_FOUR_BYTES 26
#define LEN_IS_EIGHT_BYTES 27
#define ADDINFO_RESERVED1 28
#define ADDINFO_RESERVED2 29
#define ADDINFO_RESERVED3 30
#define LEN_IS_INDEFINITE 31
/*
24 is a special number for CBOR. Integers and lengths
less than it are encoded in the same byte as the major type.
*/
#define CBOR_TWENTY_FOUR 24
/*
Tags that are used with CBOR_MAJOR_TYPE_OPTIONAL. These
are types defined in RFC 8949 and some additional ones
in the IANA CBOR tags registry.
*/
/** See QCBOREncode_AddDateString(). */
#define CBOR_TAG_DATE_STRING 0
/** See QCBOREncode_AddDateEpoch(). */
#define CBOR_TAG_DATE_EPOCH 1
/** See QCBOREncode_AddPositiveBignum(). */
#define CBOR_TAG_POS_BIGNUM 2
/** See QCBOREncode_AddNegativeBignum(). */
#define CBOR_TAG_NEG_BIGNUM 3
/** CBOR tag for a two-element array representing a fraction with a
mantissa and base-10 scaling factor. See QCBOREncode_AddDecimalFraction()
and @ref expAndMantissa.
*/
#define CBOR_TAG_DECIMAL_FRACTION 4
/** CBOR tag for a two-element array representing a fraction with a
mantissa and base-2 scaling factor. See QCBOREncode_AddBigFloat()
and @ref expAndMantissa. */
#define CBOR_TAG_BIGFLOAT 5
/** Not Decoded by QCBOR. Tag for COSE format encryption with no recipient
identification. See [RFC 8152, COSE]
(https://tools.ietf.org/html/rfc8152). No API is provided for this
tag. */
#define CBOR_TAG_COSE_ENCRYPT0 16
#define CBOR_TAG_COSE_ENCRYPTO 16
/** Not Decoded by QCBOR. Tag for COSE format MAC'd data with no recipient
identification. See [RFC 8152, COSE]
(https://tools.ietf.org/html/rfc8152). No API is provided for this
tag.*/
#define CBOR_TAG_COSE_MAC0 17
/** Tag for COSE format single signature signing. No API is provided
for this tag. See [RFC 8152, COSE]
(https://tools.ietf.org/html/rfc8152). */
#define CBOR_TAG_COSE_SIGN1 18
/** A hint that the following byte string should be encoded in
Base64URL when converting to JSON or similar text-based
representations. Call @c
QCBOREncode_AddTag(pCtx,CBOR_TAG_ENC_AS_B64URL) before the call to
QCBOREncode_AddBytes(). */
#define CBOR_TAG_ENC_AS_B64URL 21
/** A hint that the following byte string should be encoded in Base64
when converting to JSON or similar text-based
representations. Call @c
QCBOREncode_AddTag(pCtx,CBOR_TAG_ENC_AS_B64) before the call to
QCBOREncode_AddBytes(). */
#define CBOR_TAG_ENC_AS_B64 22
/** A hint that the following byte string should be encoded in base-16
format per [RFC 4648] (https://tools.ietf.org/html/rfc4648) when
converting to JSON or similar text-based
representations. Essentially, Base-16 encoding is the standard
case- insensitive hex encoding and may be referred to as
"hex". Call @c QCBOREncode_AddTag(pCtx,CBOR_TAG_ENC_AS_B16) before
the call to QCBOREncode_AddBytes(). */
#define CBOR_TAG_ENC_AS_B16 23
/** See QCBORDecode_EnterBstrWrapped()). */
#define CBOR_TAG_CBOR 24
/** See QCBOREncode_AddURI(). */
#define CBOR_TAG_URI 32
/** See QCBOREncode_AddB64URLText(). */
#define CBOR_TAG_B64URL 33
/** See QCBOREncode_AddB64Text(). */
#define CBOR_TAG_B64 34
/** See QCBOREncode_AddRegex(). */
#define CBOR_TAG_REGEX 35
/** See QCBOREncode_AddMIMEData(). */
#define CBOR_TAG_MIME 36
/** See QCBOREncode_AddBinaryUUID(). */
#define CBOR_TAG_BIN_UUID 37
/** The data is a CBOR Web Token per [RFC 8392]
(https://tools.ietf.org/html/rfc8932). No API is provided for this
tag. */
#define CBOR_TAG_CWT 61
/** Tag for COSE format encryption. See [RFC 8152, COSE]
(https://tools.ietf.org/html/rfc8152). No API is provided for this
tag. */
#define CBOR_TAG_CBOR_SEQUENCE 63
/** Not Decoded by QCBOR. Tag for COSE format encryption with recipient
identification. See [RFC 8152, COSE]
(https://tools.ietf.org/html/rfc8152). No API is provided for this
tag. */
#define CBOR_TAG_COSE_ENCRYPT 96
#define CBOR_TAG_ENCRYPT 96
/** Not Decoded by QCBOR. Tag for COSE format MAC. See [RFC 8152, COSE]
(https://tools.ietf.org/html/rfc8152). No API is provided for this
tag. */
#define CBOR_TAG_COSE_MAC 97
#define CBOR_TAG_MAC 97
/** Not Decoded by QCBOR. Tag for COSE format signed data. See [RFC 8152, COSE]
(https://tools.ietf.org/html/rfc8152). No API is provided for this
tag. */
#define CBOR_TAG_COSE_SIGN 98
#define CBOR_TAG_SIGN 98
/** Tag for date counted by days from Jan 1 1970 per [RFC 8943]
(https://tools.ietf.org/html/rfc8943). See
QCBOREncode_AddTDaysEpoch(). */
#define CBOR_TAG_DAYS_EPOCH 100
/** Not Decoded by QCBOR. World geographic coordinates. See ISO 6709, [RFC 5870]
(https://tools.ietf.org/html/rfc5870) and WGS-84. No API is
provided for this tag. */
#define CBOR_TAG_GEO_COORD 103
/** Binary MIME.*/
#define CBOR_TAG_BINARY_MIME 257
/** Tag for date string without time or time zone per [RFC 8943]
(https://tools.ietf.org/html/rfc8943). See
QCBOREncode_AddTDaysString(). */
#define CBOR_TAG_DAYS_STRING 1004
/** The magic number, self-described CBOR. No API is provided for this
tag. */
#define CBOR_TAG_CBOR_MAGIC 55799
/** The 16-bit invalid tag from the CBOR tags registry */
#define CBOR_TAG_INVALID16 0xffff
/** The 32-bit invalid tag from the CBOR tags registry */
#define CBOR_TAG_INVALID32 0xffffffff
/** The 64-bit invalid tag from the CBOR tags registry */
#define CBOR_TAG_INVALID64 0xffffffffffffffff
/*
Values for the 5 bits for items of major type 7
*/
#define CBOR_SIMPLEV_FALSE 20
#define CBOR_SIMPLEV_TRUE 21
#define CBOR_SIMPLEV_NULL 22
#define CBOR_SIMPLEV_UNDEF 23
#define CBOR_SIMPLEV_ONEBYTE 24
#define HALF_PREC_FLOAT 25
#define SINGLE_PREC_FLOAT 26
#define DOUBLE_PREC_FLOAT 27
#define CBOR_SIMPLE_BREAK 31
#define CBOR_SIMPLEV_RESERVED_START CBOR_SIMPLEV_ONEBYTE
#define CBOR_SIMPLEV_RESERVED_END CBOR_SIMPLE_BREAK
/**
* Error codes returned by QCBOR Encoder and Decoder.
*
* The errors are grouped to keep the code size of
* QCBORDecode_IsNotWellFormedError() and
* QCBORDecode_IsUnrecoverableError() minimal.
*
* 1..19: Encode errors
* 20..: Decode errors
* 20-39: QCBORDecode_IsNotWellFormedError()
* 30..59: QCBORDecode_IsUnrecoverableError()
* 60..: Other decode errors
*
* Error renumbering may occur in the future when new error codes are
* added for new QCBOR features.
*/
typedef enum {
/** The encode or decode completely correctly. */
QCBOR_SUCCESS = 0,
/** The buffer provided for the encoded output when doing encoding
was too small and the encoded output will not fit. */
QCBOR_ERR_BUFFER_TOO_SMALL = 1,
/** During encoding, an attempt to create simple value between 24
and 31. */
QCBOR_ERR_ENCODE_UNSUPPORTED = 2,
/** During encoding, the length of the encoded CBOR exceeded
QCBOR_MAX_ARRAY_OFFSET, which is slightly less than
@c UINT32_MAX. */
QCBOR_ERR_BUFFER_TOO_LARGE = 3,
/** During encoding, the array or map nesting was deeper than this
implementation can handle. Note that in the interest of code
size and memory use, this implementation has a hard limit on
array nesting. The limit is defined as the constant @ref
QCBOR_MAX_ARRAY_NESTING. */
QCBOR_ERR_ARRAY_NESTING_TOO_DEEP = 4,
/** During encoding, @c QCBOREncode_CloseXxx() called with a
different type than is currently open. */
QCBOR_ERR_CLOSE_MISMATCH = 5,
/** During encoding, the array or map had too many items in it.
This limit @ref QCBOR_MAX_ITEMS_IN_ARRAY, typically 65,535. */
QCBOR_ERR_ARRAY_TOO_LONG = 6,
/** During encoding, more arrays or maps were closed than
opened. This is a coding error on the part of the caller of the
encoder. */
QCBOR_ERR_TOO_MANY_CLOSES = 7,
/** During encoding the number of array or map opens was not
matched by the number of closes. Also occurs with opened
byte strings that are not closed. */
QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN = 8,
/** During encode, opening a byte string while a byte string is open
is not allowed. . */
QCBOR_ERR_OPEN_BYTE_STRING = 9,
/** Trying to cancel a byte string wrapping after items have been
added to it. */
QCBOR_ERR_CANNOT_CANCEL = 10,
#define QCBOR_START_OF_NOT_WELL_FORMED_ERRORS 20
/** During decoding, the CBOR is not well-formed because a simple
value between 0 and 31 is encoded in a two-byte integer rather
than one. */
QCBOR_ERR_BAD_TYPE_7 = 20,
/** During decoding, returned by QCBORDecode_Finish() if all the
inputs bytes have not been consumed. This is considered not
well-formed. */
QCBOR_ERR_EXTRA_BYTES = 21,
/** During decoding, some CBOR construct was encountered that this
decoder doesn't support, primarily this is the reserved
additional info values, 28 through 30. The CBOR is not
well-formed.*/
QCBOR_ERR_UNSUPPORTED = 22,
/** During decoding, the an array or map was not fully consumed.
Returned by QCBORDecode_Finish(). The CBOR is not
well-formed. */
QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED = 23,
/** During decoding, an integer type is encoded with a bad length
(that of an indefinite length string). The CBOR is not-well
formed. */
QCBOR_ERR_BAD_INT = 24,
#define QCBOR_START_OF_UNRECOVERABLE_DECODE_ERRORS 30
/** During decoding, one of the chunks in an indefinite-length
string is not of the type of the start of the string. The CBOR
is not well-formed. This error makes no further decoding
possible. */
QCBOR_ERR_INDEFINITE_STRING_CHUNK = 30,
/** During decoding, hit the end of the given data to decode. For
example, a byte string of 100 bytes was expected, but the end
of the input was hit before finding those 100 bytes. Corrupted
CBOR input will often result in this error. See also @ref
QCBOR_ERR_NO_MORE_ITEMS. The CBOR is not well-formed. This
error makes no further decoding possible. */
QCBOR_ERR_HIT_END = 31,
/** During decoding, a break occurred outside an indefinite-length
item. The CBOR is not well-formed. This error makes no further
decoding possible. */
QCBOR_ERR_BAD_BREAK = 32,
#define QCBOR_END_OF_NOT_WELL_FORMED_ERRORS 39
/** During decoding, the input is too large. It is greater than
QCBOR_MAX_DECODE_INPUT_SIZE. This is an implementation limit.
This error makes no further decoding possible. */
QCBOR_ERR_INPUT_TOO_LARGE = 40,
/** During decoding, the array or map nesting was deeper than this
implementation can handle. Note that in the interest of code
size and memory use, this implementation has a hard limit on
array nesting. The limit is defined as the constant @ref
QCBOR_MAX_ARRAY_NESTING. This error makes no further decoding
possible. */
QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP = 41,
/** During decoding, the array or map had too many items in it.
This limit @ref QCBOR_MAX_ITEMS_IN_ARRAY, typically 65,534,
UINT16_MAX - 1. This error makes no further decoding
possible. */
QCBOR_ERR_ARRAY_DECODE_TOO_LONG = 42,
/** When decoding, a string's size is greater than what a size_t
can hold less 4. In all but some very strange situations this
is because of corrupt input CBOR and should be treated as
such. The strange situation is a CPU with a very small size_t
(e.g., a 16-bit CPU) and a large string (e.g., > 65KB). This
error makes no further decoding possible. */
QCBOR_ERR_STRING_TOO_LONG = 43,
/** Something is wrong with a decimal fraction or bigfloat such as
it not consisting of an array with two integers. This error
makes no further decoding possible. */
QCBOR_ERR_BAD_EXP_AND_MANTISSA = 44,
/** Unable to decode an indefinite-length string because no string
allocator was configured. See QCBORDecode_SetMemPool() or
QCBORDecode_SetUpAllocator(). This error makes no further
decoding possible. */
QCBOR_ERR_NO_STRING_ALLOCATOR = 45,
/** Error allocating space for a string, usually for an
indefinite-length string. This error makes no further decoding
possible. */
QCBOR_ERR_STRING_ALLOCATE = 46,
/** During decoding, the type of the label for a map entry is not
one that can be handled in the current decoding mode. Typically
this is because a label is not an intger or a string. This is
an implemation limit. */
QCBOR_ERR_MAP_LABEL_TYPE = 47,
/** When the built-in tag decoding encounters an unexpected type,
this error is returned. This error is unrecoverable because the
built-in tag decoding doesn't try to consume the unexpected
type. In previous versions of QCBOR this was considered a
recoverable error hence QCBOR_ERR_BAD_TAG_CONTENT. Going back
further, RFC 7049 use the name "optional tags". That name is no
longer used because "optional" was causing confusion. See
also @ref QCBOR_ERR_RECOVERABLE_BAD_TAG_CONTENT. */
QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT = 48,
QCBOR_ERR_BAD_TAG_CONTENT = 48,
QCBOR_ERR_BAD_OPT_TAG = 48,
/** Indefinite length string handling is disabled and there is an
indefinite length string in the input CBOR. */
QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED = 49,
/** Indefinite length arrays and maps handling are disabled and there is an
indefinite length map or array in the input CBOR. */
QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED = 50,
#define QCBOR_END_OF_UNRECOVERABLE_DECODE_ERRORS 59
/** More than @ref QCBOR_MAX_TAGS_PER_ITEM tags encountered for a
CBOR ITEM. @ref QCBOR_MAX_TAGS_PER_ITEM is a limit of this
implementation. During decoding, too many tags in the
caller-configured tag list, or not enough space in @ref
QCBORTagListOut. This error makes no further decoding
possible. */
QCBOR_ERR_TOO_MANY_TAGS = 60,
/** When decoding for a specific type, the type was not was
expected. */
QCBOR_ERR_UNEXPECTED_TYPE = 61,
/** Duplicate label in map detected. */
QCBOR_ERR_DUPLICATE_LABEL = 62,
/** During decoding, the buffer given to QCBORDecode_SetMemPool()
is either too small, smaller than
QCBOR_DECODE_MIN_MEM_POOL_SIZE or too large, larger than
UINT32_MAX. */
QCBOR_ERR_MEM_POOL_SIZE = 63,
/** During decoding, an integer smaller than INT64_MIN was received
(CBOR can represent integers smaller than INT64_MIN, but C
cannot). */
QCBOR_ERR_INT_OVERFLOW = 64,
/** During decoding, a date greater than +- 292 billion years from
Jan 1 1970 encountered during parsing. This is an
implementation limit. */
QCBOR_ERR_DATE_OVERFLOW = 65,
/** During decoding, @c QCBORDecode_ExitXxx() was called for a
different type than @c QCBORDecode_EnterXxx(). */
QCBOR_ERR_EXIT_MISMATCH = 66,
/** All well-formed data items have been consumed and there are no
more. If parsing a CBOR stream this indicates the non-error end
of the stream. If not parsing a CBOR stream / sequence, this
probably indicates that some data items expected are not
present. See also @ref QCBOR_ERR_HIT_END. */
QCBOR_ERR_NO_MORE_ITEMS = 67,
/** When finding an item by label, an item with the requested label
was not found. */
QCBOR_ERR_LABEL_NOT_FOUND = 68,
/** Number conversion failed because of sign. For example a
negative int64_t can't be converted to a uint64_t */
QCBOR_ERR_NUMBER_SIGN_CONVERSION = 69,
/** When converting a decoded number, the value is too large or to
small for the conversion target */
QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW = 70,
/** Trying to get an item by label when a map has not been
entered. */
QCBOR_ERR_MAP_NOT_ENTERED = 71,
/** A @ref QCBORItemCallback callback indicates processing should not
continue for some non-CBOR reason. */
QCBOR_ERR_CALLBACK_FAIL = 72,
/** This error code is deprecated. Instead,
@ref QCBOR_ERR_HALF_PRECISION_DISABLED,
@ref QCBOR_ERR_HW_FLOAT_DISABLED or @ref QCBOR_ERR_ALL_FLOAT_DISABLED
is returned depending on the specific floating-point functionality
that is disabled and the type of floating-point input. */
QCBOR_ERR_FLOAT_DATE_DISABLED = 73,
/** Support for half-precision float decoding is disabled. */
QCBOR_ERR_HALF_PRECISION_DISABLED = 74,
/** Use of floating-point HW is disabled. This affects all type
conversions to and from double and float types. */
QCBOR_ERR_HW_FLOAT_DISABLED = 75,
/** Unable to complete operation because a floating-point value
that is a NaN (not a number), that is too large, too small,
infinity or -infinity was encountered in encoded CBOR. Usually
this because conversion of the float-point value was being
attempted. */
QCBOR_ERR_FLOAT_EXCEPTION = 76,
/** Floating point support is completely turned off, encoding/decoding
floating point numbers is not possible. */
QCBOR_ERR_ALL_FLOAT_DISABLED = 77,
/** Like @ref QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT, but recoverable.
If an implementation decodes a tag and can and does consume the
whole tag contents when it is not the correct tag content, this
error can be returned. None of the built-in tag decoders do
this (to save object code). */
QCBOR_ERR_RECOVERABLE_BAD_TAG_CONTENT = 78
/* This is stored in uint8_t; never add values > 255 */
} QCBORError;
/* Function for getting an error string from an error code */
const char *qcbor_err_to_str(QCBORError err);
/**
The maximum nesting of arrays and maps when encoding or decoding. The
error @ref QCBOR_ERR_ARRAY_NESTING_TOO_DEEP will be returned on
encoding or QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP on decoding if it is exceeded.
*/
#define QCBOR_MAX_ARRAY_NESTING QCBOR_MAX_ARRAY_NESTING1
/**
* The maximum number of items in a single array or map when encoding of decoding.
*/
/* -1 because the value UINT16_MAX is used to track indefinite-length arrays */
#define QCBOR_MAX_ITEMS_IN_ARRAY (UINT16_MAX-1)
/**
This is deprecated. See QCBORDecode_GetNthTag() and QCBORDecode_GetNthTagOfLast()
for tag handling.
The maximum number of tags that can be in @ref QCBORTagListIn and passed to
QCBORDecode_SetCallerConfiguredTagList()
*/
#define QCBOR_MAX_CUSTOM_TAGS 16
#endif /* qcbor_common_h */

1463
3rdparty/exported/QCBOR/qcbor/qcbor_decode.h поставляемый Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

3468
3rdparty/exported/QCBOR/qcbor/qcbor_encode.h поставляемый Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

351
3rdparty/exported/QCBOR/qcbor/qcbor_private.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,351 @@
/*==============================================================================
Copyright (c) 2016-2018, The Linux Foundation.
Copyright (c) 2018-2021, Laurence Lundblade.
Copyright (c) 2021, Arm Limited.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors, nor the name "Laurence Lundblade" may be used to
endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#ifndef qcbor_private_h
#define qcbor_private_h
#include <stdint.h>
#include "UsefulBuf.h"
#ifdef __cplusplus
extern "C" {
#if 0
} // Keep editor indention formatting happy
#endif
#endif
/*
The maxium nesting of arrays and maps when encoding or decoding.
(Further down in the file there is a definition that refers to this
that is public. This is done this way so there can be a nice
separation of public and private parts in this file.
*/
#define QCBOR_MAX_ARRAY_NESTING1 15 // Do not increase this over 255
/* The largest offset to the start of an array or map. It is slightly
less than UINT32_MAX so the error condition can be tested on 32-bit machines.
UINT32_MAX comes from uStart in QCBORTrackNesting being a uin32_t.
This will cause trouble on a machine where size_t is less than 32-bits.
*/
#define QCBOR_MAX_ARRAY_OFFSET (UINT32_MAX - 100)
/* The number of tags that are 16-bit or larger that can be handled
in a decode.
*/
#define QCBOR_NUM_MAPPED_TAGS 4
/* The number of tags (of any size) recorded for an individual item. */
#define QCBOR_MAX_TAGS_PER_ITEM1 4
/*
Convenience macro for selecting the proper return value in case floating
point feature(s) are disabled.
The macros:
FLOAT_ERR_CODE_NO_FLOAT(x) Can be used when disabled floating point should
result error, and all other cases should return
'x'.
The below macros always return QCBOR_ERR_ALL_FLOAT_DISABLED when all floating
point is disabled.
FLOAT_ERR_CODE_NO_HALF_PREC(x) Can be used when disabled preferred float
results in error, and all other cases should
return 'x'.
FLOAT_ERR_CODE_NO_FLOAT_HW(x) Can be used when disabled hardware floating
point results in error, and all other cases
should return 'x'.
FLOAT_ERR_CODE_NO_HALF_PREC_NO_FLOAT_HW(x) Can be used when either disabled
preferred float or disabling
hardware floating point results in
error, and all other cases should
return 'x'.
*/
#ifdef USEFULBUF_DISABLE_ALL_FLOAT
#define FLOAT_ERR_CODE_NO_FLOAT(x) QCBOR_ERR_ALL_FLOAT_DISABLED
#define FLOAT_ERR_CODE_NO_HALF_PREC(x) QCBOR_ERR_ALL_FLOAT_DISABLED
#define FLOAT_ERR_CODE_NO_FLOAT_HW(x) QCBOR_ERR_ALL_FLOAT_DISABLED
#define FLOAT_ERR_CODE_NO_HALF_PREC_NO_FLOAT_HW(x) QCBOR_ERR_ALL_FLOAT_DISABLED
#else /* USEFULBUF_DISABLE_ALL_FLOAT*/
#define FLOAT_ERR_CODE_NO_FLOAT(x) x
#ifdef QCBOR_DISABLE_PREFERRED_FLOAT
#define FLOAT_ERR_CODE_NO_HALF_PREC(x) QCBOR_ERR_HALF_PRECISION_DISABLED
#define FLOAT_ERR_CODE_NO_HALF_PREC_NO_FLOAT_HW(x) QCBOR_ERR_HALF_PRECISION_DISABLED
#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
#define FLOAT_ERR_CODE_NO_HALF_PREC(x) x
#ifdef QCBOR_DISABLE_FLOAT_HW_USE
#define FLOAT_ERR_CODE_NO_HALF_PREC_NO_FLOAT_HW(x) QCBOR_ERR_HW_FLOAT_DISABLED
#else
#define FLOAT_ERR_CODE_NO_HALF_PREC_NO_FLOAT_HW(x) x
#endif
#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
#ifdef QCBOR_DISABLE_FLOAT_HW_USE
#define FLOAT_ERR_CODE_NO_FLOAT_HW(x) QCBOR_ERR_HW_FLOAT_DISABLED
#else /* QCBOR_DISABLE_FLOAT_HW_USE */
#define FLOAT_ERR_CODE_NO_FLOAT_HW(x) x
#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
#endif /*USEFULBUF_DISABLE_ALL_FLOAT*/
/*
PRIVATE DATA STRUCTURE
Holds the data for tracking array and map nesting during encoding. Pairs up
with the Nesting_xxx functions to make an "object" to handle nesting encoding.
uStart is a uint32_t instead of a size_t to keep the size of this
struct down so it can be on the stack without any concern. It would be about
double if size_t was used instead.
Size approximation (varies with CPU/compiler):
64-bit machine: (15 + 1) * (4 + 2 + 1 + 1 pad) + 8 = 136 bytes
32-bit machine: (15 + 1) * (4 + 2 + 1 + 1 pad) + 4 = 132 bytes
*/
typedef struct __QCBORTrackNesting {
// PRIVATE DATA STRUCTURE
struct {
// See function QCBOREncode_OpenMapOrArray() for details on how this works
uint32_t uStart; // uStart is the byte position where the array starts
uint16_t uCount; // Number of items in the arrary or map; counts items
// in a map, not pairs of items
uint8_t uMajorType; // Indicates if item is a map or an array
} pArrays[QCBOR_MAX_ARRAY_NESTING1+1], // stored state for the nesting levels
*pCurrentNesting; // the current nesting level
} QCBORTrackNesting;
/*
PRIVATE DATA STRUCTURE
Context / data object for encoding some CBOR. Used by all encode functions to
form a public "object" that does the job of encdoing.
Size approximation (varies with CPU/compiler):
64-bit machine: 27 + 1 (+ 4 padding) + 136 = 32 + 136 = 168 bytes
32-bit machine: 15 + 1 + 132 = 148 bytes
*/
struct _QCBOREncodeContext {
// PRIVATE DATA STRUCTURE
UsefulOutBuf OutBuf; // Pointer to output buffer, its length and
// position in it
uint8_t uError; // Error state, always from QCBORError enum
QCBORTrackNesting nesting; // Keep track of array and map nesting
};
/*
PRIVATE DATA STRUCTURE
Holds the data for array and map nesting for decoding work. This
structure and the DecodeNesting_Xxx() functions in qcbor_decode.c
form an "object" that does the work for arrays and maps. All access
to this structure is through DecodeNesting_Xxx() functions.
64-bit machine size
128 = 16 * 8 for the two unions
64 = 16 * 4 for the uLevelType, 1 byte padded to 4 bytes for alignment
16 = 16 bytes for two pointers
208 TOTAL
32-bit machine size is 200 bytes
*/
typedef struct __QCBORDecodeNesting {
// PRIVATE DATA STRUCTURE
struct nesting_decode_level {
/*
This keeps tracking info for each nesting level. There are two
main types of levels:
1) Byte count tracking. This is for the top level input CBOR
which might be a single item or a CBOR sequence and byte
string wrapped encoded CBOR.
2) Item tracking. This is for maps and arrays.
uLevelType has value QCBOR_TYPE_BYTE_STRING for 1) and
QCBOR_TYPE_MAP or QCBOR_TYPE_ARRAY or QCBOR_TYPE_MAP_AS_ARRAY
for 2).
Item tracking is either for definite or indefinite-length
maps/arrays. For definite lengths, the total count and items
unconsumed are tracked. For indefinite-length, uTotalCount is
QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH (UINT16_MAX) and there
is no per-item count of members. For indefinite-length maps and
arrays, uCountCursor is UINT16_MAX if not consumed and zero if
it is consumed in the pre-order traversal. Additionally, if
entered in bounded mode, uCountCursor is
QCBOR_COUNT_INDICATES_ZERO_LENGTH to indicate it is empty.
This also records whether a level is bounded or not. All
byte-count tracked levels (the top-level sequence and
bstr-wrapped CBOR) are bounded. Maps and arrays may or may not
be bounded. They are bounded if they were Entered() and not if
they were traversed with GetNext(). They are marked as bounded
by uStartOffset not being UINT32_MAX.
*/
/*
If uLevelType can put in a separately indexed array, the union/
struct will be 8 bytes rather than 9 and a lot of wasted
padding for alignment will be saved.
*/
uint8_t uLevelType;
union {
struct {
#define QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH UINT16_MAX
#define QCBOR_COUNT_INDICATES_ZERO_LENGTH UINT16_MAX-1
uint16_t uCountTotal;
uint16_t uCountCursor;
#define QCBOR_NON_BOUNDED_OFFSET UINT32_MAX
uint32_t uStartOffset;
} ma; /* for maps and arrays */
struct {
/* The end of the input before the bstr was entered so that
* it can be restored when the bstr is exited. */
uint32_t uSavedEndOffset;
/* The beginning of the bstr so that it can be rewound. */
uint32_t uBstrStartOffset;
} bs; /* for top-level sequence and bstr-wrapped CBOR */
} u;
} pLevels[QCBOR_MAX_ARRAY_NESTING1+1],
*pCurrent,
*pCurrentBounded;
/*
pCurrent is for item-by-item pre-order traversal.
pCurrentBounded points to the current bounding level or is NULL if
there isn't one.
pCurrent must always be below pCurrentBounded as the pre-order
traversal is always bounded by the bounding level.
When a bounded level is entered, the pre-order traversal is set to
the first item in the bounded level. When a bounded level is
exited, the pre-order traversl is set to the next item after the
map, array or bstr. This may be more than one level up, or even
the end of the input CBOR.
*/
} QCBORDecodeNesting;
typedef struct {
// PRIVATE DATA STRUCTURE
void *pAllocateCxt;
UsefulBuf (* pfAllocator)(void *pAllocateCxt, void *pOldMem, size_t uNewSize);
} QCBORInternalAllocator;
/*
PRIVATE DATA STRUCTURE
The decode context. This data structure plus the public QCBORDecode_xxx
functions form an "object" that does CBOR decoding.
Size approximation (varies with CPU/compiler):
64-bit machine: 32 + 1 + 1 + 6 bytes padding + 72 + 16 + 8 + 8 = 144 bytes
32-bit machine: 16 + 1 + 1 + 2 bytes padding + 68 + 8 + 8 + 4 = 108 bytes
*/
struct _QCBORDecodeContext {
// PRIVATE DATA STRUCTURE
UsefulInputBuf InBuf;
QCBORDecodeNesting nesting;
// If a string allocator is configured for indefinite-length
// strings, it is configured here.
QCBORInternalAllocator StringAllocator;
// These are special for the internal MemPool allocator.
// They are not used otherwise. We tried packing these
// in the MemPool itself, but there are issues
// with memory alignment.
uint32_t uMemPoolSize;
uint32_t uMemPoolFreeOffset;
// A cached offset to the end of the current map
// 0 if no value is cached.
#define QCBOR_MAP_OFFSET_CACHE_INVALID UINT32_MAX
uint32_t uMapEndOffsetCache;
uint8_t uDecodeMode;
uint8_t bStringAllocateAll;
uint8_t uLastError; // QCBORError stuffed into a uint8_t
/* See MapTagNumber() for description of how tags are mapped. */
uint64_t auMappedTags[QCBOR_NUM_MAPPED_TAGS];
uint16_t uLastTags[QCBOR_MAX_TAGS_PER_ITEM1];
};
// Used internally in the impementation here
// Must not conflict with any of the official CBOR types
#define CBOR_MAJOR_NONE_TYPE_RAW 9
#define CBOR_MAJOR_NONE_TAG_LABEL_REORDER 10
#define CBOR_MAJOR_NONE_TYPE_BSTR_LEN_ONLY 11
#define CBOR_MAJOR_NONE_TYPE_OPEN_BSTR 12
// Add this to types to indicate they are to be encoded as indefinite lengths
#define QCBOR_INDEFINITE_LEN_TYPE_MODIFIER 0x80
#define CBOR_MAJOR_NONE_TYPE_ARRAY_INDEFINITE_LEN \
CBOR_MAJOR_TYPE_ARRAY + QCBOR_INDEFINITE_LEN_TYPE_MODIFIER
#define CBOR_MAJOR_NONE_TYPE_MAP_INDEFINITE_LEN \
CBOR_MAJOR_TYPE_MAP + QCBOR_INDEFINITE_LEN_TYPE_MODIFIER
#define CBOR_MAJOR_NONE_TYPE_SIMPLE_BREAK \
CBOR_MAJOR_TYPE_SIMPLE + QCBOR_INDEFINITE_LEN_TYPE_MODIFIER
/* Value of QCBORItem.val.string.len when the string length is
* indefinite. Used temporarily in the implementation and never
* returned in the public interface.
*/
#define QCBOR_STRING_LENGTH_INDEFINITE SIZE_MAX
/* The number of elements in a C array of a particular type */
#define C_ARRAY_COUNT(array, type) (sizeof(array)/sizeof(type))
#ifdef __cplusplus
}
#endif
#endif /* qcbor_private_h */

2565
3rdparty/exported/QCBOR/qcbor/qcbor_spiffy_decode.h поставляемый Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

426
3rdparty/exported/QCBOR/src/UsefulBuf.c поставляемый Normal file
Просмотреть файл

@ -0,0 +1,426 @@
/*==============================================================================
Copyright (c) 2016-2018, The Linux Foundation.
Copyright (c) 2018-2022, Laurence Lundblade.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors, nor the name "Laurence Lundblade" may be used to
endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
/*=============================================================================
FILE: UsefulBuf.c
DESCRIPTION: General purpose input and output buffers
EDIT HISTORY FOR FILE:
This section contains comments describing changes made to the module.
Notice that changes are listed in reverse chronological order.
when who what, where, why
-------- ---- ---------------------------------------------------
4/11/2022 llundblade Add GetOutPlace and Advance to UsefulOutBuf
3/6/2021 mcr/llundblade Fix warnings related to --Wcast-qual
01/28/2020 llundblade Refine integer signedness to quiet static analysis.
01/08/2020 llundblade Documentation corrections & improved code formatting.
11/08/2019 llundblade Re check pointer math and update comments
3/6/2019 llundblade Add UsefulBuf_IsValue()
09/07/17 llundbla Fix critical bug in UsefulBuf_Find() -- a read off
the end of memory when the bytes to find is longer
than the bytes to search.
06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected comparison
for < or > for unequal length buffers. Added
UsefulBuf_Set() function.
05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
11/13/16 llundbla Initial Version.
============================================================================*/
#include "UsefulBuf.h"
// used to catch use of uninitialized or corrupted UsefulOutBuf
#define USEFUL_OUT_BUF_MAGIC (0x0B0F)
/*
Public function -- see UsefulBuf.h
*/
UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src)
{
// Do this with subtraction so it doesn't give erroneous
// result if uOffset + Src.len overflows
if(uOffset > Dest.len || Src.len > Dest.len - uOffset) { // uOffset + Src.len > Dest.len
return NULLUsefulBufC;
}
memcpy((uint8_t *)Dest.ptr + uOffset, Src.ptr, Src.len);
return (UsefulBufC){Dest.ptr, Src.len + uOffset};
}
/*
Public function -- see UsefulBuf.h
*/
int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2)
{
// use the comparisons rather than subtracting lengths to
// return an int instead of a size_t
if(UB1.len < UB2.len) {
return -1;
} else if (UB1.len > UB2.len) {
return 1;
} // else UB1.len == UB2.len
return memcmp(UB1.ptr, UB2.ptr, UB1.len);
}
/*
Public function -- see UsefulBuf.h
*/
size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue)
{
if(UsefulBuf_IsNULLOrEmptyC(UB)) {
/* Not a match */
return 0;
}
const uint8_t * const pEnd = (const uint8_t *)UB.ptr + UB.len;
for(const uint8_t *p = UB.ptr; p < pEnd; p++) {
if(*p != uValue) {
/* Byte didn't match */
/* Cast from signed to unsigned . Safe because the loop increments.*/
return (size_t)(p - (const uint8_t *)UB.ptr);
}
}
/* Success. All bytes matched */
return SIZE_MAX;
}
/*
Public function -- see UsefulBuf.h
*/
size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind)
{
if(BytesToSearch.len < BytesToFind.len) {
return SIZE_MAX;
}
for(size_t uPos = 0; uPos <= BytesToSearch.len - BytesToFind.len; uPos++) {
if(!UsefulBuf_Compare((UsefulBufC){((const uint8_t *)BytesToSearch.ptr) + uPos, BytesToFind.len}, BytesToFind)) {
return uPos;
}
}
return SIZE_MAX;
}
/*
Public function -- see UsefulBuf.h
Code Reviewers: THIS FUNCTION DOES POINTER MATH
*/
void UsefulOutBuf_Init(UsefulOutBuf *pMe, UsefulBuf Storage)
{
pMe->magic = USEFUL_OUT_BUF_MAGIC;
UsefulOutBuf_Reset(pMe);
pMe->UB = Storage;
#if 0
// This check is off by default.
// The following check fails on ThreadX
// Sanity check on the pointer and size to be sure we are not
// passed a buffer that goes off the end of the address space.
// Given this test, we know that all unsigned lengths less than
// me->size are valid and won't wrap in any pointer additions
// based off of pStorage in the rest of this code.
const uintptr_t ptrM = UINTPTR_MAX - Storage.len;
if(Storage.ptr && (uintptr_t)Storage.ptr > ptrM) // Check #0
me->err = 1;
#endif
}
/*
Public function -- see UsefulBuf.h
The core of UsefulOutBuf -- put some bytes in the buffer without writing off
the end of it.
Code Reviewers: THIS FUNCTION DOES POINTER MATH
This function inserts the source buffer, NewData, into the destination
buffer, me->UB.ptr.
Destination is represented as:
me->UB.ptr -- start of the buffer
me->UB.len -- size of the buffer UB.ptr
me->data_len -- length of value data in UB
Source is data:
NewData.ptr -- start of source buffer
NewData.len -- length of source buffer
Insertion point:
uInsertionPos.
Steps:
0. Corruption checks on UsefulOutBuf
1. Figure out if the new data will fit or not
2. Is insertion position in the range of valid data?
3. If insertion point is not at the end, slide data to the right of the
insertion point to the right
4. Put the new data in at the insertion position.
*/
void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pMe, UsefulBufC NewData, size_t uInsertionPos)
{
if(pMe->err) {
// Already in error state.
return;
}
/* 0. Sanity check the UsefulOutBuf structure */
// A "counter measure". If magic number is not the right number it
// probably means me was not initialized or it was corrupted. Attackers
// can defeat this, but it is a hurdle and does good with very
// little code.
if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
pMe->err = 1;
return; // Magic number is wrong due to uninitalization or corrption
}
// Make sure valid data is less than buffer size. This would only occur
// if there was corruption of me, but it is also part of the checks to
// be sure there is no pointer arithmatic under/overflow.
if(pMe->data_len > pMe->UB.len) { // Check #1
pMe->err = 1;
// Offset of valid data is off the end of the UsefulOutBuf due to
// uninitialization or corruption
return;
}
/* 1. Will it fit? */
// WillItFit() is the same as: NewData.len <= (me->UB.len - me->data_len)
// Check #1 makes sure subtraction in RoomLeft will not wrap around
if(! UsefulOutBuf_WillItFit(pMe, NewData.len)) { // Check #2
// The new data will not fit into the the buffer.
pMe->err = 1;
return;
}
/* 2. Check the Insertion Position */
// This, with Check #1, also confirms that uInsertionPos <= me->data_len and
// that uInsertionPos + pMe->UB.ptr will not wrap around the end of the
// address space.
if(uInsertionPos > pMe->data_len) { // Check #3
// Off the end of the valid data in the buffer.
pMe->err = 1;
return;
}
/* 3. Slide existing data to the right */
uint8_t *pSourceOfMove = ((uint8_t *)pMe->UB.ptr) + uInsertionPos; // PtrMath #1
size_t uNumBytesToMove = pMe->data_len - uInsertionPos; // PtrMath #2
uint8_t *pDestinationOfMove = pSourceOfMove + NewData.len; // PtrMath #3
if(uNumBytesToMove && pMe->UB.ptr) {
// To know memmove won't go off end of destination, see PtrMath #4
// Use memove because it handles overlapping buffers
memmove(pDestinationOfMove, pSourceOfMove, uNumBytesToMove);
}
/* 4. Put the new data in */
uint8_t *pInsertionPoint = ((uint8_t *)pMe->UB.ptr) + uInsertionPos; // PtrMath #5
if(pMe->UB.ptr) {
// To know memmove won't go off end of destination, see PtrMath #6
memmove(pInsertionPoint, NewData.ptr, NewData.len);
}
pMe->data_len += NewData.len;
}
/*
Rationale that describes why the above pointer math is safe
PtrMath #1 will never wrap around over because
Check #0 in UsefulOutBuf_Init makes sure me->UB.ptr + me->UB.len doesn't wrap
Check #1 makes sure me->data_len is less than me->UB.len
Check #3 makes sure uInsertionPos is less than me->data_len
PtrMath #2 will never wrap around under because
Check #3 makes sure uInsertionPos is less than me->data_len
PtrMath #3 will never wrap around over because
PtrMath #1 is checked resulting in pSourceOfMove being between me->UB.ptr and me->UB.ptr + me->data_len
Check #2 that NewData.len will fit in the unused space left in me->UB
PtrMath #4 will never wrap under because
Calculation for extent or memmove is uRoomInDestination = me->UB.len - (uInsertionPos + NewData.len)
Check #3 makes sure uInsertionPos is less than me->data_len
Check #3 allows Check #2 to be refactored as NewData.Len > (me->size - uInsertionPos)
This algebraically rearranges to me->size > uInsertionPos + NewData.len
PtrMath #5 is exactly the same as PtrMath #1
PtrMath #6 will never wrap under because
Calculation for extent of memove is uRoomInDestination = me->UB.len - uInsertionPos;
Check #1 makes sure me->data_len is less than me->size
Check #3 makes sure uInsertionPos is less than me->data_len
*/
/*
* Public function for advancing data length. See qcbor/UsefulBuf.h
*/
void UsefulOutBuf_Advance(UsefulOutBuf *pMe, size_t uAmount)
{
/* This function is a trimmed down version of
* UsefulOutBuf_InsertUsefulBuf(). This could be combined with the
* code in UsefulOutBuf_InsertUsefulBuf(), but that would make
* UsefulOutBuf_InsertUsefulBuf() bigger and this will be very
* rarely used.
*/
if(pMe->err) {
/* Already in error state. */
return;
}
/* 0. Sanity check the UsefulOutBuf structure
*
* A "counter measure". If magic number is not the right number it
* probably means me was not initialized or it was
* corrupted. Attackers can defeat this, but it is a hurdle and
* does good with very little code.
*/
if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
pMe->err = 1;
return; /* Magic number is wrong due to uninitalization or corrption */
}
/* Make sure valid data is less than buffer size. This would only
* occur if there was corruption of me, but it is also part of the
* checks to be sure there is no pointer arithmatic
* under/overflow.
*/
if(pMe->data_len > pMe->UB.len) { // Check #1
pMe->err = 1;
/* Offset of valid data is off the end of the UsefulOutBuf due
* to uninitialization or corruption.
*/
return;
}
/* 1. Will it fit?
*
* WillItFit() is the same as: NewData.len <= (me->UB.len -
* me->data_len) Check #1 makes sure subtraction in RoomLeft will
* not wrap around
*/
if(! UsefulOutBuf_WillItFit(pMe, uAmount)) { /* Check #2 */
/* The new data will not fit into the the buffer. */
pMe->err = 1;
return;
}
pMe->data_len += uAmount;
}
/*
Public function -- see UsefulBuf.h
*/
UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pMe)
{
if(pMe->err) {
return NULLUsefulBufC;
}
if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
pMe->err = 1;
return NULLUsefulBufC;
}
return (UsefulBufC){pMe->UB.ptr, pMe->data_len};
}
/*
Public function -- see UsefulBuf.h
Copy out the data accumulated in to the output buffer.
*/
UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pMe, UsefulBuf pDest)
{
const UsefulBufC Tmp = UsefulOutBuf_OutUBuf(pMe);
if(UsefulBuf_IsNULLC(Tmp)) {
return NULLUsefulBufC;
}
return UsefulBuf_Copy(pDest, Tmp);
}
/*
Public function -- see UsefulBuf.h
The core of UsefulInputBuf -- consume bytes without going off end of buffer.
Code Reviewers: THIS FUNCTION DOES POINTER MATH
*/
const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pMe, size_t uAmount)
{
// Already in error state. Do nothing.
if(pMe->err) {
return NULL;
}
if(!UsefulInputBuf_BytesAvailable(pMe, uAmount)) {
// Number of bytes asked for at current position are more than available
pMe->err = 1;
return NULL;
}
// This is going to succeed
const void * const result = ((const uint8_t *)pMe->UB.ptr) + pMe->cursor;
// Will not overflow because of check using UsefulInputBuf_BytesAvailable()
pMe->cursor += uAmount;
return result;
}

505
3rdparty/exported/QCBOR/src/ieee754.c поставляемый Normal file
Просмотреть файл

@ -0,0 +1,505 @@
/*==============================================================================
ieee754.c -- floating-point conversion between half, double & single-precision
Copyright (c) 2018-2020, Laurence Lundblade. All rights reserved.
Copyright (c) 2021, Arm Limited. All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
See BSD-3-Clause license in README.md
Created on 7/23/18
=============================================================================*/
/*
Include before QCBOR_DISABLE_PREFERRED_FLOAT is checked as
QCBOR_DISABLE_PREFERRED_FLOAT might be defined in qcbor/qcbor_common.h
*/
#include "qcbor/qcbor_common.h"
#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
#include "ieee754.h"
#include <string.h> // For memcpy()
/*
This code is written for clarity and verifiability, not for size, on
the assumption that the optimizer will do a good job. The LLVM
optimizer, -Os, does seem to do the job and the resulting object code
is smaller from combining code for the many different cases (normal,
subnormal, infinity, zero...) for the conversions. GCC is no where near
as good.
This code has really long lines and is much easier to read because of
them. Some coding guidelines prefer 80 column lines (can they not afford
big displays?). It would make this code much worse even to wrap at 120
columns.
Dead stripping is also really helpful to get code size down when
floating-point encoding is not needed. (If this is put in a library
and linking is against the library, then dead stripping is automatic).
This code works solely using shifts and masks and thus has no
dependency on any math libraries. It can even work if the CPU doesn't
have any floating-point support, though that isn't the most useful
thing to do.
The memcpy() dependency is only for CopyFloatToUint32() and friends
which only is needed to avoid type punning when converting the actual
float bits to an unsigned value so the bit shifts and masks can work.
*/
/*
The references used to write this code:
- IEEE 754-2008, particularly section 3.6 and 6.2.1
- https://en.wikipedia.org/wiki/IEEE_754 and subordinate pages
- https://stackoverflow.com/questions/19800415/why-does-ieee-754-reserve-so-many-nan-values
- https://stackoverflow.com/questions/46073295/implicit-type-promotion-rules
- https://stackoverflow.com/questions/589575/what-does-the-c-standard-state-the-size-of-int-long-type-to-be
*/
// ----- Half Precsion -----------
#define HALF_NUM_SIGNIFICAND_BITS (10)
#define HALF_NUM_EXPONENT_BITS (5)
#define HALF_NUM_SIGN_BITS (1)
#define HALF_SIGNIFICAND_SHIFT (0)
#define HALF_EXPONENT_SHIFT (HALF_NUM_SIGNIFICAND_BITS)
#define HALF_SIGN_SHIFT (HALF_NUM_SIGNIFICAND_BITS + HALF_NUM_EXPONENT_BITS)
#define HALF_SIGNIFICAND_MASK (0x3ffU) // The lower 10 bits // 0x03ff
#define HALF_EXPONENT_MASK (0x1fU << HALF_EXPONENT_SHIFT) // 0x7c00 5 bits of exponent
#define HALF_SIGN_MASK (0x01U << HALF_SIGN_SHIFT) // // 0x8000 1 bit of sign
#define HALF_QUIET_NAN_BIT (0x01U << (HALF_NUM_SIGNIFICAND_BITS-1)) // 0x0200
/* Biased Biased Unbiased Use
0x00 0 -15 0 and subnormal
0x01 1 -14 Smallest normal exponent
0x1e 30 15 Largest normal exponent
0x1F 31 16 NaN and Infinity */
#define HALF_EXPONENT_BIAS (15)
#define HALF_EXPONENT_MAX (HALF_EXPONENT_BIAS) // 15 Unbiased
#define HALF_EXPONENT_MIN (-HALF_EXPONENT_BIAS+1) // -14 Unbiased
#define HALF_EXPONENT_ZERO (-HALF_EXPONENT_BIAS) // -15 Unbiased
#define HALF_EXPONENT_INF_OR_NAN (HALF_EXPONENT_BIAS+1) // 16 Unbiased
// ------ Single-Precision --------
#define SINGLE_NUM_SIGNIFICAND_BITS (23)
#define SINGLE_NUM_EXPONENT_BITS (8)
#define SINGLE_NUM_SIGN_BITS (1)
#define SINGLE_SIGNIFICAND_SHIFT (0)
#define SINGLE_EXPONENT_SHIFT (SINGLE_NUM_SIGNIFICAND_BITS)
#define SINGLE_SIGN_SHIFT (SINGLE_NUM_SIGNIFICAND_BITS + SINGLE_NUM_EXPONENT_BITS)
#define SINGLE_SIGNIFICAND_MASK (0x7fffffU) // The lower 23 bits
#define SINGLE_EXPONENT_MASK (0xffU << SINGLE_EXPONENT_SHIFT) // 8 bits of exponent
#define SINGLE_SIGN_MASK (0x01U << SINGLE_SIGN_SHIFT) // 1 bit of sign
#define SINGLE_QUIET_NAN_BIT (0x01U << (SINGLE_NUM_SIGNIFICAND_BITS-1))
/* Biased Biased Unbiased Use
0x0000 0 -127 0 and subnormal
0x0001 1 -126 Smallest normal exponent
0x7f 127 0 1
0xfe 254 127 Largest normal exponent
0xff 255 128 NaN and Infinity */
#define SINGLE_EXPONENT_BIAS (127)
#define SINGLE_EXPONENT_MAX (SINGLE_EXPONENT_BIAS) // 127 unbiased
#define SINGLE_EXPONENT_MIN (-SINGLE_EXPONENT_BIAS+1) // -126 unbiased
#define SINGLE_EXPONENT_ZERO (-SINGLE_EXPONENT_BIAS) // -127 unbiased
#define SINGLE_EXPONENT_INF_OR_NAN (SINGLE_EXPONENT_BIAS+1) // 128 unbiased
// --------- Double-Precision ----------
#define DOUBLE_NUM_SIGNIFICAND_BITS (52)
#define DOUBLE_NUM_EXPONENT_BITS (11)
#define DOUBLE_NUM_SIGN_BITS (1)
#define DOUBLE_SIGNIFICAND_SHIFT (0)
#define DOUBLE_EXPONENT_SHIFT (DOUBLE_NUM_SIGNIFICAND_BITS)
#define DOUBLE_SIGN_SHIFT (DOUBLE_NUM_SIGNIFICAND_BITS + DOUBLE_NUM_EXPONENT_BITS)
#define DOUBLE_SIGNIFICAND_MASK (0xfffffffffffffULL) // The lower 52 bits
#define DOUBLE_EXPONENT_MASK (0x7ffULL << DOUBLE_EXPONENT_SHIFT) // 11 bits of exponent
#define DOUBLE_SIGN_MASK (0x01ULL << DOUBLE_SIGN_SHIFT) // 1 bit of sign
#define DOUBLE_QUIET_NAN_BIT (0x01ULL << (DOUBLE_NUM_SIGNIFICAND_BITS-1))
/* Biased Biased Unbiased Use
0x00000000 0 -1023 0 and subnormal
0x00000001 1 -1022 Smallest normal exponent
0x000007fe 2046 1023 Largest normal exponent
0x000007ff 2047 1024 NaN and Infinity */
#define DOUBLE_EXPONENT_BIAS (1023)
#define DOUBLE_EXPONENT_MAX (DOUBLE_EXPONENT_BIAS) // unbiased
#define DOUBLE_EXPONENT_MIN (-DOUBLE_EXPONENT_BIAS+1) // unbiased
#define DOUBLE_EXPONENT_ZERO (-DOUBLE_EXPONENT_BIAS) // unbiased
#define DOUBLE_EXPONENT_INF_OR_NAN (DOUBLE_EXPONENT_BIAS+1) // unbiased
/*
Convenient functions to avoid type punning, compiler warnings and
such. The optimizer reduces them to a simple assignment. This is a
crusty corner of C. It shouldn't be this hard.
These are also in UsefulBuf.h under a different name. They are copied
here to avoid a dependency on UsefulBuf.h. There is no object code
size impact because these always optimze down to a simple assignment.
*/
static inline uint32_t CopyFloatToUint32(float f)
{
uint32_t u32;
memcpy(&u32, &f, sizeof(uint32_t));
return u32;
}
static inline uint64_t CopyDoubleToUint64(double d)
{
uint64_t u64;
memcpy(&u64, &d, sizeof(uint64_t));
return u64;
}
static inline double CopyUint64ToDouble(uint64_t u64)
{
double d;
memcpy(&d, &u64, sizeof(uint64_t));
return d;
}
// Public function; see ieee754.h
uint16_t IEEE754_FloatToHalf(float f)
{
// Pull the three parts out of the single-precision float
const uint32_t uSingle = CopyFloatToUint32(f);
const int32_t nSingleUnbiasedExponent = (int32_t)((uSingle & SINGLE_EXPONENT_MASK) >> SINGLE_EXPONENT_SHIFT) - SINGLE_EXPONENT_BIAS;
const uint32_t uSingleSign = (uSingle & SINGLE_SIGN_MASK) >> SINGLE_SIGN_SHIFT;
const uint32_t uSingleSignificand = uSingle & SINGLE_SIGNIFICAND_MASK;
// Now convert the three parts to half-precision.
// All works is done on uint32_t with conversion to uint16_t at
// the end. This avoids integer promotions that static analyzers
// complain about and reduces code size.
uint32_t uHalfSign, uHalfSignificand, uHalfBiasedExponent;
if(nSingleUnbiasedExponent == SINGLE_EXPONENT_INF_OR_NAN) {
// +/- Infinity and NaNs -- single biased exponent is 0xff
uHalfBiasedExponent = HALF_EXPONENT_INF_OR_NAN + HALF_EXPONENT_BIAS;
if(!uSingleSignificand) {
// Infinity
uHalfSignificand = 0;
} else {
// Copy the LSBs of the NaN payload that will fit from the
// single to the half
uHalfSignificand = uSingleSignificand & (HALF_SIGNIFICAND_MASK & ~HALF_QUIET_NAN_BIT);
if(uSingleSignificand & SINGLE_QUIET_NAN_BIT) {
// It's a qNaN; copy the qNaN bit
uHalfSignificand |= HALF_QUIET_NAN_BIT;
} else {
// It's an sNaN; make sure the significand is not zero
// so it stays a NaN This is needed because not all
// significand bits are copied from single
if(!uHalfSignificand) {
// Set the LSB. This is what wikipedia shows for
// sNAN.
uHalfSignificand |= 0x01;
}
}
}
} else if(nSingleUnbiasedExponent == SINGLE_EXPONENT_ZERO) {
// 0 or a subnormal number -- singled biased exponent is 0
uHalfBiasedExponent = 0;
uHalfSignificand = 0; // Any subnormal single will be too small to express as a half precision
} else if(nSingleUnbiasedExponent > HALF_EXPONENT_MAX) {
// Exponent is too large to express in half-precision; round
// up to infinity
uHalfBiasedExponent = HALF_EXPONENT_INF_OR_NAN + HALF_EXPONENT_BIAS;
uHalfSignificand = 0;
} else if(nSingleUnbiasedExponent < HALF_EXPONENT_MIN) {
// Exponent is too small to express in half-precision normal;
// make it a half-precision subnormal
uHalfBiasedExponent = HALF_EXPONENT_ZERO + HALF_EXPONENT_BIAS;
uHalfSignificand = 0;
// Could convert some of these values to a half-precision
// subnormal, but the layer above this will never use it. See
// layer above. There is code to do this in github history
// for this file, but it was removed because it was never
// invoked.
} else {
// The normal case, exponent is in range for half-precision
uHalfBiasedExponent = (uint32_t)(nSingleUnbiasedExponent + HALF_EXPONENT_BIAS);
uHalfSignificand = uSingleSignificand >> (SINGLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS);
}
uHalfSign = uSingleSign;
// Put the 3 values in the right place for a half precision
const uint32_t uHalfPrecision = uHalfSignificand |
(uHalfBiasedExponent << HALF_EXPONENT_SHIFT) |
(uHalfSign << HALF_SIGN_SHIFT);
// Cast is safe because all the masks and shifts above work to
// make a half precision value which is only 16 bits.
return (uint16_t)uHalfPrecision;
}
// Public function; see ieee754.h
uint16_t IEEE754_DoubleToHalf(double d)
{
// Pull the three parts out of the double-precision float
const uint64_t uDouble = CopyDoubleToUint64(d);
const int64_t nDoubleUnbiasedExponent = (int64_t)((uDouble & DOUBLE_EXPONENT_MASK) >> DOUBLE_EXPONENT_SHIFT) - DOUBLE_EXPONENT_BIAS;
const uint64_t uDoubleSign = (uDouble & DOUBLE_SIGN_MASK) >> DOUBLE_SIGN_SHIFT;
const uint64_t uDoubleSignificand = uDouble & DOUBLE_SIGNIFICAND_MASK;
// Now convert the three parts to half-precision.
// All works is done on uint64_t with conversion to uint16_t at
// the end. This avoids integer promotions that static analyzers
// complain about. Other options are for these to be unsigned int
// or fast_int16_t. Code size doesn't vary much between all these
// options for 64-bit LLVM, 64-bit GCC and 32-bit Armv7 LLVM.
uint64_t uHalfSign, uHalfSignificand, uHalfBiasedExponent;
if(nDoubleUnbiasedExponent == DOUBLE_EXPONENT_INF_OR_NAN) {
// +/- Infinity and NaNs -- single biased exponent is 0xff
uHalfBiasedExponent = HALF_EXPONENT_INF_OR_NAN + HALF_EXPONENT_BIAS;
if(!uDoubleSignificand) {
// Infinity
uHalfSignificand = 0;
} else {
// Copy the LSBs of the NaN payload that will fit from the
// double to the half
uHalfSignificand = uDoubleSignificand & (HALF_SIGNIFICAND_MASK & ~HALF_QUIET_NAN_BIT);
if(uDoubleSignificand & DOUBLE_QUIET_NAN_BIT) {
// It's a qNaN; copy the qNaN bit
uHalfSignificand |= HALF_QUIET_NAN_BIT;
} else {
// It's an sNaN; make sure the significand is not zero
// so it stays a NaN This is needed because not all
// significand bits are copied from single
if(!uHalfSignificand) {
// Set the LSB. This is what wikipedia shows for
// sNAN.
uHalfSignificand |= 0x01;
}
}
}
} else if(nDoubleUnbiasedExponent == DOUBLE_EXPONENT_ZERO) {
// 0 or a subnormal number -- double biased exponent is 0
uHalfBiasedExponent = 0;
uHalfSignificand = 0; // Any subnormal single will be too small to express as a half precision; TODO, is this really true?
} else if(nDoubleUnbiasedExponent > HALF_EXPONENT_MAX) {
// Exponent is too large to express in half-precision; round
// up to infinity; TODO, is this really true?
uHalfBiasedExponent = HALF_EXPONENT_INF_OR_NAN + HALF_EXPONENT_BIAS;
uHalfSignificand = 0;
} else if(nDoubleUnbiasedExponent < HALF_EXPONENT_MIN) {
// Exponent is too small to express in half-precision; round
// down to zero
uHalfBiasedExponent = HALF_EXPONENT_ZERO + HALF_EXPONENT_BIAS;
uHalfSignificand = 0;
// Could convert some of these values to a half-precision
// subnormal, but the layer above this will never use it. See
// layer above. There is code to do this in github history
// for this file, but it was removed because it was never
// invoked.
} else {
// The normal case, exponent is in range for half-precision
uHalfBiasedExponent = (uint32_t)(nDoubleUnbiasedExponent + HALF_EXPONENT_BIAS);
uHalfSignificand = uDoubleSignificand >> (DOUBLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS);
}
uHalfSign = uDoubleSign;
// Put the 3 values in the right place for a half precision
const uint64_t uHalfPrecision = uHalfSignificand |
(uHalfBiasedExponent << HALF_EXPONENT_SHIFT) |
(uHalfSign << HALF_SIGN_SHIFT);
// Cast is safe because all the masks and shifts above work to
// make a half precision value which is only 16 bits.
return (uint16_t)uHalfPrecision;
}
/*
EEE754_HalfToFloat() was created but is not needed. It can be retrieved from
github history if needed.
*/
// Public function; see ieee754.h
double IEEE754_HalfToDouble(uint16_t uHalfPrecision)
{
// Pull out the three parts of the half-precision float. Do all
// the work in 64 bits because that is what the end result is. It
// may give smaller code size and will keep static analyzers
// happier.
const uint64_t uHalfSignificand = uHalfPrecision & HALF_SIGNIFICAND_MASK;
const int64_t nHalfUnBiasedExponent = (int64_t)((uHalfPrecision & HALF_EXPONENT_MASK) >> HALF_EXPONENT_SHIFT) - HALF_EXPONENT_BIAS;
const uint64_t uHalfSign = (uHalfPrecision & HALF_SIGN_MASK) >> HALF_SIGN_SHIFT;
// Make the three parts of hte single-precision number
uint64_t uDoubleSignificand, uDoubleSign, uDoubleBiasedExponent;
if(nHalfUnBiasedExponent == HALF_EXPONENT_ZERO) {
// 0 or subnormal
uDoubleBiasedExponent = DOUBLE_EXPONENT_ZERO + DOUBLE_EXPONENT_BIAS;
if(uHalfSignificand) {
// Subnormal case
uDoubleBiasedExponent = -HALF_EXPONENT_BIAS + DOUBLE_EXPONENT_BIAS +1;
// A half-precision subnormal can always be converted to a
// normal double-precision float because the ranges line
// up
uDoubleSignificand = uHalfSignificand;
// Shift bits from right of the decimal to left, reducing
// the exponent by 1 each time
do {
uDoubleSignificand <<= 1;
uDoubleBiasedExponent--;
} while ((uDoubleSignificand & 0x400) == 0);
uDoubleSignificand &= HALF_SIGNIFICAND_MASK;
uDoubleSignificand <<= (DOUBLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS);
} else {
// Just zero
uDoubleSignificand = 0;
}
} else if(nHalfUnBiasedExponent == HALF_EXPONENT_INF_OR_NAN) {
// NaN or Inifinity
uDoubleBiasedExponent = DOUBLE_EXPONENT_INF_OR_NAN + DOUBLE_EXPONENT_BIAS;
if(uHalfSignificand) {
// NaN
// First preserve the NaN payload from half to single
uDoubleSignificand = uHalfSignificand & ~HALF_QUIET_NAN_BIT;
if(uHalfSignificand & HALF_QUIET_NAN_BIT) {
// Next, set qNaN if needed since half qNaN bit is not
// copied above
uDoubleSignificand |= DOUBLE_QUIET_NAN_BIT;
}
} else {
// Infinity
uDoubleSignificand = 0;
}
} else {
// Normal number
uDoubleBiasedExponent = (uint64_t)(nHalfUnBiasedExponent + DOUBLE_EXPONENT_BIAS);
uDoubleSignificand = uHalfSignificand << (DOUBLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS);
}
uDoubleSign = uHalfSign;
// Shift the 3 parts into place as a double-precision
const uint64_t uDouble = uDoubleSignificand |
(uDoubleBiasedExponent << DOUBLE_EXPONENT_SHIFT) |
(uDoubleSign << DOUBLE_SIGN_SHIFT);
return CopyUint64ToDouble(uDouble);
}
/*
IEEE754_FloatToDouble(uint32_t uFloat) was created but is not needed. It can be retrieved from
github history if needed.
*/
// Public function; see ieee754.h
IEEE754_union IEEE754_FloatToSmallest(float f)
{
IEEE754_union result;
// Pull the neeed two parts out of the single-precision float
const uint32_t uSingle = CopyFloatToUint32(f);
const int32_t nSingleExponent = (int32_t)((uSingle & SINGLE_EXPONENT_MASK) >> SINGLE_EXPONENT_SHIFT) - SINGLE_EXPONENT_BIAS;
const uint32_t uSingleSignificand = uSingle & SINGLE_SIGNIFICAND_MASK;
// Bit mask that is the significand bits that would be lost when
// converting from single-precision to half-precision
const uint64_t uDroppedSingleBits = SINGLE_SIGNIFICAND_MASK >> HALF_NUM_SIGNIFICAND_BITS;
// Optimizer will re organize so there is only one call to
// IEEE754_FloatToHalf() in the final code.
if(uSingle == 0) {
// Value is 0.0000, not a a subnormal
result.uSize = IEEE754_UNION_IS_HALF;
result.uValue = IEEE754_FloatToHalf(f);
} else if(nSingleExponent == SINGLE_EXPONENT_INF_OR_NAN) {
// NaN, +/- infinity
result.uSize = IEEE754_UNION_IS_HALF;
result.uValue = IEEE754_FloatToHalf(f);
} else if((nSingleExponent >= HALF_EXPONENT_MIN) && nSingleExponent <= HALF_EXPONENT_MAX && (!(uSingleSignificand & uDroppedSingleBits))) {
// Normal number in exponent range and precision won't be lost
result.uSize = IEEE754_UNION_IS_HALF;
result.uValue = IEEE754_FloatToHalf(f);
} else {
// Subnormal, exponent out of range, or precision will be lost
result.uSize = IEEE754_UNION_IS_SINGLE;
result.uValue = uSingle;
}
return result;
}
// Public function; see ieee754.h
IEEE754_union IEEE754_DoubleToSmallestInternal(double d, int bAllowHalfPrecision)
{
IEEE754_union result;
// Pull the needed two parts out of the double-precision float
const uint64_t uDouble = CopyDoubleToUint64(d);
const int64_t nDoubleExponent = (int64_t)((uDouble & DOUBLE_EXPONENT_MASK) >> DOUBLE_EXPONENT_SHIFT) - DOUBLE_EXPONENT_BIAS;
const uint64_t uDoubleSignificand = uDouble & DOUBLE_SIGNIFICAND_MASK;
// Masks to check whether dropped significand bits are zero or not
const uint64_t uDroppedHalfBits = DOUBLE_SIGNIFICAND_MASK >> HALF_NUM_SIGNIFICAND_BITS;
const uint64_t uDroppedSingleBits = DOUBLE_SIGNIFICAND_MASK >> SINGLE_NUM_SIGNIFICAND_BITS;
// This will not convert to half-precion or single-precision
// subnormals. Values that could be converted will be output as
// the double they are or occasionally to a normal single. This
// could be implemented, but it is more code and would rarely be
// used and rarely reduce the output size.
// The various cases
if(d == 0.0) { // Take care of positive and negative zero
// Value is 0.0000, not a a subnormal
result.uSize = IEEE754_UNION_IS_HALF;
result.uValue = IEEE754_DoubleToHalf(d);
} else if(nDoubleExponent == DOUBLE_EXPONENT_INF_OR_NAN) {
// NaN, +/- infinity
result.uSize = IEEE754_UNION_IS_HALF;
result.uValue = IEEE754_DoubleToHalf(d);
} else if(bAllowHalfPrecision && (nDoubleExponent >= HALF_EXPONENT_MIN) && nDoubleExponent <= HALF_EXPONENT_MAX && (!(uDoubleSignificand & uDroppedHalfBits))) {
// Can convert to half without precision loss
result.uSize = IEEE754_UNION_IS_HALF;
result.uValue = IEEE754_DoubleToHalf(d);
} else if((nDoubleExponent >= SINGLE_EXPONENT_MIN) && nDoubleExponent <= SINGLE_EXPONENT_MAX && (!(uDoubleSignificand & uDroppedSingleBits))) {
// Can convert to single without precision loss
result.uSize = IEEE754_UNION_IS_SINGLE;
result.uValue = CopyFloatToUint32((float)d);
} else {
// Can't convert without precision loss
result.uSize = IEEE754_UNION_IS_DOUBLE;
result.uValue = uDouble;
}
return result;
}
#else
int x;
#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */

147
3rdparty/exported/QCBOR/src/ieee754.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,147 @@
/*==============================================================================
ieee754.c -- floating-point conversion between half, double & single-precision
Copyright (c) 2018-2020, Laurence Lundblade. All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
See BSD-3-Clause license in README.md
Created on 7/23/18
=============================================================================*/
#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
#ifndef ieee754_h
#define ieee754_h
#include <stdint.h>
/*
General comments
This is a complete in that it handles all conversion cases including
+/- infinity, +/- zero, subnormal numbers, qNaN, sNaN and NaN
payloads.
This conforms to IEEE 754-2008, but note that this doesn't specify
conversions, just the encodings.
NaN payloads are preserved with alignment on the LSB. The qNaN bit is
handled differently and explicity copied. It is always the MSB of the
significand. The NaN payload MSBs (except the qNaN bit) are truncated
when going from double or single to half.
TODO: what does the C cast do with NaN payloads from
double to single? It probably depends entirely on the
CPU.
*/
/*
Most simply just explicilty encode the type you want, single or
double. This works easily everywhere since standard C supports both
these types and so does qcbor. This encoder also supports half
precision and there's a few ways to use it to encode floating-point
numbers in less space.
Without losing precision, you can encode a single or double such that
the special values of 0, NaN and Infinity encode as half-precision.
This CBOR decodoer and most others should handle this properly.
If you don't mind losing precision, then you can use half-precision.
One way to do this is to set up your environment to use
___fp_16. Some compilers and CPUs support it even though it is not
standard C. What is nice about this is that your program will use
less memory and floating-point operations like multiplying, adding
and such will be faster.
Another way to make use of half-precision is to represent the values
in your program as single or double, but encode them in CBOR as
half-precision. This cuts the size of the encoded messages by 2 or 4,
but doesn't reduce memory needs or speed because you are still using
single or double in your code.
*/
/*
Convert single-precision float to half-precision float. Precision
and NaN payload bits will be lost. Too-large values will round up to
infinity and too small to zero.
*/
uint16_t IEEE754_FloatToHalf(float f);
/*
Convert double-precision float to half-precision float. Precision
and NaN payload bits will be lost. Too-large values will round up to
infinity and too small to zero.
*/
uint16_t IEEE754_DoubleToHalf(double d);
/*
Convert half-precision float to double-precision float.
This is a loss-less conversion.
*/
double IEEE754_HalfToDouble(uint16_t uHalfPrecision);
// Both tags the value and gives the size
#define IEEE754_UNION_IS_HALF 2
#define IEEE754_UNION_IS_SINGLE 4
#define IEEE754_UNION_IS_DOUBLE 8
typedef struct {
uint8_t uSize; // One of IEEE754_IS_xxxx
uint64_t uValue;
} IEEE754_union;
/*
Converts double-precision to single-precision or half-precision if
possible without loss of precisions. If not, leaves it as a
double. Only converts to single-precision unless bAllowHalfPrecision
is set.
*/
IEEE754_union IEEE754_DoubleToSmallestInternal(double d, int bAllowHalfPrecision);
/*
Converts double-precision to single-precision if possible without
loss of precision. If not, leaves it as a double.
*/
static inline IEEE754_union IEEE754_DoubleToSmall(double d)
{
return IEEE754_DoubleToSmallestInternal(d, 0);
}
/*
Converts double-precision to single-precision or half-precision if
possible without loss of precisions. If not, leaves it as a double.
*/
static inline IEEE754_union IEEE754_DoubleToSmallest(double d)
{
return IEEE754_DoubleToSmallestInternal(d, 1);
}
/*
Converts single-precision to half-precision if possible without loss
of precision. If not leaves as single-precision.
*/
IEEE754_union IEEE754_FloatToSmallest(float f);
#endif /* ieee754_h */
#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */

6001
3rdparty/exported/QCBOR/src/qcbor_decode.c поставляемый Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

1071
3rdparty/exported/QCBOR/src/qcbor_encode.c поставляемый Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

69
3rdparty/exported/QCBOR/src/qcbor_err_to_str.c поставляемый Normal file
Просмотреть файл

@ -0,0 +1,69 @@
/*==============================================================================
err_to_str.c -- strings names for errors
Copyright (c) 2020, Patrick Uiterwijk. All rights reserved.
Copyright (c) 2020, Laurence Lundblade.
Copyright (c) 2021, Arm Limited. All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
See BSD-3-Clause license in README.md
Created on 3/21/20
=============================================================================*/
#include "qcbor/qcbor_common.h"
#define _ERR_TO_STR(errpart) case QCBOR_##errpart: return "QCBOR_" #errpart;
const char *qcbor_err_to_str(QCBORError err) {
switch (err) {
_ERR_TO_STR(SUCCESS)
_ERR_TO_STR(ERR_BUFFER_TOO_SMALL)
_ERR_TO_STR(ERR_ENCODE_UNSUPPORTED)
_ERR_TO_STR(ERR_BUFFER_TOO_LARGE)
_ERR_TO_STR(ERR_ARRAY_NESTING_TOO_DEEP)
_ERR_TO_STR(ERR_CLOSE_MISMATCH)
_ERR_TO_STR(ERR_ARRAY_TOO_LONG)
_ERR_TO_STR(ERR_TOO_MANY_CLOSES)
_ERR_TO_STR(ERR_ARRAY_OR_MAP_STILL_OPEN)
_ERR_TO_STR(ERR_BAD_TYPE_7)
_ERR_TO_STR(ERR_EXTRA_BYTES)
_ERR_TO_STR(ERR_UNSUPPORTED)
_ERR_TO_STR(ERR_ARRAY_OR_MAP_UNCONSUMED)
_ERR_TO_STR(ERR_BAD_INT)
_ERR_TO_STR(ERR_INDEFINITE_STRING_CHUNK)
_ERR_TO_STR(ERR_HIT_END)
_ERR_TO_STR(ERR_BAD_BREAK)
_ERR_TO_STR(ERR_INPUT_TOO_LARGE)
_ERR_TO_STR(ERR_ARRAY_DECODE_NESTING_TOO_DEEP)
_ERR_TO_STR(ERR_ARRAY_DECODE_TOO_LONG)
_ERR_TO_STR(ERR_STRING_TOO_LONG)
_ERR_TO_STR(ERR_BAD_EXP_AND_MANTISSA)
_ERR_TO_STR(ERR_NO_STRING_ALLOCATOR)
_ERR_TO_STR(ERR_STRING_ALLOCATE)
_ERR_TO_STR(ERR_TOO_MANY_TAGS)
_ERR_TO_STR(ERR_MAP_LABEL_TYPE)
_ERR_TO_STR(ERR_UNEXPECTED_TYPE)
_ERR_TO_STR(ERR_BAD_OPT_TAG)
_ERR_TO_STR(ERR_DUPLICATE_LABEL)
_ERR_TO_STR(ERR_MEM_POOL_SIZE)
_ERR_TO_STR(ERR_INT_OVERFLOW)
_ERR_TO_STR(ERR_DATE_OVERFLOW)
_ERR_TO_STR(ERR_EXIT_MISMATCH)
_ERR_TO_STR(ERR_NO_MORE_ITEMS)
_ERR_TO_STR(ERR_LABEL_NOT_FOUND)
_ERR_TO_STR(ERR_NUMBER_SIGN_CONVERSION)
_ERR_TO_STR(ERR_CONVERSION_UNDER_OVER_FLOW)
_ERR_TO_STR(ERR_MAP_NOT_ENTERED)
_ERR_TO_STR(ERR_CALLBACK_FAIL)
_ERR_TO_STR(ERR_FLOAT_DATE_DISABLED)
_ERR_TO_STR(ERR_HALF_PRECISION_DISABLED)
_ERR_TO_STR(ERR_HW_FLOAT_DISABLED)
_ERR_TO_STR(ERR_FLOAT_EXCEPTION)
_ERR_TO_STR(ERR_ALL_FLOAT_DISABLED)
default:
return "Unidentified error";
}
}

869
3rdparty/exported/QCBOR/test/UsefulBuf_Tests.c поставляемый Normal file
Просмотреть файл

@ -0,0 +1,869 @@
/*==============================================================================
Copyright (c) 2016-2018, The Linux Foundation.
Copyright (c) 2018-2022, Laurence Lundblade.
Copyright (c) 2021, Arm Limited.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors, nor the name "Laurence Lundblade" may be used to
endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include "UsefulBuf.h"
/* This calls the main methods to add stuff to a UsefulOutBuf.
* The result in the UsefulOutBuf is "heffalump unbounce bluster hunny bear"
*/
const char *AddStuffToUOB(UsefulOutBuf *pUOB)
{
const char *szReturn = NULL;
if(!UsefulOutBuf_AtStart(pUOB)) {
szReturn = "Not at start";
goto Done;
}
/* Put 7 bytes at beginning of buf */
UsefulOutBuf_AppendData(pUOB, "bluster", 7);
if(UsefulOutBuf_AtStart(pUOB)) {
szReturn = "At start";
goto Done;
}
/* add a space to end */
UsefulOutBuf_AppendByte(pUOB, ' ');
/* Add 6 bytes to the end */
UsefulBufC UBC = {"hunny ", 6};
UsefulOutBuf_AppendUsefulBuf(pUOB, UBC);
/* Insert 9 bytes at the beginning, slide the previous stuff right */
UsefulOutBuf_InsertData(pUOB, "heffalump", 9, 0);
UsefulOutBuf_InsertByte(pUOB, ' ', 9);
/* Put 9 bytes in at position 10 -- just after "heffalump " */
UsefulBufC UBC2 = {"unbounce ", 9};
UsefulOutBuf_InsertUsefulBuf(pUOB, UBC2, 10);
/* Add 4 bytes to the end, by accessing the buffer directly and then advancing it */
UsefulBuf UB = UsefulOutBuf_GetOutPlace(pUOB);
if (!UsefulBuf_IsNULL(UB)) {
memcpy(UB.ptr, "bear", UB.len < 4 ? UB.len : 4);
}
UsefulOutBuf_Advance(pUOB, 4);
Done:
return szReturn;
}
/* Basic exercise of a UsefulOutBuf
*
* Call all the main public functions.
*
* Binary compare the result to the expected.
*
* There is nothing adversarial in this test
*/
const char * UOBTest_NonAdversarial(void)
{
const char *szReturn = NULL;
UsefulBuf_MAKE_STACK_UB(outbuf, 50);
UsefulOutBuf UOB;
UsefulOutBuf_Init(&UOB, outbuf);
szReturn = AddStuffToUOB(&UOB);
if(szReturn) {
goto Done;
}
const UsefulBufC Expected = UsefulBuf_FROM_SZ_LITERAL("heffalump unbounce bluster hunny bear");
UsefulBufC U = UsefulOutBuf_OutUBuf(&UOB);
if(UsefulBuf_IsNULLC(U) ||
UsefulBuf_Compare(Expected, U) ||
UsefulOutBuf_GetError(&UOB)) {
szReturn = "OutUBuf";
goto Done;
}
UsefulBuf_MAKE_STACK_UB(buf, 50);
UsefulBufC Out = UsefulOutBuf_CopyOut(&UOB, buf);
if(UsefulBuf_IsNULLC(Out) || UsefulBuf_Compare(Expected, Out)) {
szReturn = "CopyOut";
goto Done;
}
/* Now test the size calculation mode */
UsefulOutBuf_Init(&UOB, SizeCalculateUsefulBuf);
szReturn = AddStuffToUOB(&UOB);
if(szReturn) {
goto Done;
}
U = UsefulOutBuf_OutUBuf(&UOB);
if(U.len != Expected.len || U.ptr != NULL) {
szReturn = "size calculation failed";
}
Done:
return szReturn;
}
/*
Append test utility.
pUOB is the buffer to append too
num is the amount to append
expected is the expected return code, 0 or 1
returns 0 if test passed
*/
static int AppendTest(UsefulOutBuf *pUOB, size_t num, int expected)
{
//reset
UsefulOutBuf_Reset(pUOB);
// check status first
if(UsefulOutBuf_GetError(pUOB))
return 1;
// append the bytes
UsefulOutBuf_AppendData(pUOB, (const uint8_t *)"bluster", num);
// check error status after
if(UsefulOutBuf_GetError(pUOB) != expected)
return 1;
return 0;
}
/*
Same as append, but takes a position param too
*/
static int InsertTest(UsefulOutBuf *pUOB, size_t num, size_t pos, int expected)
{
// reset
UsefulOutBuf_Reset(pUOB);
// check
if(UsefulOutBuf_GetError(pUOB))
return 1;
UsefulOutBuf_InsertData(pUOB, (const uint8_t *)"bluster", num, pos);
if(UsefulOutBuf_GetError(pUOB) != expected)
return 1;
return 0;
}
/*
Boundary conditions to test
- around 0
- around the buffer size
- around MAX size_t
Test these for the buffer size and the cursor, the insert amount, the
append amount and the insert position
*/
const char *UOBTest_BoundaryConditionsTest(void)
{
UsefulBuf_MAKE_STACK_UB(outbuf, 2);
UsefulOutBuf UOB;
UsefulOutBuf_Init(&UOB, outbuf);
// append 0 byte to a 2 byte buffer --> success
if(AppendTest(&UOB, 0, 0))
return "Append 0 bytes failed";
// append 1 byte to a 2 byte buffer --> success
if(AppendTest(&UOB, 1, 0))
return "Append of 1 byte failed";
// append 2 byte to a 2 byte buffer --> success
if(AppendTest(&UOB, 2, 0))
return "Append to fill buffer failed";
// append 3 bytes to a 2 byte buffer --> failure
if(AppendTest(&UOB, 3, 1))
return "Overflow of buffer not caught";
// append max size_t to a 2 byte buffer --> failure
if(AppendTest(&UOB, SIZE_MAX, 1))
return "Append of SIZE_MAX error not caught";
if(InsertTest(&UOB, 1, 0, 0))
return "Insert 1 byte at start failed";
if(InsertTest(&UOB, 2, 0, 0))
return "Insert 2 bytes at start failed";
if(InsertTest(&UOB, 3, 0, 1))
return "Insert overflow not caught";
if(InsertTest(&UOB, 1, 1, 1))
return "Bad insertion point not caught";
UsefulBuf_MAKE_STACK_UB(outBuf2,10);
UsefulOutBuf_Init(&UOB, outBuf2);
UsefulOutBuf_Reset(&UOB);
// put data in the buffer
UsefulOutBuf_AppendString(&UOB, "abc123");
UsefulOutBuf_InsertString(&UOB, "xyz*&^", 0);
if(!UsefulOutBuf_GetError(&UOB)) {
return "insert with data should have failed";
}
UsefulOutBuf_Init(&UOB, (UsefulBuf){NULL, SIZE_MAX - 5});
UsefulOutBuf_AppendData(&UOB, "123456789", SIZE_MAX -6);
if(UsefulOutBuf_GetError(&UOB)) {
return "insert in huge should have succeeded";
}
UsefulOutBuf_Init(&UOB, (UsefulBuf){NULL, SIZE_MAX - 5});
UsefulOutBuf_AppendData(&UOB, "123456789", SIZE_MAX -5);
if(UsefulOutBuf_GetError(&UOB)) {
return "insert in huge should have succeeded";
}
UsefulOutBuf_Init(&UOB, (UsefulBuf){NULL, SIZE_MAX - 5});
UsefulOutBuf_AppendData(&UOB, "123456789", SIZE_MAX - 4);
if(!UsefulOutBuf_GetError(&UOB)) {
return "lengths near max size";
}
UsefulOutBuf_Init(&UOB, (UsefulBuf){NULL, 100});
if(!UsefulOutBuf_IsBufferNULL(&UOB)) {
return "NULL check failed";
}
return NULL;
}
// Test function to get size and magic number check
const char *TestBasicSanity(void)
{
UsefulBuf_MAKE_STACK_UB(outbuf,10);
UsefulOutBuf UOB;
// First -- make sure that the room left function returns the right amount
UsefulOutBuf_Init(&UOB, outbuf);
if(UsefulOutBuf_RoomLeft(&UOB) != 10)
return "room left failed";
if(!UsefulOutBuf_WillItFit(&UOB, 9)) {
return "it did not fit";
}
if(UsefulOutBuf_WillItFit(&UOB, 11)) {
return "it should have not fit";
}
// Next -- make sure that the magic number checking is working right
UOB.magic = 8888; // make magic bogus
UsefulOutBuf_AppendData(&UOB, (const uint8_t *)"bluster", 7);
if(!UsefulOutBuf_GetError(&UOB)) {
return "magic corruption check failed";
}
// Next make sure that the valid data length check is working right
UsefulOutBuf_Init(&UOB, outbuf);
UOB.data_len = UOB.UB.len+1; // make size bogus
UsefulOutBuf_AppendData(&UOB, (const uint8_t *)"bluster", 7);
if(!UsefulOutBuf_GetError(&UOB))
return "valid data check failed";
return NULL;
}
const char *UBMacroConversionsTest(void)
{
char *szFoo = "foo";
UsefulBufC Foo = UsefulBuf_FromSZ(szFoo);
if(Foo.len != 3 || strncmp(Foo.ptr, szFoo, 3))
return "SZToUsefulBufC failed";
UsefulBufC Too = UsefulBuf_FROM_SZ_LITERAL("Toooo");
if(Too.len != 5 || strncmp(Too.ptr, "Toooo", 5))
return "UsefulBuf_FROM_SZ_LITERAL failed";
uint8_t pB[] = {0x42, 0x6f, 0x6f};
UsefulBufC Boo = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pB);
if(Boo.len != 3 || strncmp(Boo.ptr, "Boo", 3))
return "UsefulBuf_FROM_BYTE_ARRAY_LITERAL failed";
char *String = "string"; // Intentionally not const
UsefulBuf B = (UsefulBuf){(void *)String, strlen(String)};
UsefulBufC BC = UsefulBuf_Const(B);
if(BC.len != strlen(String) || BC.ptr != String)
return "UsefulBufConst failed";
return NULL;
}
const char *UBUtilTests(void)
{
UsefulBuf UB = NULLUsefulBuf;
if(!UsefulBuf_IsNULL(UB)){
return "IsNull failed";
}
if(!UsefulBuf_IsEmpty(UB)){
return "IsEmpty failed";
}
if(!UsefulBuf_IsNULLOrEmpty(UB)) {
return "IsNULLOrEmpty failed";
}
const UsefulBufC UBC = UsefulBuf_Const(UB);
if(!UsefulBuf_IsNULLC(UBC)){
return "IsNull const failed";
}
if(!UsefulBuf_IsEmptyC(UBC)){
return "IsEmptyC failed";
}
if(!UsefulBuf_IsNULLOrEmptyC(UBC)){
return "IsNULLOrEmptyC failed";
}
const UsefulBuf UB2 = UsefulBuf_Unconst(UBC);
if(!UsefulBuf_IsEmpty(UB2)) {
return "Back to UB is Empty failed";
}
UB.ptr = "x"; // just some valid pointer
if(UsefulBuf_IsNULL(UB)){
return "IsNull failed";
}
if(!UsefulBuf_IsEmptyC(UBC)){
return "IsEmpty failed";
}
// test the Unconst.
if(UsefulBuf_Unconst(UBC).ptr != NULL) {
return "Unconst failed";
}
// Set 100 bytes of '+'; validated a few tests later
UsefulBuf_MAKE_STACK_UB(Temp, 100);
const UsefulBufC TempC = UsefulBuf_Set(Temp, '+');
// Try to copy into a buf that is too small and see failure
UsefulBuf_MAKE_STACK_UB(Temp2, 99);
if(!UsefulBuf_IsNULLC(UsefulBuf_Copy(Temp2, TempC))) {
return "Copy should have failed";
}
if(UsefulBuf_IsNULLC(UsefulBuf_CopyPtr(Temp2, "xx", 2))) {
return "CopyPtr failed";
}
UsefulBufC xxyy = UsefulBuf_CopyOffset(Temp2, 2, UsefulBuf_FROM_SZ_LITERAL("yy"));
if(UsefulBuf_IsNULLC(xxyy)) {
return "CopyOffset Failed";
}
if(UsefulBuf_Compare(UsefulBuf_Head(xxyy, 3), UsefulBuf_FROM_SZ_LITERAL("xxy"))) {
return "head failed";
}
if(UsefulBuf_Compare(UsefulBuf_Tail(xxyy, 1), UsefulBuf_FROM_SZ_LITERAL("xyy"))) {
return "tail failed";
}
if(!UsefulBuf_IsNULLC(UsefulBuf_Head(xxyy, 5))) {
return "head should have failed";
}
if(!UsefulBuf_IsNULLC(UsefulBuf_Tail(xxyy, 5))) {
return "tail should have failed";
}
if(!UsefulBuf_IsNULLC(UsefulBuf_Tail(NULLUsefulBufC, 0))) {
return "tail of NULLUsefulBufC is not NULLUsefulBufC";
}
const UsefulBufC TailResult = UsefulBuf_Tail((UsefulBufC){NULL, 100}, 99);
if(TailResult.ptr != NULL || TailResult.len != 1) {
return "tail of NULL and length incorrect";
}
if(!UsefulBuf_IsNULLC(UsefulBuf_CopyOffset(Temp2, 100, UsefulBuf_FROM_SZ_LITERAL("yy")))) {
return "Copy Offset should have failed";
}
// Try to copy into a NULL/empty buf and see failure
const UsefulBuf UBNull = NULLUsefulBuf;
if(!UsefulBuf_IsNULLC(UsefulBuf_Copy(UBNull, TempC))) {
return "Copy to NULL should have failed";
}
// Try to set a NULL/empty buf; nothing should happen
UsefulBuf_Set(UBNull, '+'); // This will crash on failure
// Copy successfully to a buffer
UsefulBuf_MAKE_STACK_UB(Temp3, 101);
if(UsefulBuf_IsNULLC(UsefulBuf_Copy(Temp3, TempC))) {
return "Copy should not have failed";
}
static const uint8_t pExpected[] = {
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
};
UsefulBufC Expected = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pExpected);
// This validates comparison for equality and the UsefulBuf_Set
if(UsefulBuf_Compare(Expected, TempC)) {
return "Set / Copy / Compare failed";
}
// Compare two empties and expect success
if(UsefulBuf_Compare(NULLUsefulBufC, NULLUsefulBufC)){
return "Compare Empties failed";
}
// Compare with empty and expect the first to be larger
if(UsefulBuf_Compare(Expected, NULLUsefulBufC) <= 0){
return "Compare with empty failed";
}
static const uint8_t pExpectedBigger[] = {
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', ',',
};
const UsefulBufC ExpectedBigger = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pExpectedBigger);
// Expect -1 when the first arg is smaller
if(UsefulBuf_Compare(Expected, ExpectedBigger) >= 0){
return "Compare with bigger";
}
static const uint8_t pExpectedSmaller[] = {
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '*',
};
const UsefulBufC ExpectedSmaller = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pExpectedSmaller);
// Expect +1 when the first arg is larger
if(UsefulBuf_Compare(Expected, ExpectedSmaller) <= 0){
return "Compare with smaller";
}
static const uint8_t pExpectedLonger[] = {
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+', '+'
};
const UsefulBufC ExpectedLonger = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pExpectedLonger);
// Expect -1 when the first arg is smaller
if(UsefulBuf_Compare(Expected, ExpectedLonger) >= 0){
return "Compare with longer";
}
static const uint8_t pExpectedShorter[] = {
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+', '+',
'+', '+', '+', '+', '+', '+', '+', '+', '+',
};
const UsefulBufC ExpectedShorter = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pExpectedShorter);
// Expect +1 with the first arg is larger
if(UsefulBuf_Compare(Expected, ExpectedShorter) <= 0){
return "Compare with shorter";
}
if(UsefulBuf_IsNULLC(UsefulBuf_Copy(Temp, NULLUsefulBufC))) {
return "Copy null/empty failed";
}
if(UsefulBuf_IsValue(ExpectedShorter, '+') != SIZE_MAX) {
return "IsValue failed to match all";
}
if(UsefulBuf_IsValue(ExpectedShorter, '-') != 0) {
return "IsValue should have failed right away";
}
if(UsefulBuf_IsValue(NULLUsefulBufC, 0x00) != 0) {
return "IsValue failed on NULLUsefulBufC";
}
if(UsefulBuf_IsValue((UsefulBufC){(uint8_t[]){0x00}, 1}, 0x00) != SIZE_MAX) {
return "IsValue failed finding 0 in one byte of 0";
}
if(UsefulBuf_IsValue((UsefulBufC){(uint8_t[]){0x00}, 1}, 0x01) != 0) {
return "IsValue failed not finding 1 in one byte of 0";
}
if(UsefulBuf_IsValue(ExpectedSmaller, '+') != ExpectedSmaller.len -1) {
return "IsValue failed to find final *";
}
// Look for +++++... in +++++... and find it at the beginning
if(0 != UsefulBuf_FindBytes(ExpectedLonger, ExpectedShorter)){
return "Failed to find";
}
// look for ++* in ....++* and find it at the end
static const uint8_t pToFind[] = {'+', '+', '*'};
const UsefulBufC ToBeFound = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pToFind);
if(97 != UsefulBuf_FindBytes(ExpectedSmaller, ToBeFound)){
return "Failed to find 2";
}
// look for ++* in ....++, and find it near the end
if(SIZE_MAX != UsefulBuf_FindBytes(ExpectedBigger, ToBeFound)){
return "Failed to not find";
}
// Look for the whole buffer in itself and succeed.
if(0 != UsefulBuf_FindBytes(ExpectedLonger, ExpectedLonger)){
return "Failed to find 3";
}
const uint8_t pB[] = {0x01, 0x02, 0x03};
UsefulBufC Boo = UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pB);
// Try to map a pointer before
if(UsefulBuf_PointerToOffset(Boo, pB-1) != SIZE_MAX) {
return "Didn't error on pointer before";
}
// Try to map a pointer after
if(UsefulBuf_PointerToOffset(Boo, pB+sizeof(pB)) != SIZE_MAX) {
return "Didn't error on pointer after";
}
// Try to map a pointer inside
if(UsefulBuf_PointerToOffset(Boo, pB+1) != 1) {
return "Incorrect pointer offset";
}
// Try to map a pointer at the start
if(UsefulBuf_PointerToOffset(Boo, pB) != 0) {
return "Incorrect pointer offset for start";
}
// Try to map a pointer at the end
if(UsefulBuf_PointerToOffset(Boo, pB + sizeof(pB)-1) != 2) {
return "Incorrect pointer offset for end";
}
// Try to map a pointer on a NULL UB
if(UsefulBuf_PointerToOffset(NULLUsefulBufC, pB ) != SIZE_MAX) {
return "Incorrect pointer offset for start";
}
return NULL;
}
const char * UIBTest_IntegerFormat(void)
{
UsefulOutBuf_MakeOnStack(UOB, 100);
const uint32_t u32 = 0x0A0B0C0D; // from https://en.wikipedia.org/wiki/Endianness
const uint64_t u64 = 1984738472938472;
const uint16_t u16 = 40000;
const uint8_t u8 = 9;
#ifndef USEFULBUF_DISABLE_ALL_FLOAT
const float f = (float)314.15;
const double d = 2.1e10;
#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
UsefulOutBuf_AppendUint32(&UOB, u32); // Also tests UsefulOutBuf_InsertUint64 and UsefulOutBuf_GetEndPosition
UsefulOutBuf_AppendUint64(&UOB, u64); // Also tests UsefulOutBuf_InsertUint32
UsefulOutBuf_AppendUint16(&UOB, u16); // Also tests UsefulOutBuf_InsertUint16
UsefulOutBuf_AppendByte(&UOB, u8);
#ifndef USEFULBUF_DISABLE_ALL_FLOAT
UsefulOutBuf_AppendFloat(&UOB, f); // Also tests UsefulOutBuf_InsertFloat
UsefulOutBuf_AppendDouble(&UOB, d); // Also tests UsefulOutBuf_InsertDouble
#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
const UsefulBufC O = UsefulOutBuf_OutUBuf(&UOB);
if(UsefulBuf_IsNULLC(O))
return "Couldn't output integers";
// from https://en.wikipedia.org/wiki/Endianness
const uint8_t pExpectedNetworkOrder[4] = {0x0A, 0x0B, 0x0C, 0x0D};
if(memcmp(O.ptr, pExpectedNetworkOrder, 4)) {
return "not in network order";
}
UsefulInputBuf UIB;
UsefulInputBuf_Init(&UIB, O);
if(UsefulInputBuf_Tell(&UIB) != 0) {
return "UsefulInputBuf_Tell failed";
}
if(UsefulInputBuf_GetUint32(&UIB) != u32) {
return "u32 out then in failed";
}
if(UsefulInputBuf_GetUint64(&UIB) != u64) {
return "u64 out then in failed";
}
if(UsefulInputBuf_GetUint16(&UIB) != u16) {
return "u16 out then in failed";
}
if(UsefulInputBuf_GetByte(&UIB) != u8) {
return "u8 out then in failed";
}
#ifndef USEFULBUF_DISABLE_ALL_FLOAT
if(UsefulInputBuf_GetFloat(&UIB) != f) {
return "float out then in failed";
}
if(UsefulInputBuf_GetDouble(&UIB) != d) {
return "double out then in failed";
}
#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
// Reset and go again for a few more tests
UsefulInputBuf_Init(&UIB, O);
const UsefulBufC Four = UsefulInputBuf_GetUsefulBuf(&UIB, 4);
if(UsefulBuf_IsNULLC(Four)) {
return "Four is NULL";
}
if(UsefulBuf_Compare(Four, UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pExpectedNetworkOrder))) {
return "Four compare failed";
}
#ifndef USEFULBUF_DISABLE_ALL_FLOAT
if(UsefulInputBuf_BytesUnconsumed(&UIB) != 23){
return "Wrong number of unconsumed bytes";
}
if(!UsefulInputBuf_BytesAvailable(&UIB, 23)){
return "Wrong number of bytes available I";
}
if(UsefulInputBuf_BytesAvailable(&UIB, 24)){
return "Wrong number of bytes available II";
}
#else /* USEFULBUF_DISABLE_ALL_FLOAT */
if(UsefulInputBuf_BytesUnconsumed(&UIB) != 11){
return "Wrong number of unconsumed bytes";
}
if(!UsefulInputBuf_BytesAvailable(&UIB, 11)){
return "Wrong number of bytes available I";
}
if(UsefulInputBuf_BytesAvailable(&UIB, 12)){
return "Wrong number of bytes available II";
}
#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
UsefulInputBuf_Seek(&UIB, 0);
if(UsefulInputBuf_GetError(&UIB)) {
return "unexpected error after seek";
}
const uint8_t *pGetBytes = (const uint8_t *)UsefulInputBuf_GetBytes(&UIB, 4);
if(pGetBytes == NULL) {
return "GetBytes returns NULL";
}
if(memcmp(pGetBytes, pExpectedNetworkOrder, 4)) {
return "Got wrong bytes";
}
UsefulInputBuf_Seek(&UIB, 28);
if(!UsefulInputBuf_GetError(&UIB)) {
return "expected error after seek";
}
if(UsefulInputBuf_PointerToOffset(&UIB, O.ptr) != 0) {
return "PointerToOffset not working";
}
return NULL;
}
#ifndef USEFULBUF_DISABLE_ALL_FLOAT
const char *UBUTest_CopyUtil(void)
{
if(UsefulBufUtil_CopyFloatToUint32(65536.0F) != 0x47800000) {
return "CopyFloatToUint32 failed";
}
if(UsefulBufUtil_CopyDoubleToUint64(4e-40F) != 0X37C16C2800000000ULL) {
return "CopyDoubleToUint64 failed";
}
if(UsefulBufUtil_CopyUint64ToDouble(0X37C16C2800000000ULL) != 4e-40F) {
return "CopyUint64ToDouble failed";
}
if(UsefulBufUtil_CopyUint32ToFloat(0x47800000) != 65536.0F) {
return "CopyUint32ToFloat failed";
}
return NULL;
}
#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
const char *UBAdvanceTest(void)
{
#define ADVANCE_TEST_SIZE 10
UsefulOutBuf_MakeOnStack(UOB, ADVANCE_TEST_SIZE);
UsefulBuf Place = UsefulOutBuf_GetOutPlace(&UOB);
if(Place.len != 10) {
return "GetOutPlace wrong size";
}
memset(Place.ptr, 'x', Place.len/2);
UsefulOutBuf_Advance(&UOB, Place.len/2);
UsefulOutBuf_AppendByte(&UOB, 'y');
Place = UsefulOutBuf_GetOutPlace(&UOB);
if(Place.len != ADVANCE_TEST_SIZE/2 -1 ) {
return "GetOutPlace wrong size 2";
}
memset(Place.ptr, 'z', Place.len);
UsefulOutBuf_Advance(&UOB, Place.len);
UsefulBufC O = UsefulOutBuf_OutUBuf(&UOB);
UsefulBuf_Compare(O, UsefulBuf_FROM_SZ_LITERAL("xxxxxyzzzz"));
Place = UsefulOutBuf_GetOutPlace(&UOB);
if(Place.len != 0 || Place.ptr != NULL) {
return "GetOutPlace not null";
}
if(UsefulOutBuf_GetError(&UOB)) {
return "GetOutPlace error set";
}
UsefulOutBuf_Advance(&UOB, 1);
if(!UsefulOutBuf_GetError(&UOB)) {
return "Advance off end didn't set error";
}
return NULL;
}

55
3rdparty/exported/QCBOR/test/UsefulBuf_Tests.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,55 @@
/*==============================================================================
Copyright (c) 2016-2018, The Linux Foundation.
Copyright (c) 2018, Laurence Lundblade.
Copyright (c) 2021, Arm Limited.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors, nor the name "Laurence Lundblade" may be used to
endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
==============================================================================*/
#ifndef UsefulBuf_UsefulBuf_Tests_h
#define UsefulBuf_UsefulBuf_Tests_h
const char * UOBTest_NonAdversarial(void);
const char * TestBasicSanity(void);
const char * UOBTest_BoundaryConditionsTest(void);
const char * UBMacroConversionsTest(void);
const char * UBUtilTests(void);
const char * UIBTest_IntegerFormat(void);
#ifndef USEFULBUF_DISABLE_ALL_FLOAT
const char * UBUTest_CopyUtil(void);
#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
const char * UBAdvanceTest(void);
#endif

1091
3rdparty/exported/QCBOR/test/float_tests.c поставляемый Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

40
3rdparty/exported/QCBOR/test/float_tests.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,40 @@
/*==============================================================================
float_tests.h -- tests for float and conversion to/from half-precision
Copyright (c) 2018-2020, Laurence Lundblade. All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
See BSD-3-Clause license in README.md
Created on 9/19/18
=============================================================================*/
#ifndef float_tests_h
#define float_tests_h
#include <stdint.h>
#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
int32_t HalfPrecisionDecodeBasicTests(void);
int32_t DoubleAsSmallestTest(void);
int32_t HalfPrecisionAgainstRFCCodeTest(void);
#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
/*
This calls each and every method for encoding
floating-point numbers.
*/
int32_t GeneralFloatEncodeTests(void);
/*
Tests basic float decoding.
*/
int32_t GeneralFloatDecodeTests(void);
#endif /* float_tests_h */

49
3rdparty/exported/QCBOR/test/half_to_double_from_rfc7049.c поставляемый Normal file
Просмотреть файл

@ -0,0 +1,49 @@
/*
Copyright (c) 2013 IETF Trust and the persons identified as the
document authors. All rights reserved.
Copyright (c) 2021, Arm Limited. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal
Provisions Relating to IETF Documents
(http://trustee.ietf.org/license-info) in effect on the date of
publication of this document. Please review these documents
carefully, as they describe your rights and restrictions with respect
to this document. Code Components extracted from this document must
include Simplified BSD License text as described in Section 4.e of
the Trust Legal Provisions and are provided without warranty as
described in the Simplified BSD License.
*/
/*
This code is from RFC 7049/8949. It is not used in the main implementation
because:
a) it adds a dependency on <math.h> and ldexp().
b) the license may be an issue
QCBOR does support half-precision, but rather than using
floating-point math like this, it does it with bit shifting
and masking.
This code is here to test that code.
*/
#include "half_to_double_from_rfc7049.h"
#include <math.h>
#ifndef USEFULBUF_DISABLE_ALL_FLOAT
double decode_half(unsigned char *halfp) {
int half = (halfp[0] << 8) + halfp[1];
int exp = (half >> 10) & 0x1f;
int mant = half & 0x3ff;
double val;
if (exp == 0) val = ldexp(mant, -24);
else if (exp != 31) val = ldexp(mant + 1024, exp - 25);
else val = mant == 0 ? INFINITY : NAN;
return half & 0x8000 ? -val : val;
}
#endif /* USEFULBUF_DISABLE_ALL_FLOAT */

21
3rdparty/exported/QCBOR/test/half_to_double_from_rfc7049.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,21 @@
/*==============================================================================
half_to_double_from_rfc7049.h -- interface to IETF float conversion code.
Copyright (c) 2018-2020, Laurence Lundblade. All rights reserved.
Copyright (c) 2021, Arm Limited. All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
See BSD-3-Clause license in README.md
Created on 9/23/18
============================================================================*/
#ifndef half_to_double_from_rfc7049_h
#define half_to_double_from_rfc7049_h
#ifndef USEFULBUF_DISABLE_ALL_FLOAT
double decode_half(unsigned char *halfp);
#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
#endif /* half_to_double_from_rfc7049_h */

334
3rdparty/exported/QCBOR/test/not_well_formed_cbor.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,334 @@
/*==============================================================================
not_well_formed_cbor.h -- vectors to test for handling of not-well-formed CBOR
This is part of QCBOR -- https://github.com/laurencelundblade/QCBOR
Copyright (c) 2019, Laurence Lundblade. All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
See BSD-3-Clause license in README.md
Created on 7/27/19
==============================================================================*/
#ifndef not_well_formed_cbor_h
#define not_well_formed_cbor_h
#include <stdint.h> // for size_t and uint8_t
struct someBinaryBytes {
const uint8_t *p; // Pointer to the bytes
size_t n; // Length of the bytes
};
static const struct someBinaryBytes paNotWellFormedCBOR[] = {
#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
// Indefinite length strings must be closed off
// An indefinite length byte string not closed off
{(uint8_t[]){0x5f, 0x41, 0x00}, 3},
// An indefinite length text string not closed off
{(uint8_t[]){0x7f, 0x61, 0x00}, 3},
// All the chunks in an indefinite length string must be of the
// type of indefinite length string and indefinite
// indefinite length byte string with text string chunk
{(uint8_t[]){0x5f, 0x61, 0x00, 0xff}, 4},
// indefinite length text string with a byte string chunk
{(uint8_t[]){0x7f, 0x41, 0x00, 0xff}, 4},
// indefinite length byte string with an positive integer chunk
{(uint8_t[]){0x5f, 0x00, 0xff}, 3},
// indefinite length byte string with an negative integer chunk
{(uint8_t[]){0x5f, 0x21, 0xff}, 3},
// indefinite length byte string with an array chunk
{(uint8_t[]){0x5f, 0x80, 0xff}, 3},
// indefinite length byte string with an map chunk
{(uint8_t[]){0x5f, 0xa0, 0xff}, 3},
// indefinite length byte string with tagged integer chunk
{(uint8_t[]){0x5f, 0xc0, 0x00, 0xff}, 4},
// indefinite length byte string with an simple type chunk
{(uint8_t[]){0x5f, 0xe0, 0xff}, 3},
// indefinite length byte string with indefinite string inside
{(uint8_t[]){0x5f, 0x5f, 0x41, 0x00, 0xff, 0xff}, 6},
// indefinite length text string with indefinite string inside
{(uint8_t[]){0x7f, 0x7f, 0x61, 0x00, 0xff, 0xff}, 6},
#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
// Definte length maps and arrays must be closed by having the
// right number of items
// A definte length array that is supposed to have 1 item, but has none
{(uint8_t[]){0x81}, 1},
// A definte length array that is supposed to have 2 items, but has only 1
{(uint8_t[]){0x82, 0x00}, 2},
// A definte length array that is supposed to have 511 items, but has only 1
{(uint8_t[]){0x9a, 0x01, 0xff, 0x00}, 4},
// A definte length map that is supposed to have 1 item, but has none
{(uint8_t[]){0xa1}, 1},
// A definte length map that is supposed to have s item, but has only 1
{(uint8_t[]){0xa2, 0x01, 0x02}, 3},
#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
// Indefinte length maps and arrays must be ended by a break
// Indefinite length array with zero items and no break
{(uint8_t[]){0x9f}, 1},
// Indefinite length array with two items and no break
{(uint8_t[]){0x9f, 0x01, 0x02}, 3},
// Indefinite length map with zero items and no break
{(uint8_t[]){0xbf}, 1},
// Indefinite length map with two items and no break
{(uint8_t[]){0xbf, 0x01, 0x02, 0x01, 0x02}, 5},
// Some extra test vectors for unclosed arrays and maps
// Unclosed indefinite array containing a close definite array
{(uint8_t[]){0x9f, 0x80, 0x00}, 3},
// Definite length array containing an unclosed indefinite array
{(uint8_t[]){0x81, 0x9f}, 2},
// Deeply nested definite length arrays with deepest one unclosed
{(uint8_t[]){0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81}, 9},
// Deeply nested indefinite length arrays with deepest one unclosed
{(uint8_t[]){0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0xff, 0xff, 0xff, 0xff}, 9},
// Mixed nesting with indefinite unclosed
{(uint8_t[]){0x9f, 0x81, 0x9f, 0x81, 0x9f, 0x9f, 0xff, 0xff, 0xff}, 9},
// Mixed nesting with definite unclosed
{(uint8_t[]){0x9f, 0x82, 0x9f, 0x81, 0x9f, 0x9f, 0xff, 0xff, 0xff, 0xff}, 10},
#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
// The "argument" for the data item is missing bytes
// Positive integer missing 1 byte argument
{(uint8_t[]){0x18}, 1},
// Positive integer missing 2 byte argument
{(uint8_t[]){0x19}, 1},
// Positive integer missing 4 byte argument
{(uint8_t[]){0x1a}, 1},
// Positive integer missing 8 byte argument
{(uint8_t[]){0x1b}, 1},
// Positive integer missing 1 byte of 2 byte argument
{(uint8_t[]){0x19, 0x01}, 2},
// Positive integer missing 2 bytes of 4 byte argument
{(uint8_t[]){0x1a, 0x01, 0x02}, 3},
// Positive integer missing 1 bytes of 7 byte argument
{(uint8_t[]){0x1b, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}, 8},
// Negative integer missing 1 byte argument
{(uint8_t[]){0x38}, 1},
// Binary string missing 1 byte argument
{(uint8_t[]){0x58}, 1},
// Text string missing 1 byte argument
{(uint8_t[]){0x78}, 1},
// Array missing 1 byte argument
{(uint8_t[]){0x98}, 1},
// Map missing 1 byte argument
{(uint8_t[]){0xb8}, 1},
// Tag missing 1 byte argument
{(uint8_t[]){0xd8}, 1},
// Simple missing 1 byte argument
{(uint8_t[]){0xf8}, 1},
// Half-precision missing 1 byte
{(uint8_t[]){0xf9, 0x00}, 2},
// Float missing 2 bytes
{(uint8_t[]){0xfa, 0x00, 0x00}, 3},
// Double missing 5 bytes
{(uint8_t[]){0xfb, 0x00, 0x00, 0x00}, 4},
// Breaks must not occur in definite length arrays and maps
// Array of length 1 with sole member replaced by a break
{(uint8_t[]){0x81, 0xff}, 2},
// Array of length 2 with 2nd member replaced by a break
{(uint8_t[]){0x82, 0x00, 0xff}, 3},
// Map of length 1 with sole member label replaced by a break
{(uint8_t[]){0xa1, 0xff}, 2},
// Map of length 1 with sole member label replaced by break
// Alternate representation that some decoders handle difference
{(uint8_t[]){0xa1, 0xff, 0x00}, 3},
// Array of length 1 with 2nd member value replaced by a break
{(uint8_t[]){0xa1, 0x00, 0xff}, 3},
// Map of length 2 with 2nd member replaced by a break
{(uint8_t[]){0xa2, 0x00, 0x00, 0xff}, 4},
// Breaks must not occur on their own out of an indefinite length
// data item
// A bare break is not well formed
{(uint8_t[]){0xff}, 1},
// A bare break after a zero length definite length array
{(uint8_t[]){0x80, 0xff}, 2},
#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
// A bare break after a zero length indefinite length map
{(uint8_t[]){0x9f, 0xff, 0xff}, 3},
#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
// Forbidden two-byte encodings of simple types
// Must use 0xe0 instead
{(uint8_t[]){0xf8, 0x00}, 2},
// Should use 0xe1 instead
{(uint8_t[]){0xf8, 0x01}, 2},
// Should use 0xe2 instead
{(uint8_t[]){0xf8, 0x02}, 2},
// Should use 0xe3 instead
{(uint8_t[]){0xf8, 0x03}, 2},
// Should use 0xe4 instead
{(uint8_t[]){0xf8, 0x04}, 2},
// Should use 0xe5 instead
{(uint8_t[]){0xf8, 0x05}, 2},
// Should use 0xe6 instead
{(uint8_t[]){0xf8, 0x06}, 2},
// Should use 0xe7 instead
{(uint8_t[]){0xf8, 0x07}, 2},
// Should use 0xe8 instead
{(uint8_t[]){0xf8, 0x08}, 2},
// Should use 0xe9 instead
{(uint8_t[]){0xf8, 0x09}, 2},
// Should use 0xea instead
{(uint8_t[]){0xf8, 0x0a}, 2},
// Should use 0xeb instead
{(uint8_t[]){0xf8, 0x0b}, 2},
// Should use 0xec instead
{(uint8_t[]){0xf8, 0x0c}, 2},
// Should use 0xed instead
{(uint8_t[]){0xf8, 0x0d}, 2},
// Should use 0xee instead
{(uint8_t[]){0xf8, 0x0e}, 2},
// Should use 0xef instead
{(uint8_t[]){0xf8, 0x0f}, 2},
// Should use 0xf0 instead
{(uint8_t[]){0xf8, 0x10}, 2},
// Should use 0xf1 instead
{(uint8_t[]){0xf8, 0x11}, 2},
// Should use 0xf2 instead
{(uint8_t[]){0xf8, 0x12}, 2},
// Must use 0xf3 instead
{(uint8_t[]){0xf8, 0x13}, 2},
// Must use 0xf4 instead
{(uint8_t[]){0xf8, 0x14}, 2},
// Must use 0xf5 instead
{(uint8_t[]){0xf8, 0x15}, 2},
// Must use 0xf6 instead
{(uint8_t[]){0xf8, 0x16}, 2},
// Must use 0xf7 instead
{(uint8_t[]){0xf8, 0x17}, 2},
// Reserved (as defined in RFC 8126), considered not-well-formed
{(uint8_t[]){0xf8, 0x18}, 2},
// Reserved (as defined in RFC 8126), considered not-well-formed
{(uint8_t[]){0xf8, 0x19}, 2},
// Reserved (as defined in RFC 8126), considered not-well-formed
{(uint8_t[]){0xf8, 0x1a}, 2},
// Reserved (as defined in RFC 8126), considered not-well-formed
{(uint8_t[]){0xf8, 0x1b}, 2},
// Reserved (as defined in RFC 8126), considered not-well-formed
{(uint8_t[]){0xf8, 0x1c}, 2},
// Reserved (as defined in RFC 8126), considered not-well-formed
{(uint8_t[]){0xf8, 0x1d}, 2},
// Reserved (as defined in RFC 8126), considered not-well-formed
{(uint8_t[]){0xf8, 0x1e}, 2},
// Reserved (as defined in RFC 8126), considered not-well-formed
{(uint8_t[]){0xf8, 0x1f}, 2},
// Integers with "argument" equal to an indefinite length
// Positive integer with "argument" an indefinite length
{(uint8_t[]){0x1f}, 1},
// Negative integer with "argument" an indefinite length
{(uint8_t[]){0x3f}, 1},
// CBOR tag with "argument" an indefinite length
{(uint8_t[]){0xdf, 0x00}, 2},
// CBOR tag with "argument" an indefinite length alternate vector
{(uint8_t[]){0xdf}, 1},
// Missing content bytes from a definite length string
// A byte string is of length 1 without the 1 byte
{(uint8_t[]){0x41}, 1},
// A text string is of length 1 without the 1 byte
{(uint8_t[]){0x61}, 1},
// Byte string should have 65520 bytes, but has one
{(uint8_t[]){0x59, 0xff, 0xf0, 0x00}, 6},
// Byte string should have 65520 bytes, but has one
{(uint8_t[]){0x79, 0xff, 0xf0, 0x00}, 6},
// Use of unassigned additional information values
// Major type positive integer with reserved value 28
{(uint8_t[]){0x1c}, 1},
// Major type positive integer with reserved value 29
{(uint8_t[]){0x1d}, 1},
// Major type positive integer with reserved value 30
{(uint8_t[]){0x1e}, 1},
// Major type negative integer with reserved value 28
{(uint8_t[]){0x3c}, 1},
// Major type negative integer with reserved value 29
{(uint8_t[]){0x3d}, 1},
// Major type negative integer with reserved value 30
{(uint8_t[]){0x3e}, 1},
// Major type byte string with reserved value 28 length
{(uint8_t[]){0x5c}, 1},
// Major type byte string with reserved value 29 length
{(uint8_t[]){0x5d}, 1},
// Major type byte string with reserved value 30 length
{(uint8_t[]){0x5e}, 1},
// Major type text string with reserved value 28 length
{(uint8_t[]){0x7c}, 1},
// Major type text string with reserved value 29 length
{(uint8_t[]){0x7d}, 1},
// Major type text string with reserved value 30 length
{(uint8_t[]){0x7e}, 1},
// Major type array with reserved value 28 length
{(uint8_t[]){0x9c}, 1},
// Major type array with reserved value 29 length
{(uint8_t[]){0x9d}, 1},
// Major type array with reserved value 30 length
{(uint8_t[]){0x9e}, 1},
// Major type map with reserved value 28 length
{(uint8_t[]){0xbc}, 1},
// Major type map with reserved value 29 length
{(uint8_t[]){0xbd}, 1},
// Major type map with reserved value 30 length
{(uint8_t[]){0xbe}, 1},
// Major type tag with reserved value 28 length
{(uint8_t[]){0xdc}, 1},
// Major type tag with reserved value 29 length
{(uint8_t[]){0xdd}, 1},
// Major type tag with reserved value 30 length
{(uint8_t[]){0xde}, 1},
// Major type simple with reserved value 28 length
{(uint8_t[]){0xfc}, 1},
// Major type simple with reserved value 29 length
{(uint8_t[]){0xfd}, 1},
// Major type simple with reserved value 30 length
{(uint8_t[]){0xfe}, 1},
// Maps must have an even number of data items (key & value)
// Map with 1 item when it should have 2
{(uint8_t[]){0xa1, 0x00}, 2},
// Map with 3 item when it should have 4
{(uint8_t[]){0xa2, 0x00, 0x00, 0x00}, 2},
#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
// Map with 1 item when it should have 2
{(uint8_t[]){0xbf, 0x00, 0xff}, 3},
// Map with 3 item when it should have 4
{(uint8_t[]){0xbf, 0x00, 0x00, 0x00, 0xff}, 5},
#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
};
#endif /* not_well_formed_cbor_h */

7985
3rdparty/exported/QCBOR/test/qcbor_decode_tests.c поставляемый Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

321
3rdparty/exported/QCBOR/test/qcbor_decode_tests.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,321 @@
/*==============================================================================
Copyright (c) 2016-2018, The Linux Foundation.
Copyright (c) 2018-2021, Laurence Lundblade.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors, nor the name "Laurence Lundblade" may be used to
endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
============================================================================*/
#ifndef __QCBOR__qcbort_decode_tests__
#define __QCBOR__qcbort_decode_tests__
#include <stdint.h>
/*
Notes:
- All the functions in qcbor_decode.h are called once in the aggregation
of all the tests below.
- All the types that are supported are given as input and parsed by these tests
- There is some hostile input such as invalid lengths and CBOR too complex
and types this parser doesn't handle
*/
/*
Parse a well-known set of integers including those around the boundaries and
make sure the expected values come out
*/
int32_t IntegerValuesParseTest(void);
/*
Decode a simple CBOR encoded array and make sure it returns all the correct values.
This is a decode test.
*/
int32_t SimpleArrayTest(void);
/*
Tests with empty maps and arrays
*/
int32_t EmptyMapsAndArraysTest(void);
/*
Make sure a maximally deep array can be parsed and that the
reported nesting level is correct. This uses test vector
of CBOR encoded data with a depth of 10. This a parse test.
*/
int32_t ParseDeepArrayTest(void);
/*
See that the correct error is reported when parsing
an array of depth 11, one too large.
*/
int32_t ParseTooDeepArrayTest(void);
/*
Try to parse some legit CBOR types that this parsers
doesn't support.
*/
int32_t UnsupportedCBORDecodeTest(void);
/*
This takes the encoded CBOR integers used in the above test and parses
it over and over with one more byte less each time. It should fail
every time on incorrect CBOR input. This is a hostile input decode test.
*/
int32_t ShortBufferParseTest(void);
/*
Same as ShortBufferParseTest, but with a different encoded CBOR input.
It is another hostile input test
*/
int32_t ShortBufferParseTest2(void);
/*
Parses the somewhat complicated CBOR MAP and makes sure all the correct
values parse out. About 15 values are tested. This is a decode test.
*/
int32_t ParseMapTest(void);
/*
Parses a map that contains a zero-length map as value.
*/
int32_t ParseEmptyMapInMapTest(void);
/*
Test the decoder mode where maps are treated as arrays.
*/
int32_t ParseMapAsArrayTest(void);
/*
Test parsing of some simple values like true, false, null...
*/
int32_t ParseSimpleTest(void);
/*
This tests all the not-well-formed CBOR from the CBOR RFC.
(This is the CBORbis RFC which is not yet published at the
time this test was added).
*/
int32_t NotWellFormedTests(void);
/*
Tests a number of failure cases on bad CBOR to get the right error code
*/
int32_t DecodeFailureTests(void);
/*
Parses all possible inputs that are two bytes long. Main point
is that the test doesn't crash as it doesn't evaluate the
input for correctness in any way.
(Parsing all possible 3 byte strings takes too long on all but
very fast machines).
*/
int32_t ComprehensiveInputTest(void);
/*
Parses all possible inputs that are four bytes long. Main point
is that the test doesn't crash as it doesn't evaluate the
input for correctness in any way. This runs very slow, so it
is only practical as a once-in-a-while regression test on
fast machines.
*/
int32_t BigComprehensiveInputTest(void);
/*
Test the date types -- epoch and strings
*/
int32_t DateParseTest(void);
/*
Test spiffy date decoding functions
*/
int32_t SpiffyDateDecodeTest(void);
/*
Test decode of CBOR tagging like the CBOR magic number and many others.
*/
int32_t OptTagParseTest(void);
/*
Parse some big numbers, positive and negative
*/
int32_t BignumParseTest(void);
/*
Test of mode where only string labels are allowed
*/
int32_t StringDecoderModeFailTest(void);
/*
Parse some nested maps
*/
int32_t NestedMapTest(void);
/*
Parse maps with indefinite lengths
*/
int32_t NestedMapTestIndefLen(void);
/*
Parse some maps and arrays with indefinite lengths.
Includes some error cases.
*/
int32_t IndefiniteLengthArrayMapTest(void);
/*
Parse indefinite length strings. Uses
MemPool. Includes error cases.
*/
int32_t IndefiniteLengthStringTest(void);
/*
Test deep nesting of indefinite length
maps and arrays including too deep.
*/
int32_t IndefiniteLengthNestTest(void);
/*
Test parsing strings were all strings, not
just indefinite length strings, are
allocated. Includes error test cases.
*/
int32_t AllocAllStringsTest(void);
/*
Direct test of MemPool string allocator
*/
int32_t MemPoolTest(void);
/*
Test the setting up of an external string allocator.
*/
int32_t SetUpAllocatorTest(void);
#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
/*
Test decoding of decimal fractions and big floats, both of which are
made up of an exponent and mantissa.
*/
int32_t ExponentAndMantissaDecodeTests(void);
/*
Hostile input tests for decimal fractions and big floats.
*/
int32_t ExponentAndMantissaDecodeFailTests(void);
#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
int32_t EnterMapTest(void);
int32_t IntegerConvertTest(void);
/*
Tests decoding of CBOR Sequences defined in RFC 8742
*/
int32_t CBORSequenceDecodeTests(void);
/*
Tests for functions to safely convert integer types.
*/
int32_t IntToTests(void);
/*
Test the decoding of bstr-wrapped CBOR.
*/
int32_t EnterBstrTest(void);
/*
Test decoding of tagged types like UUID
*/
int32_t DecodeTaggedTypeTests(void);
/*
Test the detection of input that is too large. Requires
a special build that makes QCBOR_MAX_DECODE_INPUT_SIZE small.
*/
int32_t TooLargeInputTest(void);
/*
Test spiffy decoding of indefinite length strings.
*/
int32_t SpiffyIndefiniteLengthStringsTests(void);
/*
Test PeekNext().
*/
int32_t PeekAndRewindTest(void);
/*
Test decoding of booleans
*/
int32_t BoolTest(void);
/*
Test GitHub issue #134: decode an indefinite-length string with a zero-length first chunk.
*/
int32_t CBORTestIssue134(void);
#endif /* defined(__QCBOR__qcbort_decode_tests__) */

3077
3rdparty/exported/QCBOR/test/qcbor_encode_tests.c поставляемый Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

196
3rdparty/exported/QCBOR/test/qcbor_encode_tests.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,196 @@
/*==============================================================================
Copyright (c) 2016-2018, The Linux Foundation.
Copyright (c) 2018-2022, Laurence Lundblade.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of The Linux Foundation nor the names of its
contributors, nor the name "Laurence Lundblade" may be used to
endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#ifndef __QCBOR__qcbor_encode_tests__
#define __QCBOR__qcbor_encode_tests__
#include <stdint.h>
/*
Notes:
- All the functions in qcbor_encode.h are called once in the aggregation of all
the tests below.
*/
/*
Most basic test.
*/
int32_t BasicEncodeTest(void);
/*
Encode lots of integer values, particularly around the boundary and
make sure they Match the expected binary output. Primarily an
encoding test.
*/
int32_t IntegerValuesTest1(void);
/*
Create nested arrays to the max depth allowed and make sure it
succeeds. This is an encoding test.
*/
int32_t ArrayNestingTest1(void);
/*
Create nested arrays to one more than the meax depth and make sure it
fails. This is an encoding test.
*/
int32_t ArrayNestingTest2(void);
/*
Encoding test. Create arrays to max depth and close one extra time
and look for correct error code
*/
int32_t ArrayNestingTest3(void);
/*
This tests the QCBOREncode_AddRaw() function by adding two chunks or
RAWCBOR to an array and comparing with expected values. This is an
encoding test.
*/
int32_t EncodeRawTest(void);
/*
This creates a somewhat complicated CBOR MAP and verifies it against
expected data. This is an encoding test.
*/
int32_t MapEncodeTest(void);
/*
Encodes a goodly number of floats and doubles and checks encoding is right
*/
int32_t FloatValuesTest1(void);
/*
Encodes true, false and the like
*/
int32_t SimpleValuesTest1(void);
/*
Encodes basic maps and arrays with indefinite length
*/
int32_t SimpleValuesIndefiniteLengthTest1(void);
/*
Indefinite length arrays and maps use the 'magic' number 31, verify
that everything with length 31 still works properly
*/
int32_t EncodeLengthThirtyoneTest(void);
/*
* Tests Encoding most data formats that are supported.
*/
int32_t EncodeDateTest(void);
/*
Encodes particular data structure that a particular app will need...
*/
int32_t RTICResultsTest(void);
/*
Calls all public encode methods in qcbor_encode.h once.
*/
int32_t AllAddMethodsTest(void);
/*
The binary string wrapping of maps and arrays used by COSE
*/
int32_t BstrWrapTest(void);
/*
Test error cases for bstr wrapping encoding such as closing an open
array with CloseBstrWrap
*/
int32_t BstrWrapErrorTest(void);
/*
Test complicated nested bstr wrapping
*/
int32_t BstrWrapNestTest(void);
/*
Test encoding a COSE_Sign1 with bstr wrapping
*/
int32_t CoseSign1TBSTest(void);
#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
/*
Test encoding of decimal fractions and big floats, both of which are
made up of an exponent and mantissa
*/
int32_t ExponentAndMantissaEncodeTests(void);
#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
/*
Test the error cases when encoding CBOR such as buffer too large,
buffer too small, array nesting too deep. Aims to cover the error
codes returned when encoding CBOR
*/
int32_t EncodeErrorTests(void);
/*
Test QCBOREncode_EncodeHead(). This is a minimal test because every other
test here exercises it in some way.
*/
int32_t QCBORHeadTest(void);
/* Fully test QCBOREncode_OpenBytes(), QCBOREncode_CloseBytes()
* and friends.
*/
int32_t OpenCloseBytesTest(void);
#endif /* defined(__QCBOR__qcbor_encode_tests__) */

348
3rdparty/exported/QCBOR/test/run_tests.c поставляемый Normal file
Просмотреть файл

@ -0,0 +1,348 @@
/*==============================================================================
run_tests.c -- test aggregator and results reporting
Copyright (c) 2018-2021, Laurence Lundblade. All rights reserved.
Copyright (c) 2021, Arm Limited. All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
See BSD-3-Clause license in README.md
Created on 9/30/18
=============================================================================*/
#include "run_tests.h"
#include "UsefulBuf.h"
#include <stdbool.h>
#include "float_tests.h"
#include "qcbor_decode_tests.h"
#include "qcbor_encode_tests.h"
#include "UsefulBuf_Tests.h"
// For size printing and some conditionals
#include "qcbor/qcbor_encode.h"
#include "qcbor/qcbor_decode.h"
#include "qcbor/qcbor_spiffy_decode.h"
/*
Test configuration
*/
typedef int32_t (test_fun_t)(void);
typedef const char * (test_fun2_t)(void);
#define TEST_ENTRY(test_name) {#test_name, test_name, true}
#define TEST_ENTRY_DISABLED(test_name) {#test_name, test_name, false}
typedef struct {
const char *szTestName;
test_fun_t *test_fun;
bool bEnabled;
} test_entry;
typedef struct {
const char *szTestName;
test_fun2_t *test_fun;
bool bEnabled;
} test_entry2;
static test_entry2 s_tests2[] = {
#ifndef USEFULBUF_DISABLE_ALL_FLOAT
TEST_ENTRY(UBUTest_CopyUtil),
#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
TEST_ENTRY(UOBTest_NonAdversarial),
TEST_ENTRY(TestBasicSanity),
TEST_ENTRY(UOBTest_BoundaryConditionsTest),
TEST_ENTRY(UBMacroConversionsTest),
TEST_ENTRY(UBUtilTests),
TEST_ENTRY(UIBTest_IntegerFormat),
TEST_ENTRY(UBAdvanceTest)
};
static test_entry s_tests[] = {
TEST_ENTRY(OpenCloseBytesTest),
TEST_ENTRY(EnterBstrTest),
TEST_ENTRY(IntegerConvertTest),
TEST_ENTRY(EnterMapTest),
TEST_ENTRY(QCBORHeadTest),
TEST_ENTRY(EmptyMapsAndArraysTest),
TEST_ENTRY(NotWellFormedTests),
TEST_ENTRY(ParseMapAsArrayTest),
#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
TEST_ENTRY(IndefiniteLengthNestTest),
TEST_ENTRY(IndefiniteLengthArrayMapTest),
TEST_ENTRY(NestedMapTestIndefLen),
#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
TEST_ENTRY(ParseSimpleTest),
TEST_ENTRY(DecodeFailureTests),
TEST_ENTRY(EncodeRawTest),
TEST_ENTRY(RTICResultsTest),
TEST_ENTRY(MapEncodeTest),
TEST_ENTRY(ArrayNestingTest1),
TEST_ENTRY(ArrayNestingTest2),
#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
TEST_ENTRY(ArrayNestingTest3),
#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
TEST_ENTRY(EncodeDateTest),
TEST_ENTRY(SimpleValuesTest1),
TEST_ENTRY(IntegerValuesTest1),
TEST_ENTRY(AllAddMethodsTest),
TEST_ENTRY(ParseTooDeepArrayTest),
TEST_ENTRY(ComprehensiveInputTest),
TEST_ENTRY(ParseMapTest),
TEST_ENTRY(BasicEncodeTest),
TEST_ENTRY(NestedMapTest),
TEST_ENTRY(BignumParseTest),
TEST_ENTRY(OptTagParseTest),
TEST_ENTRY(DateParseTest),
TEST_ENTRY(SpiffyDateDecodeTest),
TEST_ENTRY(ShortBufferParseTest2),
TEST_ENTRY(ShortBufferParseTest),
TEST_ENTRY(ParseDeepArrayTest),
TEST_ENTRY(SimpleArrayTest),
TEST_ENTRY(IntegerValuesParseTest),
#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
TEST_ENTRY(AllocAllStringsTest),
TEST_ENTRY(MemPoolTest),
TEST_ENTRY(IndefiniteLengthStringTest),
TEST_ENTRY(SpiffyIndefiniteLengthStringsTests),
TEST_ENTRY(SetUpAllocatorTest),
TEST_ENTRY(CBORTestIssue134),
#endif /* #ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
TEST_ENTRY(HalfPrecisionDecodeBasicTests),
TEST_ENTRY(DoubleAsSmallestTest),
TEST_ENTRY(HalfPrecisionAgainstRFCCodeTest),
#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
#ifndef USEFULBUF_DISABLE_ALL_FLOAT
TEST_ENTRY(GeneralFloatEncodeTests),
TEST_ENTRY(GeneralFloatDecodeTests),
#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
TEST_ENTRY(BstrWrapTest),
TEST_ENTRY(BstrWrapErrorTest),
TEST_ENTRY(BstrWrapNestTest),
TEST_ENTRY(CoseSign1TBSTest),
TEST_ENTRY(StringDecoderModeFailTest),
TEST_ENTRY_DISABLED(BigComprehensiveInputTest),
TEST_ENTRY_DISABLED(TooLargeInputTest),
TEST_ENTRY(EncodeErrorTests),
TEST_ENTRY(SimpleValuesIndefiniteLengthTest1),
TEST_ENTRY(EncodeLengthThirtyoneTest),
TEST_ENTRY(CBORSequenceDecodeTests),
TEST_ENTRY(IntToTests),
TEST_ENTRY(DecodeTaggedTypeTests),
TEST_ENTRY(PeekAndRewindTest),
#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
TEST_ENTRY(EncodeLengthThirtyoneTest),
TEST_ENTRY(ExponentAndMantissaDecodeTests),
TEST_ENTRY(ExponentAndMantissaDecodeFailTests),
TEST_ENTRY(ExponentAndMantissaEncodeTests),
#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
TEST_ENTRY(ParseEmptyMapInMapTest),
TEST_ENTRY(BoolTest)
};
/*
Convert a number up to 999999999 to a string. This is so sprintf doesn't
have to be linked in so as to minimized dependencies even in test code.
StringMem should be 12 bytes long, 9 for digits, 1 for minus and
1 for \0 termination.
*/
static const char *NumToString(int32_t nNum, UsefulBuf StringMem)
{
const int32_t nMax = 1000000000;
UsefulOutBuf OutBuf;
UsefulOutBuf_Init(&OutBuf, StringMem);
if(nNum < 0) {
UsefulOutBuf_AppendByte(&OutBuf, '-');
nNum = -nNum;
}
if(nNum > nMax-1) {
return "XXX";
}
bool bDidSomeOutput = false;
for(int32_t n = nMax; n > 0; n/=10) {
int nDigitValue = nNum/n;
if(nDigitValue || bDidSomeOutput){
bDidSomeOutput = true;
UsefulOutBuf_AppendByte(&OutBuf, (uint8_t)('0' + nDigitValue));
nNum -= nDigitValue * n;
}
}
if(!bDidSomeOutput){
UsefulOutBuf_AppendByte(&OutBuf, '0');
}
UsefulOutBuf_AppendByte(&OutBuf, '\0');
return UsefulOutBuf_GetError(&OutBuf) ? "" : StringMem.ptr;
}
/*
Public function. See run_test.h.
*/
int RunTestsQCBOR(const char *szTestNames[],
OutputStringCB pfOutput,
void *poutCtx,
int *pNumTestsRun)
{
int nTestsFailed = 0;
int nTestsRun = 0;
UsefulBuf_MAKE_STACK_UB(StringStorage, 12);
test_entry2 *t2;
const test_entry2 *s_tests2_end = s_tests2 + sizeof(s_tests2)/sizeof(test_entry2);
for(t2 = s_tests2; t2 < s_tests2_end; t2++) {
if(szTestNames[0]) {
// Some tests have been named
const char **szRequestedNames;
for(szRequestedNames = szTestNames; *szRequestedNames; szRequestedNames++) {
if(!strcmp(t2->szTestName, *szRequestedNames)) {
break; // Name matched
}
}
if(*szRequestedNames == NULL) {
// Didn't match this test
continue;
}
} else {
// no tests named, but don't run "disabled" tests
if(!t2->bEnabled) {
// Don't run disabled tests when all tests are being run
// as indicated by no specific test names being given
continue;
}
}
const char * szTestResult = (t2->test_fun)();
nTestsRun++;
if(pfOutput) {
(*pfOutput)(t2->szTestName, poutCtx, 0);
}
if(szTestResult) {
if(pfOutput) {
(*pfOutput)(" FAILED (returned ", poutCtx, 0);
(*pfOutput)(szTestResult, poutCtx, 0);
(*pfOutput)(")", poutCtx, 1);
}
nTestsFailed++;
} else {
if(pfOutput) {
(*pfOutput)( " PASSED", poutCtx, 1);
}
}
}
test_entry *t;
const test_entry *s_tests_end = s_tests + sizeof(s_tests)/sizeof(test_entry);
for(t = s_tests; t < s_tests_end; t++) {
if(szTestNames[0]) {
// Some tests have been named
const char **szRequestedNames;
for(szRequestedNames = szTestNames; *szRequestedNames; szRequestedNames++) {
if(!strcmp(t->szTestName, *szRequestedNames)) {
break; // Name matched
}
}
if(*szRequestedNames == NULL) {
// Didn't match this test
continue;
}
} else {
// no tests named, but don't run "disabled" tests
if(!t->bEnabled) {
// Don't run disabled tests when all tests are being run
// as indicated by no specific test names being given
continue;
}
}
int32_t nTestResult = (t->test_fun)();
nTestsRun++;
if(pfOutput) {
(*pfOutput)(t->szTestName, poutCtx, 0);
}
if(nTestResult) {
if(pfOutput) {
(*pfOutput)(" FAILED (returned ", poutCtx, 0);
(*pfOutput)(NumToString(nTestResult, StringStorage), poutCtx, 0);
(*pfOutput)(")", poutCtx, 1);
}
nTestsFailed++;
} else {
if(pfOutput) {
(*pfOutput)( " PASSED", poutCtx, 1);
}
}
}
if(pNumTestsRun) {
*pNumTestsRun = nTestsRun;
}
if(pfOutput) {
(*pfOutput)( "SUMMARY: ", poutCtx, 0);
(*pfOutput)( NumToString(nTestsRun, StringStorage), poutCtx, 0);
(*pfOutput)( " tests run; ", poutCtx, 0);
(*pfOutput)( NumToString(nTestsFailed, StringStorage), poutCtx, 0);
(*pfOutput)( " tests failed", poutCtx, 1);
}
return nTestsFailed;
}
/*
Public function. See run_test.h.
*/
static void PrintSize(const char *szWhat,
uint32_t uSize,
OutputStringCB pfOutput,
void *pOutCtx)
{
UsefulBuf_MAKE_STACK_UB(buffer, 20);
(*pfOutput)(szWhat, pOutCtx, 0);
(*pfOutput)(" ", pOutCtx, 0);
(*pfOutput)(NumToString((int32_t)uSize, buffer), pOutCtx, 0);
(*pfOutput)("", pOutCtx, 1);
}
/*
Public function. See run_test.h.
*/
void PrintSizesQCBOR(OutputStringCB pfOutput, void *pOutCtx)
{
// These will never be large so cast is safe
PrintSize("sizeof(QCBORTrackNesting)", (uint32_t)sizeof(QCBORTrackNesting), pfOutput, pOutCtx);
PrintSize("sizeof(QCBOREncodeContext)", (uint32_t)sizeof(QCBOREncodeContext), pfOutput, pOutCtx);
PrintSize("sizeof(QCBORDecodeNesting)", (uint32_t)sizeof(QCBORDecodeNesting), pfOutput, pOutCtx);
PrintSize("sizeof(QCBORDecodeContext)", (uint32_t)sizeof(QCBORDecodeContext), pfOutput, pOutCtx);
PrintSize("sizeof(QCBORItem)", (uint32_t)sizeof(QCBORItem), pfOutput, pOutCtx);
PrintSize("sizeof(QCBORTagListIn)", (uint32_t)sizeof(QCBORTagListIn), pfOutput, pOutCtx);
PrintSize("sizeof(QCBORTagListOut)", (uint32_t)sizeof(QCBORTagListOut), pfOutput, pOutCtx);
PrintSize("sizeof(TagSpecification)", (uint32_t)sizeof(TagSpecification), pfOutput, pOutCtx);
(*pfOutput)("", pOutCtx, 1);
}

69
3rdparty/exported/QCBOR/test/run_tests.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,69 @@
/*==============================================================================
run_tests.h -- test aggregator and results reporting
Copyright (c) 2018-2020, Laurence Lundblade. All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
See BSD-3-Clause license in README.md
Created 9/30/18
=============================================================================*/
/**
@file run_tests.h
*/
/**
@brief Type for function to output a text string
@param[in] szString The string to output
@param[in] pOutCtx A context pointer; NULL if not needed
@param[in] bNewline If non-zero, output a newline after the string
This is a prototype of a function to be passed to RunTests() to
output text strings.
This can be implemented with stdio (if available) using a straight
call to fputs() where the FILE * is passed as the pOutCtx as shown in
the example code below. This code is for Linux where the newline is
a \\n. Windows usually prefers \\r\\n.
@code
static void fputs_wrapper(const char *szString, void *pOutCtx, int bNewLine)
{
fputs(szString, (FILE *)pOutCtx);
if(bNewLine) {
fputs("\n", pOutCtx);
}
}
@endcode
*/
typedef void (*OutputStringCB)(const char *szString, void *pOutCtx, int bNewline);
/**
@brief Runs the QCBOR tests.
@param[in] szTestNames An argv-style list of test names to run. If
empty, all are run.
@param[in] pfOutput Function that is called to output text strings.
@param[in] pOutCtx Context pointer passed to output function.
@param[out] pNumTestsRun Returns the number of tests run. May be NULL.
@return The number of tests that failed. Zero means overall success.
*/
int RunTestsQCBOR(const char *szTestNames[],
OutputStringCB pfOutput,
void *pOutCtx,
int *pNumTestsRun);
/**
@brief Print sizes of encoder / decoder contexts.
@param[in] pfOutput Function that is called to output text strings.
@param[in] pOutCtx Context pointer passed to output function.
*/
void PrintSizesQCBOR(OutputStringCB pfOutput, void *pOutCtx);

260
3rdparty/exported/QCBOR/ub-example.c поставляемый Normal file
Просмотреть файл

@ -0,0 +1,260 @@
/* =========================================================================
ub-example.c -- Example code for UsefulBuf
Copyright (c) 2022, Laurence Lundblade. All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
See BSD-3-Clause license in README.md
Created on 4/8/22
========================================================================== */
#include "ub-example.h"
#include "UsefulBuf.h"
/*
* A considerable number of the security issues with C code come from
* mistakes made with pointers and lengths. UsefulBuf adopts a
* convention that a pointer and length *always* go together to help
* mitigate this. With UsefulBuf there are never pointers without
* lengths, so you always know how big a buffer or some binary data
* is.
*
* C99 allows passing structures so a structure is used. Compilers are
* smart these days so the object code produced is little different
* than passing two separate parameters. Passing structures also makes
* the interfaces prettier. Assignments of structures also can make
* code prettier.
*
* ALong with the UsefulBuf structure, there are a bunch of (tested!)
* functions to manipulate them so code using it may have no pointer
* manipulation at all.
*
* Constness is also a useful and desirous thing. See
* https://stackoverflow.com/questions/117293/use-of-const-for-function-parameters
* Keeping const distinct from non-const is helpful when reading the
* code and helps avoid some coding mistakes. In this example the
* buffers filled in with data are const and the ones that are
* to-be-filled in are not const.
*
* This contrived example copies data from input to output expanding
* bytes with the value 'x' to 'xx'.
*
* Input -- This is the pointer and length of the input, the bytes to
* copy. Note that UsefulBufC.ptr is a const void * indicating that
* input data won't be changed by this function. There is a "C" in
* "UsefulBufC "to indicate the value is const. The length here is
* the length of the valid input data. Note also that the parameter
* Input is const, so this is fully const and clearly an [in]
* parameter.
*
* OutputBuffer -- This is a pointer and length of the memory to be
* used to store the output. The correct length here is critical for
* code security. Note that UsefulBuf.ptr is void *, it is not const
* indicating data can be written to it. Note that the parameter
* itself *is* const indicating that the code below will not point
* this to some other buffer or change the length and clearly marking
* it as an [in] parameter.
*
* Output -- This is the interesting and unusual one. To stay
* consistent with always pairing a length and a pointer, this is
* returned as a UsefulBuC. Also, to stay consistent with valid data
* being const, it is a UsefulBufC, not a UsefulBuf. It is however, an
* [out] parameter so the parameter is a pointer to a UsefulBufC.
*
* In this case and most cases, the pointer in Output->ptr will be the
* same as OutputBuffer.ptr. This may seem redundant, but there are a
* few reasons for it. First, is the goal of always pairing a pointer
* and a length. Second is being more strict and correct with
* constness. Third is the code hygiene and clarity of having
* variables for to-be-filled buffers be distinct from those
* containing valid data. Fourth, there are no [in,out] parameters,
* only [in] parameters and [out] parameters (the to-be-filled-in
* buffer is considered an [in] parameter).
*
* Note that the compiler will be smart and should generate pretty
* much the same code as for a traditional interface. On x86 with
* gcc-11 and no stack guards, the UB code is 81 bytes and the
* traditional code is 77 bytes.
*
* Finally, this supports computing of the length of the would-be
* output without actually doing any outputting. Pass {NULL, SIZE_MAX}
* for the OutputBuffer and the length will be returned in Output.
*/
int
ExpandxUB(const UsefulBufC Input,
const UsefulBuf OutputBuffer,
UsefulBufC *Output)
{
size_t uInputPosition;
size_t uOutputPosition;
uOutputPosition = 0;
/* Loop over all the bytes in Input */
for(uInputPosition = 0; uInputPosition < Input.len; uInputPosition++) {
const uint8_t uInputByte = ((const uint8_t*)Input.ptr)[uInputPosition];
/* Copy every byte */
if(OutputBuffer.ptr != NULL) {
((uint8_t *)OutputBuffer.ptr)[uOutputPosition] = uInputByte;
}
uOutputPosition++;
if(uOutputPosition >= OutputBuffer.len) {
return -1;
}
/* Double output 'x' because that is what this contrived example does */
if(uInputByte== 'x') {
if(OutputBuffer.ptr != NULL) {
((uint8_t *)OutputBuffer.ptr)[uOutputPosition] = 'x';
}
uOutputPosition++;
if(uOutputPosition >= OutputBuffer.len) {
return -1;
}
}
}
*Output = (UsefulBufC){OutputBuffer.ptr, uOutputPosition};
return 0; /* success */
}
/* This is the more tradional way to implement this. */
int
ExpandxTraditional(const uint8_t *pInputPointer,
const size_t uInputLength,
uint8_t *pOutputBuffer,
const size_t uOutputBufferLength,
size_t *puOutputLength)
{
size_t uInputPosition;
size_t uOutputPosition;
uOutputPosition = 0;
/* Loop over all the bytes in Input */
for(uInputPosition = 0; uInputPosition < uInputLength; uInputPosition++) {
const uint8_t uInputByte = ((const uint8_t*)pInputPointer)[uInputPosition];
/* Copy every byte */
if(pOutputBuffer != NULL) {
((uint8_t *)pOutputBuffer)[uOutputPosition] = uInputByte;
}
uOutputPosition++;
if(uOutputPosition >= uOutputBufferLength) {
return -1;
}
/* Double output 'x' because that is what this contrived example does */
if(uInputByte== 'x') {
if(pOutputBuffer != NULL) {
((uint8_t *)pOutputBuffer)[uOutputPosition] = 'x';
}
uOutputPosition++;
if(uOutputPosition >= uOutputBufferLength) {
return -1;
}
}
}
*puOutputLength = uOutputPosition;
return 0; /* success */
}
/*
* Here's an example of going from a traditional interface
* interface to a UsefulBuf interface.
*/
int
ExpandxTraditionalAdaptor(const uint8_t *pInputPointer,
size_t uInputLength,
uint8_t *pOutputBuffer,
size_t uOutputBufferLength,
size_t *puOutputLength)
{
UsefulBufC Input;
UsefulBuf OutputBuffer;
UsefulBufC Output;
int nReturn;
Input = (UsefulBufC){pInputPointer, uInputLength};
OutputBuffer = (UsefulBuf){pOutputBuffer, uOutputBufferLength};
nReturn = ExpandxUB(Input, OutputBuffer, &Output);
*puOutputLength = Output.len;
return nReturn;
}
/* Here's an example for going from a UsefulBuf interface
to a traditional interface. */
int
ExpandxUBAdaptor(const UsefulBufC Input,
const UsefulBuf OutputBuffer,
UsefulBufC *Output)
{
Output->ptr = OutputBuffer.ptr;
return ExpandxTraditional(Input.ptr, Input.len,
OutputBuffer.ptr, OutputBuffer.len,
&(Output->len));
}
#define INPUT "xyz123xyz"
int32_t RunUsefulBufExample()
{
/* ------------ UsefulBuf examples ------------- */
UsefulBufC Input = UsefulBuf_FROM_SZ_LITERAL(INPUT);
/* This macros makes a 20 byte buffer on the stack. It also makes
* a UsefulBuf on the stack. It sets up the UsefulBuf to point to
* the 20 byte buffer and sets it's length to 20 bytes. This
* is the empty, to-be-filled in memory for the output. It is not
* const. */
MakeUsefulBufOnStack(OutBuf, sizeof(INPUT) * 2);
/* This is were the pointer and the length of the completed output
* will be placed. Output.ptr is a pointer to const bytes. */
UsefulBufC Output;
ExpandxUB(Input, OutBuf, &Output);
ExpandxUBAdaptor(Input, OutBuf, &Output);
/* ------ Get Size example -------- */
ExpandxUB(Input, (UsefulBuf){NULL, SIZE_MAX}, &Output);
/* Size is in Output.len */
/* ---------- Traditional examples (for comparison) --------- */
uint8_t puBuffer[sizeof(INPUT) * 2];
size_t uOutputSize;
ExpandxTraditional((const uint8_t *)INPUT, sizeof(INPUT),
puBuffer, sizeof(puBuffer),
&uOutputSize);
ExpandxTraditionalAdaptor((const uint8_t *)INPUT, sizeof(INPUT),
puBuffer, sizeof(puBuffer),
&uOutputSize);
return 0;
}

19
3rdparty/exported/QCBOR/ub-example.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,19 @@
/* =========================================================================
ub-example.h -- Example code for UsefulBuf
Copyright (c) 2022, Laurence Lundblade. All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
See BSD-3-Clause license in README.md
Created on 4/8/22
========================================================================== */
#ifndef ub_example_h
#define ub_example_h
#include <stdint.h>
int32_t RunUsefulBufExample(void);
#endif /* ub_example_h */

101
3rdparty/exported/t_cose/.github/workflows/ci.yml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,101 @@
name: CI
on: [push, pull_request]
jobs:
main:
strategy:
fail-fast: false
matrix:
c-compiler: [gcc, clang]
config:
# OpenSSL 1.1.1 (Ubuntu 20.04)
- os-image: ubuntu-latest
container: ubuntu:20.04
crypto-provider: OpenSSL
# OpenSSL 3.0 (Ubuntu 22.04)
- os-image: ubuntu-latest
container: ubuntu:22.04
crypto-provider: OpenSSL
- os-image: ubuntu-latest
container: ubuntu:20.04
crypto-provider: MbedTLS
crypto-provider-version: '2.28.0'
- os-image: ubuntu-latest
container: ubuntu:20.04
crypto-provider: MbedTLS
crypto-provider-version: '3.1.0'
- os-image: ubuntu-latest
container: ubuntu:20.04
crypto-provider: Test
name: ${{ matrix.config.crypto-provider }} ${{ matrix.config.crypto-provider-version }} • ${{ matrix.c-compiler }} • ${{ matrix.config.container }}
runs-on: ${{ matrix.config.os-image }}
container: ${{ matrix.config.container }}
steps:
- uses: actions/checkout@v3
- name: Install build tools
run: |
set -ex
export DEBIAN_FRONTEND=noninteractive
apt-get update
apt-get install -y build-essential cmake python3 ${{ matrix.c-compiler }}
echo "CC=${{ matrix.c-compiler }}" >> $GITHUB_ENV
- name: Install OpenSSL
if: matrix.config.crypto-provider == 'OpenSSL'
run: apt-get install -y libssl-dev
- name: Fetch MbedTLS
if: matrix.config.crypto-provider == 'MbedTLS'
uses: actions/checkout@v3
with:
repository: ARMmbed/mbedtls
ref: v${{ matrix.config.crypto-provider-version }}
path: mbedtls
- name: Install MbedTLS
if: matrix.config.crypto-provider == 'MbedTLS'
run: |
cd mbedtls
make -j $(nproc)
make install
- name: Fetch QCBOR
uses: actions/checkout@v3
with:
repository: laurencelundblade/QCBOR
path: QCBOR
- name: Install QCBOR
run: |
cd QCBOR
make -j$(nproc)
make install
- name: Build t_cose
run: |
set -ex
mkdir build
cd build
cmake -DCRYPTO_PROVIDER=${{ matrix.config.crypto-provider }} ..
make -j $(nproc)
- name: Run OpenSSL example
if: matrix.config.crypto-provider == 'OpenSSL'
run: build/t_cose_basic_example_ossl
- name: Run MbedTLS example
if: matrix.config.crypto-provider == 'MbedTLS'
run: build/t_cose_basic_example_psa
- name: Run tests
run: build/t_cose_test

33
3rdparty/exported/t_cose/.github/workflows/pages.yml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,33 @@
name: GitHub Pages
on:
push:
branches:
- "master"
workflow_dispatch:
permissions: read-all
jobs:
main:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v3
- name: Install Doxygen
run: sudo apt-get install doxygen
- name: Run Doxygen
run: doxygen doxygen/t_cose_doxyfile
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: doxygen/output/html
publish_branch: gh-pages
force_orphan: true

62
3rdparty/exported/t_cose/.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,62 @@
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
# Compiled binaries
t_cose_test
t_cose_basic_example_ossl
# CMake build folder
build/
# Doxygen output folder
doxygen/output

135
3rdparty/exported/t_cose/CMakeLists.txt поставляемый Normal file
Просмотреть файл

@ -0,0 +1,135 @@
cmake_minimum_required(VERSION 3.12)
project(t_cose
DESCRIPTION "t_cose"
LANGUAGES C
VERSION 1.0.1)
# Constants
set(CRYPTO_PROVIDERS "OpenSSL" "MbedTLS" "Test")
# Project options
set(CRYPTO_PROVIDER "OpenSSL" CACHE STRING "The crypto provider to use: ${CRYPTO_PROVIDERS}")
set(BUILD_TESTS ON CACHE BOOL "Build tests")
set(BUILD_EXAMPLES ON CACHE BOOL "Build examples")
if (NOT CRYPTO_PROVIDER IN_LIST CRYPTO_PROVIDERS)
message(FATAL_ERROR "CRYPTO_PROVIDER must be one of ${CRYPTO_PROVIDERS}")
endif()
# Built-in CMake options
set(BUILD_SHARED_LIBS OFF CACHE BOOL "Create shared instead of static libraries")
# Used in find_package() calls as preferred search paths
set(QCBOR_ROOT "" CACHE PATH "Installation prefix of QCBOR")
set(MbedTLS_ROOT "" CACHE PATH "Installation prefix of MbedTLS")
set(OpenSSL_ROOT "" CACHE PATH "Installation prefix of OpenSSL")
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "No build type selected, defaulting to Release")
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type" FORCE)
endif()
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
if(CRYPTO_PROVIDER STREQUAL "MbedTLS")
find_package(MbedTLS REQUIRED)
set(CRYPTO_LIBRARY MbedTLS::MbedCrypto)
set(CRYPTO_COMPILE_DEFS -DT_COSE_USE_PSA_CRYPTO=1)
set(CRYPTO_ADAPTER_SRC crypto_adapters/t_cose_psa_crypto.c)
elseif(CRYPTO_PROVIDER STREQUAL "OpenSSL")
find_package(OpenSSL REQUIRED)
set(CRYPTO_LIBRARY OpenSSL::Crypto)
set(CRYPTO_COMPILE_DEFS -DT_COSE_USE_OPENSSL_CRYPTO=1)
set(CRYPTO_ADAPTER_SRC crypto_adapters/t_cose_openssl_crypto.c)
elseif(CRYPTO_PROVIDER STREQUAL "Test")
add_library(b_con_hash crypto_adapters/b_con_hash/sha256.c)
target_include_directories(b_con_hash PUBLIC crypto_adapters/b_con_hash)
set(CRYPTO_LIBRARY b_con_hash)
set(CRYPTO_COMPILE_DEFS -DT_COSE_USE_B_CON_SHA256 -DT_COSE_ENABLE_HASH_FAIL_TEST)
set(CRYPTO_ADAPTER_SRC crypto_adapters/t_cose_test_crypto.c)
else()
message(FATAL_ERROR "Bug!")
endif()
# Global compile options applying to all targets
add_compile_options(-pedantic -Wall)
set(T_COSE_SRC_COMMON
src/t_cose_sign1_sign.c
src/t_cose_parameters.c
src/t_cose_sign1_verify.c
src/t_cose_util.c
)
find_package(QCBOR REQUIRED)
add_library(t_cose ${T_COSE_SRC_COMMON} ${CRYPTO_ADAPTER_SRC})
target_compile_options(t_cose PRIVATE -ffunction-sections)
target_compile_definitions(t_cose PRIVATE ${CRYPTO_COMPILE_DEFS})
target_include_directories(t_cose PUBLIC inc PRIVATE src)
target_link_libraries(t_cose PUBLIC QCBOR::QCBOR PRIVATE ${CRYPTO_LIBRARY})
include(GNUInstallDirs)
install(TARGETS t_cose
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
install(DIRECTORY inc/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
if (BUILD_EXAMPLES)
if (CRYPTO_PROVIDER STREQUAL "MbedTLS")
add_executable(t_cose_basic_example_psa examples/t_cose_basic_example_psa.c)
target_link_libraries(t_cose_basic_example_psa PRIVATE t_cose ${CRYPTO_LIBRARY})
elseif (CRYPTO_PROVIDER STREQUAL "OpenSSL")
add_executable(t_cose_basic_example_ossl examples/t_cose_basic_example_ossl.c)
target_link_libraries(t_cose_basic_example_ossl PRIVATE t_cose ${CRYPTO_LIBRARY})
endif()
endif()
if (BUILD_TESTS)
enable_testing()
set(TEST_SRC_COMMON
main.c
test/run_tests.c
test/t_cose_make_test_messages.c
test/t_cose_test.c
)
if (NOT CRYPTO_PROVIDER STREQUAL "Test")
list(APPEND TEST_SRC_COMMON test/t_cose_sign_verify_test.c)
endif()
if (CRYPTO_PROVIDER STREQUAL "MbedTLS")
set(TEST_SRC_EXTRA test/t_cose_make_psa_test_key.c)
set(TEST_EXTRA_DEFS)
elseif(CRYPTO_PROVIDER STREQUAL "OpenSSL")
set(TEST_SRC_EXTRA test/t_cose_make_openssl_test_key.c)
set(TEST_EXTRA_DEFS)
elseif(CRYPTO_PROVIDER STREQUAL "Test")
set(TEST_SRC_EXTRA)
set(TEST_EXTRA_DEFS -DT_COSE_ENABLE_HASH_FAIL_TEST -DT_COSE_DISABLE_SIGN_VERIFY_TESTS)
else()
message(FATAL_ERROR "Bug!")
endif()
add_executable(t_cose_test ${TEST_SRC_COMMON} ${TEST_SRC_EXTRA})
target_include_directories(t_cose_test PRIVATE src test)
target_link_libraries(t_cose_test PRIVATE t_cose ${CRYPTO_LIBRARY})
# Crypto defs are needed because the tests include headers from src/
target_compile_definitions(t_cose_test PRIVATE ${CRYPTO_COMPILE_DEFS} ${TEST_EXTRA_DEFS})
add_test(NAME t_cose_test COMMAND t_cose_test)
endif()

29
3rdparty/exported/t_cose/LICENSE поставляемый Normal file
Просмотреть файл

@ -0,0 +1,29 @@
BSD 3-Clause License
Copyright (c) 2019, Laurence Lundblade
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

141
3rdparty/exported/t_cose/Makefile.ossl поставляемый Normal file
Просмотреть файл

@ -0,0 +1,141 @@
# Makefile -- UNIX-style make for t_cose using OpenSSL crypto
#
# Copyright (c) 2019-2021, Laurence Lundblade. All rights reserved.
# Copyright (c) 2020, Michael Eckel, Fraunhofer SIT.
#
# SPDX-License-Identifier: BSD-3-Clause
#
# See BSD-3-Clause license in README.md
#
# ---- comment ----
# This is for OpenSSL Crypto. Adjust CRYPTO_INC and CRYPTO_LIB for the
# location of the openssl libraries on your build machine.
# ---- QCBOR location ----
# This is for direct reference to QCBOR that is not installed in
# /usr/local or some system location. The path may need to be
# adjusted for your location of QCBOR.
#QCBOR_DIR=../../QCBOR/master
#QCBOR_INC=-I $(QCBOR_DIR)/inc
#QCBOR_LIB=$(QCBOR_DIR)/libqcbor.a
# This is for reference to QCBOR that has been installed in
# /usr/local/ or in some system location. This will typically
# use dynamic linking if there is a libqcbor.so
QCBOR_INC=-I /usr/local/include
QCBOR_LIB=-lqcbor
# ---- crypto configuration -----
# These two are for direct reference to OpenSSL that is not installed
# in /usr/local/ /usr/local or some system location. The path names
# may need to be adjusted for your location of OpenSSL
#CRYPTO_INC=-I ../../openssl/openssl-1.1.1b/include/openssl -I ../../openssl/openssl-1.1.1b/include
#CRYPTO_LIB=../../openssl/openssl-1.1.1b/libcrypto.a
# These two are for reference to OpenSSL that has been installed in
# /usr/local/ or in some system location.
CRYPTO_LIB=-l crypto
CRYPTO_INC=-I /usr/local/include
CRYPTO_CONFIG_OPTS=-DT_COSE_USE_OPENSSL_CRYPTO
CRYPTO_OBJ=crypto_adapters/t_cose_openssl_crypto.o
CRYPTO_TEST_OBJ=test/t_cose_make_openssl_test_key.o
# ---- compiler configuration -----
# Optimize for size
C_OPTS=-Os -fPIC
# ---- T_COSE Config and test options ----
TEST_CONFIG_OPTS=
TEST_OBJ=test/t_cose_test.o test/run_tests.o test/t_cose_sign_verify_test.o test/t_cose_make_test_messages.o $(CRYPTO_TEST_OBJ)
# ---- the main body that is invariant ----
INC=-I inc -I test -I src
ALL_INC=$(INC) $(CRYPTO_INC) $(QCBOR_INC)
CFLAGS=$(CMD_LINE) $(ALL_INC) $(C_OPTS) $(TEST_CONFIG_OPTS) $(CRYPTO_CONFIG_OPTS)
SRC_OBJ=src/t_cose_sign1_verify.o src/t_cose_sign1_sign.o src/t_cose_util.o src/t_cose_parameters.o
.PHONY: all install install_headers install_so uninstall clean
all: libt_cose.a t_cose_test t_cose_basic_example_ossl
libt_cose.a: $(SRC_OBJ) $(CRYPTO_OBJ)
ar -r $@ $^
# The shared library is not made by default because of platform
# variability For example MacOS and Linux behave differently and some
# IoT OS's don't support them at all.
libt_cose.so: $(SRC_OBJ) $(CRYPTO_OBJ)
cc -shared $^ -o $@ $(CRYPTO_LIB) $(QCBOR_LIB)
t_cose_test: main.o $(TEST_OBJ) libt_cose.a
cc -o $@ $^ $(QCBOR_LIB) $(CRYPTO_LIB)
t_cose_basic_example_ossl: examples/t_cose_basic_example_ossl.o libt_cose.a
cc -o $@ $^ $(QCBOR_LIB) $(CRYPTO_LIB)
# ---- Installation ----
ifeq ($(PREFIX),)
PREFIX := /usr/local
endif
install: libt_cose.a install_headers
install -d $(DESTDIR)$(PREFIX)/lib/
install -m 644 libt_cose.a $(DESTDIR)$(PREFIX)/lib/
install_headers: $(PUBLIC_INTERFACE)
install -d $(DESTDIR)$(PREFIX)/include/t_cose
install -m 644 inc/t_cose/t_cose_common.h $(DESTDIR)$(PREFIX)/include/t_cose
install -m 644 inc/t_cose/q_useful_buf.h $(DESTDIR)$(PREFIX)/include/t_cose
install -m 644 inc/t_cose/t_cose_sign1_sign.h $(DESTDIR)$(PREFIX)/include/t_cose
install -m 644 inc/t_cose/t_cose_sign1_verify.h $(DESTDIR)$(PREFIX)/include/t_cose
# The shared library is not installed by default because of platform variability.
install_so: libt_cose.so install_headers
install -m 755 libt_cose.so $(DESTDIR)$(PREFIX)/lib/libt_cose.so.1.0.0
ln -sf libt_cose.so.1 $(DESTDIR)$(PREFIX)/lib/libt_cose.so
ln -sf libt_cose.so.1.0.0 $(DESTDIR)$(PREFIX)/lib/libt_cose.so.1
uninstall: libt_cose.a $(PUBLIC_INTERFACE)
$(RM) -d $(DESTDIR)$(PREFIX)/include/t_cose/*
$(RM) -d $(DESTDIR)$(PREFIX)/include/t_cose/
$(RM) $(addprefix $(DESTDIR)$(PREFIX)/lib/, \
libt_cose.a libt_cose.so libt_cose.so.1 libt_cose.so.1.0.0)
clean:
rm -f $(SRC_OBJ) $(TEST_OBJ) $(CRYPTO_OBJ) t_cose_basic_example_ossl examples/*.o t_cose_test libt_cose.a libt_cose.so main.o
# ---- public headers -----
PUBLIC_INTERFACE=inc/t_cose/t_cose_common.h inc/t_cose/t_cose_sign1_sign.h inc/t_cose/t_cose_sign1_verify.h
# ---- source dependecies -----
src/t_cose_util.o: src/t_cose_util.h src/t_cose_standard_constants.h inc/t_cose/t_cose_common.h src/t_cose_crypto.h
src/t_cose_sign1_verify.o: inc/t_cose/t_cose_sign1_verify.h src/t_cose_crypto.h src/t_cose_util.h src/t_cose_parameters.h inc/t_cose/t_cose_common.h src/t_cose_standard_constants.h
src/t_cose_parameters.o: src/t_cose_parameters.h src/t_cose_standard_constants.h inc/t_cose/t_cose_sign1_verify.h inc/t_cose/t_cose_common.h
src/t_cose_sign1_sign.o: inc/t_cose/t_cose_sign1_sign.h src/t_cose_standard_constants.h src/t_cose_crypto.h src/t_cose_util.h inc/t_cose/t_cose_common.h
# ---- test dependencies -----
test/t_cose_test.o: test/t_cose_test.h test/t_cose_make_test_messages.h src/t_cose_crypto.h $(PUBLIC_INTERFACE)
test/t_cose_sign_verify_test.o: test/t_cose_sign_verify_test.h test/t_cose_make_test_messages.h src/t_cose_crypto.h test/t_cose_make_test_pub_key.h $(PUBLIC_INTERFACE)
test/t_cose_make_test_messages.o: test/t_cose_make_test_messages.h inc/t_cose/t_cose_sign1_sign.h inc/t_cose/t_cose_common.h src/t_cose_standard_constants.h src/t_cose_crypto.h src/t_cose_util.h
test/run_test.o: test/run_test.h test/t_cose_test.h test/t_cose_hash_fail_test.h
test/t_cose_make_openssl_test_key.o: test/t_cose_make_test_pub_key.h src/t_cose_standard_constants.h inc/t_cose/t_cose_common.h
# ---- crypto dependencies ----
crypto_adapters/t_cose_openssl_crypto.o: src/t_cose_crypto.h inc/t_cose/t_cose_common.h src/t_cose_standard_constants.h inc/t_cose/q_useful_buf.h
# ---- example dependencies ----
examples/t_cose_basic_example_ossl.o: $(PUBLIC_INTERFACE)

143
3rdparty/exported/t_cose/Makefile.psa поставляемый Normal file
Просмотреть файл

@ -0,0 +1,143 @@
# Makefile -- UNIX-style make for t_cose using crypto with Mbed Crypto
# Mbed Crypto uses the PSA Crypto interface
#
# Copyright (c) 2019-2021, Laurence Lundblade. All rights reserved.
# Copyright (c) 2020, Michael Eckel, Fraunhofer SIT.
#
# SPDX-License-Identifier: BSD-3-Clause
#
# See BSD-3-Clause license in README.md
#
# ---- comment ----
# This is for PSA Crypto / Mbed Crypto. See longer explanation in README.md
# Adjust CRYPTO_INC and CRYPTO_LIB for the
# location of the openssl libraries on your build machine.
# ---- QCBOR location ----
# This is for direct reference to QCBOR that is not installed in
# /usr/local or some system location. The path may need to be
# adjusted for your location of QCBOR.
#QCBOR_DIR=../../QCBOR/master
#QCBOR_INC=-I $(QCBOR_DIR)/inc
#QCBOR_LIB=$(QCBOR_DIR)/libqcbor.a
# This is for reference to QCBOR that has been installed in
# /usr/local/ or in some system location. This will typically
# use dynamic linking if there is a libqcbor.so
QCBOR_INC=-I /usr/local/include
QCBOR_LIB=-lqcbor
# ---- crypto configuration -----
# These two are for direct reference to Mbed Crypto that is not installed
# in /usr/local/ /usr/local or some system location. The path names
# may need to be adjusted for your location of Mbed Crypto
#CRYPTO_INC=-I ../../mbedtls/include/
#CRYPTO_LIB=../../mbedtls/library/libmbedcrypto.a
# These two are for reference to Mbed Crypto that has been installed in
# /usr/local/ or in some system location.
CRYPTO_LIB=-l mbedcrypto
CRYPTO_INC=-I /usr/local/include
CRYPTO_CONFIG_OPTS=-DT_COSE_USE_PSA_CRYPTO
CRYPTO_OBJ=crypto_adapters/t_cose_psa_crypto.o
CRYPTO_TEST_OBJ=test/t_cose_make_psa_test_key.o
# ---- compiler configuration -----
# Optimize for size
C_OPTS=-Os -fPIC
# ---- T_COSE Config and test options ----
TEST_CONFIG_OPTS=
TEST_OBJ=test/t_cose_test.o test/run_tests.o test/t_cose_sign_verify_test.o test/t_cose_make_test_messages.o $(CRYPTO_TEST_OBJ)
# ---- the main body that is invariant ----
INC=-I inc -I test -I src
ALL_INC=$(INC) $(CRYPTO_INC) $(QCBOR_INC)
CFLAGS=$(CMD_LINE) $(ALL_INC) $(C_OPTS) $(TEST_CONFIG_OPTS) $(CRYPTO_CONFIG_OPTS)
SRC_OBJ=src/t_cose_sign1_verify.o src/t_cose_sign1_sign.o src/t_cose_util.o src/t_cose_parameters.o
.PHONY: all install install_headers install_so uninstall clean
all: libt_cose.a t_cose_test t_cose_basic_example_psa
libt_cose.a: $(SRC_OBJ) $(CRYPTO_OBJ)
ar -r $@ $^
# The shared library is not made by default because of platform
# variability For example MacOS and Linux behave differently and some
# IoT OS's don't support them at all.
libt_cose.so: $(SRC_OBJ) $(CRYPTO_OBJ)
cc -shared $^ -o $@ $(CRYPTO_LIB) $(QCBOR_LIB)
t_cose_test: main.o $(TEST_OBJ) libt_cose.a
cc -o $@ $^ $(QCBOR_LIB) $(CRYPTO_LIB)
t_cose_basic_example_psa: examples/t_cose_basic_example_psa.o libt_cose.a
cc -o $@ $^ $(QCBOR_LIB) $(CRYPTO_LIB)
# ---- Installation ----
ifeq ($(PREFIX),)
PREFIX := /usr/local
endif
install: libt_cose.a install_headers
install -d $(DESTDIR)$(PREFIX)/lib/
install -m 644 libt_cose.a $(DESTDIR)$(PREFIX)/lib/
install_headers: $(PUBLIC_INTERFACE)
install -d $(DESTDIR)$(PREFIX)/include/t_cose
install -m 644 inc/t_cose/t_cose_common.h $(DESTDIR)$(PREFIX)/include/t_cose
install -m 644 inc/t_cose/q_useful_buf.h $(DESTDIR)$(PREFIX)/include/t_cose
install -m 644 inc/t_cose/t_cose_sign1_sign.h $(DESTDIR)$(PREFIX)/include/t_cose
install -m 644 inc/t_cose/t_cose_sign1_verify.h $(DESTDIR)$(PREFIX)/include/t_cose
# The shared library is not installed by default because of platform variability.
install_so: libt_cose.so install_headers
install -m 755 libt_cose.so $(DESTDIR)$(PREFIX)/lib/libt_cose.so.1.0.0
ln -sf libt_cose.so.1 $(DESTDIR)$(PREFIX)/lib/libt_cose.so
ln -sf libt_cose.so.1.0.0 $(DESTDIR)$(PREFIX)/lib/libt_cose.so.1
uninstall: libt_cose.a $(PUBLIC_INTERFACE)
$(RM) -d $(DESTDIR)$(PREFIX)/include/t_cose/*
$(RM) -d $(DESTDIR)$(PREFIX)/include/t_cose/
$(RM) $(addprefix $(DESTDIR)$(PREFIX)/lib/, \
libt_cose.a libt_cose.so libt_cose.so.1 libt_cose.so.1.0.0)
clean:
rm -f $(SRC_OBJ) $(TEST_OBJ) $(CRYPTO_OBJ) t_cose_basic_example_psa t_cose_test libt_cose.a libt_cose.so examples/*.o main.o
# ---- public headers -----
PUBLIC_INTERFACE=inc/t_cose/t_cose_common.h inc/t_cose/t_cose_sign1_sign.h inc/t_cose/t_cose_sign1_verify.h
# ---- source dependecies -----
src/t_cose_util.o: src/t_cose_util.h src/t_cose_standard_constants.h inc/t_cose/t_cose_common.h src/t_cose_crypto.h
src/t_cose_sign1_verify.o: inc/t_cose/t_cose_sign1_verify.h src/t_cose_crypto.h src/t_cose_util.h src/t_cose_parameters.h inc/t_cose/t_cose_common.h src/t_cose_standard_constants.h
src/t_cose_parameters.o: src/t_cose_parameters.h src/t_cose_standard_constants.h inc/t_cose/t_cose_sign1_verify.h inc/t_cose/t_cose_common.h
src/t_cose_sign1_sign.o: inc/t_cose/t_cose_sign1_sign.h src/t_cose_standard_constants.h src/t_cose_crypto.h src/t_cose_util.h inc/t_cose/t_cose_common.h
# ---- test dependencies -----
test/t_cose_test.o: test/t_cose_test.h test/t_cose_make_test_messages.h src/t_cose_crypto.h $(PUBLIC_INTERFACE)
test/t_cose_sign_verify_test.o: test/t_cose_sign_verify_test.h test/t_cose_make_test_messages.h src/t_cose_crypto.h test/t_cose_make_test_pub_key.h $(PUBLIC_INTERFACE)
test/t_cose_make_test_messages.o: test/t_cose_make_test_messages.h inc/t_cose/t_cose_sign1_sign.h inc/t_cose/t_cose_common.h src/t_cose_standard_constants.h src/t_cose_crypto.h src/t_cose_util.h
test/run_test.o: test/run_test.h test/t_cose_test.h test/t_cose_hash_fail_test.h
test/t_cose_make_psa_test_key.o: test/t_cose_make_test_pub_key.h src/t_cose_standard_constants.h inc/t_cose/t_cose_common.h
# ---- crypto dependencies ----
crypto_adapters/t_cose_psa_crypto.o: src/t_cose_crypto.h inc/t_cose/t_cose_common.h src/t_cose_standard_constants.h inc/t_cose/q_useful_buf.h
# ---- example dependencies ----
examples/t_cose_basic_example_psa.o: $(PUBLIC_INTERFACE)

88
3rdparty/exported/t_cose/Makefile.test поставляемый Normal file
Просмотреть файл

@ -0,0 +1,88 @@
# Makefile -- UNIX-style make for no-crypto test config for t_cose
#
# Copyright (c) 2019-2022, Laurence Lundblade. All rights reserved.
# Copyright (c) 2020, Michael Eckel, Fraunhofer SIT.
#
# SPDX-License-Identifier: BSD-3-Clause
#
# See BSD-3-Clause license in README.md
#
# ---- comment ----
# This t_cose makefile is for test crypto
# It has no dependency on any external crypto library, but doesn't
# support real ECDSA signing. The only external code needed is QCBOR.
# ---- QCBOR location ----
# Adjust this to the location of QCBOR in your build environment
#QCBOR_INC= -I ../../QCBOR/master/inc
#QCBOR_LIB=../../QCBOR/master/libqcbor.a
QCBOR_INC= -I/usr/include -I/usr/local/include
QCBOR_LIB= -l qcbor
# ---- crypto configuration -----
# Uses only the internal Brad Conte hash implementation that is bundled with t_cose
CRYPTO_INC=-I crypto_adapters/b_con_hash
CRYPTO_LIB=
CRYPTO_CONFIG_OPTS=-DT_COSE_USE_B_CON_SHA256
CRYPTO_OBJ=crypto_adapters/t_cose_test_crypto.o crypto_adapters/b_con_hash/sha256.o
CRYPTO_TEST_OBJ=
# ---- compiler configuration -----
# Optimize for size
C_OPTS=-Os -fPIC
# ---- T_COSE Config and test options ----
TEST_CONFIG_OPTS=-DT_COSE_ENABLE_HASH_FAIL_TEST -DT_COSE_DISABLE_SIGN_VERIFY_TESTS
TEST_OBJ=test/t_cose_test.o test/run_tests.o test/t_cose_make_test_messages.o $(CRYPTO_TEST_OBJ)
# ---- the main body that is invariant ----
INC=-I inc -I test -I src
ALL_INC=$(CRYPTO_INC) $(QCBOR_INC) $(INC)
CFLAGS=$(CMD_LINE) $(ALL_INC) $(C_OPTS) $(TEST_CONFIG_OPTS) $(CRYPTO_CONFIG_OPTS)
SRC_OBJ=src/t_cose_sign1_verify.o src/t_cose_sign1_sign.o src/t_cose_util.o src/t_cose_parameters.o
.PHONY: all clean
all: libt_cose.a t_cose_test
libt_cose.a: $(SRC_OBJ) $(CRYPTO_OBJ)
ar -r $@ $^
libt_cose.so: $(SRC_OBJ) $(CRYPTO_OBJ)
cc $^ $(CFLAGS) -dead_strip -o $@ -shared $(QCBOR_LIB) $(CRYPTO_LIB)
t_cose_test: main.o $(TEST_OBJ) libt_cose.a
cc -o $@ $^ $(QCBOR_LIB) $(CRYPTO_LIB)
clean:
rm -f $(SRC_OBJ) $(TEST_OBJ) $(CRYPTO_OBJ) libt_cose.a libt_cose.so t_cose_test main.o
# ---- public headers -----
PUBLIC_INTERFACE=inc/t_cose/t_cose_common.h inc/t_cose/t_cose_sign1_sign.h inc/t_cose/t_cose_sign1_verify.h
# ---- source dependecies -----
src/t_cose_util.o: src/t_cose_util.h src/t_cose_standard_constants.h inc/t_cose/t_cose_common.h src/t_cose_crypto.h
src/t_cose_sign1_verify.o: inc/t_cose/t_cose_sign1_verify.h src/t_cose_crypto.h src/t_cose_util.h src/t_cose_parameters.h inc/t_cose/t_cose_common.h src/t_cose_standard_constants.h
src/t_cose_parameters.o: src/t_cose_parameters.h src/t_cose_standard_constants.h inc/t_cose/t_cose_sign1_verify.h inc/t_cose/t_cose_common.h
src/t_cose_sign1_sign.o: inc/t_cose/t_cose_sign1_sign.h src/t_cose_standard_constants.h src/t_cose_crypto.h src/t_cose_util.h inc/t_cose/t_cose_common.h
# ---- test dependencies -----
test/t_cose_test.o: test/t_cose_test.h test/t_cose_make_test_messages.h src/t_cose_crypto.h $(PUBLIC_INTERFACE)
test/t_cose_make_test_messages.o: test/t_cose_make_test_messages.h inc/t_cose/t_cose_sign1_sign.h inc/t_cose/t_cose_common.h src/t_cose_standard_constants.h src/t_cose_crypto.h src/t_cose_util.h
test/run_test.o: test/run_test.h test/t_cose_test.h test/t_cose_hash_fail_test.h
# ---- crypto dependencies ----
crypto_adapters/t_cose_test_crypto.o: src/t_cose_crypto.h inc/t_cose/t_cose_common.h src/t_cose_standard_constants.h inc/t_cose/q_useful_buf.h crypto_adapters/b_con_hash/sha256.h
crypto_adapters/b_con_hash/sha256.o: crypto_adapters/b_con_hash/sha256.h

318
3rdparty/exported/t_cose/README.md поставляемый Normal file
Просмотреть файл

@ -0,0 +1,318 @@
![t_cose](https://github.com/laurencelundblade/t_cose/blob/master/t-cose-logo.png?raw=true)
*t_cose* implements enough of COSE to support [CBOR Web Token, RFC 8392](https://tools.ietf.org/html/rfc8392)
and [Entity Attestation Token (EAT)](https://tools.ietf.org/html/draft-ietf-rats-eat-01).
This is the COSE_Sign1 part of [COSE, RFC 9052](https://tools.ietf.org/html/rfc9052).
**Implemented in C with minimal dependency** – There are three main
dependencies: 1) [QCBOR](https://github.com/laurencelundblade/QCBOR),
2) A cryptographic library for ECDSA and SHA-2, 3) C99, <stdint.h>,
<stddef.h>, <stdbool.h> and <string.h>. It is highly
portable to different HW, OS's and cryptographic libraries. Except for
some minor configuration for the cryptographic library, no #ifdefs or
compiler options need to be set for it to run correctly.
**Crypto Library Integration Layer** – Works with different cryptographic
libraries via a simple integration layer. The integration layer is kept small and simple,
just enough for the use cases, so that integration is simpler. Integration layers for
the OpenSSL and ARM Mbed TLS (PSA Cryptography API) cryptographic libraries
are included.
**Secure coding style** – Uses a construct called UsefulBuf / q_useful_buf as a
discipline for safe coding and handling of binary data.
**Small simple memory model** – Malloc is not needed. Besides the
cryptographic library and payload buffer, about 600 bytes of heap/stack is needed
for signing and 1500 bytes for verifying. The caller supplies the output buffer
and context structures so the caller has control over memory usage making it
useful for embedded implementations that have to run in small fixed memory.
## Documentation
[API documentation is here](https://laurencelundblade.github.io/t_cose/)
## Code Status
As of March 2022, the code is in good working order and the public interface has been
stable for over a year.
Integration with the [OpenSSL](https://www.openssl.org) and [Arm Mbed
TLS](https://github.com/ARMmbed/mbedtls) cryptographic libraries is
fully supported.
t_cose 1.0 only supports COSE Sign1, signing with one recipeint.
## Future Work
As of March 2022, work is underway to support encryption, MAC and
other COSE features. When a good set of these are complete to
commercial quality, a 2.0 version of t_cose will be released.
Note that there is no committed time line to complete t_cose
2.0. t_cose is mostly implemented on a volunteer basis. You can
volunteer! Work like adding support for more algorithms is not too
difficult and is nicely framed up.
## Building and Dependencies
Except for the crypto library set up, t_cose is very portable and
should largely just work in any environment. It needs a few standard
libraries and [QCBOR](https://github.com/laurencelundblade/QCBOR)
(which is also very portable). Hence most of this section is about
crypto library set up.
### QCBOR
If QCBOR is installed in /usr/local, then the makefiles should find
it. If not then QCBOR may need to be downloaded. The makefiles can be
modified to reference it other than in /usr/local.
### Supported Cryptographic Libraries
Here's three crypto library configurations that are supported. Others
can be added with relative ease.
#### Test Crypto -- Makefile.test
This configuration should work instantly on any device and is useful
to do a large amount of testing with, but can't be put to full
commercial use. What it lacks is integration with an ECDSA
implementation so it can't produce real ECDSA signatures. It does
however produce fake signatures called "short-circuit
signatures" that are very useful for testing. See header
documentation for details on short-circuit sigs.
This configuration (and only this configuration) uses a bundled
SHA-256 implementation (SHA-256 is simple and easy to bundle, ECDSA is
not).
To build run:
make -f Makefile.test
#### OpenSSL Crypto -- Makefile.ossl
This OpenSSL integration supports SHA-256, SHA-384 and SHA-512 with
ECDSA to support the COSE algorithms ES256, ES384 and ES512. It is a
full and tested integration with OpenSSL crypto.
If OpenSSL is installed in /usr/local or as a standar library, you can
probably just run make:
make -f Makefile.ossl
The specific things that Makefile.ossl does is:
* Links the crypto_adapters/t_cose_openssl_crypto.o into libt_cose.a
* Links test/test/t_cose_make_openssl_test_key.o into the test binary
* `#define T_COSE_USE_OPENSSL_CRYPTO`
t_cose is regularly tested against OpenSSL 1.1.1 and 3.0.
The crypto adaptor for OpenSSL is about twice the size of that for
Mbed TLS because the API doesn't line up well with the needs for COSE
(OpenSSL is ASN.1/DER oriented). Memory allocation is performed inside
OpenSSL and in the crypto adaptation layer. This makes the OpenSSL
crypto library less suitable for embedded use.
No deprecated or to-be-deprecated APIs are used.
There are several different sets of APIs in OpenSSL that can be used
to implement ECDSA and hashing. The ones chosen are the most official
and well-supported, however others might suit particular uses cases
better. An older t_cose used some to-be-deprecated APIs and is a more
efficient than this one. It is unfortunate that these APIs
(ECDSA_do_sign and ECDSA_do_verify) are slated for deprecation and
there is no supported alternative to those that work only with DER-encoded
signatures.
There are no known problems with the code and test coverage for the
adaptor is good. Not every single memory allocation failure has
test coverage, but the code should handle them all correctly.
#### PSA Crypto -- Makefile.psa
As of March 2022, t_cose works with the PSA 1.0 Crypto API as
implemented by Mbed TLS 2.x and 3.x.
This integration supports SHA-256, SHA-384 and SHA-512 with ECDSA to
support the COSE algorithms ES256, ES384 and ES512.
If Mbed TLS is installed in /usr/local, you can probably just run
make:
make -f Makefile.psa
If this doesn't work or you have Mbed TLS elsewhere edit the makefile.
The specific things that Makefile.psa does is:
* Links the crypto_adapters/t_cose_psa_crypto.o into libt_cose.a
* Links test/test/t_cose_make_psa_test_key.o into the test binary
* `#define T_COSE_USE_PSA_CRYPTO`
This crypto adapter is small and simple. The adapter allocates no
memory and as far as I know it internally allocates no memory. It is a
good choice for embedded use.
It makes use of the 1.0 version of the PSA cryptographic API. No
deprecated or to-be-deprecated functions are called (an older t_cose
used some to be deprecated APIs).
It is regularly tested against the latest version 2 and version 3 of
Mbed TLS, an implementation of the PSA crypto API.
Confidence in the adaptor code is high and reasonably well tested
because it is simple.
### General Crypto Library Strategy
The functions that t_cose needs from the crypto library are all
defined in src/t_cose_crypto.h. This is a porting or adaption
layer. There are no #ifdefs in the main t_cose code for different
crypto libraries. When it needs a crypto function it just calls the
interface defined in t_cose_crypto.h.
When integrating t_cose with a new cryptographic library, what is
necessary is to write some code, an "adaptor", that implements
t_cose_crypto.h using the new target cryptographic library. This can
be done without changes to any t_cose code for many cryptographic
libraries. See the interface documentation in t_cose_crypto.h for what
needs to be implemented.
That said, there is one case where t_cose source code needs to be
modified. This is for hash algorithm implementations that are linked
into and run inline with t_cose and that have a context structure. In
this case t_cose_crypto.h should be modified to use that context
structure. Use the OpenSSL configuration as an example.
To complete the set up for a new cryptographic library and test it, a
new test adaptation file is also needed. This file makes public key
pairs of the correct type for use with testing. This file is usually
named test/t_cose_make_xxxx_test_key.c and is linked in with the test
app. The keys it makes are passed through t_cose untouched, through
the t_cose_crypto.h interface into the underlying crypto.
## Memory Usage
### Code
Here are code sizes on 64-bit x86 optimized for size
| | smallest | largest |
|---------------------------|----------|---------|
| signing only | 1500 | 2300 |
| verification only | 2500 | 3300 |
| common to sign and verify | (500)| (800)|
| combined | 3500 | 4800 |
Things that make the code smaller:
* PSA / Mbed crypto takes less code to interface with than OpenSSL
* gcc is usually smaller than llvm because stack guards are off by default
* Use only 256-bit crypto with the T_COSE_DISABLE_ESXXX options
* Disable short-circut sig debug faclity T_COSE_DISABLE_SHORT_CIRCUIT_SIGN
* Disable the content type header T_COSE_DISABLE_CONTENT_TYPE
#### Change in code size with spiffy decode
The encode size is as before.
Compared to the previous t_cose, the code size for decoding/verifying
is reduced by about 600 bytes. However, spiffy decode functions in
QCBOR are now required and they are about 2KB, so there is a net size
increase of 1.4KB. But use of spiffy decode will also make other parts
of the overall SW stack smaller, perhaps by a lot, so this will likely
break even. For example, EAT or CWT decoding will be reduced a lot
through use of spiffy decode. Basically, the more CBOR maps a SW
stack has to handle, the more saving there will be from spiffy decode.
### Heap and stack
Malloc is not used.
Stack usage is variable depending on the key and hash size and the
stack usage by the cryptographic library that performs the hash and
public key crypto functions. The maximum requirement is roughly
2KB. This is an estimate from examining the code, not an actual
measurement.
Since the keys, hash outputs and signatures are stored on the stack,
the stronger the security, the more stack is used. By default up to
512 bit EC is enabled. Disable 512 and 384 bit EC to reduce stack
usage by about 100 bytes.
Different cryptographic libraries may have very different stack usage
characteristics. For example if one use malloc rather than the stack,
it will (hopefully) use less stack. The guess estimate range of usage
by the cryptographic library is between 64 and 1024 bytes of stack.
Aside from the cryptographic library, the base stack use by t_cose is
500 bytes for signing and 1500 bytes for verification. With a large
cryptographic library, the total is about 1500 bytes for signing and
2000 bytes for verification (for verification, the crypto library
stack re uses stack used to decode header parameters so the increment
isn't so large).
The design is such that only one copy of the output, the COSE_Sign1,
need be in memory. It makes use of special features in QCBOR that
allows contstuction of the output including the payload, using just
the single output buffer to accomplish this.
A buffer to hold the signed COSE result must be passed in. It must be
about 100 bytes larger than the combined size of the payload and key
id for ECDSA 256. It can be allocated as the caller wishes.
### Crypto library memory usage
In addition to the above memory usage, the crypto library will use
some stack and/or heap memory. This will vary quite a bit by crypto
library. Some may use malloc. Some may not.
So far no support for RSA is available, but since the keys and
signatures are much bigger, implementing it will increase stack and
memory usage substantially.
The OpenSSL library does use malloc, even with ECDSA. Another
implementation of ECDSA might not use malloc, as the keys are small
enough.
### Mixed code style
QCBOR uses camelCase and t_cose follows
[Arm's coding guidelines](https://git.trustedfirmware.org/TF-M/trusted-firmware-m.git/tree/docs/contributing/coding_guide.rst)
resulting in code with mixed styles. For better or worse, an Arm-style version of UsefulBuf
is created and used and so there is a duplicate of UsefulBuf. The two are identical. They
just have different names.
## Limitations
* Most inputs and outputs must be in a continguous buffer. One
exception to this is that CBOR payloads being signed can be
constructed piecemeal into the output buffer and signed without
using a separate buffer.
* Doesn't handle COSE string algorithm IDs. Only COSE integer
algorithm IDs are handled. Thus far no string algorithm IDs have
been assigned by IANA.
* No way to add custom headers when creating signed messages or
process them during verification.
* Only ECDSA is supported so far (facilities are available to add
others).
* Does not handle CBOR indefinite length strings (indefinite length
maps and arrays are handled).
* Counter signatures are not supported.
## Credit
* Maik Riechert for cmake, CI and other.
* Ken Takayama for the bulk of the detached content implementation.
* Tamas Ban for lots code review comments, design ideas and porting to ARM PSA.
* Rob Coombs, Shebu Varghese Kuriakose and other ARM folks for sponsorship.
* Michael Eckel for makefile fixes.
## Copyright and License
t_cose is available under the 3-Clause BSD License.

27
3rdparty/exported/t_cose/SECURITY.md поставляемый Normal file
Просмотреть файл

@ -0,0 +1,27 @@
# Security Policy
## Reporting a Vulnerability
Please report security vulnerabilities by sending email to lgl@island-resort.com.
Please include "t_cose SECURITY" in the subject line.
In most cases the vulnerability should not be reported by filing an issue in GitHub as this
will publically disclose the issue before a fix is available.
Laurence Lundblade maintains this code and will respond in a day or two with an initial
evaluation.
Security fixes will be prioritized over other work.
Vulnerabilities will be fixed promptly, but some may be more complex than others
and take longer. If the fix is quick, it will usually be turned around in a
few days.
## Availability of Fixes
When the fix has been created, it will be privately verified with the party that reported it.
Only after the fix has been verified and the reporter has had a chance to integrate the fix,
will it be made available as a public commit in GitHub.
If the reporter doesn't respond or can't integrate the fix, it will be made public after 30 days.

108
3rdparty/exported/t_cose/cmake/FindMbedTLS.cmake поставляемый Normal file
Просмотреть файл

@ -0,0 +1,108 @@
#[=======================================================================[.rst:
FindMbedTLS
-------
Finds the mbedTLS library.
Imported Targets
^^^^^^^^^^^^^^^^
This module provides the following imported targets, if found:
``MbedTLS::MbedTLS``
The mbedTLS library
``MbedTLS::MbedCrypto``
The mbedTLS crypto library
``MbedTLS::MbedX509``
The mbedTLS X509 library
Result Variables
^^^^^^^^^^^^^^^^
This will define the following variables:
``MbedTLS_FOUND``
True if the system has the MbedTLS library.
``MbedTLS_INCLUDE_DIRS``
Include directories needed to use MbedTLS.
``MbedTLS_LIBRARIES``
Libraries needed to link to MbedTLS.
Cache Variables
^^^^^^^^^^^^^^^
The following cache variables may also be set:
``MbedTLS_INCLUDE_DIR``
The directory containing ``mbedtls/``.
``MbedTLS_LIBRARY``
The path to the mbedtls library.
``MbedTLS_CRYPTO_LIBRARY``
The path to the mbedcrypto library.
``MbedTLS_X509_LIBRARY``
The path to the mbedx509 library.
#]=======================================================================]
find_path(MbedTLS_INCLUDE_DIR
NAMES mbedtls/version.h
)
find_library(MbedTLS_LIBRARY
NAMES mbedtls
)
find_library(MbedTLS_CRYPTO_LIBRARY
NAMES mbedcrypto
)
find_library(MbedTLS_X509_LIBRARY
NAMES mbedx509
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(MbedTLS
FOUND_VAR MbedTLS_FOUND
REQUIRED_VARS
MbedTLS_LIBRARY
MbedTLS_CRYPTO_LIBRARY
MbedTLS_X509_LIBRARY
MbedTLS_INCLUDE_DIR
)
if(MbedTLS_FOUND)
set(MbedTLS_LIBRARIES "${MbedTLS_LIBRARY}" "${MbedTLS_X509_LIBRARY}" "${MbedTLS_CRYPTO_LIBRARY}")
set(MbedTLS_INCLUDE_DIRS "${MbedTLS_INCLUDE_DIR}")
endif()
if(MbedTLS_FOUND AND NOT TARGET MbedTLS::MbedCrypto)
add_library(MbedTLS::MbedCrypto UNKNOWN IMPORTED)
set_target_properties(MbedTLS::MbedCrypto PROPERTIES
IMPORTED_LOCATION "${MbedTLS_CRYPTO_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${MbedTLS_INCLUDE_DIR}"
)
endif()
if(MbedTLS_FOUND AND NOT TARGET MbedTLS::MbedX509)
add_library(MbedTLS::MbedX509 UNKNOWN IMPORTED)
set_target_properties(MbedTLS::MbedX509 PROPERTIES
IMPORTED_LOCATION "${MbedTLS_X509_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${MbedTLS_INCLUDE_DIR}"
)
target_link_libraries(MbedTLS::MbedX509 INTERFACE MbedTLS::MbedCrypto)
endif()
if(MbedTLS_FOUND AND NOT TARGET MbedTLS::MbedTLS)
add_library(MbedTLS::MbedTLS UNKNOWN IMPORTED)
set_target_properties(MbedTLS::MbedTLS PROPERTIES
IMPORTED_LOCATION "${MbedTLS_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${MbedTLS_INCLUDE_DIR}"
)
target_link_libraries(MbedTLS::MbedX509 INTERFACE MbedTLS::MbedCrypto MbedTLS::MbedX509)
endif()
mark_as_advanced(
MbedTLS_INCLUDE_DIR
MbedTLS_LIBRARY
MbedTLS_CRYPTO_LIBRARY
MbedTLS_X509_LIBRARY
)

81
3rdparty/exported/t_cose/cmake/FindQCBOR.cmake поставляемый Normal file
Просмотреть файл

@ -0,0 +1,81 @@
#[=======================================================================[.rst:
FindQCBOR
-------
Finds the QCBOR library.
Imported Targets
^^^^^^^^^^^^^^^^
This module provides the following imported targets, if found:
``QCBOR::QCBOR``
The QCBOR library
Result Variables
^^^^^^^^^^^^^^^^
This will define the following variables:
``QCBOR_FOUND``
True if the system has the QCBOR library.
``QCBOR_INCLUDE_DIRS``
Include directories needed to use QCBOR.
``QCBOR_LIBRARIES``
Libraries needed to link to QCBOR.
Cache Variables
^^^^^^^^^^^^^^^
The following cache variables may also be set:
``QCBOR_INCLUDE_DIR``
The directory containing ``t_cose/``.
``QCBOR_LIBRARY``
The path to the QCBOR library.
#]=======================================================================]
include(CheckLibraryExists)
find_path(QCBOR_INCLUDE_DIR
NAMES qcbor/qcbor.h
)
find_library(QCBOR_LIBRARY
NAMES qcbor
)
CHECK_LIBRARY_EXISTS(m sin "" HAVE_LIB_M)
set(EXTRA_LIBS)
if(HAVE_LIB_M)
set(EXTRA_LIBS m)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(QCBOR
FOUND_VAR QCBOR_FOUND
REQUIRED_VARS
QCBOR_LIBRARY
QCBOR_INCLUDE_DIR
)
if(QCBOR_FOUND)
set(QCBOR_LIBRARIES "${QCBOR_LIBRARY} ${EXTRA_LIBS}")
set(QCBOR_INCLUDE_DIRS "${QCBOR_INCLUDE_DIR}")
endif()
if(QCBOR_FOUND AND NOT TARGET QCBOR::QCBOR)
add_library(QCBOR::QCBOR UNKNOWN IMPORTED)
set_target_properties(QCBOR::QCBOR PROPERTIES
IMPORTED_LOCATION "${QCBOR_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${QCBOR_INCLUDE_DIR}"
)
if (EXTRA_LIBS)
target_link_libraries(QCBOR::QCBOR INTERFACE ${EXTRA_LIBS})
endif()
endif()
mark_as_advanced(
QCBOR_INCLUDE_DIR
QCBOR_LIBRARY
)

161
3rdparty/exported/t_cose/crypto_adapters/b_con_hash/sha256.c поставляемый Normal file
Просмотреть файл

@ -0,0 +1,161 @@
/*********************************************************************
* Filename: sha256.c
* Author: Brad Conte (brad AT bradconte.com)
* Copyright:
* Disclaimer: This code is presented "as is" without any guarantees.
* Details: Implementation of the SHA-256 hashing algorithm.
SHA-256 is one of the three algorithms in the SHA2
specification. The others, SHA-384 and SHA-512, are not
offered in this implementation.
Algorithm specification can be found here:
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf
This implementation uses little endian byte order.
* Copyright Laurence Lundblade 2020 for addition of casts so it
compiles without warnings with pendantic compilers settings.
*********************************************************************/
/*************************** HEADER FILES ***************************/
#include <stdlib.h>
#include <memory.h>
#include "sha256.h"
/****************************** MACROS ******************************/
#define ROTLEFT(a,b) (((a) << (b)) | ((a) >> (32-(b))))
#define ROTRIGHT(a,b) (((a) >> (b)) | ((a) << (32-(b))))
#define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z)))
#define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
#define EP0(x) (ROTRIGHT(x,2) ^ ROTRIGHT(x,13) ^ ROTRIGHT(x,22))
#define EP1(x) (ROTRIGHT(x,6) ^ ROTRIGHT(x,11) ^ ROTRIGHT(x,25))
#define SIG0(x) (ROTRIGHT(x,7) ^ ROTRIGHT(x,18) ^ ((x) >> 3))
#define SIG1(x) (ROTRIGHT(x,17) ^ ROTRIGHT(x,19) ^ ((x) >> 10))
/**************************** VARIABLES *****************************/
static const WORD k[64] = {
0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
};
/*********************** FUNCTION DEFINITIONS ***********************/
void sha256_transform(SHA256_CTX *ctx, const BYTE data[])
{
WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64];
for (i = 0, j = 0; i < 16; ++i, j += 4)
m[i] = (WORD)((data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]));
for ( ; i < 64; ++i)
m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];
a = ctx->state[0];
b = ctx->state[1];
c = ctx->state[2];
d = ctx->state[3];
e = ctx->state[4];
f = ctx->state[5];
g = ctx->state[6];
h = ctx->state[7];
for (i = 0; i < 64; ++i) {
t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i];
t2 = EP0(a) + MAJ(a,b,c);
h = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
}
ctx->state[0] += a;
ctx->state[1] += b;
ctx->state[2] += c;
ctx->state[3] += d;
ctx->state[4] += e;
ctx->state[5] += f;
ctx->state[6] += g;
ctx->state[7] += h;
}
void sha256_init(SHA256_CTX *ctx)
{
ctx->datalen = 0;
ctx->bitlen = 0;
ctx->state[0] = 0x6a09e667;
ctx->state[1] = 0xbb67ae85;
ctx->state[2] = 0x3c6ef372;
ctx->state[3] = 0xa54ff53a;
ctx->state[4] = 0x510e527f;
ctx->state[5] = 0x9b05688c;
ctx->state[6] = 0x1f83d9ab;
ctx->state[7] = 0x5be0cd19;
}
void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len)
{
WORD i;
for (i = 0; i < len; ++i) {
ctx->data[ctx->datalen] = data[i];
ctx->datalen++;
if (ctx->datalen == 64) {
sha256_transform(ctx, ctx->data);
ctx->bitlen += 512;
ctx->datalen = 0;
}
}
}
void sha256_final(SHA256_CTX *ctx, BYTE hash[])
{
WORD i;
i = ctx->datalen;
// Pad whatever data is left in the buffer.
if (ctx->datalen < 56) {
ctx->data[i++] = 0x80;
while (i < 56)
ctx->data[i++] = 0x00;
}
else {
ctx->data[i++] = 0x80;
while (i < 64)
ctx->data[i++] = 0x00;
sha256_transform(ctx, ctx->data);
memset(ctx->data, 0, 56);
}
// Append to the padding the total message's length in bits and transform.
ctx->bitlen += ctx->datalen * 8;
ctx->data[63] = (BYTE)(ctx->bitlen);
ctx->data[62] = (BYTE)(ctx->bitlen >> 8);
ctx->data[61] = (BYTE)(ctx->bitlen >> 16);
ctx->data[60] = (BYTE)(ctx->bitlen >> 24);
ctx->data[59] = (BYTE)(ctx->bitlen >> 32);
ctx->data[58] = (BYTE)(ctx->bitlen >> 40);
ctx->data[57] = (BYTE)(ctx->bitlen >> 48);
ctx->data[56] = (BYTE)(ctx->bitlen >> 56);
sha256_transform(ctx, ctx->data);
// Since this implementation uses little endian byte ordering and SHA uses big endian,
// reverse all the bytes when copying the final state to the output hash.
for (i = 0; i < 4; ++i) {
hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff;
hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff;
hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff;
hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff;
hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff;
hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff;
hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff;
hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff;
}
}

34
3rdparty/exported/t_cose/crypto_adapters/b_con_hash/sha256.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,34 @@
/*********************************************************************
* Filename: sha256.h
* Author: Brad Conte (brad AT bradconte.com)
* Copyright:
* Disclaimer: This code is presented "as is" without any guarantees.
* Details: Defines the API for the corresponding SHA1 implementation.
*********************************************************************/
#ifndef SHA256_H
#define SHA256_H
/*************************** HEADER FILES ***************************/
#include <stddef.h>
/****************************** MACROS ******************************/
#define SHA256_BLOCK_SIZE 32 // SHA256 outputs a 32 byte digest
/**************************** DATA TYPES ****************************/
typedef unsigned char BYTE; // 8-bit byte
typedef unsigned int WORD; // 32-bit word, change to "long" for 16-bit machines
typedef struct {
BYTE data[64];
WORD datalen;
unsigned long long bitlen;
WORD state[8];
} SHA256_CTX;
/*********************** FUNCTION DECLARATIONS **********************/
void sha256_init(SHA256_CTX *ctx);
void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len);
void sha256_final(SHA256_CTX *ctx, BYTE hash[]);
#endif // SHA256_H

639
3rdparty/exported/t_cose/crypto_adapters/t_cose_openssl_crypto.c поставляемый Normal file
Просмотреть файл

@ -0,0 +1,639 @@
/*
* t_cose_openssl_crypto.c
*
* Copyright 2019-2022, Laurence Lundblade
*
* SPDX-License-Identifier: BSD-3-Clause
*
* See BSD-3-Clause license in README.md
*
* Created 3/31/2019.
*/
#include "t_cose_crypto.h" /* The interface this code implements */
#include <openssl/ecdsa.h> /* Needed for signature format conversion */
#include <openssl/evp.h>
#include <openssl/err.h>
/**
* \file t_cose_openssl_crypto.c
*
* \brief Crypto Adaptation for t_cose to use OpenSSL ECDSA and hashes.
*
* This connects up the abstracted crypto services defined in
* t_cose_crypto.h to the OpenSSL implementation of them.
*
* Having this adapter layer doesn't bloat the implementation as everything here
* had to be done anyway -- the mapping of algorithm IDs, the data format
* rearranging, the error code translation.
*
* This code should just work out of the box if compiled and linked
* against OpenSSL and with the T_COSE_USE_OPENSSL_CRYPTO preprocessor
* define set for the build.
*
* This works with OpenSSL 1.1.1 and 3.0. It uses the APIs common
* to these two and that are not marked for future deprecation.
*
* A few complaints about OpenSSL in comparison to Mbed TLS:
*
* OpenSSL mallocs for various things where MBed TLS does not.
* This makes the OpenSSL code more complex because checks for malloc
* failures are necessary.
*
* There's a lot of APIs in OpenSSL, but there's a needle to thread to
* get the APIS that are in 1.1.1, 3.0 and not slated for future
* deprecation.
*
* The APIs that fit the above only work for DER-encoded signatures.
* t_cose encodes signatures in a more simple way. This difference
* requires the code here to do conversion which increases its size
* and complexity and requires intermediate buffers and requires more
* use of malloc.
*
* An older version of t_cose (anything from 2021) uses simpler
* OpenSSL APIs. They still work but may be deprecated in the
* future. They could be used in use cases where a particular version
* of the OpenSSL library is selected and reduce code size
* a llittle.
*/
/**
* \brief Convert DER-encoded signature to COSE-serialized signature
*
* \param[in] key_len Size of the key in bytes -- governs sig size.
* \param[in] der_signature DER-encoded signature.
* \param[in] signature_buffer The buffer for output.
*
* \return The pointer and length of serialized signature in \c signature_buffer
or NULL_Q_USEFUL_BUF_C on error.
*
* The serialized format is defined by COSE in RFC 8152 section
* 8.1. The signature which consist of two integers, r and s,
* are simply zero padded to the nearest byte length and
* concatenated.
*/
static inline struct q_useful_buf_c
signature_der_to_cose(unsigned key_len,
struct q_useful_buf_c der_signature,
struct q_useful_buf signature_buffer)
{
size_t r_len;
size_t s_len;
const BIGNUM *r_bn;
const BIGNUM *s_bn;
struct q_useful_buf_c cose_signature;
void *r_start_ptr;
void *s_start_ptr;
const unsigned char *temp_der_sig_pointer;
ECDSA_SIG *es;
/* Put DER-encode sig into an ECDSA_SIG so we can get the r and s out. */
temp_der_sig_pointer = der_signature.ptr;
es = d2i_ECDSA_SIG(NULL, &temp_der_sig_pointer, (long)der_signature.len);
if(es == NULL) {
cose_signature = NULL_Q_USEFUL_BUF_C;
goto Done;
}
/* Zero the buffer so that bytes r and s are padded with zeros */
q_useful_buf_set(signature_buffer, 0);
/* Get the signature r and s as BIGNUMs */
r_bn = NULL;
s_bn = NULL;
ECDSA_SIG_get0(es, &r_bn, &s_bn);
/* ECDSA_SIG_get0 returns void */
/* Internal consistency check that the r and s values will fit
* into the expected size. Be sure the output buffer is not
* overrun.
*/
/* Cast is safe because BN_num_bytes() is documented to not return
* negative numbers.
*/
r_len = (size_t)BN_num_bytes(r_bn);
s_len = (size_t)BN_num_bytes(s_bn);
if(r_len + s_len > signature_buffer.len) {
cose_signature = NULL_Q_USEFUL_BUF_C;
goto Done2;
}
/* Copy r and s of signature to output buffer and set length */
r_start_ptr = (uint8_t *)(signature_buffer.ptr) + key_len - r_len;
BN_bn2bin(r_bn, r_start_ptr);
s_start_ptr = (uint8_t *)signature_buffer.ptr + 2 * key_len - s_len;
BN_bn2bin(s_bn, s_start_ptr);
cose_signature = (UsefulBufC){signature_buffer.ptr, 2 * key_len};
Done2:
ECDSA_SIG_free(es);
Done:
return cose_signature;
}
/**
* \brief Convert COSE-serialized signature to DER-encoded signature.
*
* \param[in] key_len Size of the key in bytes -- governs sig size.
* \param[in] cose_signature The COSE-serialized signature.
* \param[in] buffer Place to write DER-format signature.
* \param[out] der_signature The returned DER-encoded signature
*
* \return one of the \ref t_cose_err_t error codes.
*
* The serialized format is defined by COSE in RFC 8152 section
* 8.1. The signature which consist of two integers, r and s,
* are simply zero padded to the nearest byte length and
* concatenated.
*
* OpenSSL has a preference for DER-encoded signatures.
*
* This uses an ECDSA_SIG as an intermediary to convert
* between the two.
*/
static enum t_cose_err_t
signature_cose_to_der(unsigned key_len,
struct q_useful_buf_c cose_signature,
struct q_useful_buf buffer,
struct q_useful_buf_c *der_signature)
{
enum t_cose_err_t return_value;
BIGNUM *signature_r_bn = NULL;
BIGNUM *signature_s_bn = NULL;
int ossl_result;
ECDSA_SIG *signature;
unsigned char *der_signature_ptr;
int der_signature_len;
/* Check the signature length against expected */
if(cose_signature.len != key_len * 2) {
return_value = T_COSE_ERR_SIG_VERIFY;
goto Done;
}
/* Put the r and the s from the signature into big numbers */
signature_r_bn = BN_bin2bn(cose_signature.ptr, (int)key_len, NULL);
if(signature_r_bn == NULL) {
return_value = T_COSE_ERR_INSUFFICIENT_MEMORY;
goto Done;
}
signature_s_bn = BN_bin2bn(((const uint8_t *)cose_signature.ptr)+key_len,
(int)key_len,
NULL);
if(signature_s_bn == NULL) {
BN_free(signature_r_bn);
return_value = T_COSE_ERR_INSUFFICIENT_MEMORY;
goto Done;
}
/* Put the signature bytes into an ECDSA_SIG */
signature = ECDSA_SIG_new();
if(signature == NULL) {
/* Don't leak memory in error condition */
BN_free(signature_r_bn);
BN_free(signature_s_bn);
return_value = T_COSE_ERR_INSUFFICIENT_MEMORY;
goto Done;
}
/* Put the r and s bignums into an ECDSA_SIG. Freeing
* ossl_sig_to_verify will now free r and s.
*/
ossl_result = ECDSA_SIG_set0(signature,
signature_r_bn,
signature_s_bn);
if(ossl_result != 1) {
BN_free(signature_r_bn);
BN_free(signature_s_bn);
return_value = T_COSE_ERR_SIG_FAIL;
goto Done;
}
/* Now output the ECDSA_SIG structure in DER format.
*
* Code safety is the priority here. i2d_ECDSA_SIG() has two
* output buffer modes, one where it just writes to the buffer
* given and the other were it allocates memory. It would be
* better to avoid the allocation, but the copy mode is not safe
* because you can't give it a buffer length. This is bad stuff
* from last century.
*
* So the allocation mode is used on the presumption that it is
* safe and correct even though there is more copying and memory
* use.
*/
der_signature_ptr = NULL;
der_signature_len = i2d_ECDSA_SIG(signature, &der_signature_ptr);
ECDSA_SIG_free(signature);
if(der_signature_len < 0) {
return_value = T_COSE_ERR_SIG_FAIL;
goto Done;
}
*der_signature = q_useful_buf_copy_ptr(buffer,
der_signature_ptr,
(size_t)der_signature_len);
if(q_useful_buf_c_is_null_or_empty(*der_signature)) {
return_value = T_COSE_ERR_SIG_FAIL;
goto Done;
}
OPENSSL_free(der_signature_ptr);
return_value = T_COSE_SUCCESS;
Done:
/* All the memory frees happen along the way in the code above. */
return return_value;
}
/**
* \brief Common checks and conversions for signing and verification key.
*
* \param[in] t_cose_key The key to check and convert.
* \param[out] return_ossl_ec_key The OpenSSL key in memory.
* \param[out] return_key_size_in_bytes How big the key is.
*
* \return Error or \ref T_COSE_SUCCESS.
*
* It pulls the OpenSSL key out of \c t_cose_key and checks
* it and figures out the number of bytes in the key rounded up. This
* is also the size of r and s in the signature.
*/
static enum t_cose_err_t
key_convert_and_size(struct t_cose_key t_cose_key,
EVP_PKEY **return_ossl_ec_key,
unsigned *return_key_size_in_bytes)
{
enum t_cose_err_t return_value;
int key_len_bits; /* type unsigned is conscious choice */
unsigned key_len_bytes; /* type unsigned is conscious choice */
EVP_PKEY *ossl_ec_key;
/* Check the signing key and get it out of the union */
if(t_cose_key.crypto_lib != T_COSE_CRYPTO_LIB_OPENSSL) {
return_value = T_COSE_ERR_INCORRECT_KEY_FOR_LIB;
goto Done;
}
if(t_cose_key.k.key_ptr == NULL) {
return_value = T_COSE_ERR_EMPTY_KEY;
goto Done;
}
ossl_ec_key = (EVP_PKEY *)t_cose_key.k.key_ptr;
key_len_bits = EVP_PKEY_bits(ossl_ec_key);
/* Calculation of size per RFC 8152 section 8.1 -- round up to
* number of bytes. */
key_len_bytes = (unsigned)key_len_bits / 8;
if(key_len_bits % 8) {
key_len_bytes++;
}
*return_key_size_in_bytes = key_len_bytes;
*return_ossl_ec_key = ossl_ec_key;
return_value = T_COSE_SUCCESS;
Done:
return return_value;
}
/*
* Public Interface. See documentation in t_cose_crypto.h
*/
enum t_cose_err_t t_cose_crypto_sig_size(int32_t cose_algorithm_id,
struct t_cose_key signing_key,
size_t *sig_size)
{
enum t_cose_err_t return_value;
unsigned key_len_bytes;
EVP_PKEY *signing_key_evp; /* Unused */
if(!t_cose_algorithm_is_ecdsa(cose_algorithm_id)) {
return_value = T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
goto Done;
}
return_value = key_convert_and_size(signing_key, &signing_key_evp, &key_len_bytes);
if(return_value != T_COSE_SUCCESS) {
goto Done;
}
/* Double because signature is made of up r and s values */
*sig_size = key_len_bytes * 2;
return_value = T_COSE_SUCCESS;
Done:
return return_value;
}
/*
* See documentation in t_cose_crypto.h
*/
enum t_cose_err_t
t_cose_crypto_sign(const int32_t cose_algorithm_id,
const struct t_cose_key signing_key,
const struct q_useful_buf_c hash_to_sign,
const struct q_useful_buf signature_buffer,
struct q_useful_buf_c *signature)
{
/* This is the overhead for the DER encoding of an EC signature as
* described by ECDSA-Sig-Value in RFC 3279. It is at max 3 * (1
* type byte and 2 length bytes) + 2 zero pad bytes = 11
* bytes. We make it 16 to have a little extra. It is expected that
* EVP_PKEY_sign() will not over write the buffer so there will
* be no security problem if this is too short. */
#define DER_SIG_ENCODE_OVER_HEAD 16
enum t_cose_err_t return_value;
EVP_PKEY_CTX *sign_context;
EVP_PKEY *signing_key_evp;
int ossl_result;
unsigned key_size_bytes;
MakeUsefulBufOnStack( der_format_signature, T_COSE_MAX_SIG_SIZE + DER_SIG_ENCODE_OVER_HEAD);
/* This implementation supports only ECDSA so far. The
* interface allows it to support other, but none are implemented.
*
* This implementation works for different key lengths and
* curves. That is, the curve and key length is associated with
* the signing_key passed in, not the cose_algorithm_id This
* check looks for ECDSA signing as indicated by COSE and rejects
* what is not since it only supports ECDSA.
*/
if(!t_cose_algorithm_is_ecdsa(cose_algorithm_id)) {
return_value = T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
goto Done2;
}
/* Pull the pointer to the OpenSSL-format EVP_PKEY out of the
* t_cose key structure and get the key size. */
return_value = key_convert_and_size(signing_key, &signing_key_evp, &key_size_bytes);
if(return_value != T_COSE_SUCCESS) {
goto Done2;
}
/* Create and initialize the OpenSSL EVP_PKEY_CTX that is the
* signing context. */
sign_context = EVP_PKEY_CTX_new(signing_key_evp, NULL);
if(sign_context == NULL) {
return_value = T_COSE_ERR_INSUFFICIENT_MEMORY;
goto Done;
}
ossl_result = EVP_PKEY_sign_init(sign_context);
if(ossl_result != 1) {
return_value = T_COSE_ERR_SIG_FAIL;
goto Done;
}
/* Actually do the signature operation. */
ossl_result = EVP_PKEY_sign(sign_context,
der_format_signature.ptr, &der_format_signature.len,
hash_to_sign.ptr, hash_to_sign.len);
if(ossl_result != 1) {
return_value = T_COSE_ERR_SIG_FAIL;
goto Done;
}
/* The signature produced by OpenSSL is DER-encoded. That encoding
* has to be removed and turned into the serialization format used
* by COSE. It is unfortunate that the OpenSSL APIs that create
* signatures that are not in DER-format are slated for
* deprecation.
*/
*signature = signature_der_to_cose((unsigned)key_size_bytes,
q_usefulbuf_const(der_format_signature),
signature_buffer);
if(q_useful_buf_c_is_null(*signature)) {
return_value = T_COSE_ERR_SIG_FAIL;
goto Done;
}
/* Everything succeeded */
return_value = T_COSE_SUCCESS;
Done:
/* This checks for NULL before free, so it is not
* necessary to check for NULL here.
*/
EVP_PKEY_CTX_free(sign_context);
Done2:
return return_value;
}
/*
* See documentation in t_cose_crypto.h
*/
enum t_cose_err_t
t_cose_crypto_verify(const int32_t cose_algorithm_id,
const struct t_cose_key verification_key,
const struct q_useful_buf_c kid,
const struct q_useful_buf_c hash_to_verify,
const struct q_useful_buf_c cose_signature)
{
int ossl_result;
enum t_cose_err_t return_value;
EVP_PKEY_CTX *verify_context = NULL;
EVP_PKEY *verification_key_evp;
unsigned key_size;
MakeUsefulBufOnStack( der_format_buffer, T_COSE_MAX_SIG_SIZE + DER_SIG_ENCODE_OVER_HEAD);
struct q_useful_buf_c der_format_signature;
/* This implementation doesn't use any key store with the ability
* to look up a key based on kid. */
(void)kid;
if(!t_cose_algorithm_is_ecdsa(cose_algorithm_id)) {
return_value = T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
goto Done;
}
/* Get the verification key in an EVP_PKEY structure which is what
* is needed for sig verification. This also gets the key size
* which is needed to convert the format of the signature. */
return_value = key_convert_and_size(verification_key,
&verification_key_evp,
&key_size);
if(return_value != T_COSE_SUCCESS) {
goto Done;
}
/* Unfortunately the officially supported OpenSSL API supports
* only DER-encoded signatures so the COSE format signatures must
* be converted to DER for verification. This requires a temporary
* buffer and a fair bit of work inside signature_cose_to_der().
*/
return_value = signature_cose_to_der(key_size,
cose_signature,
der_format_buffer,
&der_format_signature);
if(return_value) {
goto Done;
}
/* Create the verification context and set it up with the
* necessary verification key.
*/
verify_context = EVP_PKEY_CTX_new(verification_key_evp, NULL);
if(verify_context == NULL) {
return_value = T_COSE_ERR_INSUFFICIENT_MEMORY;
goto Done;
}
ossl_result = EVP_PKEY_verify_init(verify_context);
if(ossl_result != 1) {
return_value = T_COSE_ERR_SIG_FAIL;
goto Done;
}
/* Actually do the signature verification */
ossl_result = EVP_PKEY_verify(verify_context,
der_format_signature.ptr,
der_format_signature.len,
hash_to_verify.ptr,
hash_to_verify.len);
if(ossl_result == 0) {
/* The operation succeeded, but the signature doesn't match */
return_value = T_COSE_ERR_SIG_VERIFY;
goto Done;
} else if (ossl_result != 1) {
/* Failed before even trying to verify the signature */
return_value = T_COSE_ERR_SIG_FAIL;
goto Done;
}
/* Everything succeeded */
return_value = T_COSE_SUCCESS;
Done:
EVP_PKEY_CTX_free(verify_context);
return return_value;
}
/*
* See documentation in t_cose_crypto.h
*/
enum t_cose_err_t
t_cose_crypto_hash_start(struct t_cose_crypto_hash *hash_ctx,
int32_t cose_hash_alg_id)
{
int ossl_result;
int nid;
const EVP_MD *message_digest;
switch(cose_hash_alg_id) {
case COSE_ALGORITHM_SHA_256:
nid = NID_sha256;
break;
#ifndef T_COSE_DISABLE_ES384
case COSE_ALGORITHM_SHA_384:
nid = NID_sha384;
break;
#endif
#ifndef T_COSE_DISABLE_ES512
case COSE_ALGORITHM_SHA_512:
nid = NID_sha512;
break;
#endif
default:
return T_COSE_ERR_UNSUPPORTED_HASH;
}
message_digest = EVP_get_digestbynid(nid);
if(message_digest == NULL){
return T_COSE_ERR_UNSUPPORTED_HASH;
}
hash_ctx->evp_ctx = EVP_MD_CTX_new();
if(hash_ctx->evp_ctx == NULL) {
return T_COSE_ERR_INSUFFICIENT_MEMORY;
}
ossl_result = EVP_DigestInit_ex(hash_ctx->evp_ctx, message_digest, NULL);
if(ossl_result == 0) {
EVP_MD_CTX_free(hash_ctx->evp_ctx);
return T_COSE_ERR_HASH_GENERAL_FAIL;
}
hash_ctx->cose_hash_alg_id = cose_hash_alg_id;
hash_ctx->update_error = 1; /* 1 is success in OpenSSL */
return T_COSE_SUCCESS;
}
/*
* See documentation in t_cose_crypto.h
*/
void
t_cose_crypto_hash_update(struct t_cose_crypto_hash *hash_ctx,
struct q_useful_buf_c data_to_hash)
{
if(hash_ctx->update_error) { /* 1 is no error, 0 means error for OpenSSL */
if(data_to_hash.ptr) {
hash_ctx->update_error = EVP_DigestUpdate(hash_ctx->evp_ctx,
data_to_hash.ptr,
data_to_hash.len);
}
}
}
/*
* See documentation in t_cose_crypto.h
*/
enum t_cose_err_t
t_cose_crypto_hash_finish(struct t_cose_crypto_hash *hash_ctx,
struct q_useful_buf buffer_to_hold_result,
struct q_useful_buf_c *hash_result)
{
int ossl_result;
unsigned int hash_result_len;
if(!hash_ctx->update_error) {
return T_COSE_ERR_HASH_GENERAL_FAIL;
}
hash_result_len = (unsigned int)buffer_to_hold_result.len;
ossl_result = EVP_DigestFinal_ex(hash_ctx->evp_ctx,
buffer_to_hold_result.ptr,
&hash_result_len);
*hash_result = (UsefulBufC){buffer_to_hold_result.ptr, hash_result_len};
EVP_MD_CTX_free(hash_ctx->evp_ctx);
/* OpenSSL returns 1 for success, not 0 */
return ossl_result ? T_COSE_SUCCESS : T_COSE_ERR_HASH_GENERAL_FAIL;
}

369
3rdparty/exported/t_cose/crypto_adapters/t_cose_psa_crypto.c поставляемый Normal file
Просмотреть файл

@ -0,0 +1,369 @@
/*
* t_cose_psa_crypto.c
*
* Copyright 2019-2022, Laurence Lundblade
*
* SPDX-License-Identifier: BSD-3-Clause
*
* See BSD-3-Clause license in README.md
*/
/**
* \file t_cose_psa_crypto.c
*
* \brief Crypto Adaptation for t_cose to use ARM's PSA ECDSA and hashes.
*
* This connects up the abstract interface in t_cose_crypto.h to the
* implementations of ECDSA signing and hashing in ARM's Mbed TLS crypto
* library that implements the Arm PSA 1.0 crypto API.
*
* This adapter layer doesn't bloat the implementation as everything
* here had to be done anyway -- the mapping of algorithm IDs, the
* data format rearranging, the error code translation.
*
* This code should just work out of the box if compiled and linked
* against ARM's PSA crypto. No preprocessor #defines are needed.
*
* You can disable SHA-384 and SHA-512 to save code and space by
* defining T_COSE_DISABLE_ES384 or T_COSE_DISABLE_ES512. This saving
* is most in stack space in the main t_cose implementation. (It seems
* likely that changes to PSA itself would be needed to remove the
* SHA-384 and SHA-512 implementations to save that code. Lack of
* reference and dead stripping the executable won't do it).
*/
#include "t_cose_crypto.h" /* The interface this implements */
#include <psa/crypto.h> /* PSA Crypto Interface to mbed crypto or such */
/* Avoid compiler warning due to unused argument */
#define ARG_UNUSED(arg) (void)(arg)
/**
* \brief Map a COSE signing algorithm ID to a PSA signing algorithm ID
*
* \param[in] cose_alg_id The COSE algorithm ID.
*
* \return The PSA algorithm ID or 0 if this doesn't map the COSE ID.
*/
static psa_algorithm_t cose_alg_id_to_psa_alg_id(int32_t cose_alg_id)
{
/* The #ifdefs save a little code when algorithms are disabled */
return cose_alg_id == COSE_ALGORITHM_ES256 ? PSA_ALG_ECDSA(PSA_ALG_SHA_256) :
#ifndef T_COSE_DISABLE_ES384
cose_alg_id == COSE_ALGORITHM_ES384 ? PSA_ALG_ECDSA(PSA_ALG_SHA_384) :
#endif
#ifndef T_COSE_DISABLE_ES512
cose_alg_id == COSE_ALGORITHM_ES512 ? PSA_ALG_ECDSA(PSA_ALG_SHA_512) :
#endif
0;
/* psa/crypto_values.h doesn't seem to define a "no alg" value,
* but zero seems OK for that use in the ECDSA context. */
}
/**
* \brief Map a PSA error into a t_cose error for signing.
*
* \param[in] err The PSA status.
*
* \return The \ref t_cose_err_t.
*/
static enum t_cose_err_t psa_status_to_t_cose_error_signing(psa_status_t err)
{
/* Intentionally keeping to fewer mapped errors to save object code */
return err == PSA_SUCCESS ? T_COSE_SUCCESS :
err == PSA_ERROR_INVALID_SIGNATURE ? T_COSE_ERR_SIG_VERIFY :
err == PSA_ERROR_NOT_SUPPORTED ? T_COSE_ERR_UNSUPPORTED_SIGNING_ALG:
err == PSA_ERROR_INSUFFICIENT_MEMORY ? T_COSE_ERR_INSUFFICIENT_MEMORY :
err == PSA_ERROR_CORRUPTION_DETECTED ? T_COSE_ERR_TAMPERING_DETECTED :
T_COSE_ERR_SIG_FAIL;
}
/*
* See documentation in t_cose_crypto.h
*/
enum t_cose_err_t
t_cose_crypto_verify(int32_t cose_algorithm_id,
struct t_cose_key verification_key,
struct q_useful_buf_c kid,
struct q_useful_buf_c hash_to_verify,
struct q_useful_buf_c signature)
{
psa_algorithm_t psa_alg_id;
psa_status_t psa_result;
enum t_cose_err_t return_value;
mbedtls_svc_key_id_t verification_key_psa;
/* This implementation does no look up keys by kid in the key
* store */
ARG_UNUSED(kid);
/* Convert to PSA algorithm ID scheme */
psa_alg_id = cose_alg_id_to_psa_alg_id(cose_algorithm_id);
/* This implementation supports ECDSA and only ECDSA. The
* interface allows it to support other, but none are implemented.
* This implementation works for different keys lengths and
* curves. That is the curve and key length as associated with the
* signing_key passed in, not the cose_algorithm_id This check
* looks for ECDSA signing as indicated by COSE and rejects what
* is not. (Perhaps this check can be removed to save object code
* if it is the case that psa_verify_hash() does the right
* checks).
*/
if(!PSA_ALG_IS_ECDSA(psa_alg_id)) {
return_value = T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
goto Done;
}
verification_key_psa = (mbedtls_svc_key_id_t)verification_key.k.key_handle;
psa_result = psa_verify_hash(verification_key_psa,
psa_alg_id,
hash_to_verify.ptr,
hash_to_verify.len,
signature.ptr,
signature.len);
return_value = psa_status_to_t_cose_error_signing(psa_result);
Done:
return return_value;
}
/*
* See documentation in t_cose_crypto.h
*/
enum t_cose_err_t
t_cose_crypto_sign(int32_t cose_algorithm_id,
struct t_cose_key signing_key,
struct q_useful_buf_c hash_to_sign,
struct q_useful_buf signature_buffer,
struct q_useful_buf_c *signature)
{
enum t_cose_err_t return_value;
psa_status_t psa_result;
psa_algorithm_t psa_alg_id;
mbedtls_svc_key_id_t signing_key_psa;
size_t signature_len;
psa_alg_id = cose_alg_id_to_psa_alg_id(cose_algorithm_id);
/* This implementation supports ECDSA and only ECDSA. The
* interface allows it to support other, but none are implemented.
* This implementation works for different keys lengths and
* curves. That is the curve and key length as associated with the
* signing_key passed in, not the cose_algorithm_id This check
* looks for ECDSA signing as indicated by COSE and rejects what
* is not. (Perhaps this check can be removed to save object code
* if it is the case that psa_verify_hash() does the right
* checks).
*/
if(!PSA_ALG_IS_ECDSA(psa_alg_id)) {
return_value = T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
goto Done;
}
signing_key_psa = (mbedtls_svc_key_id_t)signing_key.k.key_handle;
/* It is assumed that this call is checking the signature_buffer
* length and won't write off the end of it.
*/
psa_result = psa_sign_hash(signing_key_psa,
psa_alg_id,
hash_to_sign.ptr,
hash_to_sign.len,
signature_buffer.ptr, /* Sig buf */
signature_buffer.len, /* Sig buf size */
&signature_len); /* Sig length */
return_value = psa_status_to_t_cose_error_signing(psa_result);
if(return_value == T_COSE_SUCCESS) {
/* Success, fill in the return useful_buf */
signature->ptr = signature_buffer.ptr;
signature->len = signature_len;
}
Done:
return return_value;
}
/*
* See documentation in t_cose_crypto.h
*/
enum t_cose_err_t t_cose_crypto_sig_size(int32_t cose_algorithm_id,
struct t_cose_key signing_key,
size_t *sig_size)
{
enum t_cose_err_t return_value;
mbedtls_svc_key_id_t signing_key_psa;
size_t key_len_bits;
size_t key_len_bytes;
psa_key_attributes_t key_attributes;
psa_status_t status;
/* If desperate to save code, this can return the constant
* T_COSE_MAX_SIG_SIZE instead of doing an exact calculation. The
* buffer size calculation will return too large of a value and
* waste a little heap / stack, but everything will still work
* (except the tests that test for exact values will fail). This
* will save 100 bytes or so of object code.
*/
if(!t_cose_algorithm_is_ecdsa(cose_algorithm_id)) {
return_value = T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
goto Done;
}
signing_key_psa = (mbedtls_svc_key_id_t)signing_key.k.key_handle;
key_attributes = psa_key_attributes_init();
status = psa_get_key_attributes(signing_key_psa, &key_attributes);
key_len_bits = psa_get_key_bits(&key_attributes);
return_value = psa_status_to_t_cose_error_signing(status);
if(return_value == T_COSE_SUCCESS) {
/* Calculation of size per RFC 8152 section 8.1 -- round up to
* number of bytes. */
key_len_bytes = key_len_bits / 8;
if(key_len_bits % 8) {
key_len_bytes++;
}
/* Double because signature is made of up r and s values */
*sig_size = key_len_bytes * 2;
}
return_value = T_COSE_SUCCESS;
Done:
return return_value;
}
/**
* \brief Convert COSE hash algorithm ID to a PSA hash algorithm ID
*
* \param[in] cose_hash_alg_id The COSE-based ID for the
*
* \return PSA-based hash algorithm ID, or USHRT_MAX on error.
*
*/
static inline psa_algorithm_t
cose_hash_alg_id_to_psa(int32_t cose_hash_alg_id)
{
return cose_hash_alg_id == COSE_ALGORITHM_SHA_256 ? PSA_ALG_SHA_256 :
#ifndef T_COSE_DISABLE_ES384
cose_hash_alg_id == COSE_ALGORITHM_SHA_384 ? PSA_ALG_SHA_384 :
#endif
#ifndef T_COSE_DISABLE_ES512
cose_hash_alg_id == COSE_ALGORITHM_SHA_512 ? PSA_ALG_SHA_512 :
#endif
UINT16_MAX;
}
/**
* \brief Map a PSA error into a t_cose error for hashes.
*
* \param[in] status The PSA status.
*
* \return The \ref t_cose_err_t.
*/
static enum t_cose_err_t
psa_status_to_t_cose_error_hash(psa_status_t status)
{
/* Intentionally limited to just this minimum set of errors to
* save object code as hashes don't really fail much
*/
return status == PSA_SUCCESS ? T_COSE_SUCCESS :
status == PSA_ERROR_NOT_SUPPORTED ? T_COSE_ERR_UNSUPPORTED_HASH :
status == PSA_ERROR_INVALID_ARGUMENT ? T_COSE_ERR_UNSUPPORTED_HASH :
status == PSA_ERROR_BUFFER_TOO_SMALL ? T_COSE_ERR_HASH_BUFFER_SIZE :
T_COSE_ERR_HASH_GENERAL_FAIL;
}
/*
* See documentation in t_cose_crypto.h
*/
enum t_cose_err_t t_cose_crypto_hash_start(struct t_cose_crypto_hash *hash_ctx,
int32_t cose_hash_alg_id)
{
psa_algorithm_t psa_alg;
/* Map the algorithm ID */
psa_alg = cose_hash_alg_id_to_psa(cose_hash_alg_id);
/* initialize PSA hash context */
hash_ctx->ctx = psa_hash_operation_init();
/* Actually do the hash set up */
hash_ctx->status = psa_hash_setup(&(hash_ctx->ctx), psa_alg);
/* Map errors and return */
return psa_status_to_t_cose_error_hash((psa_status_t)hash_ctx->status);
}
/*
* See documentation in t_cose_crypto.h
*/
void t_cose_crypto_hash_update(struct t_cose_crypto_hash *hash_ctx,
struct q_useful_buf_c data_to_hash)
{
if(hash_ctx->status != PSA_SUCCESS) {
/* In error state. Nothing to do. */
return;
}
if(data_to_hash.ptr == NULL) {
/* This allows for NULL buffers to be passed in all the way at
* the top of signer or message creator when all that is
* happening is the size of the result is being computed.
*/
return;
}
/* Actually hash the data */
hash_ctx->status = psa_hash_update(&(hash_ctx->ctx),
data_to_hash.ptr,
data_to_hash.len);
}
/*
* See documentation in t_cose_crypto.h
*/
enum t_cose_err_t
t_cose_crypto_hash_finish(struct t_cose_crypto_hash *hash_ctx,
struct q_useful_buf buffer_to_hold_result,
struct q_useful_buf_c *hash_result)
{
if(hash_ctx->status != PSA_SUCCESS) {
/* Error state. Nothing to do */
goto Done;
}
/* Actually finish up the hash */
hash_ctx->status = psa_hash_finish(&(hash_ctx->ctx),
buffer_to_hold_result.ptr,
buffer_to_hold_result.len,
&(hash_result->len));
hash_result->ptr = buffer_to_hold_result.ptr;
Done:
return psa_status_to_t_cose_error_hash(hash_ctx->status);
}

170
3rdparty/exported/t_cose/crypto_adapters/t_cose_test_crypto.c поставляемый Normal file
Просмотреть файл

@ -0,0 +1,170 @@
/*
* t_cose_test_crypto.c
*
* Copyright 2019-2020, Laurence Lundblade
*
* SPDX-License-Identifier: BSD-3-Clause
*
* See BSD-3-Clause license in README.md
*
* Created 3/31/2019.
*/
#include "t_cose_crypto.h"
/*
* This file is stub crypto for initial bring up and test of t_cose.
* It is NOT intended for commercial use. When this file is used as
* the crypto adapter, no external crypto library is necessary. This is
* convenient because sometime it takes a while to sort out the crypto
* porting layer for a new platform. With this most of t_cose can be tested
* and demo signatures (short-circuit signatures) can be generated to
* simulate out this would work.
*
* This file uses no signature algorithm. It uses the Brad Conte hash
* implementation that is bundled with t_cose for the purpose of this
* testing, not for commercial use.
*/
/* The Brad Conte hash implementaiton bundled with t_cose */
#include "sha256.h"
/* Use of this file requires definition of T_COSE_USE_B_CON_SHA256 when
* making t_cose_crypto.h.
*
* This only implements SHA-256 as that is all that is needed for the
* non signing and verification tests using short-circuit signatures.
*/
#ifdef T_COSE_ENABLE_HASH_FAIL_TEST
/* Global variable just for this particular test. Not thread
* safe or good for commercial use.
*/
int hash_test_mode = 0;
#endif
/*
* See documentation in t_cose_crypto.h
*/
enum t_cose_err_t t_cose_crypto_sig_size(int32_t cose_algorithm_id,
struct t_cose_key signing_key,
size_t *sig_size)
{
(void)cose_algorithm_id;
(void)signing_key;
*sig_size = T_COSE_MAX_SIG_SIZE;
return T_COSE_SUCCESS;
}
/*
* See documentation in t_cose_crypto.h
*/
enum t_cose_err_t
t_cose_crypto_sign(int32_t cose_algorithm_id,
struct t_cose_key signing_key,
struct q_useful_buf_c hash_to_sign,
struct q_useful_buf signature_buffer,
struct q_useful_buf_c *signature)
{
(void)cose_algorithm_id;
(void)signing_key;
(void)hash_to_sign;
(void)signature_buffer;
(void)signature;
return T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
}
/*
* See documentation in t_cose_crypto.h
*/
enum t_cose_err_t
t_cose_crypto_verify(int32_t cose_algorithm_id,
struct t_cose_key verification_key,
struct q_useful_buf_c kid,
struct q_useful_buf_c hash_to_verify,
struct q_useful_buf_c signature)
{
(void)cose_algorithm_id;
(void)verification_key;
(void)kid;
(void)hash_to_verify;
(void)signature;
return T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
}
/*
* Public function, see t_cose_make_test_pub_key.h
*/
int check_for_key_pair_leaks()
{
/* No check for leaks with this stubbed out crypto. With this test
crypto there is no file with code to make keys so there is no place
but here for this function to live.
*/
return 0;
}
/*
* See documentation in t_cose_crypto.h
*/
enum t_cose_err_t
t_cose_crypto_hash_start(struct t_cose_crypto_hash *hash_ctx,
int32_t cose_hash_alg_id)
{
#ifdef T_COSE_ENABLE_HASH_FAIL_TEST
if(hash_test_mode == 1) {
return T_COSE_ERR_HASH_GENERAL_FAIL;
}
#endif
if(cose_hash_alg_id != COSE_ALGORITHM_SHA_256) {
return T_COSE_ERR_UNSUPPORTED_HASH;
}
sha256_init(&(hash_ctx->b_con_hash_context));
return 0;
}
/*
* See documentation in t_cose_crypto.h
*/
void t_cose_crypto_hash_update(struct t_cose_crypto_hash *hash_ctx,
struct q_useful_buf_c data_to_hash)
{
if(data_to_hash.ptr) {
sha256_update(&(hash_ctx->b_con_hash_context),
data_to_hash.ptr,
data_to_hash.len);
}
}
/*
* See documentation in t_cose_crypto.h
*/
enum t_cose_err_t
t_cose_crypto_hash_finish(struct t_cose_crypto_hash *hash_ctx,
struct q_useful_buf buffer_to_hold_result,
struct q_useful_buf_c *hash_result)
{
#ifdef T_COSE_ENABLE_HASH_FAIL_TEST
if(hash_test_mode == 2) {
return T_COSE_ERR_HASH_GENERAL_FAIL;
}
#endif
sha256_final(&(hash_ctx->b_con_hash_context), buffer_to_hold_result.ptr);
*hash_result = (UsefulBufC){buffer_to_hold_result.ptr, 32};
return 0;
}

544
3rdparty/exported/t_cose/examples/t_cose_basic_example_ossl.c поставляемый Normal file
Просмотреть файл

@ -0,0 +1,544 @@
/*
* t_cose_basic_example_ossl.c
*
* Copyright 2019-2022, Laurence Lundblade
*
* SPDX-License-Identifier: BSD-3-Clause
*
* See BSD-3-Clause license in README.md
*/
/**
* \file t_cose_basic_example_ossl.c
*
* \brief Example code for signing and verifying a COSE_Sign1 message
* using OpenSSL
*
* This file has simple code to sign a payload and verify it.
*
* This works with OpenSSL. It assumes t_cose has been wired up to the
* OpenSSL crypto library and hase code specific to OpenSSL to make an
* EC key pair. See t_cose README for more details on how integration
* with crypto libraries works.
*/
#include "t_cose/t_cose_common.h"
#include "t_cose/t_cose_sign1_sign.h"
#include "t_cose/t_cose_sign1_verify.h"
#include "t_cose/q_useful_buf.h"
#include <stdio.h>
#include "openssl/ecdsa.h"
#include "openssl/err.h"
#include "openssl/evp.h"
/**
* \brief Make an EC key pair in OpenSSL library form.
*
* \param[in] cose_algorithm_id The algorithm to sign with, for example
* \ref T_COSE_ALGORITHM_ES256.
* \param[out] key_pair The key pair. This must be freed.
*
* The key made here is fixed and just useful for testing.
*/
enum t_cose_err_t make_ossl_ecdsa_key_pair(int32_t cose_algorithm_id,
struct t_cose_key *key_pair)
{
enum t_cose_err_t return_value;
int ossl_result;
int ossl_nid;
EVP_PKEY *pkey = NULL;
EVP_PKEY_CTX *ctx;
switch (cose_algorithm_id) {
case T_COSE_ALGORITHM_ES256:
ossl_nid = NID_X9_62_prime256v1;
break;
case T_COSE_ALGORITHM_ES384:
ossl_nid = NID_secp384r1;
break;
case T_COSE_ALGORITHM_ES512:
ossl_nid = NID_secp521r1;
break;
default:
return T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
}
ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
if(ctx == NULL) {
return_value = T_COSE_ERR_INSUFFICIENT_MEMORY;
goto Done;
}
if (EVP_PKEY_keygen_init(ctx) <= 0) {
return_value = T_COSE_ERR_FAIL;
goto Done;
}
ossl_result = EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, ossl_nid);
if(ossl_result != 1) {
return_value = T_COSE_ERR_FAIL;
goto Done;
}
pkey = EVP_PKEY_new();
ossl_result = EVP_PKEY_keygen(ctx, &pkey);
if(ossl_result != 1) {
return_value = T_COSE_ERR_FAIL;
goto Done;
}
key_pair->k.key_ptr = pkey;
key_pair->crypto_lib = T_COSE_CRYPTO_LIB_OPENSSL;
return_value = T_COSE_SUCCESS;
Done:
return return_value;
}
/**
* \brief Free a PSA / MBed key.
*
* \param[in] key_pair The key pair to close / deallocate / free.
*/
void free_ossl_ecdsa_key_pair(struct t_cose_key key_pair)
{
EVP_PKEY_free(key_pair.k.key_ptr);
}
/**
* \brief Print a q_useful_buf_c on stdout in hex ASCII text.
*
* \param[in] string_label A string label to output first
* \param[in] buf The q_useful_buf_c to output.
*
* This is just for pretty printing.
*/
static void print_useful_buf(const char *string_label, struct q_useful_buf_c buf)
{
if(string_label) {
printf("%s", string_label);
}
printf(" %ld bytes\n", buf.len);
printf(" ");
size_t i;
for(i = 0; i < buf.len; i++) {
const uint8_t Z = ((const uint8_t *)buf.ptr)[i];
printf("%02x ", Z);
if((i % 8) == 7) {
printf("\n ");
}
}
printf("\n");
fflush(stdout);
}
/**
* \brief Sign and verify example with one-step signing
*
* The one-step (plus init and key set up) signing uses more memory, but
* is simpler to use. In the code below constructed_payload_buffer is
* the extra buffer that two-step signing avoids.
*/
int32_t one_step_sign_example()
{
struct t_cose_sign1_sign_ctx sign_ctx;
enum t_cose_err_t return_value;
Q_USEFUL_BUF_MAKE_STACK_UB( signed_cose_buffer, 300);
struct q_useful_buf_c signed_cose;
Q_USEFUL_BUF_MAKE_STACK_UB( constructed_payload_buffer, 300);
struct q_useful_buf_c constructed_payload;
struct q_useful_buf_c returned_payload;
struct t_cose_key key_pair;
struct t_cose_sign1_verify_ctx verify_ctx;
QCBOREncodeContext cbor_encode;
QCBORError qcbor_result;
/* ------ Construct the payload ------
*
* The payload is constructed into its own continguous buffer.
* In this case the payload is CBOR format so it uses QCBOR to
* encode it, but CBOR is not required for COSE payloads so it could
* be anything at all.
*
* The payload constructed here is a map of some label-value
* pairs similar to a CWT or EAT, but using string labels
* rather than integers. It is just a little example.
*/
QCBOREncode_Init(&cbor_encode, constructed_payload_buffer);
QCBOREncode_OpenMap(&cbor_encode);
QCBOREncode_AddSZStringToMap(&cbor_encode, "BeingType", "Humanoid");
QCBOREncode_AddSZStringToMap(&cbor_encode, "Greeting", "We come in peace");
QCBOREncode_AddInt64ToMap(&cbor_encode, "ArmCount", 2);
QCBOREncode_AddInt64ToMap(&cbor_encode, "HeadCount", 1);
QCBOREncode_AddSZStringToMap(&cbor_encode, "BrainSize", "medium");
QCBOREncode_AddBoolToMap(&cbor_encode, "DrinksWater", true);
QCBOREncode_CloseMap(&cbor_encode);
qcbor_result = QCBOREncode_Finish(&cbor_encode, &constructed_payload);
printf("Encoded payload (size = %ld): %d (%s)\n",
constructed_payload.len,
qcbor_result,
qcbor_result ? "fail" : "success");
if(qcbor_result) {
return_value = (enum t_cose_err_t)qcbor_result;
goto Done;
}
/* ------ Make an ECDSA key pair ------
*
* The key pair will be used for both signing and encryption. The
* data type is struct t_cose_key on the outside, but internally
* the format is that of the crypto library used, PSA in this
* case. They key is just passed through t_cose to the underlying
* crypto library.
*
* The making and destroying of the key pair is the only code
* dependent on the crypto library in this file.
*/
return_value = make_ossl_ecdsa_key_pair(T_COSE_ALGORITHM_ES256, &key_pair);
printf("Made EC key with curve prime256v1: %d (%s)\n", return_value, return_value ? "fail" : "success");
if(return_value) {
goto Done;
}
/* ------ Initialize for signing ------
*
* Initialize the signing context by telling it the signing
* algorithm and signing options. No options are set here hence
* the 0 value.
*
* Set up the signing key and kid (key ID). No kid is passed here
* hence the NULL_Q_USEFUL_BUF_C.
*/
t_cose_sign1_sign_init(&sign_ctx, 0, T_COSE_ALGORITHM_ES256);
t_cose_sign1_set_signing_key(&sign_ctx, key_pair, NULL_Q_USEFUL_BUF_C);
printf("Initialized t_cose and configured signing key\n");
/* ------ Sign ------
*
* This performs encoding of the headers, the signing and formatting
* in one shot.
*
* With this API the payload ends up in memory twice, once as the
* input and once in the output. If the payload is large, this
* needs about double the size of the payload to work.
*/
return_value = t_cose_sign1_sign(/* The context set up with signing key */
&sign_ctx,
/* Pointer and length of payload to be
* signed.
*/
constructed_payload,
/* Non-const pointer and length of the
* buffer where the completed output is
* written to. The length here is that
* of the whole buffer.
*/
signed_cose_buffer,
/* Const pointer and actual length of
* the completed, signed and encoded
* COSE_Sign1 message. This points
* into the output buffer and has the
* lifetime of the output buffer.
*/
&signed_cose);
printf("Finished signing: %d (%s)\n", return_value, return_value ? "fail" : "success");
if(return_value) {
goto Done;
}
print_useful_buf("Completed COSE_Sign1 message:\n", signed_cose);
printf("\n");
/* ------ Set up for verification ------
*
* Initialize the verification context.
*
* The verification key works the same way as the signing
* key. Internally it must be in the format for the crypto library
* used. It is passed straight through t_cose.
*/
t_cose_sign1_verify_init(&verify_ctx, 0);
t_cose_sign1_set_verification_key(&verify_ctx, key_pair);
printf("Initialized t_cose for verification and set verification key\n");
/* ------ Perform the verification ------
*
* Verification is relatively simple. The COSE_Sign1 message to
* verify is passed in and the payload is returned if verification
* is successful. The key must be of the correct type for the
* algorithm used to sign the COSE_Sign1.
*
* The COSE header parameters will be returned if requested, but
* in this example they are not as NULL is passed for the location
* to put them.
*/
return_value = t_cose_sign1_verify(&verify_ctx,
signed_cose, /* COSE to verify */
&returned_payload, /* Payload from signed_cose */
NULL); /* Don't return parameters */
printf("Verification complete: %d (%s)\n", return_value, return_value ? "fail" : "success");
if(return_value) {
goto Done;
}
print_useful_buf("Signed payload:\n", returned_payload);
/* ------ Free key pair ------
*
* Some implementations of PSA allocate slots for the keys in
* use. This call indicates that the key slot can be de allocated.
*/
printf("Freeing key pair\n\n\n");
free_ossl_ecdsa_key_pair(key_pair);
Done:
return (int32_t)return_value;
}
/**
* \brief Sign and verify example with two-step signing
*
* The two-step (plus init and key set up) signing has the payload
* constructed directly into the output buffer, uses less memory,
* but is more complicated to use.
*/
int two_step_sign_example()
{
struct t_cose_sign1_sign_ctx sign_ctx;
enum t_cose_err_t return_value;
Q_USEFUL_BUF_MAKE_STACK_UB( signed_cose_buffer, 300);
struct q_useful_buf_c signed_cose;
struct q_useful_buf_c payload;
struct t_cose_key key_pair;
QCBOREncodeContext cbor_encode;
QCBORError cbor_error;
struct t_cose_sign1_verify_ctx verify_ctx;
/* ------ Make an ECDSA key pair ------
*
* The key pair will be used for both signing and encryption. The
* data type is struct t_cose_key on the outside, but internally
* the format is that of the crypto library used, PSA in this
* case. They key is just passed through t_cose to the underlying
* crypto library.
*
* The making and destroying of the key pair is the only code
* dependent on the crypto library in this file.
*/
return_value = make_ossl_ecdsa_key_pair(T_COSE_ALGORITHM_ES256, &key_pair);
printf("Made EC key with curve prime256v1: %d (%s)\n", return_value, return_value ? "fail" : "success");
if(return_value) {
goto Done;
}
/* ------ Initialize for signing ------
*
* Set up the QCBOR encoding context with the output buffer. This
* is where all the outputs including the payload goes. In this
* case the maximum size is small and known so a fixed length
* buffer is given. If it is not known then QCBOR and t_cose can
* run without a buffer to calculate the needed size. In all
* cases, if the buffer is too small QCBOR and t_cose will error
* out gracefully and not overrun any buffers.
*
* Initialize the signing context by telling it the signing
* algorithm and signing options. No options are set here hence
* the 0 value.
*
* Set up the signing key and kid (key ID). No kid is passed here
* hence the NULL_Q_USEFUL_BUF_C.
*/
QCBOREncode_Init(&cbor_encode, signed_cose_buffer);
t_cose_sign1_sign_init(&sign_ctx, 0, T_COSE_ALGORITHM_ES256);
t_cose_sign1_set_signing_key(&sign_ctx, key_pair, NULL_Q_USEFUL_BUF_C);
printf("Initialized QCBOR, t_cose and configured signing key\n");
/* ------ Encode the headers ------
*
* This just outputs the COSE_Sign1 header parameters and gets set
* up for the payload to be output.
*/
return_value = t_cose_sign1_encode_parameters(&sign_ctx, &cbor_encode);
printf("Encoded COSE headers: %d (%s)\n", return_value, return_value ? "fail" : "success");
if(return_value) {
goto Done;
}
/* ------ Output the payload ------
*
* QCBOREncode functions are used to add the payload. It all goes
* directly into the output buffer without any temporary copies.
* QCBOR keeps track of the what is the payload so t_cose knows
* what to hash and sign.
*
* The encoded CBOR here can be very large and complex. The only
* limit is that the output buffer is large enough. If it is too
* small, one of the following two calls will report the error as
* QCBOR tracks encoding errors internally so the code calling it
* doesn't have to.
*
* The payload constructed here is a map of some label-value
* pairs similar to a CWT or EAT, but using string labels
* rather than integers. It is just a little example.
*
* A simpler alternative is to call t_cose_sign1_sign() instead of
* t_cose_sign1_encode_parameters() and
* t_cose_sign1_encode_signature(), however this requires memory
* to hold a copy of the payload and the output COSE_Sign1
* message. For that call the payload is just passed in as a
* buffer.
*/
QCBOREncode_OpenMap(&cbor_encode);
QCBOREncode_AddSZStringToMap(&cbor_encode, "BeingType", "Humanoid");
QCBOREncode_AddSZStringToMap(&cbor_encode, "Greeting", "We come in peace");
QCBOREncode_AddInt64ToMap(&cbor_encode, "ArmCount", 2);
QCBOREncode_AddInt64ToMap(&cbor_encode, "HeadCount", 1);
QCBOREncode_AddSZStringToMap(&cbor_encode, "BrainSize", "medium");
QCBOREncode_AddBoolToMap(&cbor_encode, "DrinksWater", true);
QCBOREncode_CloseMap(&cbor_encode);
printf("Payload added\n");
/* ------ Sign ------
*
* This call signals the end payload construction, causes the actual
* signing to run.
*/
return_value = t_cose_sign1_encode_signature(&sign_ctx, &cbor_encode);
printf("Fnished signing: %d (%s)\n", return_value, return_value ? "fail" : "success");
if(return_value) {
goto Done;
}
/* ------ Complete CBOR Encoding ------
*
* This closes out the CBOR encoding returning any errors that
* might have been recorded.
*
* The resulting signed message is returned in signed_cose. It is
* a pointer and length into the buffer give to
* QCBOREncode_Init().
*/
cbor_error = QCBOREncode_Finish(&cbor_encode, &signed_cose);
printf("Finished CBOR encoding: %d (%s)\n", cbor_error, return_value ? "fail" : "success");
if(cbor_error) {
goto Done;
}
print_useful_buf("Completed COSE_Sign1 message:\n", signed_cose);
printf("\n");
/* ------ Set up for verification ------
*
* Initialize the verification context.
*
* The verification key works the same way as the signing
* key. Internally it must be in the format for the crypto library
* used. It is passed straight through t_cose.
*/
t_cose_sign1_verify_init(&verify_ctx, 0);
t_cose_sign1_set_verification_key(&verify_ctx, key_pair);
printf("Initialized t_cose for verification and set verification key\n");
/* ------ Perform the verification ------
*
* Verification is relatively simple. The COSE_Sign1 message to
* verify is passed in and the payload is returned if verification
* is successful. The key must be of the correct type for the
* algorithm used to sign the COSE_Sign1.
*
* The COSE header parameters will be returned if requested, but
* in this example they are not as NULL is passed for the location
* to put them.
*/
return_value = t_cose_sign1_verify(&verify_ctx,
signed_cose, /* COSE to verify */
&payload, /* Payload from signed_cose */
NULL); /* Don't return parameters */
printf("Verification complete: %d (%s)\n", return_value, return_value ? "fail" : "success");
if(return_value) {
goto Done;
}
print_useful_buf("Signed payload:\n", payload);
/* ------ Free key pair ------
*
* OpenSSL uses memory allocation for keys, so they must be freed.
*/
printf("Freeing key pair\n\n\n");
free_ossl_ecdsa_key_pair(key_pair);
Done:
return (int)return_value;
}
int main(int argc, const char * argv[])
{
(void)argc; /* Avoid unused parameter error */
(void)argv;
one_step_sign_example();
two_step_sign_example();
}

605
3rdparty/exported/t_cose/examples/t_cose_basic_example_psa.c поставляемый Normal file
Просмотреть файл

@ -0,0 +1,605 @@
/*
* t_cose_basic_example_psa.c
*
* Copyright 2019-2022, Laurence Lundblade
*
* SPDX-License-Identifier: BSD-3-Clause
*
* See BSD-3-Clause license in README.md
*/
#include "t_cose/t_cose_common.h"
#include "t_cose/t_cose_sign1_sign.h"
#include "t_cose/t_cose_sign1_verify.h"
#include "t_cose/q_useful_buf.h"
#include "psa/crypto.h"
#include <stdio.h>
/**
* \file t_cose_basic_example_psa.c
*
* \brief Example code for signing and verifying a COSE_Sign1 message using PSA
*
* This file has simple code to sign a payload and verify it.
*
* This works with PSA / MBed Crypto. It assumes t_cose has been wired
* up to PSA / MBed Crypto and has code specific to this library to
* make a key pair that will be passed through t_cose. See t_cose
* README for more details on how integration with crypto libraries
* works.
*/
/*
* Some hard coded keys for the test cases here.
*/
#define PRIVATE_KEY_prime256v1 \
0xf1, 0xb7, 0x14, 0x23, 0x43, 0x40, 0x2f, 0x3b, 0x5d, 0xe7, 0x31, 0x5e, 0xa8, \
0x94, 0xf9, 0xda, 0x5c, 0xf5, 0x03, 0xff, 0x79, 0x38, 0xa3, 0x7c, 0xa1, 0x4e, \
0xb0, 0x32, 0x86, 0x98, 0x84, 0x50
#define PRIVATE_KEY_secp384r1 \
0x03, 0xdf, 0x14, 0xf4, 0xb8, 0xa4, 0x3f, 0xd8, 0xab, 0x75, 0xa6, 0x04, 0x6b, \
0xd2, 0xb5, 0xea, 0xa6, 0xfd, 0x10, 0xb2, 0xb2, 0x03, 0xfd, 0x8a, 0x78, 0xd7, \
0x91, 0x6d, 0xe2, 0x0a, 0xa2, 0x41, 0xeb, 0x37, 0xec, 0x3d, 0x4c, 0x69, 0x3d, \
0x23, 0xba, 0x2b, 0x4f, 0x6e, 0x5b, 0x66, 0xf5, 0x7f
#define PRIVATE_KEY_secp521r1 \
0x00, 0x45, 0xd2, 0xd1, 0x43, 0x94, 0x35, 0xfa, 0xb3, 0x33, 0xb1, 0xc6, 0xc8, \
0xb5, 0x34, 0xf0, 0x96, 0x93, 0x96, 0xad, 0x64, 0xd5, 0xf5, 0x35, 0xd6, 0x5f, \
0x68, 0xf2, 0xa1, 0x60, 0x65, 0x90, 0xbb, 0x15, 0xfd, 0x53, 0x22, 0xfc, 0x97, \
0xa4, 0x16, 0xc3, 0x95, 0x74, 0x5e, 0x72, 0xc7, 0xc8, 0x51, 0x98, 0xc0, 0x92, \
0x1a, 0xb3, 0xb8, 0xe9, 0x2d, 0xd9, 0x01, 0xb5, 0xa4, 0x21, 0x59, 0xad, 0xac, \
0x6d
/**
* \brief Make an EC key pair in PSA / Mbed library form.
*
* \param[in] cose_algorithm_id The algorithm to sign with, for example
* \ref T_COSE_ALGORITHM_ES256.
* \param[out] key_pair The key pair. This must be freed.
*
* The key made here is fixed and just useful for testing.
*/
enum t_cose_err_t make_psa_ecdsa_key_pair(int32_t cose_algorithm_id,
struct t_cose_key *key_pair)
{
psa_key_type_t key_type;
psa_status_t crypto_result;
mbedtls_svc_key_id_t key_handle;
psa_algorithm_t key_alg;
const uint8_t *private_key;
size_t private_key_len;
psa_key_attributes_t key_attributes;
static const uint8_t private_key_256[] = {PRIVATE_KEY_prime256v1};
static const uint8_t private_key_384[] = {PRIVATE_KEY_secp384r1};
static const uint8_t private_key_521[] = {PRIVATE_KEY_secp521r1};
/* There is not a 1:1 mapping from alg to key type, but
* there is usually an obvious curve for an algorithm. That
* is what this does.
*/
switch(cose_algorithm_id) {
case T_COSE_ALGORITHM_ES256:
private_key = private_key_256;
private_key_len = sizeof(private_key_256);
key_type = PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1);
key_alg = PSA_ALG_ECDSA(PSA_ALG_SHA_256);
break;
case T_COSE_ALGORITHM_ES384:
private_key = private_key_384;
private_key_len = sizeof(private_key_384);
key_type = PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1);
key_alg = PSA_ALG_ECDSA(PSA_ALG_SHA_384);
break;
case T_COSE_ALGORITHM_ES512:
private_key = private_key_521;
private_key_len = sizeof(private_key_521);
key_type = PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1);
key_alg = PSA_ALG_ECDSA(PSA_ALG_SHA_512);
break;
default:
return T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
}
/* OK to call this multiple times */
crypto_result = psa_crypto_init();
if(crypto_result != PSA_SUCCESS) {
return T_COSE_ERR_FAIL;
}
/* When importing a key with the PSA API there are two main things
* to do.
*
* First you must tell it what type of key it is as this cannot be
* discovered from the raw data. The variable key_type contains
* that information including the EC curve. This is sufficient for
* psa_import_key() to succeed, but you probably want actually use
* the key.
*
* Second, you must say what algorithm(s) and operations the key
* can be used as the PSA Crypto Library has policy enforcement.
*
* How this is done varies quite a lot in the newer
* PSA Crypto API compared to the older.
*/
key_attributes = psa_key_attributes_init();
/* Say what algorithm and operations the key can be used with / for */
psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH);
psa_set_key_algorithm(&key_attributes, key_alg);
/* The type of key including the EC curve */
psa_set_key_type(&key_attributes, key_type);
/* Import the private key. psa_import_key() automatically
* generates the public key from the private so no need to import
* more than the private key. (With ECDSA the public key is always
* deterministically derivable from the private key).
*/
crypto_result = psa_import_key(&key_attributes,
private_key,
private_key_len,
&key_handle);
if (crypto_result != PSA_SUCCESS) {
return T_COSE_ERR_FAIL;
}
key_pair->k.key_handle = key_handle;
key_pair->crypto_lib = T_COSE_CRYPTO_LIB_PSA;
return T_COSE_SUCCESS;
}
/**
* \brief Free a PSA / MBed key.
*
* \param[in] key_pair The key pair to close / deallocate / free.
*/
void free_psa_ecdsa_key_pair(struct t_cose_key key_pair)
{
psa_close_key((mbedtls_svc_key_id_t)key_pair.k.key_handle);
}
/**
* \brief Print a q_useful_buf_c on stdout in hex ASCII text.
*
* \param[in] string_label A string label to output first
* \param[in] buf The q_useful_buf_c to output.
*
* This is just for pretty printing.
*/
static void print_useful_buf(const char *string_label, struct q_useful_buf_c buf)
{
if(string_label) {
printf("%s", string_label);
}
printf(" %ld bytes\n", buf.len);
printf(" ");
size_t i;
for(i = 0; i < buf.len; i++) {
const uint8_t Z = ((const uint8_t *)buf.ptr)[i];
printf("%02x ", Z);
if((i % 8) == 7) {
printf("\n ");
}
}
printf("\n");
fflush(stdout);
}
/**
* \brief Sign and verify example with one-step signing
*
* The one-step (plus init and key set up) signing uses more memory, but
* is simpler to use. In the code below constructed_payload_buffer is
* the extra buffer that two-step signing avoids.
*/
int32_t one_step_sign_example()
{
struct t_cose_sign1_sign_ctx sign_ctx;
enum t_cose_err_t return_value;
Q_USEFUL_BUF_MAKE_STACK_UB( signed_cose_buffer, 300);
struct q_useful_buf_c signed_cose;
Q_USEFUL_BUF_MAKE_STACK_UB( constructed_payload_buffer, 300);
struct q_useful_buf_c constructed_payload;
struct q_useful_buf_c returned_payload;
struct t_cose_key key_pair;
struct t_cose_sign1_verify_ctx verify_ctx;
QCBOREncodeContext cbor_encode;
QCBORError qcbor_result;
/* ------ Construct the payload ------
*
* The payload is constructed into its own continguous buffer.
* In this case the payload is CBOR formatm so it uses QCBOR to
* encode it, but CBOR is not
* required by COSE so it could be anything at all.
*
* The payload constructed here is a map of some label-value
* pairs similar to a CWT or EAT, but using string labels
* rather than integers. It is just a little example.
*/
QCBOREncode_Init(&cbor_encode, constructed_payload_buffer);
QCBOREncode_OpenMap(&cbor_encode);
QCBOREncode_AddSZStringToMap(&cbor_encode, "BeingType", "Humanoid");
QCBOREncode_AddSZStringToMap(&cbor_encode, "Greeting", "We come in peace");
QCBOREncode_AddInt64ToMap(&cbor_encode, "ArmCount", 2);
QCBOREncode_AddInt64ToMap(&cbor_encode, "HeadCount", 1);
QCBOREncode_AddSZStringToMap(&cbor_encode, "BrainSize", "medium");
QCBOREncode_AddBoolToMap(&cbor_encode, "DrinksWater", true);
QCBOREncode_CloseMap(&cbor_encode);
qcbor_result = QCBOREncode_Finish(&cbor_encode, &constructed_payload);
printf("Encoded payload (size = %ld): %d (%s)\n",
constructed_payload.len,
qcbor_result,
qcbor_result ? "fail" : "success");
if(qcbor_result) {
return_value = (enum t_cose_err_t)qcbor_result;
goto Done;
}
/* ------ Make an ECDSA key pair ------
*
* The key pair will be used for both signing and encryption. The
* data type is struct t_cose_key on the outside, but internally
* the format is that of the crypto library used, PSA in this
* case. They key is just passed through t_cose to the underlying
* crypto library.
*
* The making and destroying of the key pair is the only code
* dependent on the crypto library in this file.
*/
return_value = make_psa_ecdsa_key_pair(T_COSE_ALGORITHM_ES256, &key_pair);
printf("Made EC key with curve prime256v1: %d (%s)\n", return_value, return_value ? "fail" : "success");
if(return_value) {
goto Done;
}
/* ------ Initialize for signing ------
*
* Initialize the signing context by telling it the signing
* algorithm and signing options. No options are set here hence
* the 0 value.
*
* Set up the signing key and kid (key ID). No kid is passed here
* hence the NULL_Q_USEFUL_BUF_C.
*/
t_cose_sign1_sign_init(&sign_ctx, 0, T_COSE_ALGORITHM_ES256);
t_cose_sign1_set_signing_key(&sign_ctx, key_pair, NULL_Q_USEFUL_BUF_C);
printf("Initialized t_cose and configured signing key\n");
/* ------ Sign ------
*
* This performs encoding of the headers, the signing and formatting
* in one shot.
*
* With this API the payload ends up in memory twice, once as the
* input and once in the output. If the payload is large, this
* needs about double the size of the payload to work.
*/
return_value = t_cose_sign1_sign(/* The context set up with signing key */
&sign_ctx,
/* Pointer and length of payload to be
* signed.
*/
constructed_payload,
/* Non-const pointer and length of the
* buffer where the completed output is
* written to. The length here is that
* of the whole buffer.
*/
signed_cose_buffer,
/* Const pointer and actual length of
* the completed, signed and encoded
* COSE_Sign1 message. This points
* into the output buffer and has the
* lifetime of the output buffer.
*/
&signed_cose);
printf("Finished signing: %d (%s)\n", return_value, return_value ? "fail" : "success");
if(return_value) {
goto Done;
}
print_useful_buf("Completed COSE_Sign1 message:\n", signed_cose);
printf("\n");
/* ------ Set up for verification ------
*
* Initialize the verification context.
*
* The verification key works the same way as the signing
* key. Internally it must be in the format for the crypto library
* used. It is passed straight through t_cose.
*/
t_cose_sign1_verify_init(&verify_ctx, 0);
t_cose_sign1_set_verification_key(&verify_ctx, key_pair);
printf("Initialized t_cose for verification and set verification key\n");
/* ------ Perform the verification ------
*
* Verification is relatively simple. The COSE_Sign1 message to
* verify is passed in and the payload is returned if verification
* is successful. The key must be of the correct type for the
* algorithm used to sign the COSE_Sign1.
*
* The COSE header parameters will be returned if requested, but
* in this example they are not as NULL is passed for the location
* to put them.
*/
return_value = t_cose_sign1_verify(&verify_ctx,
signed_cose, /* COSE to verify */
&returned_payload, /* Payload from signed_cose */
NULL); /* Don't return parameters */
printf("Verification complete: %d (%s)\n", return_value, return_value ? "fail" : "success");
if(return_value) {
goto Done;
}
print_useful_buf("Signed payload:\n", returned_payload);
/* ------ Free key pair ------
*
* Some implementations of PSA allocate slots for the keys in
* use. This call indicates that the key slot can be de allocated.
*/
printf("Freeing key pair\n\n\n");
free_psa_ecdsa_key_pair(key_pair);
Done:
return (int32_t)return_value;
}
/**
* \brief Sign and verify example with two-step signing
*
* The two-step (plus init and key set up) signing has the payload
* constructed directly into the output buffer, uses less memory,
* but is more complicated to use.
*/
int two_step_sign_example()
{
struct t_cose_sign1_sign_ctx sign_ctx;
enum t_cose_err_t return_value;
Q_USEFUL_BUF_MAKE_STACK_UB( signed_cose_buffer, 300);
struct q_useful_buf_c signed_cose;
struct q_useful_buf_c payload;
struct t_cose_key key_pair;
QCBOREncodeContext cbor_encode;
QCBORError cbor_error;
struct t_cose_sign1_verify_ctx verify_ctx;
/* ------ Make an ECDSA key pair ------
*
* The key pair will be used for both signing and encryption. The
* data type is struct t_cose_key on the outside, but internally
* the format is that of the crypto library used, PSA in this
* case. They key is just passed through t_cose to the underlying
* crypto library.
*
* The making and destroying of the key pair is the only code
* dependent on the crypto library in this file.
*/
return_value = make_psa_ecdsa_key_pair(T_COSE_ALGORITHM_ES256, &key_pair);
printf("Made EC key with curve prime256v1: %d (%s)\n", return_value, return_value ? "fail" : "success");
if(return_value) {
goto Done;
}
/* ------ Initialize for signing ------
*
* Set up the QCBOR encoding context with the output buffer. This
* is where all the outputs including the payload goes. In this
* case the maximum size is small and known so a fixed length
* buffer is given. If it is not known then QCBOR and t_cose can
* run without a buffer to calculate the needed size. In all
* cases, if the buffer is too small QCBOR and t_cose will error
* out gracefully and not overrun any buffers.
*
* Initialize the signing context by telling it the signing
* algorithm and signing options. No options are set here hence
* the 0 value.
*
* Set up the signing key and kid (key ID). No kid is passed here
* hence the NULL_Q_USEFUL_BUF_C.
*/
QCBOREncode_Init(&cbor_encode, signed_cose_buffer);
t_cose_sign1_sign_init(&sign_ctx, 0, T_COSE_ALGORITHM_ES256);
t_cose_sign1_set_signing_key(&sign_ctx, key_pair, NULL_Q_USEFUL_BUF_C);
printf("Initialized QCBOR, t_cose and configured signing key\n");
/* ------ Encode the headers ------
*
* This just outputs the COSE_Sign1 header parameters and gets set
* up for the payload to be output.
*/
return_value = t_cose_sign1_encode_parameters(&sign_ctx, &cbor_encode);
printf("Encoded COSE headers: %d (%s)\n", return_value, return_value ? "fail" : "success");
if(return_value) {
goto Done;
}
/* ------ Output the payload ------
*
* QCBOREncode functions are used to add the payload. It all goes
* directly into the output buffer without any temporary copies.
* QCBOR keeps track of the what is the payload so t_cose knows
* what to hash and sign.
*
* The encoded CBOR here can be very large and complex. The only
* limit is that the output buffer is large enough. If it is too
* small, one of the following two calls will report the error as
* QCBOR tracks encoding errors internally so the code calling it
* doesn't have to.
*
* The payload constructed here is a map of some label-value
* pairs similar to a CWT or EAT, but using string labels
* rather than integers. It is just a little example.
*
* A simpler alternative is to call t_cose_sign1_sign() instead of
* t_cose_sign1_encode_parameters() and
* t_cose_sign1_encode_signature(), however this requires memory
* to hold a copy of the payload and the output COSE_Sign1
* message. For that call the payload is just passed in as a
* buffer.
*/
QCBOREncode_OpenMap(&cbor_encode);
QCBOREncode_AddSZStringToMap(&cbor_encode, "BeingType", "Humanoid");
QCBOREncode_AddSZStringToMap(&cbor_encode, "Greeting", "We come in peace");
QCBOREncode_AddInt64ToMap(&cbor_encode, "ArmCount", 2);
QCBOREncode_AddInt64ToMap(&cbor_encode, "HeadCount", 1);
QCBOREncode_AddSZStringToMap(&cbor_encode, "BrainSize", "medium");
QCBOREncode_AddBoolToMap(&cbor_encode, "DrinksWater", true);
QCBOREncode_CloseMap(&cbor_encode);
printf("Payload added\n");
/* ------ Sign ------
*
* This call signals the end payload construction, causes the actual
* signing to run.
*/
return_value = t_cose_sign1_encode_signature(&sign_ctx, &cbor_encode);
printf("Fnished signing: %d (%s)\n", return_value, return_value ? "fail" : "success");
if(return_value) {
goto Done;
}
/* ------ Complete CBOR Encoding ------
*
* This closes out the CBOR encoding returning any errors that
* might have been recorded.
*
* The resulting signed message is returned in signed_cose. It is
* a pointer and length into the buffer give to
* QCBOREncode_Init().
*/
cbor_error = QCBOREncode_Finish(&cbor_encode, &signed_cose);
printf("Finished CBOR encoding: %d (%s)\n", cbor_error, return_value ? "fail" : "success");
if(cbor_error) {
goto Done;
}
print_useful_buf("Completed COSE_Sign1 message:\n", signed_cose);
printf("\n");
/* ------ Set up for verification ------
*
* Initialize the verification context.
*
* The verification key works the same way as the signing
* key. Internally it must be in the format for the crypto library
* used. It is passed straight through t_cose.
*/
t_cose_sign1_verify_init(&verify_ctx, 0);
t_cose_sign1_set_verification_key(&verify_ctx, key_pair);
printf("Initialized t_cose for verification and set verification key\n");
/* ------ Perform the verification ------
*
* Verification is relatively simple. The COSE_Sign1 message to
* verify is passed in and the payload is returned if verification
* is successful. The key must be of the correct type for the
* algorithm used to sign the COSE_Sign1.
*
* The COSE header parameters will be returned if requested, but
* in this example they are not as NULL is passed for the location
* to put them.
*/
return_value = t_cose_sign1_verify(&verify_ctx,
signed_cose, /* COSE to verify */
&payload, /* Payload from signed_cose */
NULL); /* Don't return parameters */
printf("Verification complete: %d (%s)\n", return_value, return_value ? "fail" : "success");
if(return_value) {
goto Done;
}
print_useful_buf("Signed payload:\n", payload);
/* ------ Free key pair ------
*
* Some implementations of PSA allocate slots for the keys in
* use. This call indicates that the key slot can be de allocated.
*/
printf("Freeing key pair\n\n\n");
free_psa_ecdsa_key_pair(key_pair);
Done:
return (int)return_value;
}
int main(int argc, const char * argv[])
{
(void)argc; /* Avoid unused parameter error */
(void)argv;
one_step_sign_example();
two_step_sign_example();
}

54
3rdparty/exported/t_cose/main.c поставляемый Normal file
Просмотреть файл

@ -0,0 +1,54 @@
/*
* main.c
*
* Copyright 2019-2020, Laurence Lundblade
*
* SPDX-License-Identifier: BSD-3-Clause
*
* See BSD-3-Clause license in README.md.
*
* Created 4/21/2019.
*/
#include <stdio.h>
#include "run_tests.h"
#include "t_cose_make_test_pub_key.h"
/*
This is an implementation of OutputStringCB built using stdio. If
you don't have stdio, replaces this.
*/
static void fputs_wrapper(const char *szString, void *pOutCtx, int bNewLine)
{
fputs(szString, (FILE *)pOutCtx);
if(bNewLine) {
fputs("\n", pOutCtx);
}
}
int main(int argc, const char * argv[])
{
int return_value;
(void)argc; // Avoid unused parameter error
// This call prints out sizes of data structures to remind us
// to keep them small.
PrintSizesTCose(&fputs_wrapper, stdout);
// This runs all the tests
return_value = RunTestsTCose(argv+1, &fputs_wrapper, stdout, NULL);
if(return_value) {
return return_value;
}
return_value = check_for_key_pair_leaks();
if(return_value) {
printf("Detected key pair leaks: %d FAIL\n", return_value);
}
return return_value;
}

570
3rdparty/exported/t_cose/src/t_cose_crypto.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,570 @@
/*
* t_cose_crypto.h
*
* Copyright 2019-2022, Laurence Lundblade
*
* SPDX-License-Identifier: BSD-3-Clause
*
* See BSD-3-Clause license in README.md
*/
#ifndef __T_COSE_CRYPTO_H__
#define __T_COSE_CRYPTO_H__
#include <stdint.h>
#include <stdbool.h>
#include "t_cose/t_cose_common.h"
#include "t_cose/q_useful_buf.h"
#include "t_cose_standard_constants.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \file t_cose_crypto.h
*
* \brief This defines the adaptation layer for cryptographic
* functions needed by t_cose.
*
* This is small wrapper around the cryptographic functions to:
* - Map COSE algorithm IDs to cryptographic library IDs
* - Map cryptographic library errors to \ref t_cose_err_t errors
* - Have inputs and outputs be \c struct \c q_useful_buf_c and
* \c struct \c q_useful_buf
* - Handle key selection
*
* An implementation must be made of these functions
* for the various cryptographic libraries that are used on
* various platforms and OSs. The functions are:
* - t_cose_t_crypto_sig_size()
* - t_cose_crypto_pub_key_sign()
* - t_cose_crypto_pub_key_verify()
* - t_cose_crypto_hash_start()
* - t_cose_crypto_hash_update()
* - t_cose_crypto_hash_finish()
*
* This runs entirely off of COSE-style algorithm identifiers. They
* are simple integers and thus work nice as function parameters. An
* initial set is defined by [COSE (RFC 8152)]
* (https://tools.ietf.org/html/rfc8152). New ones can be registered
* in the [IANA COSE Registry]
* (https://www.iana.org/assignments/cose/cose.xhtml). Local use new
* ones can also be defined (\c \#define) if what is needed is not in
* the IANA registry.
*
* \anchor useful_buf_use
* Binary data is returned to the caller using a \c struct \c
* q_useful_buf to pass the buffer to receive the data and its length in
* and a \c q_useful_buf_c to return the pointer and length of the
* returned data. The point of this is coding hygiene. The buffer
* passed in is not const as it is to be modified. The \c
* q_useful_buf_c returned is const. The lengths of buffers are
* handled in a clear, consistent and enforced manner.
*
* The pointer in the \c q_useful_buf_c will always point to the
* buffer passed in via the \c q_useful_buf so the lifetime of the
* data is under control of the caller.
*
* This is not intended as any sort of general cryptographic API. It
* is just the functions needed by t_cose in the form that is most
* useful for t_cose.
*
* No other file in t_cose should need modification for new algorithms,
* new key types and sizes or the integration of cryptographic libraries
* except on some occasions, this file as follows:
*
* - Support for a new COSE_ALGORITHM_XXX signature algorithm
* - See t_cose_algorithm_is_ecdsa()
* - If not ECDSA add another function like t_cose_algorithm_is_ecdsa()
* - Support for a new COSE_ALGORITHM_XXX signature algorithm is added
* - See \ref T_COSE_CRYPTO_MAX_HASH_SIZE for additional hashes
* - Support larger key sizes (and thus signature sizes)
* - See \ref T_COSE_MAX_SIG_SIZE
* - Support another hash implementation that is not a service
* - See struct \ref t_cose_crypto_hash
*
* To reduce stack usage and save a little code these can be defined.
* - T_COSE_DISABLE_ES384
* - T_COSE_DISABLE_ES512
*
* The actual code that implements these hashes in the crypto library may
* or may not be saved with these defines depending on how the library
* works, whether dead stripping of object code is on and such.
*/
#define T_COSE_EC_P256_SIG_SIZE 64 /* size for secp256r1 */
#define T_COSE_EC_P384_SIG_SIZE 96 /* size for secp384r1 */
#define T_COSE_EC_P512_SIG_SIZE 132 /* size for secp521r1 */
/**
* There is a stack variable to hold the output of the signing
* operation. This sets the maximum signature size this code can
* handle based on the COSE algorithms configured. The size of the
* signature goes with the size of the key, not the algorithm, so a
* key could be given for signing or verification that is larger than
* this. However, it is not typical to do so. If the key or signature
* is too large the failure will be graceful with an error.
*
* For ECDSA the signature format used is defined in RFC 8152 section
* 8.1. It is the concatenation of r and s, each of which is the key
* size in bits rounded up to the nearest byte. That is twice the key
* size in bytes.
*/
#ifndef T_COSE_DISABLE_ES512
#define T_COSE_MAX_SIG_SIZE T_COSE_EC_P512_SIG_SIZE
#else
#ifndef T_COSE_DISABLE_ES384
#define T_COSE_MAX_SIG_SIZE T_COSE_EC_P384_SIG_SIZE
#else
#define T_COSE_MAX_SIG_SIZE T_COSE_EC_P256_SIG_SIZE
#endif
#endif
/**
* \brief Returns the size of a signature given the key and algorithm.
*
* \param[in] cose_algorithm_id The algorithm ID
* \param[in] signing_key Key to compute size of
* \param[out] sig_size The returned size in bytes.
*
* \return An error code or \ref T_COSE_SUCCESS.
*
* This is used the caller wishes to compute the size of a token in
* order to allocate memory for it.
*
* The size of a signature depends primarily on the key size but it is
* usually necessary to know the algorithm too.
*
* This always returns the exact size of the signature.
*/
enum t_cose_err_t
t_cose_crypto_sig_size(int32_t cose_algorithm_id,
struct t_cose_key signing_key,
size_t *sig_size);
/**
* \brief Perform public key signing. Part of the t_cose crypto
* adaptation layer.
*
* \param[in] cose_algorithm_id The algorithm to sign with. The IDs are
* defined in [COSE (RFC 8152)]
* (https://tools.ietf.org/html/rfc8152) or
* in the [IANA COSE Registry]
* (https://www.iana.org/assignments/cose/cose.xhtml).
* A proprietary ID can also be defined
* locally (\c \#define) if the needed
* one hasn't been registered.
* \param[in] signing_key Indicates or contains key to sign with.
* \param[in] hash_to_sign The bytes to sign. Typically, a hash of
* a payload.
* \param[in] signature_buffer Pointer and length of buffer into which
* the resulting signature is put.
* \param[in] signature Pointer and length of the signature
* returned.
*
* \retval T_COSE_SUCCESS
* Successfully created the signature.
* \retval T_COSE_ERR_SIG_BUFFER_SIZE
* The \c signature_buffer too small.
* \retval T_COSE_ERR_UNSUPPORTED_SIGNING_ALG
* The requested signing algorithm, \c cose_algorithm_id, is not
* supported.
* \retval T_COSE_ERR_UNKNOWN_KEY
* The key identified by \c key_select was not found.
* \retval T_COSE_ERR_WRONG_TYPE_OF_KEY
* The key was found, but it was the wrong type.
* \retval T_COSE_ERR_INVALID_ARGUMENT
* Some (unspecified) argument was not valid.
* \retval T_COSE_ERR_INSUFFICIENT_MEMORY
* Insufficient heap memory.
* \retval T_COSE_ERR_FAIL
* General unspecific failure.
* \retval T_COSE_ERR_TAMPERING_DETECTED
* Equivalent to \c PSA_ERROR_CORRUPTION_DETECTED.
*
* This is called to do public key signing. The implementation will
* vary from one platform / OS to another but should conform to the
* description here.
*
* The contents of signing_key is usually the type that holds
* a key for the cryptographic library.
*
* See the note in the Detailed Description (the \\file comment block)
* for details on how \c q_useful_buf and \c q_useful_buf_c are used
* to return the signature.
*
* To find out the size of the signature buffer needed, call this with
* \c signature_buffer->ptr \c NULL and \c signature_buffer->len a
* very large number like \c UINT32_MAX. The size will be returned in
* \c signature->len.
*/
enum t_cose_err_t
t_cose_crypto_sign(int32_t cose_algorithm_id,
struct t_cose_key signing_key,
struct q_useful_buf_c hash_to_sign,
struct q_useful_buf signature_buffer,
struct q_useful_buf_c *signature);
/**
* \brief Perform public key signature verification. Part of the
* t_cose crypto adaptation layer.
*
* \param[in] cose_algorithm_id The algorithm to use for verification.
* The IDs are defined in [COSE (RFC 8152)]
* (https://tools.ietf.org/html/rfc8152)
* or in the [IANA COSE Registry]
* (https://www.iana.org/assignments/cose/cose.xhtml).
* A proprietary ID can also be defined
* locally (\c \#define) if the needed one
* hasn't been registered.
* \param[in] verification_key The verification key to use.
* \param[in] kid The COSE kid (key ID) or \c NULL_Q_USEFUL_BUF_C.
* \param[in] hash_to_verify The data or hash that is to be verified.
* \param[in] signature The COSE-format signature.
*
* This verifies that the \c signature passed in was over the \c
* hash_to_verify passed in.
*
* The public key used to verify the signature is selected by the \c
* kid if it is not \c NULL_Q_USEFUL_BUF_C or the \c key_select if it
* is.
*
* The key selected must be, or include, a public key of the correct
* type for \c cose_algorithm_id.
*
* \retval T_COSE_SUCCESS
* The signature is valid
* \retval T_COSE_ERR_SIG_VERIFY
* Signature verification failed. For example, the
* cryptographic operations completed successfully but hash
* wasn't as expected.
* \retval T_COSE_ERR_UNKNOWN_KEY
* The key identified by \c key_select or a \c kid was
* not found.
* \retval T_COSE_ERR_WRONG_TYPE_OF_KEY
* The key was found, but it was the wrong type
* for the operation.
* \retval T_COSE_ERR_UNSUPPORTED_SIGNING_ALG
* The requested signing algorithm is not supported.
* \retval T_COSE_ERR_INVALID_ARGUMENT
* Some (unspecified) argument was not valid.
* \retval T_COSE_ERR_INSUFFICIENT_MEMORY
* Out of heap memory.
* \retval T_COSE_ERR_FAIL
* General unspecific failure.
* \retval T_COSE_ERR_TAMPERING_DETECTED
* Equivalent to \c PSA_ERROR_CORRUPTION_DETECTED.
*/
enum t_cose_err_t
t_cose_crypto_verify(int32_t cose_algorithm_id,
struct t_cose_key verification_key,
struct q_useful_buf_c kid,
struct q_useful_buf_c hash_to_verify,
struct q_useful_buf_c signature);
#ifdef T_COSE_USE_PSA_CRYPTO
#include "psa/crypto.h"
#elif T_COSE_USE_OPENSSL_CRYPTO
#include "openssl/evp.h"
#elif T_COSE_USE_B_CON_SHA256
/* This is code for use with Brad Conte's crypto. See
* https://github.com/B-Con/crypto-algorithms and see the description
* of t_cose_crypto_hash
*/
#include "sha256.h"
#endif
/**
* The context for use with the hash adaptation layer here.
*
* Hash implementations for this porting layer are put into two
* different categories.
*
* The first can be supported generically without any dependency on
* the actual hash implementation in this header. These only need a
* pointer or handle for the hash context. Usually these are
* implemented by a service, system API or crypto HW that runs in a
* separate context or process. They probably allocate memory
* internally. These can use context.ptr or context.handle to hold the
* pointer or handle to the hash context.
*
* The second sort of hash implementations need more than just a
* pointer or handle. Typically these are libraries that are linked
* with this code and run in the same process / context / thread as
* this code. These can be efficient requiring no context switches or
* memory allocations. These type require this header be modified for
* the #include which defines the hash context and so this struct
* includes that context as a member. This context is allocated on the
* stack, so any members added here should be small enough to go on
* the stack. USE_B_CON_SHA256 is an example of this type.
*
* The actual implementation of the hash is in a separate .c file
* that will be specific to the particular platform, library,
* service or such used.
*/
struct t_cose_crypto_hash {
#ifdef T_COSE_USE_PSA_CRYPTO
/* --- The context for PSA Crypto (MBed Crypto) --- */
/* psa_hash_operation_t actually varied by the implementation of
* the crypto library. Sometimes the implementation is inline and
* thus the context is a few hundred bytes, sometimes it is not.
* This varies by what is in crypto_struct.h (which is not quite
* a public interface).
*
* This can be made smaller for PSA implementations that work inline
* by disabling the larger algorithms using PSA / MBed configuration.
*/
psa_hash_operation_t ctx;
psa_status_t status;
#elif T_COSE_USE_OPENSSL_CRYPTO
/* --- The context for OpenSSL crypto --- */
EVP_MD_CTX *evp_ctx;
int update_error; /* Used to track error return by SHAXXX_Update() */
int32_t cose_hash_alg_id; /* COSE integer ID for the hash alg */
#elif T_COSE_USE_B_CON_SHA256
/* --- Specific context for Brad Conte's sha256.c --- */
SHA256_CTX b_con_hash_context;
#else
/* --- Default: generic pointer / handle --- */
union {
void *ptr;
uint64_t handle;
} context;
int64_t status;
#endif
};
/**
* The size of the output of SHA-256.
*
* (It is safe to define these independently here as they are
* well-known and fixed. There is no need to reference
* platform-specific headers and incur messy dependence.)
*/
#define T_COSE_CRYPTO_SHA256_SIZE 32
/**
* The size of the output of SHA-384 in bytes.
*/
#define T_COSE_CRYPTO_SHA384_SIZE 48
/**
* The size of the output of SHA-512 in bytes.
*/
#define T_COSE_CRYPTO_SHA512_SIZE 64
/**
* The maximum needed to hold a hash. It is smaller and less stack is needed
* if the larger hashes are disabled.
*/
#ifndef T_COSE_DISABLE_ES512
#define T_COSE_CRYPTO_MAX_HASH_SIZE T_COSE_CRYPTO_SHA512_SIZE
#else
#ifndef T_COSE_DISABLE_ES384
#define T_COSE_CRYPTO_MAX_HASH_SIZE T_COSE_CRYPTO_SHA384_SIZE
#else
#define T_COSE_CRYPTO_MAX_HASH_SIZE T_COSE_CRYPTO_SHA256_SIZE
#endif
#endif
/**
* \brief Start cryptographic hash. Part of the t_cose crypto
* adaptation layer.
*
* \param[in,out] hash_ctx Pointer to the hash context that
* will be initialized.
* \param[in] cose_hash_alg_id Algorithm ID that identifies the
* hash to use. This is from the
* [IANA COSE Registry]
* (https://www.iana.org/assignments/cose/cose.xhtml)
*
* \retval T_COSE_ERR_UNSUPPORTED_HASH
* The requested algorithm is unknown or unsupported.
*
* \retval T_COSE_ERR_HASH_GENERAL_FAIL
* Some general failure of the hash function
*
* \retval T_COSE_SUCCESS
* Success.
*
* This initializes the hash context for the particular algorithm. It
* must be called first. A \c hash_ctx can be reused if it is
* reinitialized.
*
* \ref T_COSE_INVALID_ALGORITHM_ID may be passed to this function, in which
* case \ref T_COSE_ERR_UNSUPPORTED_HASH must be returned.
*
* Other errors can be returned and will usually be propagated up, but hashes
* generally don't fail so it is suggested not to bother (and to reduce
* object code size for mapping errors).
*/
enum t_cose_err_t
t_cose_crypto_hash_start(struct t_cose_crypto_hash *hash_ctx,
int32_t cose_hash_alg_id);
/**
* \brief Feed data into a cryptographic hash. Part of the t_cose
* crypto adaptation layer.
*
* \param[in,out] hash_ctx Pointer to the hash context in which
* accumulate the hash.
* \param[in] data_to_hash Pointer and length of data to feed into
* hash. The pointer may by \c NULL in which
* case no hashing is performed.
*
* There is no return value. If an error occurs it is remembered in \c
* hash_ctx and returned when t_cose_crypto_hash_finish() is called.
* Once in the error state, this function may be called, but it will
* not do anything.
*
* This function can be called with \c data_to_hash.ptr NULL and it
* will pretend to hash. This allows the same code that is used to
* produce the real hash to be used to return a length of the would-be
* hash for encoded data structure size calculations.
*/
void t_cose_crypto_hash_update(struct t_cose_crypto_hash *hash_ctx,
struct q_useful_buf_c data_to_hash);
/**
* \brief Finish a cryptographic hash. Part of the t_cose crypto
* adaptation layer.
*
* \param[in,out] hash_ctx Pointer to the hash context.
* \param[in] buffer_to_hold_result Pointer and length into which
* the resulting hash is put.
* \param[out] hash_result Pointer and length of the
* resulting hash.
*
* \retval T_COSE_ERR_HASH_GENERAL_FAIL
* Some general failure of the hash function.
* \retval T_COSE_ERR_HASH_BUFFER_SIZE
* The size of the buffer to hold the hash result was
* too small.
* \retval T_COSE_SUCCESS
* Success.
*
* Call this to complete the hashing operation. If the everything
* completed correctly, the resulting hash is returned. Note that any
* errors that occurred during t_cose_crypto_hash_update() are
* returned here.
*
* See \ref useful_buf_use for details on how \c q_useful_buf and
* \c q_useful_buf_c are used to return the hash.
*
* Other errors can be returned and will usually be propagated up, but
* hashes generally don't fail so it is suggested not to bother (and
* to reduce object code size for mapping errors).
*/
enum t_cose_err_t
t_cose_crypto_hash_finish(struct t_cose_crypto_hash *hash_ctx,
struct q_useful_buf buffer_to_hold_result,
struct q_useful_buf_c *hash_result);
/**
* \brief Indicate whether a COSE algorithm is ECDSA or not.
*
* \param[in] cose_algorithm_id The algorithm ID to check.
*
* \returns This returns \c true if the algorithm is ECDSA and \c false if not.
*
* This is a convenience function to check whether a given
* integer COSE algorithm ID uses the ECDSA signing algorithm
* or not.
*
* (As other types of signing algorithms are added, RSA for example,
* a similar function can be added for them.)
*/
static bool
t_cose_algorithm_is_ecdsa(int32_t cose_algorithm_id);
/*
* Inline implementations. See documentation above.
*/
/**
* \brief Look for an integer in a zero-terminated list of integers.
*
* \param[in] cose_algorithm_id The algorithm ID to check.
* \param[in] list zero-terminated list of algorithm IDs.
*
* \returns This returns \c true if an integer is in the list, \c false if not.
*
* Used to implement t_cose_algorithm_is_ecdsa() and in the future
* _is_rsa() and such.
*
* Typically used once in the crypto adaptation layer, so defining it
* inline rather than in a .c file is OK and saves creating a whole
* new .c file just for this.
*/
static inline bool
t_cose_check_list(int32_t cose_algorithm_id, const int32_t *list)
{
while(*list) {
if(*list == cose_algorithm_id) {
return true;
}
list++;
}
return false;
}
static inline bool
t_cose_algorithm_is_ecdsa(int32_t cose_algorithm_id)
{
/* The simple list of COSE alg IDs that use ECDSA */
static const int32_t ecdsa_list[] = {
COSE_ALGORITHM_ES256,
#ifndef T_COSE_DISABLE_ES384
COSE_ALGORITHM_ES384,
#endif
#ifndef T_COSE_DISABLE_ES512
COSE_ALGORITHM_ES512,
#endif
0}; /* 0 is a reserved COSE alg ID ans will never be used */
return t_cose_check_list(cose_algorithm_id, ecdsa_list);
}
#ifdef __cplusplus
}
#endif
#endif /* __T_COSE_CRYPTO_H__ */

506
3rdparty/exported/t_cose/src/t_cose_parameters.c поставляемый Normal file
Просмотреть файл

@ -0,0 +1,506 @@
/*
* t_cose_parameters.c
*
* Copyright 2019-2020, Laurence Lundblade
* Copyright (c) 2021, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
* See BSD-3-Clause license in README.md
*/
#include "t_cose_parameters.h"
#include "t_cose_standard_constants.h"
#include "qcbor/qcbor_spiffy_decode.h"
/**
* \file t_cose_parameters.c
*
* \brief Implementation of COSE header parameter decoding.
*
*/
/**
* \brief Add a new label to the end of the label list.
*
* \param[in] item Data item to add to the label list.
* \param[in,out] label_list The list to add to.
*
* \retval T_COSE_SUCCESS If added correctly.
* \retval T_COSE_ERR_TOO_MANY_PARAMETERS Label list is full.
* \retval T_COSE_ERR_PARAMETER_CBOR The item to add doesn't have a label
* type that is understood
*
* The label / key from \c item is added to \c label_list.
*/
static inline enum t_cose_err_t
add_label_to_list(const QCBORItem *item, struct t_cose_label_list *label_list)
{
/* Aproximate stack usage
* 64-bit 32-bit
* local vars 16 8
* TOTAL 16 8
*/
/* Stack use: 16 bytes for 64-bit */
enum t_cose_err_t return_value;
uint_fast8_t n;
/* Assume success until an error adding is encountered. */
return_value = T_COSE_SUCCESS;
if(item->uLabelType == QCBOR_TYPE_INT64) {
/* Add an integer-labeled parameter to the end of the list */
for(n = 0; label_list->int_labels[n] != LABEL_LIST_TERMINATOR; n++);
if(n == T_COSE_PARAMETER_LIST_MAX) {
/* List is full -- error out */
return_value = T_COSE_ERR_TOO_MANY_PARAMETERS;
goto Done;
}
label_list->int_labels[n] = item->label.int64;
} else if(item->uLabelType == QCBOR_TYPE_TEXT_STRING) {
/* Add a string-labeled parameter to the end of the list */
for(n = 0; !q_useful_buf_c_is_null(label_list->tstr_labels[n]); n++);
if(n == T_COSE_PARAMETER_LIST_MAX) {
/* List is full -- error out */
return_value = T_COSE_ERR_TOO_MANY_PARAMETERS;
goto Done;
}
label_list->tstr_labels[n] = item->label.string;
} else {
/* error because label is neither integer or string */
/* Should never occur because this is caught earlier, but
* leave it to be safe and because inlining and optimization
* should take out any unneeded code
*/
return_value = T_COSE_ERR_PARAMETER_CBOR;
}
Done:
return return_value;
}
/**
* \brief Indicate whether label list is clear or not.
*
* \param[in,out] list The list to check.
*
* \return true if the list is clear.
*/
inline static bool
is_label_list_clear(const struct t_cose_label_list *list)
{
return list->int_labels[0] == 0 &&
q_useful_buf_c_is_null_or_empty(list->tstr_labels[0]);
}
/**
* \brief Decode the parameter containing the labels of parameters considered
* critical.
*
* \param[in,out] decode_context Decode context to read critical
* parameter list from.
* \param[out] critical_labels List of labels of critical
* parameters.
*
* \retval T_COSE_ERR_CBOR_NOT_WELL_FORMED Undecodable CBOR.
* \retval T_COSE_ERR_TOO_MANY_PARAMETERS More critical labels than this
* implementation can handle.
* \retval T_COSE_ERR_PARAMETER_CBOR Unexpected CBOR data type.
*/
static inline enum t_cose_err_t
decode_critical_parameter(QCBORDecodeContext *decode_context,
struct t_cose_label_list *critical_labels)
{
/* Aproximate stack usage
* 64-bit 32-bit
* QCBORItem 56 52
* local vars 32 16
* TOTAL 88 68
*/
QCBORItem item;
uint_fast8_t num_int_labels;
uint_fast8_t num_tstr_labels;
enum t_cose_err_t return_value;
QCBORError cbor_result;
/* Assume that decoder has been entered into the parameters map */
/* Find and enter the array that is the critical parameters parameter */
QCBORDecode_EnterArrayFromMapN(decode_context, COSE_HEADER_PARAM_CRIT);
cbor_result = QCBORDecode_GetAndResetError(decode_context);
if(cbor_result == QCBOR_ERR_LABEL_NOT_FOUND) {
/* Critical paratmeters parameter doesn't exist */
return_value = T_COSE_SUCCESS;
goto Done;
} else if(cbor_result != QCBOR_SUCCESS) {
return_value = T_COSE_ERR_CRIT_PARAMETER;
goto Done;
}
if(critical_labels == NULL) {
/* crit parameter occuring in non-protected bucket */
return_value = T_COSE_ERR_PARAMETER_NOT_PROTECTED;
goto Done;
}
num_int_labels = 0;
num_tstr_labels = 0;
while(1) {
cbor_result = QCBORDecode_GetNext(decode_context, &item);
if(cbor_result == QCBOR_ERR_NO_MORE_ITEMS) {
/* successful exit from loop */
break;
}
if(cbor_result != QCBOR_SUCCESS) {
return_value = T_COSE_ERR_CBOR_NOT_WELL_FORMED;
goto Done;
}
if(item.uDataType == QCBOR_TYPE_INT64) {
if(num_int_labels >= T_COSE_PARAMETER_LIST_MAX) {
return_value = T_COSE_ERR_CRIT_PARAMETER;
goto Done;
}
critical_labels->int_labels[num_int_labels++] = item.val.int64;
} else if(item.uDataType == QCBOR_TYPE_TEXT_STRING) {
if(num_tstr_labels >= T_COSE_PARAMETER_LIST_MAX) {
return_value = T_COSE_ERR_CRIT_PARAMETER;
goto Done;
}
critical_labels->tstr_labels[num_tstr_labels++] = item.val.string;
} else {
return_value = T_COSE_ERR_CRIT_PARAMETER;
goto Done;
}
}
/* Exit out of array back up to parameters map */
QCBORDecode_ExitArray(decode_context);
if(is_label_list_clear(critical_labels)) {
/* Per RFC 8152 crit parameter can't be empty */
return_value = T_COSE_ERR_CRIT_PARAMETER;
goto Done;
}
return_value = T_COSE_SUCCESS;
Done:
return return_value;
}
/**
* Public function. See t_cose_parameters.h
*/
enum t_cose_err_t
check_critical_labels(const struct t_cose_label_list *critical_labels,
const struct t_cose_label_list *unknown_labels)
{
/* Aproximate stack usage
* 64-bit 32-bit
* local vars 24 12
* TOTAL 24 12
*/
enum t_cose_err_t return_value;
uint_fast8_t num_unknown;
uint_fast8_t num_critical;
/* Assume success until an unhandled critical label is found */
return_value = T_COSE_SUCCESS;
/* Iterate over unknown integer parameters */
for(num_unknown = 0; unknown_labels->int_labels[num_unknown]; num_unknown++) {
/* Iterate over critical int labels looking for the unknown label */
for(num_critical = 0;
critical_labels->int_labels[num_critical];
num_critical++) {
if(critical_labels->int_labels[num_critical] == unknown_labels->int_labels[num_unknown]) {
/* Found a critical label that is unknown to us */
return_value = T_COSE_ERR_UNKNOWN_CRITICAL_PARAMETER;
goto Done;
}
}
/* Exit from loop here means all no unknown label was critical */
}
/* Iterate over unknown string labels */
for(num_unknown = 0; !q_useful_buf_c_is_null(unknown_labels->tstr_labels[num_unknown]); num_unknown++) {
/* iterate over critical string labels looking for the unknown param */
for(num_critical = 0; !q_useful_buf_c_is_null(critical_labels->tstr_labels[num_critical]); num_critical++) {
if(!q_useful_buf_compare(critical_labels->tstr_labels[num_critical],
unknown_labels->tstr_labels[num_unknown])){
/* Found a critical label that is unknown to us */
return_value = T_COSE_ERR_UNKNOWN_CRITICAL_PARAMETER;
goto Done;
}
}
/* Exit from loop here means all no unknown label was critical */
}
Done:
return return_value;
}
struct cb_context {
struct t_cose_label_list *unknown_labels;
enum t_cose_err_t return_value;
};
/**
* \brief Add unknown parameter to unknown labels list
*
* \param[in] pCallbackCtx Callback context.
* \param[in] pItem The data item for the unknown parameter.
*
* \returns On failure to add to the list (because it is full) this returns
* \ref QCBOR_ERR_CALLBACK_FAIL to signal an error in traversal.
* The error details is in \c context->return_value.
*
* This gets called through QCBORDecode_GetItemsInMapWithCallback() on
* any parameter that is not recognized. (Maybe someday this will call
* out further to allow t_cose to handle custom parameters).
*/
static QCBORError header_parameter_callback(void *pCallbackCtx, const QCBORItem *pItem)
{
/* Aproximate stack usage
* 64-bit 32-bit
* local vars 16 8
* TOTAL 16 8
*/
struct cb_context *context = (struct cb_context *)pCallbackCtx;
enum t_cose_err_t result;
if(pItem->uLabelType == QCBOR_TYPE_INT64 &&
pItem->label.int64 == COSE_HEADER_PARAM_CRIT) {
/* header parameters that are not processed through the
* call to QCBORDecode_GetItemsInMapWithCallback show up
* here, but are not unknown header parameters. There is
* only one: COSE_HEADER_PARAM_CRIT
*/
result = T_COSE_SUCCESS;
} else {
/* Add an unknown header parameter to the list or unknowns */
result = add_label_to_list(pItem, context->unknown_labels);
}
context->return_value = result;
if(result == T_COSE_SUCCESS) {
return QCBOR_SUCCESS;
} else {
return QCBOR_ERR_CALLBACK_FAIL;
}
}
/**
* \brief Parse some COSE header parameters.
*
* \param[in] decode_context The QCBOR decode context to read from.
* \param[out] parameters The parsed parameters being returned.
* \param[out] critical_labels The parsed list of critical labels if
* parameter is present.
* \param[out] unknown_labels The list of labels that were not recognized.
*
* \retval T_COSE_SUCCESS The parameters were decoded
* correctly.
* \retval T_COSE_ERR_PARAMETER_CBOR CBOR is parsable, but not the
* right structure (e.g. array
* instead of a map)
* \retval T_COSE_ERR_TOO_MANY_PARAMETERS More than
* \ref T_COSE_PARAMETER_LIST_MAX
* parameters.
* \retval T_COSE_ERR_CBOR_NOT_WELL_FORMED The CBOR is not parsable.
* \retval T_COSE_ERR_NON_INTEGER_ALG_ID The algorithm ID is not an
* integer. This implementation
* doesn't support string algorithm
* IDs.
* \retval T_COSE_ERR_BAD_CONTENT_TYPE Error in content type parameter.
* \retval T_COSE_ERR_UNKNOWN_CRITICAL_PARAMETER A label marked critical is
* present and not understood.
*
* No header parameters are mandatory. Which parameters were present
* or not is indicated in \c returned_parameters. It is OK for there
* to be no parameters at all.
*
* The first item to be read from the decode_context must be the map
* data item that contains the parameters.
*/
enum t_cose_err_t
parse_cose_header_parameters(QCBORDecodeContext *decode_context,
struct t_cose_parameters *parameters,
struct t_cose_label_list *critical_labels,
struct t_cose_label_list *unknown_labels)
{
/* Aproximate stack usage
* 64-bit 32-bit
* local vars 32 16
* header_items 336 312
* MAX (GetItemsInMapWithCallback+CB 432 316
* decode_critical 88 68) 432 316
* TOTAL 768 628
*/
enum t_cose_err_t return_value;
QCBORError qcbor_result;
struct cb_context callback_context = {unknown_labels, 0};
/* Get all the non-aggregate headers in one fell swoop with
* QCBORDecode_GetItemsInMapWithCallback().
*/
#define ALG_INDEX 0
#define KID_INDEX 1
#define IV_INDEX 2
#define PARTIAL_IV_INDEX 3
#define CONTENT_TYPE 4
#define END_INDEX 5
QCBORItem header_items[END_INDEX+1];
QCBORDecode_EnterMap(decode_context, NULL);
header_items[ALG_INDEX].label.int64 = COSE_HEADER_PARAM_ALG;
header_items[ALG_INDEX].uLabelType = QCBOR_TYPE_INT64;
header_items[ALG_INDEX].uDataType = QCBOR_TYPE_INT64;
header_items[KID_INDEX].label.int64 = COSE_HEADER_PARAM_KID;
header_items[KID_INDEX].uLabelType = QCBOR_TYPE_INT64;
header_items[KID_INDEX].uDataType = QCBOR_TYPE_BYTE_STRING;
header_items[IV_INDEX].label.int64 = COSE_HEADER_PARAM_IV;
header_items[IV_INDEX].uLabelType = QCBOR_TYPE_INT64;
header_items[IV_INDEX].uDataType = QCBOR_TYPE_BYTE_STRING;
header_items[PARTIAL_IV_INDEX].label.int64 = COSE_HEADER_PARAM_PARTIAL_IV;
header_items[PARTIAL_IV_INDEX].uLabelType = QCBOR_TYPE_INT64;
header_items[PARTIAL_IV_INDEX].uDataType = QCBOR_TYPE_BYTE_STRING;
header_items[CONTENT_TYPE].label.int64 = COSE_HEADER_PARAM_CONTENT_TYPE;
header_items[CONTENT_TYPE].uLabelType = QCBOR_TYPE_INT64;
header_items[CONTENT_TYPE].uDataType = QCBOR_TYPE_ANY;
header_items[END_INDEX].uLabelType = QCBOR_TYPE_NONE;
/* This call takes care of duplicate detection in the map itself.
*
* COSE has the notion of critical parameters that can't be
* ignored, so the callback has to be set up to catch items in
* this map that are not handled by code here.
*/
QCBORDecode_GetItemsInMapWithCallback(decode_context,
header_items,
&callback_context,
header_parameter_callback);
qcbor_result = QCBORDecode_GetError(decode_context);
if(qcbor_result == QCBOR_ERR_CALLBACK_FAIL) {
return_value = callback_context.return_value;
goto Done;
} else if(qcbor_result != QCBOR_SUCCESS) {
if(QCBORDecode_IsNotWellFormedError(qcbor_result)) {
return_value = T_COSE_ERR_CBOR_NOT_WELL_FORMED;
} else {
return_value = T_COSE_ERR_PARAMETER_CBOR;
}
goto Done;
}
/* The following few clauses copy the parameters out of the
* QCBORItems retrieved into the returned parameters
* structure.
*
* Duplicate detection between protected and unprotected parameter
* headers is performed by erroring out if a parameter has already
* been filled in.
*
* Much of the type checking was performed by
* QCBORDecode_GetItemsInMapWithCallback() but not all so the rest
* is done here.
*/
/* COSE_HEADER_PARAM_ALG */
if(header_items[ALG_INDEX].uDataType != QCBOR_TYPE_NONE) {
if(critical_labels == NULL) {
/* Algorithm parameter must be protected */
return_value = T_COSE_ERR_PARAMETER_NOT_PROTECTED;
goto Done;
}
if(header_items[ALG_INDEX].val.int64 == COSE_ALGORITHM_RESERVED ||
header_items[ALG_INDEX].val.int64 > INT32_MAX) {
return_value = T_COSE_ERR_NON_INTEGER_ALG_ID;
goto Done;
}
parameters->cose_algorithm_id = (int32_t)header_items[ALG_INDEX].val.int64;
}
/* COSE_HEADER_PARAM_KID */
if(header_items[KID_INDEX].uDataType != QCBOR_TYPE_NONE) {
if(q_useful_buf_c_is_null(parameters->kid)) {
parameters->kid = header_items[KID_INDEX].val.string;
} else {
return_value = T_COSE_ERR_DUPLICATE_PARAMETER;
goto Done;
}
}
/* COSE_HEADER_PARAM_IV */
if(header_items[IV_INDEX].uDataType != QCBOR_TYPE_NONE) {
if(q_useful_buf_c_is_null(parameters->iv)) {
parameters->iv = header_items[IV_INDEX].val.string;
} else {
return_value = T_COSE_ERR_DUPLICATE_PARAMETER;
goto Done;
}
}
/* COSE_HEADER_PARAM_PARTIAL_IV */
if(header_items[PARTIAL_IV_INDEX].uDataType != QCBOR_TYPE_NONE) {
if(q_useful_buf_c_is_null(parameters->partial_iv)) {
parameters->partial_iv = header_items[PARTIAL_IV_INDEX].val.string;
} else {
return_value = T_COSE_ERR_DUPLICATE_PARAMETER;
goto Done;
}
}
#ifndef T_COSE_DISABLE_CONTENT_TYPE
/* COSE_HEADER_PARAM_CONTENT_TYPE */
if(header_items[CONTENT_TYPE].uDataType == QCBOR_TYPE_TEXT_STRING) {
if(!q_useful_buf_c_is_null_or_empty(parameters->content_type_tstr)) {
return_value = T_COSE_ERR_DUPLICATE_PARAMETER;
goto Done;
}
parameters->content_type_tstr = header_items[CONTENT_TYPE].val.string;
} else if(header_items[CONTENT_TYPE].uDataType == QCBOR_TYPE_INT64) {
if(header_items[CONTENT_TYPE].val.int64 < 0 ||
header_items[CONTENT_TYPE].val.int64 > UINT16_MAX) {
return_value = T_COSE_ERR_BAD_CONTENT_TYPE;
goto Done;
}
if(parameters->content_type_uint != T_COSE_EMPTY_UINT_CONTENT_TYPE) {
return_value = T_COSE_ERR_DUPLICATE_PARAMETER;
goto Done;
}
parameters->content_type_uint = (uint32_t)header_items[CONTENT_TYPE].val.int64;
} else if(header_items[CONTENT_TYPE].uDataType != QCBOR_TYPE_NONE) {
return_value = T_COSE_ERR_BAD_CONTENT_TYPE;
goto Done;
}
#endif
/* COSE_HEADER_PARAM_CRIT */
return_value = decode_critical_parameter(decode_context, critical_labels);
QCBORDecode_ExitMap(decode_context);
Done:
return return_value;
}

115
3rdparty/exported/t_cose/src/t_cose_parameters.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,115 @@
/*
* t_cose_parameters.h
*
* Copyright 2019-2020, Laurence Lundblade
*
* SPDX-License-Identifier: BSD-3-Clause
*
* See BSD-3-Clause license in README.md
*/
#ifndef t_cose_parameters_h
#define t_cose_parameters_h
#include <stdint.h>
#include "t_cose/t_cose_sign1_verify.h"
#include "t_cose/q_useful_buf.h"
#include "t_cose/t_cose_common.h"
#include "qcbor/qcbor.h"
/**
* \file t_cose_parameters.h
*
* \brief A list of COSE parameter labels, both integer and string.
*
* It is fixed size to avoid the complexity of memory management and
* because the number of parameters is assumed to be small.
*
* On a 64-bit machine it is 24 * PARAMETER_LIST_MAX which is 244
* bytes. That accommodates 10 string parameters and 10 integer parameters
* and is small enough to go on the stack.
*
* On a 32-bit machine: 16 * PARAMETER_LIST_MAX = 176
*
* This is a big consumer of stack in this implementation. Some
* cleverness with a union could save almost 200 bytes of stack, as
* this is on the stack twice.
*/
struct t_cose_label_list {
/* Terminated by value LABEL_LIST_TERMINATOR */
int64_t int_labels[T_COSE_PARAMETER_LIST_MAX+1];
/* Terminated by a NULL_Q_USEFUL_BUF_C */
struct q_useful_buf_c tstr_labels[T_COSE_PARAMETER_LIST_MAX+1];
};
/*
* The IANA COSE Header Parameters registry lists label 0 as
* "reserved". This means it can be used, but only by a revision of
* the COSE standard if it is deemed necessary for some large and good
* reason. It cannot just be allocated by IANA as any normal
* assignment. See [IANA COSE Registry]
* (https://www.iana.org/assignments/cose/cose.xhtml). It is thus
* considered safe to use as the list terminator.
*/
#define LABEL_LIST_TERMINATOR 0
/**
* \brief Clear a label list to empty.
*
* \param[in,out] list The list to clear.
*/
inline static void clear_label_list(struct t_cose_label_list *list)
{
memset(list, 0, sizeof(struct t_cose_label_list));
}
enum t_cose_err_t
check_critical_labels(const struct t_cose_label_list *critical_labels,
const struct t_cose_label_list *unknown_labels);
enum t_cose_err_t
parse_cose_header_parameters(QCBORDecodeContext *decode_context,
struct t_cose_parameters *returned_parameters,
struct t_cose_label_list *critical_labels,
struct t_cose_label_list *unknown_labels);
/**
* \brief Clear a struct t_cose_parameters to empty
*
* \param[in,out] parameters Parameter list to clear.
*/
static inline void clear_cose_parameters(struct t_cose_parameters *parameters)
{
#if COSE_ALGORITHM_RESERVED != 0
#error Invalid algorithm designator not 0. Parameter list initialization fails.
#endif
#if T_COSE_UNSET_ALGORITHM_ID != COSE_ALGORITHM_RESERVED
#error Constant for unset algorithm ID not aligned with COSE_ALGORITHM_RESERVED
#endif
/* This clears all the useful_bufs to NULL_Q_USEFUL_BUF_C
* and the cose_algorithm_id to COSE_ALGORITHM_RESERVED
*/
memset(parameters, 0, sizeof(struct t_cose_parameters));
#ifndef T_COSE_DISABLE_CONTENT_TYPE
/* The only non-zero clear-state value. (0 is plain text in CoAP
* content format) */
parameters->content_type_uint = T_COSE_EMPTY_UINT_CONTENT_TYPE;
#endif
}
#endif /* t_cose_parameters_h */

494
3rdparty/exported/t_cose/src/t_cose_sign1_sign.c поставляемый Normal file
Просмотреть файл

@ -0,0 +1,494 @@
/*
* t_cose_sign1_sign.c
*
* Copyright (c) 2018-2021, Laurence Lundblade. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
* See BSD-3-Clause license in README.md
*/
#include "t_cose/t_cose_sign1_sign.h"
#include "qcbor/qcbor.h"
#include "t_cose_standard_constants.h"
#include "t_cose_crypto.h"
#include "t_cose_util.h"
/**
* \file t_cose_sign1_sign.c
*
* \brief This implements t_cose signing
*
* Stack usage to sign is dependent on the signing alg and key size
* and type of hash implementation. t_cose_sign1_finish() is the main
* user of stack It is 384 for \ref COSE_ALGORITHM_ES256 and 778 for
* \ref COSE_ALGORITHM_ES512.
*/
/*
* Cross-check to make sure public definition of algorithm
* IDs matches the internal ones.
*/
#if T_COSE_ALGORITHM_ES256 != COSE_ALGORITHM_ES256
#error COSE algorithm identifier definitions are in error
#endif
#if T_COSE_ALGORITHM_ES384 != COSE_ALGORITHM_ES384
#error COSE algorithm identifier definitions are in error
#endif
#if T_COSE_ALGORITHM_ES512 != COSE_ALGORITHM_ES512
#error COSE algorithm identifier definitions are in error
#endif
#ifndef T_COSE_DISABLE_SHORT_CIRCUIT_SIGN
static inline enum t_cose_err_t
short_circuit_sig_size(int32_t cose_algorithm_id,
size_t *sig_size)
{
*sig_size = cose_algorithm_id == COSE_ALGORITHM_ES256 ? T_COSE_EC_P256_SIG_SIZE :
cose_algorithm_id == COSE_ALGORITHM_ES384 ? T_COSE_EC_P384_SIG_SIZE :
cose_algorithm_id == COSE_ALGORITHM_ES512 ? T_COSE_EC_P512_SIG_SIZE :
0;
return sig_size == 0 ? T_COSE_ERR_UNSUPPORTED_SIGNING_ALG : T_COSE_SUCCESS;
}
/**
* \brief Create a short-circuit signature
*
* \param[in] cose_algorithm_id Algorithm ID. This is used only to make
* the short-circuit signature the same size
* as the real signature would be for the
* particular algorithm.
* \param[in] hash_to_sign The bytes to sign. Typically, a hash of
* a payload.
* \param[in] signature_buffer Pointer and length of buffer into which
* the resulting signature is put.
* \param[in] signature Pointer and length of the signature
* returned.
*
* \return This returns one of the error codes defined by \ref t_cose_err_t.
*
* This creates the short-circuit signature that is a concatenation of
* hashes up to the expected size of the signature. This is a test
* mode only has it has no security value. This is retained in
* commercial production code as a useful test or demo that can run
* even if key material is not set up or accessible.
*/
static inline enum t_cose_err_t
short_circuit_sign(int32_t cose_algorithm_id,
struct q_useful_buf_c hash_to_sign,
struct q_useful_buf signature_buffer,
struct q_useful_buf_c *signature)
{
/* approximate stack use on 32-bit machine: local use: 16 bytes
*/
enum t_cose_err_t return_value;
size_t array_indx;
size_t amount_to_copy;
size_t sig_size;
return_value = short_circuit_sig_size(cose_algorithm_id, &sig_size);
/* Check the signature length against buffer size */
if(return_value != T_COSE_SUCCESS) {
goto Done;
}
if(sig_size > signature_buffer.len) {
/* Buffer too small for this signature type */
return_value = T_COSE_ERR_SIG_BUFFER_SIZE;
goto Done;
}
/* Loop concatening copies of the hash to fill out to signature size */
for(array_indx = 0; array_indx < sig_size; array_indx += hash_to_sign.len) {
amount_to_copy = sig_size - array_indx;
if(amount_to_copy > hash_to_sign.len) {
amount_to_copy = hash_to_sign.len;
}
memcpy((uint8_t *)signature_buffer.ptr + array_indx,
hash_to_sign.ptr,
amount_to_copy);
}
signature->ptr = signature_buffer.ptr;
signature->len = sig_size;
return_value = T_COSE_SUCCESS;
Done:
return return_value;
}
#endif /* T_COSE_DISABLE_SHORT_CIRCUIT_SIGN */
/**
* \brief Makes the protected header parameters for COSE.
*
* \param[in] cose_algorithm_id The COSE algorithm ID to put in the
* header parameters.
* \param[in,out] cbor_encode_ctx Encoding context to output to.
*
* \return The pointer and length of the encoded protected
* parameters is returned, or \c NULL_Q_USEFUL_BUF_C if this fails.
* This will have the same pointer as \c buffer_for_parameters,
* but the pointer is conts and the length is that of the valid
* data, not of the size of the buffer.
*
* The protected parameters are returned in fully encoded CBOR format as
* they are added to the \c COSE_Sign1 message as a binary string. This is
* different from the unprotected parameters which are not handled this
* way.
*/
static inline struct q_useful_buf_c
encode_protected_parameters(int32_t cose_algorithm_id,
QCBOREncodeContext *cbor_encode_ctx)
{
/* Aproximate stack usage
* 64-bit 32-bit
* local vars 16 8
* QCBOR (guess) 32 24
* TOTAL 48 32
*/
struct q_useful_buf_c protected_parameters;
QCBOREncode_BstrWrap(cbor_encode_ctx);
QCBOREncode_OpenMap(cbor_encode_ctx);
QCBOREncode_AddInt64ToMapN(cbor_encode_ctx,
COSE_HEADER_PARAM_ALG,
cose_algorithm_id);
QCBOREncode_CloseMap(cbor_encode_ctx);
QCBOREncode_CloseBstrWrap2(cbor_encode_ctx, false, &protected_parameters);
return protected_parameters;
}
/**
* \brief Add the unprotected parameters to a CBOR encoding context
*
* \param[in] me The t_cose signing context.
* \param[in] kid The key ID.
* \param[in] cbor_encode_ctx CBOR encoding context to output to
*
* \returns An error of type \ref t_cose_err_t.
*
* The unprotected parameters added by this are the kid and content type.
*
* In the case of a QCBOR encoding error, T_COSE_SUCCESS will be returned
* and the error will be caught when \c QCBOR_Finish() is called on \c
* cbor_encode_ctx.
*/
static inline enum t_cose_err_t
add_unprotected_parameters(const struct t_cose_sign1_sign_ctx *me,
const struct q_useful_buf_c kid,
QCBOREncodeContext *cbor_encode_ctx)
{
/* Aproximate stack usage
* 64-bit 32-bit
* QCBOR (guess) 32 24
* TOTAL 32 24
*/
QCBOREncode_OpenMap(cbor_encode_ctx);
if(!q_useful_buf_c_is_null_or_empty(kid)) {
QCBOREncode_AddBytesToMapN(cbor_encode_ctx,
COSE_HEADER_PARAM_KID,
kid);
}
#ifndef T_COSE_DISABLE_CONTENT_TYPE
if(me->content_type_uint != T_COSE_EMPTY_UINT_CONTENT_TYPE &&
me->content_type_tstr != NULL) {
/* Both the string and int content types are not allowed */
return T_COSE_ERR_DUPLICATE_PARAMETER;
}
if(me->content_type_uint != T_COSE_EMPTY_UINT_CONTENT_TYPE) {
QCBOREncode_AddUInt64ToMapN(cbor_encode_ctx,
COSE_HEADER_PARAM_CONTENT_TYPE,
me->content_type_uint);
}
if(me->content_type_tstr != NULL) {
QCBOREncode_AddSZStringToMapN(cbor_encode_ctx,
COSE_HEADER_PARAM_CONTENT_TYPE,
me->content_type_tstr);
}
#else
(void)me; /* avoid unused parameter warning */
#endif
QCBOREncode_CloseMap(cbor_encode_ctx);
return T_COSE_SUCCESS;
}
/*
* Semi-private function. See t_cose_sign1_sign.h
*/
enum t_cose_err_t
t_cose_sign1_encode_parameters_internal(struct t_cose_sign1_sign_ctx *me,
bool payload_is_detached,
QCBOREncodeContext *cbor_encode_ctx)
{
enum t_cose_err_t return_value;
struct q_useful_buf_c kid;
int32_t hash_alg_id;
/* Check the cose_algorithm_id now by getting the hash alg as an
* early error check even though it is not used until later.
*/
hash_alg_id = hash_alg_id_from_sig_alg_id(me->cose_algorithm_id);
if(hash_alg_id == T_COSE_INVALID_ALGORITHM_ID) {
return T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
}
/* Add the CBOR tag indicating COSE_Sign1 */
if(!(me->option_flags & T_COSE_OPT_OMIT_CBOR_TAG)) {
QCBOREncode_AddTag(cbor_encode_ctx, CBOR_TAG_COSE_SIGN1);
}
/* Get started with the tagged array that holds the four parts of
* a cose single signed message */
QCBOREncode_OpenArray(cbor_encode_ctx);
/* The protected parameters, which are added as a wrapped bstr */
me->protected_parameters = encode_protected_parameters(me->cose_algorithm_id, cbor_encode_ctx);
/* The Unprotected parameters */
/* Get the kid because it goes into the parameters that are about
* to be made. */
kid = me->kid;
if(me->option_flags & T_COSE_OPT_SHORT_CIRCUIT_SIG) {
#ifndef T_COSE_DISABLE_SHORT_CIRCUIT_SIGN
if(q_useful_buf_c_is_null_or_empty(kid)) {
/* No kid passed in, Use the short-circuit kid */
kid = get_short_circuit_kid();
}
#else
return_value = T_COSE_ERR_SHORT_CIRCUIT_SIG_DISABLED;
goto Done;
#endif
}
return_value = add_unprotected_parameters(me, kid, cbor_encode_ctx);
if(return_value != T_COSE_SUCCESS) {
goto Done;
}
if(!payload_is_detached) {
QCBOREncode_BstrWrap(cbor_encode_ctx);
}
/* Any failures in CBOR encoding will be caught in finish when the
* CBOR encoding is closed off. No need to track here as the CBOR
* encoder tracks it internally.
*/
Done:
return return_value;
}
/*
* Semi-private function. See t_cose_sign1_sign.h
*/
enum t_cose_err_t
t_cose_sign1_encode_signature_aad_internal(struct t_cose_sign1_sign_ctx *me,
struct q_useful_buf_c aad,
struct q_useful_buf_c detached_payload,
QCBOREncodeContext *cbor_encode_ctx)
{
enum t_cose_err_t return_value;
QCBORError cbor_err;
/* pointer and length of the completed tbs hash */
struct q_useful_buf_c tbs_hash;
/* Pointer and length of the completed signature */
struct q_useful_buf_c signature;
/* Buffer for the actual signature */
Q_USEFUL_BUF_MAKE_STACK_UB( buffer_for_signature, T_COSE_MAX_SIG_SIZE);
/* Buffer for the tbs hash. */
Q_USEFUL_BUF_MAKE_STACK_UB( buffer_for_tbs_hash, T_COSE_CRYPTO_MAX_HASH_SIZE);
struct q_useful_buf_c signed_payload;
if(q_useful_buf_c_is_null(detached_payload)) {
QCBOREncode_CloseBstrWrap2(cbor_encode_ctx, false, &signed_payload);
} else {
signed_payload = detached_payload;
}
/* Check that there are no CBOR encoding errors before proceeding
* with hashing and signing. This is not actually necessary as the
* errors will be caught correctly later, but it does make it a
* bit easier for the caller to debug problems.
*/
cbor_err = QCBOREncode_GetErrorState(cbor_encode_ctx);
if(cbor_err == QCBOR_ERR_BUFFER_TOO_SMALL) {
return_value = T_COSE_ERR_TOO_SMALL;
goto Done;
} else if(cbor_err != QCBOR_SUCCESS) {
return_value = T_COSE_ERR_CBOR_FORMATTING;
goto Done;
}
/* Create the hash of the to-be-signed bytes. Inputs to the
* hash are the protected parameters, the payload that is
* getting signed, the cose signature alg from which the hash
* alg is determined. The cose_algorithm_id was checked in
* t_cose_sign1_init() so it doesn't need to be checked here.
*/
return_value = create_tbs_hash(me->cose_algorithm_id,
me->protected_parameters,
aad,
signed_payload,
buffer_for_tbs_hash,
&tbs_hash);
if(return_value) {
goto Done;
}
/* Compute the signature using public key crypto. The key and
* algorithm ID are passed in to know how and what to sign
* with. The hash of the TBS bytes is what is signed. A buffer
* in which to place the signature is passed in and the
* signature is returned.
*
* That or just compute the length of the signature if this
* is only an output length computation.
*/
if(!(me->option_flags & T_COSE_OPT_SHORT_CIRCUIT_SIG)) {
if (QCBOREncode_IsBufferNULL(cbor_encode_ctx)) {
/* Output size calculation. Only need signature size. */
signature.ptr = NULL;
return_value = t_cose_crypto_sig_size(me->cose_algorithm_id,
me->signing_key,
&signature.len);
} else {
/* Perform the public key signing */
return_value = t_cose_crypto_sign(me->cose_algorithm_id,
me->signing_key,
tbs_hash,
buffer_for_signature,
&signature);
}
#ifndef T_COSE_DISABLE_SHORT_CIRCUIT_SIGN
} else {
if (QCBOREncode_IsBufferNULL(cbor_encode_ctx)) {
/* Output size calculation. Only need signature size. */
signature.ptr = NULL;
return_value = short_circuit_sig_size(me->cose_algorithm_id,
&signature.len);
} else {
/* Perform the a short circuit signing */
return_value = short_circuit_sign(me->cose_algorithm_id,
tbs_hash,
buffer_for_signature,
&signature);
}
#endif /* T_COSE_DISABLE_SHORT_CIRCUIT_SIGN */
}
if(return_value != T_COSE_SUCCESS) {
goto Done;
}
/* Add signature to CBOR and close out the array */
QCBOREncode_AddBytes(cbor_encode_ctx, signature);
QCBOREncode_CloseArray(cbor_encode_ctx);
/* The layer above this must check for and handle CBOR encoding
* errors CBOR encoding errors. Some are detected at the start of
* this function, but they cannot all be deteced there.
*/
Done:
return return_value;
}
/*
* Semi-private function. See t_cose_sign1_sign.h
*/
enum t_cose_err_t
t_cose_sign1_sign_aad_internal(struct t_cose_sign1_sign_ctx *me,
bool payload_is_detached,
struct q_useful_buf_c payload,
struct q_useful_buf_c aad,
struct q_useful_buf out_buf,
struct q_useful_buf_c *result)
{
/* Aproximate stack usage
* 64-bit 32-bit
* local vars 8 4
* encode context 168 148
* QCBOR (guess) 32 24
* max(encode_param, encode_signature) 224-1316 216-1024
* TOTAL 432-1524 392-1300
*/
QCBOREncodeContext encode_context;
enum t_cose_err_t return_value;
/* -- Initialize CBOR encoder context with output buffer -- */
QCBOREncode_Init(&encode_context, out_buf);
/* -- Output the header parameters into the encoder context -- */
return_value = t_cose_sign1_encode_parameters_internal(me,
payload_is_detached,
&encode_context);
if(return_value != T_COSE_SUCCESS) {
goto Done;
}
if(payload_is_detached) {
/* -- Output NULL but the payload -- */
/* In detached content mode, the output COSE binary does not
* contain the target payload, and it should be derivered
* in another channel.
*/
QCBOREncode_AddNULL(&encode_context);
} else {
/* -- Output the payload into the encoder context -- */
/* Payload may or may not actually be CBOR format here. This
* function does the job just fine because it just adds bytes to
* the encoded output without anything extra.
*/
QCBOREncode_AddEncoded(&encode_context, payload);
}
/* -- Sign and put signature in the encoder context -- */
if(!payload_is_detached) {
payload = NULL_Q_USEFUL_BUF_C;
}
return_value = t_cose_sign1_encode_signature_aad_internal(me,
aad,
payload,
&encode_context);
if(return_value) {
goto Done;
}
/* -- Close off and get the resulting encoded CBOR -- */
if(QCBOREncode_Finish(&encode_context, result)) {
return_value = T_COSE_ERR_CBOR_NOT_WELL_FORMED;
goto Done;
}
Done:
return return_value;
}

361
3rdparty/exported/t_cose/src/t_cose_sign1_verify.c поставляемый Normal file
Просмотреть файл

@ -0,0 +1,361 @@
/*
* t_cose_sign1_verify.c
*
* Copyright 2019-2021, Laurence Lundblade
*
* SPDX-License-Identifier: BSD-3-Clause
*
* See BSD-3-Clause license in README.md
*/
#include "qcbor/qcbor_decode.h"
#ifndef QCBOR_SPIFFY_DECODE
#error This t_cose requires a version of QCBOR that supports spiffy decode
#endif
#include "qcbor/qcbor_spiffy_decode.h"
#include "t_cose/t_cose_sign1_verify.h"
#include "t_cose/q_useful_buf.h"
#include "t_cose_crypto.h"
#include "t_cose_util.h"
#include "t_cose_parameters.h"
/**
* \file t_cose_sign1_verify.c
*
* \brief \c COSE_Sign1 verification implementation.
*/
#ifndef T_COSE_DISABLE_SHORT_CIRCUIT_SIGN
/**
* \brief Verify a short-circuit signature
*
* \param[in] hash_to_verify Pointer and length of hash to verify.
* \param[in] signature Pointer and length of signature.
*
* \return This returns one of the error codes defined by \ref
* t_cose_err_t.
*
* See t_cose_sign1_sign_init() for description of the short-circuit
* signature.
*/
static inline enum t_cose_err_t
t_cose_crypto_short_circuit_verify(struct q_useful_buf_c hash_to_verify,
struct q_useful_buf_c signature)
{
/* Aproximate stack usage
* 64-bit 32-bit
* local vars 24 12
* TOTAL 24 12
*/
struct q_useful_buf_c hash_from_sig;
enum t_cose_err_t return_value;
hash_from_sig = q_useful_buf_head(signature, hash_to_verify.len);
if(q_useful_buf_c_is_null(hash_from_sig)) {
return_value = T_COSE_ERR_SIG_VERIFY;
goto Done;
}
if(q_useful_buf_compare(hash_from_sig, hash_to_verify)) {
return_value = T_COSE_ERR_SIG_VERIFY;
} else {
return_value = T_COSE_SUCCESS;
}
Done:
return return_value;
}
#endif /* T_COSE_DISABLE_SHORT_CIRCUIT_SIGN */
/**
* \brief Check the tagging of the COSE about to be verified.
*
* \param[in] me The verification context.
* \param[in] decode_context The decoder context to pull from.
*
* \return This returns one of the error codes defined by \ref
* t_cose_err_t.
*
* This must be called after decoding the opening array of four that
* starts all COSE message that is the item that is the content of the
* tags.
*
* This checks that the tag usage is as requested by the caller.
*
* This returns any tags that enclose the COSE message for processing
* at the level above COSE.
*/
static inline enum t_cose_err_t
process_tags(struct t_cose_sign1_verify_ctx *me, QCBORDecodeContext *decode_context)
{
/* Aproximate stack usage
* 64-bit 32-bit
* local vars 20 16
* TOTAL 20 16
*/
uint64_t uTag;
uint32_t item_tag_index = 0;
int returned_tag_index;
/* The 0th tag is the only one that might identify the type of the
* CBOR we are trying to decode so it is handled special.
*/
uTag = QCBORDecode_GetNthTagOfLast(decode_context, item_tag_index);
item_tag_index++;
if(me->option_flags & T_COSE_OPT_TAG_REQUIRED) {
/* The protocol that is using COSE says the input CBOR must
* be a COSE tag.
*/
if(uTag != CBOR_TAG_COSE_SIGN1) {
return T_COSE_ERR_INCORRECTLY_TAGGED;
}
}
if(me->option_flags & T_COSE_OPT_TAG_PROHIBITED) {
/* The protocol that is using COSE says the input CBOR must
* not be a COSE tag.
*/
if(uTag == CBOR_TAG_COSE_SIGN1) {
return T_COSE_ERR_INCORRECTLY_TAGGED;
}
}
/* If the protocol using COSE doesn't say one way or another about the
* tag, then either is OK.
*/
/* Initialize auTags, the returned tags, to CBOR_TAG_INVALID64 */
#if CBOR_TAG_INVALID64 != 0xffffffffffffffff
#error Initializing return tags array
#endif
memset(me->auTags, 0xff, sizeof(me->auTags));
returned_tag_index = 0;
if(uTag != CBOR_TAG_COSE_SIGN1) {
/* Never return the tag that this code is about to process. Note
* that you can sign a COSE_SIGN1 recursively. This only takes out
* the one tag layer that is processed here.
*/
me->auTags[returned_tag_index] = uTag;
returned_tag_index++;
}
while(1) {
uTag = QCBORDecode_GetNthTagOfLast(decode_context, item_tag_index);
item_tag_index++;
if(uTag == CBOR_TAG_INVALID64) {
break;
}
if(returned_tag_index > T_COSE_MAX_TAGS_TO_RETURN) {
return T_COSE_ERR_TOO_MANY_TAGS;
}
me->auTags[returned_tag_index] = uTag;
returned_tag_index++;
}
return T_COSE_SUCCESS;
}
/**
* \brief Map QCBOR decode error to COSE errors.
*
* \param[in] qcbor_error The QCBOR error to map.
*
* \return This returns one of the error codes defined by
* \ref t_cose_err_t.
*/
static inline enum t_cose_err_t
qcbor_decode_error_to_t_cose_error(QCBORError qcbor_error)
{
if(qcbor_error == QCBOR_ERR_TOO_MANY_TAGS) {
return T_COSE_ERR_TOO_MANY_TAGS;
}
if(QCBORDecode_IsNotWellFormedError(qcbor_error)) {
return T_COSE_ERR_CBOR_NOT_WELL_FORMED;
}
if(qcbor_error != QCBOR_SUCCESS) {
return T_COSE_ERR_SIGN1_FORMAT;
}
return T_COSE_SUCCESS;
}
enum t_cose_err_t
t_cose_sign1_verify_internal(struct t_cose_sign1_verify_ctx *me,
struct q_useful_buf_c cose_sign1,
struct q_useful_buf_c aad,
struct q_useful_buf_c *payload,
struct t_cose_parameters *returned_parameters,
bool is_dc)
{
/* Aproximate stack usage
* 64-bit 32-bit
* local vars 80 40
* Decode context 312 256
* Hash output 32-64 32-64
* header parameter lists 244 176
* MAX(parse_headers 768 628
* process tags 20 16
* check crit 24 12
* create_tbs_hash 32-748 30-746
* crypto lib verify 64-1024 64-1024) 768-1024 768-1024
* TOTAL 1724-1436 1560-1272
*/
QCBORDecodeContext decode_context;
struct q_useful_buf_c protected_parameters;
enum t_cose_err_t return_value;
Q_USEFUL_BUF_MAKE_STACK_UB( buffer_for_tbs_hash, T_COSE_CRYPTO_MAX_HASH_SIZE);
struct q_useful_buf_c tbs_hash;
struct q_useful_buf_c signature;
struct t_cose_label_list critical_parameter_labels;
struct t_cose_label_list unknown_parameter_labels;
struct t_cose_parameters parameters;
QCBORError qcbor_error;
#ifndef T_COSE_DISABLE_SHORT_CIRCUIT_SIGN
struct q_useful_buf_c short_circuit_kid;
#endif
clear_label_list(&unknown_parameter_labels);
clear_label_list(&critical_parameter_labels);
clear_cose_parameters(&parameters);
/* === Decoding of the array of four starts here === */
QCBORDecode_Init(&decode_context, cose_sign1, QCBOR_DECODE_MODE_NORMAL);
/* --- The array of 4 and tags --- */
QCBORDecode_EnterArray(&decode_context, NULL);
return_value = qcbor_decode_error_to_t_cose_error(QCBORDecode_GetError(&decode_context));
if(return_value != T_COSE_SUCCESS) {
goto Done;
}
return_value = process_tags(me, &decode_context);
if(return_value != T_COSE_SUCCESS) {
goto Done;
}
/* --- The protected parameters --- */
QCBORDecode_EnterBstrWrapped(&decode_context, QCBOR_TAG_REQUIREMENT_NOT_A_TAG, &protected_parameters);
if(protected_parameters.len) {
return_value = parse_cose_header_parameters(&decode_context,
&parameters,
&critical_parameter_labels,
&unknown_parameter_labels);
if(return_value != T_COSE_SUCCESS) {
goto Done;
}
}
QCBORDecode_ExitBstrWrapped(&decode_context);
/* --- The unprotected parameters --- */
return_value = parse_cose_header_parameters(&decode_context,
&parameters,
NULL,
&unknown_parameter_labels);
if(return_value != T_COSE_SUCCESS) {
goto Done;
}
/* --- The payload --- */
if(is_dc) {
QCBORItem tmp;
QCBORDecode_GetNext(&decode_context, &tmp);
if (tmp.uDataType != QCBOR_TYPE_NULL) {
return_value = T_COSE_ERR_CBOR_FORMATTING;
goto Done;
}
/* In detached content mode, the payload should be set by
* function caller, so there is no need to set tye payload.
*/
} else {
QCBORDecode_GetByteString(&decode_context, payload);
}
/* --- The signature --- */
QCBORDecode_GetByteString(&decode_context, &signature);
/* --- Finish up the CBOR decode --- */
QCBORDecode_ExitArray(&decode_context);
/* This check make sure the array only had the expected four
* items. It works for definite and indefinte length arrays. Also
* makes sure there were no extra bytes. Also that the payload
* and signature were decoded correctly. */
qcbor_error = QCBORDecode_Finish(&decode_context);
return_value = qcbor_decode_error_to_t_cose_error(qcbor_error);
if(return_value != T_COSE_SUCCESS) {
goto Done;
}
/* === End of the decoding of the array of four === */
if((me->option_flags & T_COSE_OPT_REQUIRE_KID) && q_useful_buf_c_is_null(parameters.kid)) {
return_value = T_COSE_ERR_NO_KID;
goto Done;
}
return_value = check_critical_labels(&critical_parameter_labels,
&unknown_parameter_labels);
if(return_value != T_COSE_SUCCESS) {
goto Done;
}
/* -- Skip signature verification if requested --*/
if(me->option_flags & T_COSE_OPT_DECODE_ONLY) {
return_value = T_COSE_SUCCESS;
goto Done;
}
/* -- Compute the TBS bytes -- */
return_value = create_tbs_hash(parameters.cose_algorithm_id,
protected_parameters,
aad,
*payload,
buffer_for_tbs_hash,
&tbs_hash);
if(return_value) {
goto Done;
}
/* -- Check for short-circuit signature and verify if it exists -- */
#ifndef T_COSE_DISABLE_SHORT_CIRCUIT_SIGN
short_circuit_kid = get_short_circuit_kid();
if(!q_useful_buf_compare(parameters.kid, short_circuit_kid)) {
if(!(me->option_flags & T_COSE_OPT_ALLOW_SHORT_CIRCUIT)) {
return_value = T_COSE_ERR_SHORT_CIRCUIT_SIG;
goto Done;
}
return_value = t_cose_crypto_short_circuit_verify(tbs_hash, signature);
goto Done;
}
#endif /* T_COSE_DISABLE_SHORT_CIRCUIT_SIGN */
/* -- Verify the signature (if it wasn't short-circuit) -- */
return_value = t_cose_crypto_verify(parameters.cose_algorithm_id,
me->verification_key,
parameters.kid,
tbs_hash,
signature);
Done:
if(returned_parameters != NULL) {
*returned_parameters = parameters;
}
return return_value;
}

405
3rdparty/exported/t_cose/src/t_cose_standard_constants.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,405 @@
/*
* t_cose_standard_constants.h
*
* Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
* See BSD-3-Clause license in README.md
*/
#ifndef __T_COSE_STANDARD_CONSTANTS_H__
#define __T_COSE_STANDARD_CONSTANTS_H__
/**
* \file t_cose_standard_constants.h
*
* \brief Constants from COSE standard and IANA registry.
*
* This file contains constants identifiers defined in
* [COSE (RFC 8152)](https://tools.ietf.org/html/rfc8152) and
* [IANA COSE Registry](https://www.iana.org/assignments/cose/cose.xhtml).
* They include algorithm IDs and other constants.
*
* Many constants in the IANA registry are not included here yet as
* they are not needed by t_cose. They can be added if they become
* needed.
*
* This file is not part of the t_cose public interface as it contains
* lots of stuff not needed in the public interface. The parts that
* are needed in the public interface are also defined as \ref
* T_COSE_ALGORITHM_ES256 and related (there is a pre processor cross
* check to make sure they don't get defined differently in
* t_cose_sign1_sign.c).
*/
/* --------------- COSE Header parameters -----------
* https://www.iana.org/assignments/cose/cose.xhtml#header-parameters
*/
/**
* \def COSE_HEADER_PARAM_ALG
*
* \brief Label of COSE parameter that indicates an algorithm.
*
* The algorithm assignments are found in the IANA registry here
* https://www.iana.org/assignments/cose/cose.xhtml#algorithms
* Signing algorithms are identified as combinations of the
* public key algorithm, padding mode and hash. This must be
* a protected header. They may be string or integers. This
* implementation only support integer IDs.
*/
#define COSE_HEADER_PARAM_ALG 1
/**
* \def COSE_HEADER_PARAM_CRIT
*
* \brief Label of COSE parameter listing critical header parameters
*
* The contents is an array of header parameter labels, either string or
* integer. The implementation must know how to process them or it is
* an error.
*/
#define COSE_HEADER_PARAM_CRIT 2
/**
* \def COSE_HEADER_PARAM_CONTENT_TYPE
*
* \brief Label of COSE parameter with the content type
*
* Either an integer CoAP content type or a string MIME type. This is
* the type of the data in the payload.
*/
#define COSE_HEADER_PARAM_CONTENT_TYPE 3
/**
* \def COSE_HEADER_PARAM_KID
*
* \brief CBOR map label of COSE parameter that contains a kid (key ID).
*
* The kid is a byte string identifying the key. It is optional and
* there is no required format. They are not even required to be
* unique.
*/
#define COSE_HEADER_PARAM_KID 4
/**
* \def COSE_HEADER_PARAM_IV
*
* \brief CBOR map label of parameter that contains an initialization
* vector.
*
* A binary string initialization vector.
*
* This implementation only parses this.
*/
#define COSE_HEADER_PARAM_IV 5
/**
* \def COSE_HEADER_PARAM_PARTIAL_IV
*
* \brief CBOR map label of parameter containing partial
* initialization vector.
*
* A binary string partial initialization vector.
*
* This implementation only parses this.
*/
#define COSE_HEADER_PARAM_PARTIAL_IV 6
/**
* \def COSE_HEADER_PARAM_COUNTER_SIGNATURE
*
* \brief CBOR map label of parameter that holds one or more counter signature.
*
* Counter signatures can be full \c COSE_Sign1, \c COSE_Signature and
* such messages. This implementation doesn't support them.
*/
#define COSE_HEADER_PARAM_COUNTER_SIGNATURE 6
/* ------------ COSE Header Algorithm Parameters --------------
* https://www.iana.org/assignments/cose/cose.xhtml#header-algorithm-parameters
*
* None of these are defined here yet, as they are not needed by t_cose yet.
*/
/* ------------- COSE Algorithms ----------------------------
* https://www.iana.org/assignments/cose/cose.xhtml#algorithms
*/
/**
* This is defined as reserved by IANA. This implementation uses it to
* mean the end of a list of algorithm IDs or an unset algorithm ID.
*/
#define COSE_ALGORITHM_RESERVED 0
/**
* \def COSE_ALGORITHM_ES256
*
* \brief Indicates ECDSA with SHA-256.
*
* Value for \ref COSE_HEADER_PARAM_ALG to indicate ECDSA with SHA-256.
*
* RFC 8152 section 8.1 suggests, but does not require, that this
* algorithm identifier only be used with keys based on the P-256
* curve (also known as prime256v1 or secp256r1).
*
* See https://tools.ietf.org/search/rfc4492 and https://tools.ietf.org/html/rfc8152
*/
#define COSE_ALGORITHM_ES256 -7
/**
* \def COSE_ALGORITHM_ES384
*
* \brief Indicates ECDSA with SHA-384.
*
* See discussion on \ref COSE_ALGORITHM_ES256.
*
* RFC 8152 section 8.1 suggests, but does not require, that this
* algorithm identifier be used only with keys based on the P-384
* curve (also known as secp384r1).
*/
#define COSE_ALGORITHM_ES384 -35
/**
* \def COSE_ALGORITHM_ES512
*
* \brief Indicates ECDSA with SHA-512.
*
* See discussion on \ref COSE_ALGORITHM_ES256.
*
* RFC 8152 section 8.1 suggests, but does not require, that this
* algorithm identifier be used only with keys based on the P-521
* curve (also known as secp521r1)
*/
#define COSE_ALGORITHM_ES512 -36
/**
* \def COSE_ALGORITHM_SHA_256
*
* \brief Indicates simple SHA-256 hash.
*
* This is not used in the t_cose interface, just used internally.
*/
#define COSE_ALGORITHM_SHA_256 -16
/**
* \def COSE_ALGORITHM_SHA_384
*
* \brief Indicates simple SHA-384 hash.
*
* This is not used in the t_cose interface, just used internally.
*/
#define COSE_ALGORITHM_SHA_384 -43
/**
* \def COSE_ALGORITHM_SHA_512
*
* \brief Indicates simple SHA-512 hash.
*
* This is not used in the t_cose interface, just used internally.
*/
#define COSE_ALGORITHM_SHA_512 -44
/* ---------- COSE Key Common Parameters --------------
* https://www.iana.org/assignments/cose/cose.xhtml#key-common-parameters
*/
/**
* \def COSE_KEY_COMMON_KTY
*
* \brief Label for data item containing the key type.
*
* In a \c COSE_Key, label that indicates the data item containing the
* key type.
*/
#define COSE_KEY_COMMON_KTY 1
/**
* \def COSE_KEY_COMMON_KID
*
* \brief Label for data item containing the key's kid.
*
* In a \c COSE_Key, label that indicates the data item containing the
* kid of this key.
*/
#define COSE_KEY_COMMON_KID 2
/* ---------- COSE Key Type Parameters --------------------
* https://www.iana.org/assignments/cose/cose.xhtml#key-type-parameters
*
* These are not used by this implementation.
*/
/**
* \def COSE_KEY_PARAM_CRV
*
* \brief Label for data item indicating EC curve.
*
* In a \c COSE_Key that holds an EC key of either type \ref
* COSE_KEY_TYPE_EC2 or \ref COSE_KEY_TYPE_OKP this labels the data
* item with the EC curve for the key.
*/
#define COSE_KEY_PARAM_CRV -1
/**
* \def COSE_KEY_PARAM_X_COORDINATE
*
* \brief Label for data item that is an X coordinate of an EC key.
*
* In a \c COSE_Key that holds an EC key, this is label that indicates
* the data item containing the X coordinate.
*
* This is used for both key types \ref COSE_KEY_TYPE_EC2 and \ref
* COSE_KEY_TYPE_OKP.
*/
#define COSE_KEY_PARAM_X_COORDINATE -2
/**
* \def COSE_KEY_PARAM_Y_COORDINATE
*
* \brief Label for data item that is a y coordinate of an EC key.
*
* In a COSE_Key that holds an EC key, this is label that indicates
* the data item containing the Y coordinate.
*
* This is used only for key type \ref COSE_KEY_TYPE_EC2.
*/
#define COSE_KEY_PARAM_Y_COORDINATE -3
/**
* \def COSE_KEY_PARAM_PRIVATE_D
*
* \brief Label for data item that is d, the private part of EC key.
*
* In a \c COSE_Key that holds an EC key, this is label that indicates
* the data item containing the Y coordinate.
*
* This is used for both key types \ref COSE_KEY_TYPE_EC2 and \ref
* COSE_KEY_TYPE_OKP.
*/
#define COSE_KEY_PARAM_PRIVATE_D -4
/* ---------- COSE Key Types --------------------------------
* https://www.iana.org/assignments/cose/cose.xhtml#key-type
*/
/**
* \def COSE_KEY_TYPE_OKP
*
* \brief Key type is Octet Key Pair
*
* In a \c COSE_Key, this is a value of the data item labeled \ref
* COSE_KEY_COMMON_KTY that indicates the \c COSE_Key is some sort of
* key pair represented by some octets. It may or may not be an EC
* key.
*/
#define COSE_KEY_TYPE_OKP 1
/**
* \def COSE_KEY_TYPE_EC2
*
* \brief Key is a 2-parameter EC key.
*
* In a \c COSE_Key, this is a value of the data item labeled \ref
* COSE_KEY_COMMON_KTY that indicates the \c COSE_Key is an EC key
* specified with two coordinates, X and Y.
*/
#define COSE_KEY_TYPE_EC2 2
/**
* \def COSE_KEY_TYPE_SYMMETRIC
*
* \brief Key is a symmetric key.
*
* In a \c COSE_Key, this is a value of the data item labeled \ref
* COSE_KEY_COMMON_KTY that indicates the \c COSE_Key is a symmetric
* key.
*/
#define COSE_KEY_TYPE_SYMMETRIC 4
/* ----------- COSE Elliptic Curves ---------------------
* https://www.iana.org/assignments/cose/cose.xhtml#elliptic-curves
*/
/**
* \def COSE_ELLIPTIC_CURVE_P_256
*
* \brief Key type for NIST P-256 key
*
* In a \c COSE_Key, this is a value of the data item labeled \ref
* COSE_KEY_PARAM_CRV to indicate the NIST P-256 curve, also known as
* secp256r1.
*
* This key type is always \ref COSE_KEY_TYPE_EC2.
*/
#define COSE_ELLIPTIC_CURVE_P_256 1
/**
* \def COSE_ELLIPTIC_CURVE_P_384
*
* \brief Key type for NIST P-384 key
*
* In a \c COSE_Key, this is a value of the data item labeled \ref
* COSE_KEY_PARAM_CRV to indicate the NIST P-384 curve, also known as
* secp384r1.
*
* This key type is always \ref COSE_KEY_TYPE_EC2.
*/
#define COSE_ELLIPTIC_CURVE_P_384 2
/**
* \def COSE_ELLIPTIC_CURVE_P_521
*
* \brief Key type for NIST P-521 key
*
* In a \c COSE_Key, this is a value of the data item labeled \ref
* COSE_KEY_PARAM_CRV to indicate the NIST P-521 curve, also known as
* secp521r1.
*/
#define COSE_ELLIPTIC_CURVE_P_521 3
/* ------- Constants from RFC 8152 ---------
*/
/**
* \def COSE_SIG_CONTEXT_STRING_SIGNATURE1
*
* \brief This is a string constant used by COSE to label \c
* COSE_Sign1 structures. See RFC 8152, section 4.4.
*/
#define COSE_SIG_CONTEXT_STRING_SIGNATURE1 "Signature1"
#endif /* __T_COSE_STANDARD_CONSTANTS_H__ */

209
3rdparty/exported/t_cose/src/t_cose_util.c поставляемый Normal file
Просмотреть файл

@ -0,0 +1,209 @@
/*
* t_cose_util.c
*
* Copyright 2019-2021, Laurence Lundblade
*
* SPDX-License-Identifier: BSD-3-Clause
*
* See BSD-3-Clause license in README.md
*/
#include "qcbor/qcbor.h"
#include "t_cose/t_cose_common.h"
#include "t_cose_util.h"
#include "t_cose_standard_constants.h"
#include "t_cose_crypto.h"
/**
* \file t_cose_util.c
*
* \brief Implementation of t_cose utility functions.
*
* These are some functions common to signing and verification,
* primarily the to-be-signed bytes hashing.
*/
/*
* Public function. See t_cose_util.h
*/
int32_t hash_alg_id_from_sig_alg_id(int32_t cose_algorithm_id)
{
/* If other hashes, particularly those that output bigger hashes
* are added here, various other parts of this code have to be
* changed to have larger buffers, in particular
* \ref T_COSE_CRYPTO_MAX_HASH_SIZE.
*/
/* ? : operator precedence is correct here. This makes smaller
* code than a switch statement and is easier to read.
*/
return cose_algorithm_id == COSE_ALGORITHM_ES256 ? COSE_ALGORITHM_SHA_256 :
#ifndef T_COSE_DISABLE_ES384
cose_algorithm_id == COSE_ALGORITHM_ES384 ? COSE_ALGORITHM_SHA_384 :
#endif
#ifndef T_COSE_DISABLE_ES512
cose_algorithm_id == COSE_ALGORITHM_ES512 ? COSE_ALGORITHM_SHA_512 :
#endif
T_COSE_INVALID_ALGORITHM_ID;
}
/**
* \brief Hash an encoded bstr without actually encoding it in memory
*
* @param hash_ctx Hash context to hash it into
* @param bstr Bytes of the bstr
*
* If \c bstr is \c NULL_Q_USEFUL_BUF_C, a zero-length bstr will be
* hashed into the output.
*/
static void hash_bstr(struct t_cose_crypto_hash *hash_ctx,
struct q_useful_buf_c bstr)
{
/* Aproximate stack usage
* 64-bit 32-bit
* buffer_for_encoded 9 9
* useful_buf 16 8
* hash function (a guess! variable!) 16-512 16-512
* TOTAL 41-537 23-529
*/
/* make a struct q_useful_buf on the stack of size QCBOR_HEAD_BUFFER_SIZE */
Q_USEFUL_BUF_MAKE_STACK_UB (buffer_for_encoded_head, QCBOR_HEAD_BUFFER_SIZE);
struct q_useful_buf_c encoded_head;
encoded_head = QCBOREncode_EncodeHead(buffer_for_encoded_head,
CBOR_MAJOR_TYPE_BYTE_STRING,
0,
bstr.len);
/* An encoded bstr is the CBOR head with its length followed by the bytes */
t_cose_crypto_hash_update(hash_ctx, encoded_head);
t_cose_crypto_hash_update(hash_ctx, bstr);
}
/*
* Public function. See t_cose_util.h
*/
/*
* Format of to-be-signed bytes used by create_tbs_hash(). This is
* defined in COSE (RFC 8152) section 4.4. It is the input to the
* hash.
*
* Sig_structure = [
* context : "Signature" / "Signature1" / "CounterSignature",
* body_protected : empty_or_serialized_map,
* ? sign_protected : empty_or_serialized_map,
* external_aad : bstr,
* payload : bstr
* ]
*
* body_protected refers to the protected parameters from the main
* COSE_Sign1 structure. This is a little hard to to understand in the
* spec.
*/
enum t_cose_err_t create_tbs_hash(int32_t cose_algorithm_id,
struct q_useful_buf_c protected_parameters,
struct q_useful_buf_c aad,
struct q_useful_buf_c payload,
struct q_useful_buf buffer_for_hash,
struct q_useful_buf_c *hash)
{
/* Aproximate stack usage
* 64-bit 32-bit
* local vars 8 6
* hash_ctx 8-224 8-224
* hash function (a guess! variable!) 16-512 16-512
* TOTAL 32-748 30-746
*/
enum t_cose_err_t return_value;
struct t_cose_crypto_hash hash_ctx;
int32_t hash_alg_id;
/* Start the hashing */
hash_alg_id = hash_alg_id_from_sig_alg_id(cose_algorithm_id);
/* Don't check hash_alg_id for failure. t_cose_crypto_hash_start()
* will handle error properly. It was also checked earlier.
*/
return_value = t_cose_crypto_hash_start(&hash_ctx, hash_alg_id);
if(return_value) {
goto Done;
}
/*
* Format of to-be-signed bytes. This is defined in COSE (RFC
* 8152) section 4.4. It is the input to the hash.
*
* Sig_structure = [
* context : "Signature" / "Signature1" / "CounterSignature",
* body_protected : empty_or_serialized_map,
* ? sign_protected : empty_or_serialized_map,
* external_aad : bstr,
* payload : bstr
* ]
*
* sign_protected is not used with COSE_Sign1 since there is no
* signer chunk.
*
* external_aad allows external data to be covered by the
* signature, but may be a NULL_Q_USEFUL_BUF_C in which case a
* zero-length bstr will be correctly hashed into the result.
*
* Instead of formatting the TBS bytes in one buffer, they are
* formatted in chunks and fed into the hash. If actually
* formatted, the TBS bytes are slightly larger than the payload,
* so this saves a lot of memory.
*/
/* Hand-constructed CBOR for the array of 4 and the context string.
* \x84 is an array of 4. \x6A is a text string of 10 bytes. */
t_cose_crypto_hash_update(&hash_ctx, Q_USEFUL_BUF_FROM_SZ_LITERAL("\x84\x6A" COSE_SIG_CONTEXT_STRING_SIGNATURE1));
/* body_protected */
hash_bstr(&hash_ctx, protected_parameters);
/* external_aad */
hash_bstr(&hash_ctx, aad);
/* payload */
hash_bstr(&hash_ctx, payload);
/* Finish the hash and set up to return it */
return_value = t_cose_crypto_hash_finish(&hash_ctx,
buffer_for_hash,
hash);
Done:
return return_value;
}
#ifndef T_COSE_DISABLE_SHORT_CIRCUIT_SIGN
/* This is a random hard coded kid (key ID) that is used to indicate
* short-circuit signing. It is OK to hard code this as the
* probability of collision with this ID is very low and the same as
* for collision between any two key IDs of any sort.
*/
static const uint8_t defined_short_circuit_kid[] = {
0xef, 0x95, 0x4b, 0x4b, 0xd9, 0xbd, 0xf6, 0x70,
0xd0, 0x33, 0x60, 0x82, 0xf5, 0xef, 0x15, 0x2a,
0xf8, 0xf3, 0x5b, 0x6a, 0x6c, 0x00, 0xef, 0xa6,
0xa9, 0xa7, 0x1f, 0x49, 0x51, 0x7e, 0x18, 0xc6};
static struct q_useful_buf_c short_circuit_kid;
/*
* Public function. See t_cose_util.h
*/
struct q_useful_buf_c get_short_circuit_kid(void)
{
short_circuit_kid.len = sizeof(defined_short_circuit_kid);
short_circuit_kid.ptr = defined_short_circuit_kid;
return short_circuit_kid;
}
#endif

148
3rdparty/exported/t_cose/src/t_cose_util.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,148 @@
/*
* t_cose_util.h
*
* Copyright 2019-2021, Laurence Lundblade
*
* SPDX-License-Identifier: BSD-3-Clause
*
* See BSD-3-Clause license in README.md
*/
#ifndef __T_COSE_UTIL_H__
#define __T_COSE_UTIL_H__
#include <stdint.h>
#include "t_cose/q_useful_buf.h"
#include "t_cose/t_cose_common.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \file t_cose_util.h
*
* \brief Utility functions used internally by the t_cose implementation.
*
*/
/**
* This value represents an invalid or in-error algorithm ID. The
* value selected is 0 as this is reserved in the IANA COSE algorithm
* registry and is very unlikely to ever be used. (It would take am
* IETF standards-action to put it to use).
*/
#define T_COSE_INVALID_ALGORITHM_ID COSE_ALGORITHM_RESERVED
/**
* \brief Return hash algorithm ID from a signature algorithm ID
*
* \param[in] cose_algorithm_id A COSE signature algorithm identifier.
*
* \return \c T_COSE_INVALID_ALGORITHM_ID when the signature algorithm ID
is not known.
*
* This works off of algorithm identifiers defined in the
* [IANA COSE Registry](https://www.iana.org/assignments/cose/cose.xhtml).
* Corresponding local integer constants are defined in
* t_cose_standard_constants.h.
*
* COSE signing algorithms are the combination of public key
* algorithm, hash algorithm and hash size and imply an appropriate
* key size. They are simple integers making them convenient for
* direct use in code.
*
* This function returns an identifier for only the hash algorithm
* from the combined identifier.
*
* If the needed algorithm identifiers are not in the IANA registry,
* they can be added to it. This will take some time and work. It is
* also fine to use algorithms in the COSE proprietary space.
*/
int32_t hash_alg_id_from_sig_alg_id(int32_t cose_algorithm_id);
/**
* \brief Create the hash of the to-be-signed (TBS) bytes for COSE.
*
* \param[in] cose_algorithm_id The COSE signing algorithm ID. Used to
* determine which hash function to use.
* \param[in] protected_parameters Full, CBOR encoded, protected parameters.
* \param[in] aad Additional Authenitcated Data to be
* included in TBS.
* \param[in] payload The CBOR-encoded payload.
* \param[in] buffer_for_hash Pointer and length of buffer into which
* the resulting hash is put.
* \param[out] hash Pointer and length of the
* resulting hash.
*
* \return This returns one of the error codes defined by \ref t_cose_err_t.
*
* \retval T_COSE_ERR_SIG_STRUCT
* Most likely this is because the protected_parameters passed in
* is larger than \c T_COSE_SIGN1_MAX_SIZE_PROTECTED_PARAMETERS.
* \retval T_COSE_ERR_UNSUPPORTED_HASH
* If the hash algorithm is not known.
* \retval T_COSE_ERR_HASH_GENERAL_FAIL
* In case of some general hash failure.
*
* The input to the public key signature algorithm in COSE is the hash
* of a CBOR encoded structure containing the protected parameters
* algorithm ID and a few other things. This formats that structure
* and computes the hash of it. These are known as the to-be-signed or
* "TBS" bytes. The exact specification is in [RFC 8152 section
* 4.4](https://tools.ietf.org/html/rfc8152#section-4.4).
*
* \c aad can be \ref NULL_Q_USEFUL_BUF_C if not present.
*/
enum t_cose_err_t create_tbs_hash(int32_t cose_algorithm_id,
struct q_useful_buf_c protected_parameters,
struct q_useful_buf_c aad,
struct q_useful_buf_c payload,
struct q_useful_buf buffer_for_hash,
struct q_useful_buf_c *hash);
#ifndef T_COSE_DISABLE_SHORT_CIRCUIT_SIGN
/**
* Size of the key returned by get_short_circuit_kid(). It is always
* this size.
*/
#define T_COSE_SHORT_CIRCUIT_KID_SIZE 32
/**
* \brief Get the special kid for short-circuit signing.
*
* \returns Buffer with the kid.
*
* This always returns the same kid. It always indicates short-circuit
* signing. It is OK to hard code this kid value as the probability of
* collision with this ID is extremely low and the same as for
* collision between any two key IDs (kids) of any sort.
*
* This always returns a pointer to the same memory as the result
* returned by this never changes.
*
* This is the value of the kid.
*
* 0xef, 0x95, 0x4b, 0x4b, 0xd9, 0xbd, 0xf6, 0x70,
* 0xd0, 0x33, 0x60, 0x82, 0xf5, 0xef, 0x15, 0x2a,
* 0xf8, 0xf3, 0x5b, 0x6a, 0x6c, 0x00, 0xef, 0xa6,
* 0xa9, 0xa7, 0x1f, 0x49, 0x51, 0x7e, 0x18, 0xc6
*
*/
struct q_useful_buf_c get_short_circuit_kid(void);
#endif
#ifdef __cplusplus
}
#endif
#endif /* __T_COSE_UTIL_H__ */

Двоичные данные
3rdparty/exported/t_cose/t-cose-logo.png поставляемый Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 67 KiB

1018
3rdparty/exported/t_cose/t_cose.xcodeproj/project.pbxproj поставляемый Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

162
3rdparty/exported/t_cose/t_cose/q_useful_buf.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,162 @@
/*
* q_useful_buf.h
*
* Copyright 2019, Laurence Lundblade
*
* SPDX-License-Identifier: BSD-3-Clause
*
* See BSD-3-Clause license in README.md
*/
#ifndef __Q_USEFUL_BUF_H__
#define __Q_USEFUL_BUF_H__
#include "qcbor/UsefulBuf.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \file q_useful_buf.h
*
* \brief This is a TF-M coding style version of UsefulBuf.
* See UsefulBuf for documentation of these functions.
*/
#define NULL_Q_USEFUL_BUF_C NULLUsefulBufC
#define NULL_Q_USEFUL_BUF NULLUsefulBuf
static inline int q_useful_buf_c_is_null(struct q_useful_buf_c in)
{
return UsefulBuf_IsNULLC(in);
}
static inline int q_useful_buf_is_null(struct q_useful_buf in)
{
return UsefulBuf_IsNULL(in);
}
static inline int q_useful_buf_c_is_empty(struct q_useful_buf_c in)
{
return UsefulBuf_IsEmptyC(in);
}
static inline int q_useful_buf_is_empty(struct q_useful_buf in)
{
return UsefulBuf_IsEmpty(in);
}
static inline int q_useful_buf_is_null_or_empty(struct q_useful_buf in)
{
return UsefulBuf_IsNULLOrEmpty(in);
}
static inline int q_useful_buf_c_is_null_or_empty(struct q_useful_buf_c in)
{
return UsefulBuf_IsNULLOrEmptyC(in);
}
static inline struct q_useful_buf_c q_usefulbuf_const(struct q_useful_buf ub)
{
return UsefulBuf_Const(ub);
}
static inline struct q_useful_buf q_useful_buf_unconst(struct q_useful_buf_c in)
{
return UsefulBuf_Unconst(in);
}
#define Q_USEFUL_BUF_FROM_SZ_LITERAL UsefulBuf_FROM_SZ_LITERAL
#define Q_USEFUL_BUF_FROM_BYTE_ARRAY_LITERAL UsefulBuf_FROM_BYTE_ARRAY_LITERAL
#define Q_USEFUL_BUF_MAKE_STACK_UB UsefulBuf_MAKE_STACK_UB
#define Q_USEFUL_BUF_FROM_BYTE_ARRAY UsefulBuf_FROM_BYTE_ARRAY
static inline struct q_useful_buf_c q_useful_buf_from_sz(const char *string)
{
return UsefulBuf_FromSZ(string);
}
static inline struct q_useful_buf_c
useful_buf_copy_offset(struct q_useful_buf dest,
size_t offset,
struct q_useful_buf_c src)
{
return UsefulBuf_CopyOffset(dest, offset, src);
}
static inline struct q_useful_buf_c q_useful_buf_copy(struct q_useful_buf dest,
struct q_useful_buf_c src)
{
return UsefulBuf_Copy(dest, src);
}
static inline struct q_useful_buf_c q_useful_buf_set(struct q_useful_buf dest,
uint8_t value)
{
return UsefulBuf_Set(dest, value);
}
static inline struct q_useful_buf_c q_useful_buf_copy_ptr(struct q_useful_buf d,
const void *ptr,
size_t len)
{
return UsefulBuf_CopyPtr(d, ptr, len);
}
static inline struct q_useful_buf_c q_useful_buf_head(struct q_useful_buf_c buf,
size_t amount)
{
return UsefulBuf_Head(buf, amount);
}
static inline struct q_useful_buf_c q_useful_buf_tail(struct q_useful_buf_c buf,
size_t amount)
{
return UsefulBuf_Tail(buf, amount);
}
static inline int q_useful_buf_compare(const struct q_useful_buf_c buf1,
const struct q_useful_buf_c buf2)
{
return UsefulBuf_Compare(buf1, buf2);
}
static inline size_t q_useful_buf_is_value(const struct q_useful_buf_c buf,
uint8_t uValue)
{
return UsefulBuf_IsValue(buf, uValue);
}
static inline size_t
q_useful_buf_find_bytes(const struct q_useful_buf_c bytes_to_search,
const struct q_useful_buf_c bytes_to_find)
{
return UsefulBuf_FindBytes(bytes_to_search, bytes_to_find);
}
#ifdef __cplusplus
}
#endif
#endif /* __Q_USEFUL_BUF_H__ */

379
3rdparty/exported/t_cose/t_cose/t_cose_common.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,379 @@
/*
* t_cose_common.h
*
* Copyright 2019-2022, Laurence Lundblade
*
* SPDX-License-Identifier: BSD-3-Clause
*
* See BSD-3-Clause license in README.md
*/
#ifndef __T_COSE_COMMON_H__
#define __T_COSE_COMMON_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \file t_cose_common.h
*
* \brief This file contains definitions common to all public t_cose
* interfaces.
*
* t_cose_common.h contains the definitions common to all public
* t_cose interfaces, particularly the error codes, algorithm
* identification constants and the structure containing a key.
*
* **Compile Time Configuration Options**
*
* \c T_COSE_DISABLE_SHORT_CIRCUIT_SIGN -- This disables short-circuit
* signing test mode. This saves a small amount of object code
*
* \c T_COSE_DISABLE_ES512 -- Disables the COSE algorithm ES512
* algorithm. This saves a tiny amount of code and a few hundred bytes
* of stack. It saves more than \c T_COSE_DISABLE_ES384.
*
* \c T_COSE_DISABLE_ES384 -- Disables the COSE algorithm ES384
* algorithm. This saves a tiny amount of code and a few hundred bytes
* of stack. No stack will be saved if \c T_COSE_DISABLE_ES512 is not
* also defined.
*
* \c T_COSE_DISABLE_CONTENT_TYPE -- Disables the content type
* parameters for both signing and verifying.
*/
/**
* \def T_COSE_ALGORITHM_ES256
*
* \brief Indicates ECDSA with SHA-256.
*
* This value comes from the
* [IANA COSE Registry](https://www.iana.org/assignments/cose/cose.xhtml).
*
* The COSE standard recommends a key using the secp256r1 curve with
* this algorithm. This curve is also known as prime256v1 and P-256.
*/
#define T_COSE_ALGORITHM_ES256 -7
/**
* \def T_COSE_ALGORITHM_ES384
*
* \brief Indicates ECDSA with SHA-384.
*
* This value comes from the
* [IANA COSE Registry](https://www.iana.org/assignments/cose/cose.xhtml).
*
* The COSE standard recommends a key using the secp384r1 curve with
* this algorithm. This curve is also known as P-384.
*/
#define T_COSE_ALGORITHM_ES384 -35
/**
* \def T_COSE_ALGORITHM_ES512
*
* \brief Indicates ECDSA with SHA-512.
*
* This value comes from the
* [IANA COSE Registry](https://www.iana.org/assignments/cose/cose.xhtml).
*
* The COSE standard recommends a key using the secp521r1 curve with
* this algorithm. This curve is also known as P-521.
*/
#define T_COSE_ALGORITHM_ES512 -36
/**
* Indicates the cryptographic library the \ref t_cose_key is intended
* for. Usually only one cryptographic library is integrated so this
* serves as a cross-check.
*/
enum t_cose_crypto_lib_t {
/** can be used for integrations
* that don't have or don't want to have any cross-check.
*/
T_COSE_CRYPTO_LIB_UNIDENTIFIED = 0,
/** \c key_ptr points to a malloced OpenSSL EC_KEY. The caller
* needs to free it after the operation is done. */
T_COSE_CRYPTO_LIB_OPENSSL = 1,
/** \c key_handle is a \c psa_key_handle_t in Arm's Platform Security
* Architecture */
T_COSE_CRYPTO_LIB_PSA = 2
};
/**
* This structure is used to indicate or pass a key through the t_cose
* implementation to the underlying, platform-specific cryptography
* libraries for signing and verifying signature. You must know the
* cryptographic library that is integrated with t_cose to know how to
* fill in this data structure.
*
* For example, in the OpenSSL integration, \ref key_ptr should point
* to an OpenSSL \c EVP_KEY type.
*/
struct t_cose_key {
/** Identifies the crypto library this key was created for. The
* crypto library knows if it uses the handle or the pointer so
* this indirectly selects the union member. */
enum t_cose_crypto_lib_t crypto_lib;
union {
/** For libraries that use a pointer to the key or key
* handle. \c NULL indicates empty. */
void *key_ptr;
/** For libraries that use an integer handle to the key */
uint64_t key_handle;
} k;
};
/** An empty or \c NULL \c t_cose_key */
/*
* This has to be definied differently in C than C++ because there is
* no common construct for a literal structure.
*
* In C compound literals are used.
*
* In C++ list initalization is used. This only works
* in C++11 and later.
*
* Note that some popular C++ compilers can handle compound
* literals with on-by-default extensions, however
* this code aims for full correctness with strict
* compilers so they are not used.
*/
#ifdef __cplusplus
#define T_COSE_NULL_KEY {T_COSE_CRYPTO_LIB_UNIDENTIFIED, {0}}
#else
#define T_COSE_NULL_KEY \
((struct t_cose_key){T_COSE_CRYPTO_LIB_UNIDENTIFIED, {0}})
#endif
/* Private value. Intentionally not documented for Doxygen. This is
* the size allocated for the encoded protected header parameters. It
* needs to be big enough for encode_protected_parameters() to
* succeed. It currently sized for one parameter with an algorithm ID
* up to 32 bits long -- one byte for the wrapping map, one byte for
* the label, 5 bytes for the ID. If this is made accidentially too
* small, QCBOR will only return an error, and not overrun any
* buffers.
*
* 17 extra bytes are added, rounding it up to 24 total, in case some
* other protected header parameter is to be added and so the test
* using T_COSE_TEST_CRIT_PARAMETER_EXIST can work.
*/
#define T_COSE_SIGN1_MAX_SIZE_PROTECTED_PARAMETERS (1+1+5+17)
/**
* Error codes return by t_cose.
*/
/*
* Do not reorder these. It is OK to add new ones at the end.
*
* Explicit values are included because some tools like debuggers show
* only the value, not the symbol, and it is hard to count up through
* 35 lines to figure out the actual value.
*/
enum t_cose_err_t {
/** Operation completed successfully. */
T_COSE_SUCCESS = 0,
/** The requested signing algorithm is not supported. */
T_COSE_ERR_UNSUPPORTED_SIGNING_ALG = 1,
/** Internal error when encoding protected parameters, usually
* because they are too big. It is internal because the caller
* can't really affect the size of the protected parameters. */
T_COSE_ERR_MAKING_PROTECTED = 2,
/** The hash algorithm needed is not supported. Note that the
* signing algorithm identifier identifies the hash algorithm. */
T_COSE_ERR_UNSUPPORTED_HASH = 3,
/** Some system failure when running the hash algorithm. */
T_COSE_ERR_HASH_GENERAL_FAIL = 4,
/** The buffer to receive a hash result is too small. */
T_COSE_ERR_HASH_BUFFER_SIZE = 5,
/** The buffer to receive result of a signing operation is too
* small. */
T_COSE_ERR_SIG_BUFFER_SIZE = 6,
/** When verifying a \c COSE_Sign1, the CBOR is "well-formed", but
* something is wrong with the format of the CBOR outside of the
* header parameters. For example, it is missing something like
* the payload or something is of an unexpected type. */
T_COSE_ERR_SIGN1_FORMAT = 8,
/** When decoding some CBOR like a \c COSE_Sign1, the CBOR was not
* "well-formed". Most likely what was supposed to be CBOR is
* either not or is corrupted. The CBOR is can't be decoded. */
T_COSE_ERR_CBOR_NOT_WELL_FORMED = 9,
/** The CBOR is "well-formed", but something is wrong with format
* in the header parameters. For example, a parameter is labeled
* with other than an integer or string or the value is an integer
* when a byte string is expected. */
T_COSE_ERR_PARAMETER_CBOR = 10,
/** No algorithm ID was found when one is needed. For example,
* when verifying a \c COSE_Sign1. */
T_COSE_ERR_NO_ALG_ID = 11,
/** No kid (key ID) was found when one is needed. For example,
* when verifying a \c COSE_Sign1. */
T_COSE_ERR_NO_KID = 12,
/** Signature verification failed. For example, the cryptographic
* operations completed successfully but hash wasn't as
* expected. */
T_COSE_ERR_SIG_VERIFY = 13,
/** Verification of a short-circuit signature failed. */
T_COSE_ERR_BAD_SHORT_CIRCUIT_KID = 14,
/** Some (unspecified) argument was not valid. */
T_COSE_ERR_INVALID_ARGUMENT = 15,
/** Out of heap memory. This originates in crypto library as
* t_cose does not use malloc. */
T_COSE_ERR_INSUFFICIENT_MEMORY = 16,
/** General unspecific failure. */
T_COSE_ERR_FAIL = 17,
/** Equivalent to \c PSA_ERROR_CORRUPTION_DETECTED. */
T_COSE_ERR_TAMPERING_DETECTED = 18,
/** The key identified by a \ref t_cose_key or a key ID was not
* found. */
T_COSE_ERR_UNKNOWN_KEY = 19,
/** The key was found, but it was the wrong type for the
* operation. */
T_COSE_ERR_WRONG_TYPE_OF_KEY = 20,
/** Error constructing the COSE \c Sig_structure when signing or
* verify. */
T_COSE_ERR_SIG_STRUCT = 21,
/** Signature was short-circuit. The option \ref
* T_COSE_OPT_ALLOW_SHORT_CIRCUIT to allow verification of
* short-circuit signatures was not set. */
T_COSE_ERR_SHORT_CIRCUIT_SIG = 22,
/** Something generally went wrong in the crypto adaptor when
* signing or verifying. */
T_COSE_ERR_SIG_FAIL = 23,
/** Something went wrong formatting the CBOR. Possibly the
* payload has maps or arrays that are not closed when using
* t_cose_sign1_encode_parameters() and
* t_cose_sign1_encode_signature() to sign a \c COSE_Sign1. */
T_COSE_ERR_CBOR_FORMATTING = 24,
/** The buffer passed in to receive the output is too small. */
T_COSE_ERR_TOO_SMALL = 25,
/** More parameters (more than \ref T_COSE_PARAMETER_LIST_MAX)
* than this implementation can handle. Note that all parameters
* need to be checked for criticality so all parameters need to be
* examined. */
T_COSE_ERR_TOO_MANY_PARAMETERS = 26,
/** A parameter was encountered that was unknown and also listed in
* the crit labels parameter. */
T_COSE_ERR_UNKNOWN_CRITICAL_PARAMETER = 27,
/** A request was made to signed with a short-circuit sig, \ref
* T_COSE_OPT_SHORT_CIRCUIT_SIG, but short circuit signature are
* disabled (compiled out) for this implementation. */
T_COSE_ERR_SHORT_CIRCUIT_SIG_DISABLED = 28,
/** The key type in a \ref t_cose_key is wrong for the
* cryptographic library used by this integration of t_cose.
*/
T_COSE_ERR_INCORRECT_KEY_FOR_LIB = 29,
/** This implementation only handles integer COSE algorithm IDs with
* values less than \c INT32_MAX. */
T_COSE_ERR_NON_INTEGER_ALG_ID = 30,
/** The content type parameter contains a content type that is
* neither integer or text string or it is an integer not in the
* range of 0 to \c UINT16_MAX. */
T_COSE_ERR_BAD_CONTENT_TYPE = 31,
/** If the option \ref T_COSE_OPT_TAG_REQUIRED is set for
* t_cose_sign1_verify() and the tag is absent, this error is
* returned. */
T_COSE_ERR_INCORRECTLY_TAGGED = 32,
/** The signing or verification key given is empty. */
T_COSE_ERR_EMPTY_KEY = 33,
/** A header parameter occurs twice, perhaps once in protected and
* once in unprotected. Duplicate header parameters are not
* allowed in COSE.
*/
T_COSE_ERR_DUPLICATE_PARAMETER = 34,
/** A header parameter that should be protected (alg id or crit)
* is not. This occurs when verifying a \c COSE_Sign1 that is
* improperly constructed. */
T_COSE_ERR_PARAMETER_NOT_PROTECTED = 35,
/** Something is wrong with the crit parameter. */
T_COSE_ERR_CRIT_PARAMETER = 36,
/** More than \ref T_COSE_MAX_TAGS_TO_RETURN unprocessed tags when
* verifying a signature. */
T_COSE_ERR_TOO_MANY_TAGS = 37,
};
/**
* The maximum number of header parameters that can be handled during
* verification of a \c COSE_Sign1 message. \ref
* T_COSE_ERR_TOO_MANY_PARAMETERS will be returned by
* t_cose_sign1_verify() if the input message has more.
*
* There can be both \ref T_COSE_PARAMETER_LIST_MAX integer-labeled
* parameters and \ref T_COSE_PARAMETER_LIST_MAX string-labeled
* parameters.
*
* This is a hard maximum so the implementation doesn't need
* malloc. This constant can be increased if needed. Doing so will
* increase stack usage.
*/
#define T_COSE_PARAMETER_LIST_MAX 10
/**
* The value of an unsigned integer content type indicating no content
* type. See \ref t_cose_parameters.
*/
#define T_COSE_EMPTY_UINT_CONTENT_TYPE UINT16_MAX+1
#ifdef __cplusplus
}
#endif
#endif /* __T_COSE_COMMON_H__ */

626
3rdparty/exported/t_cose/t_cose/t_cose_sign1_sign.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,626 @@
/*
* t_cose_sign1_sign.h
*
* Copyright (c) 2018-2021, Laurence Lundblade. All rights reserved.
* Copyright (c) 2020, Michael Eckel
*
* SPDX-License-Identifier: BSD-3-Clause
*
* See BSD-3-Clause license in README.md
*/
#ifndef __T_COSE_SIGN1_H__
#define __T_COSE_SIGN1_H__
#include <stdint.h>
#include <stdbool.h>
#include "qcbor/qcbor.h"
#include "t_cose/q_useful_buf.h"
#include "t_cose/t_cose_common.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \file t_cose_sign1_sign.h
*
* \brief Create a \c COSE_Sign1 message, such as for EAT or CWT Token.
*
* This creates a \c COSE_Sign1 message in compliance with
* [COSE (RFC 8152)](https://tools.ietf.org/html/rfc8152).
* A \c COSE_Sign1 message is a CBOR encoded binary blob that contains
* header parameters, a payload and a signature. Usually the signature is made
* with an EC signing algorithm like ECDSA.
*
* This implementation is intended to be small and portable to
* different OS's and platforms. Its dependencies are:
* - [QCBOR](https://github.com/laurencelundblade/QCBOR)
* - <stdint.h>, <string.h>, <stddef.h>
* - Hash functions like SHA-256
* - Signing functions like ECDSA
*
* There is a cryptographic adaptation layer defined in
* t_cose_crypto.h. An implementation can be made of the functions in
* it for different cryptographic libraries. This means that different
* integrations with different cryptographic libraries may support
* only signing with a particular set of algorithms. Integration with
* [OpenSSL](https://www.openssl.org) is supported. Key ID look up
* also varies by different cryptographic library integrations.
*
* This implementation has a mode where a CBOR-format payload can be
* output directly into the output buffer. This saves having two
* copies of the payload in memory. For this mode use
* t_cose_sign1_encode_parameters() and
* t_cose_sign1_encode_signature(). For a simpler API that just takes
* the payload as an input buffer use t_cose_sign1_sign().
*
* See t_cose_common.h for preprocessor defines to reduce object code
* and stack use by disabling features.
*/
/**
* This is the context for creating a \c COSE_Sign1 structure. The
* caller should allocate it and pass it to the functions here. This
* is about 100 bytes so it fits easily on the stack.
*/
struct t_cose_sign1_sign_ctx {
/* Private data structure */
struct q_useful_buf_c protected_parameters; /* Encoded protected paramssy */
int32_t cose_algorithm_id;
struct t_cose_key signing_key;
uint32_t option_flags;
struct q_useful_buf_c kid;
#ifndef T_COSE_DISABLE_CONTENT_TYPE
uint32_t content_type_uint;
const char * content_type_tstr;
#endif
};
/**
* This selects a signing test mode called _short_ _circuit_
* _signing_. This mode is useful when there is no signing key
* available, perhaps because it has not been provisioned or
* configured for the particular device. It may also be because the
* public key cryptographic functions have not been connected up in
* the cryptographic adaptation layer.
*
* It has no value for security at all. Data signed this way MUST NOT
* be trusted as anyone can sign like this.
*
* In this mode, the signature is the hash of that which would
* normally be signed by the public key algorithm. To make the
* signature the correct size for the particular algorithm, instances
* of the hash are concatenated to pad it out.
*
* This mode is very useful for testing because all the code except
* the actual signing algorithm is run exactly as it would if a proper
* signing algorithm was run. This can be used for end-end system
* testing all the way to a server or relying party, not just for
* testing device code as t_cose_sign1_verify() supports it too.
*/
#define T_COSE_OPT_SHORT_CIRCUIT_SIG 0x00000001
/**
* An \c option_flag for t_cose_sign1_sign_init() to not add the CBOR
* type 6 tag for \c COSE_Sign1 whose value is 18. Some uses of COSE
* may require this tag be absent because it is known that it is a \c
* COSE_Sign1 from surrounding context.
*
* Or said another way, per the COSE RFC, this code produces a \c
* COSE_Sign1_Tagged by default and a \c COSE_Sign1 when this flag is
* set. The only difference between these two is the CBOR tag.
*/
#define T_COSE_OPT_OMIT_CBOR_TAG 0x00000002
/**
* \brief Initialize to start creating a \c COSE_Sign1.
*
* \param[in] context The t_cose signing context.
* \param[in] option_flags One of \c T_COSE_OPT_XXXX.
* \param[in] cose_algorithm_id The algorithm to sign with, for example
* \ref T_COSE_ALGORITHM_ES256.
*
* Initialize the \ref t_cose_sign1_sign_ctx context. Typically, no
* \c option_flags are needed and 0 can be passed. A \c cose_algorithm_id
* must always be given. See \ref T_COSE_OPT_SHORT_CIRCUIT_SIG and
* related for possible option flags.
*
* The algorithm ID space is from
* [COSE (RFC8152)](https://tools.ietf.org/html/rfc8152) and the
* [IANA COSE Registry](https://www.iana.org/assignments/cose/cose.xhtml).
* \ref T_COSE_ALGORITHM_ES256 and a few others are defined here for
* convenience. The signing algorithms supported depends on the
* cryptographic library that t_cose is integrated with.
*
* Errors such as the passing of an unsupported \c cose_algorithm_id
* are reported when t_cose_sign1_sign() or
* t_cose_sign1_encode_parameters() is called.
*/
static void
t_cose_sign1_sign_init(struct t_cose_sign1_sign_ctx *context,
uint32_t option_flags,
int32_t cose_algorithm_id);
/**
* \brief Set the key and kid (key ID) for signing.
*
* \param[in] context The t_cose signing context.
* \param[in] signing_key The signing key to use or \ref T_COSE_NULL_KEY.
* \param[in] kid COSE kid (key ID) parameter or \c NULL_Q_USEFUL_BUF_C.
*
* This needs to be called to set the signing key to use. The \c kid
* may be omitted by giving \c NULL_Q_USEFUL_BUF_C.
*
* If short-circuit signing is used,
* \ref T_COSE_OPT_SHORT_CIRCUIT_SIG, then this does not need to be
* called. If it is called the \c kid given will be used, but the \c
* signing_key is never used. When the \c kid is given with a
* short-circuit signature, the internally fixed kid for short circuit
* will not be used and this \c COSE_Sign1 message can not be verified
* by t_cose_sign1_verify().
*/
static void
t_cose_sign1_set_signing_key(struct t_cose_sign1_sign_ctx *context,
struct t_cose_key signing_key,
struct q_useful_buf_c kid);
#ifndef T_COSE_DISABLE_CONTENT_TYPE
/**
* \brief Set the payload content type using CoAP content types.
*
* \param[in] context The t_cose signing context.
* \param[in] content_type The content type of the payload as defined
* in the IANA CoAP Content-Formats registry.
*
* It is not allowed to have both a CoAP and MIME content type. This
* error will show up when t_cose_sign1_sign() or
* t_cose_sign1_encode_parameters() is called as no error is returned by
* this function.
*
* The IANA CoAP Content-Formats registry is found
* [here](https://www.iana.org/assignments/core-parameters/core-parameters.xhtml#content-formats).
*/
static inline void
t_cose_sign1_set_content_type_uint(struct t_cose_sign1_sign_ctx *context,
uint16_t content_type);
/**
* \brief Set the payload content type using MIME content types.
*
* \param[in] context The t_cose signing context.
* \param[in] content_type The content type of the payload as defined
* in the IANA Media Types registry.
*
* It is not allowed to have both a CoAP and MIME content type. This
* error will show up when t_cose_sign1_sign() or
* t_cose_sign1_encode_parameters() is called.
*
* The IANA Media Types registry can be found
* [here](https://www.iana.org/assignments/media-types/media-types.xhtml).
* These have been known as MIME types in the past.
*/
static inline void
t_cose_sign1_set_content_type_tstr(struct t_cose_sign1_sign_ctx *context,
const char *content_type);
#endif /* T_COSE_DISABLE_CONTENT_TYPE */
/**
* \brief Create and sign a \c COSE_Sign1 message with a payload in one call.
*
* \param[in] context The t_cose signing context.
* \param[in] payload Pointer and length of payload to sign.
* \param[in] out_buf Pointer and length of buffer to output to.
* \param[out] result Pointer and length of the resulting \c COSE_Sign1.
*
* The \c context must have been initialized with
* t_cose_sign1_sign_init() and the key set with
* t_cose_sign1_set_signing_key() before this is called.
*
* This creates the COSE header parameter, hashes and signs the
* payload and creates the signature all in one go. \c out_buf gives
* the pointer and length of the memory into which the output is
* written. The pointer and length of the completed \c COSE_Sign1 is
* returned in \c result. (\c out_buf and \c result are used instead
* of the usual in/out parameter for length because it is the
* convention for q_useful_buf and is more const correct.)
*
* The size of \c out_buf must be the size of the payload plus
* overhead for formating, the signature and the key id (if used). The
* formatting overhead is minimal at about 30 bytes.The total overhead
* is about 150 bytes for ECDSA 256 with a 32-byte key ID.
*
* To compute the size of the buffer needed before it is allocated
* call this with \c out_buf containing a \c NULL pointer and large
* length like \c UINT32_MAX. The algorithm and key, kid and such
* must be set up just as if the real \c COSE_Sign1 were to be created
* as these values are needed to compute the size correctly. The
* contents of \c result will be a \c NULL pointer and the length of
* the \c COSE_Sign1. When this is run like this, the cryptographic
* functions will not actually run, but the size of their output will
* be taken into account to give an exact size.
*
* This function requires the payload be complete and formatted in a
* contiguous buffer. The resulting \c COSE_Sign1 message also
* contains the payload preceded by the header parameters and followed
* by the signature, all CBOR formatted. This function thus requires
* two copies of the payload to be in memory. Alternatively
* t_cose_sign1_encode_parameters() and
* t_cose_sign1_encode_signature() can be used. They are more complex
* to use, but avoid the two copies of the payload and can reduce
* memory requirements by close to half.
*
* See also t_cose_sign1_sign_aad() and t_cose_sign1_sign_detached().
*/
static enum t_cose_err_t
t_cose_sign1_sign(struct t_cose_sign1_sign_ctx *context,
struct q_useful_buf_c payload,
struct q_useful_buf out_buf,
struct q_useful_buf_c *result);
/**
* \brief Create and sign a \c COSE_Sign1 message with a payload in one call.
*
* \param[in] context The t_cose signing context.
* \param[in] aad The Additional Authenticated Data or \c NULL_Q_USEFUL_BUF_C.
* \param[in] payload Pointer and length of payload to sign.
* \param[in] out_buf Pointer and length of buffer to output to.
* \param[out] result Pointer and length of the resulting \c COSE_Sign1.
*
* This is the same as t_cose_sign1_sign() additionally allowing AAD.
* AAD (Additional Authenticated Data) is extra bytes to be covered by the
* signature. See t_cose_sign1_encode_signature_aad() for more details
* about AAD.
*
* Calling this with \c aad as \c NULL_Q_USEFUL_BUF_C is equivalent to
* t_cose_sign1_sign().
*
* See also t_cose_sign1_sign_detached().
*/
static enum t_cose_err_t
t_cose_sign1_sign_aad(struct t_cose_sign1_sign_ctx *context,
struct q_useful_buf_c aad,
struct q_useful_buf_c payload,
struct q_useful_buf out_buf,
struct q_useful_buf_c *result);
/**
* \brief Create and sign a \c COSE_Sign1 message with detached payload in one call.
*
* \param[in] context The t_cose signing context.
* \param[in] aad The Additional Authenticated Data or \c NULL_Q_USEFUL_BUF_C.
* \param[in] detached_payload Pointer and length of the detached payload to sign.
* \param[in] out_buf Pointer and length of buffer to output to.
* \param[out] result Pointer and length of the resulting \c COSE_Sign1.
*
* This is similar to, but not the same as
* t_cose_sign1_sign_aad(). Here the payload is detached, not inside
* the \c COSE_Sign1 and conveyed separately. The signature is still
* over the payload as with t_cose_sign1_sign_aad(). They payload must
* conveyed to recipient by some other means than by being inside the
* \c COSE_Sign1. The recipient will be unable to verify the \c
* COSE_Sign1 without it.
*
* This may be called with \c aad as \c NULL_Q_USEFUL_BUF_C if there is
* no AAD.
*/
static enum t_cose_err_t
t_cose_sign1_sign_detached(struct t_cose_sign1_sign_ctx *context,
struct q_useful_buf_c aad,
struct q_useful_buf_c detached_payload,
struct q_useful_buf out_buf,
struct q_useful_buf_c *result);
/**
* \brief Output first part and parameters for a \c COSE_Sign1 message.
*
* \param[in] context The t_cose signing context.
* \param[in] cbor_encode_ctx Encoding context to output to.
*
* This is the more complex and more memory efficient alternative to
* t_cose_sign1_sign(). Like t_cose_sign1_sign(),
* t_cose_sign1_sign_init() and t_cose_sign1_set_signing_key() must be
* called before calling this.
*
* When this is called, the opening parts of the \c COSE_Sign1 message
* are output to the \c cbor_encode_ctx.
*
* After this is called, the CBOR-formatted payload must be written to
* the \c cbor_encode_ctx by calling all the various
* \c QCBOREncode_AddXxx calls. It can be as simple or complex as needed.
*
* To complete the \c COSE_Sign1 call t_cose_sign1_encode_signature().
*
* The \c cbor_encode_ctx must have been initialized with an output
* buffer to hold the \c COSE_Sign1 header parameters, the payload and the
* signature.
*
* This and t_cose_sign1_encode_signature() can be used to calculate
* the size of the \c COSE_Sign1 in the way \c QCBOREncode is usually
* used to calculate sizes. In this case the \c t_cose_sign1_ctx must
* be initialized with the options, algorithm, key and kid just as
* normal as these are needed to calculate the size. Then set up the
* output buffer for \c cbor_encode_ctx with a \c NULL pointer and
* large length like \c UINT32_MAX. Call
* t_cose_sign1_encode_parameters(), then format the payload into the
* encoder context, then call t_cose_sign1_encode_signature().
* Finally call \c QCBOREncode_FinishGetSize() to get the length.
*/
static enum t_cose_err_t
t_cose_sign1_encode_parameters(struct t_cose_sign1_sign_ctx *context,
QCBOREncodeContext *cbor_encode_ctx);
/**
* \brief Finish a \c COSE_Sign1 message by outputting the signature.
*
* \param[in] context The t_cose signing context.
* \param[in] cbor_encode_ctx Encoding context to output to.
*
* \return This returns one of the error codes defined by \ref t_cose_err_t.
*
* Call this to complete creation of a signed \c COSE_Sign1 started
* with t_cose_sign1_encode_parameters().
*
* This is when the cryptographic signature algorithm is run.
*
* The completed \c COSE_Sign1 message is retrieved from the
* \c cbor_encode_ctx by calling \c QCBOREncode_Finish().
*/
static enum t_cose_err_t
t_cose_sign1_encode_signature(struct t_cose_sign1_sign_ctx *context,
QCBOREncodeContext *cbor_encode_ctx);
/**
* \brief Finish a \c COSE_Sign1 message with AAD by outputting the signature.
*
* \param[in] context The t_cose signing context.
* \param[in] aad The Additional Authenticated Data.
* \param[in] cbor_encode_ctx Encoding context to output to.
*
* \return This returns one of the error codes defined by \ref t_cose_err_t.
*
* This is the same as t_cose_sign1_encode_signature() and it allows
* passing in AAD (Additional Authenticated Data) to be covered by the
* signature.
*
* AAD is simply any data that should also be covered by the
* signature. The verifier of the \c COSE_Sign1 must also have exactly
* this data to be able to successfully verify the signature. Often
* this data is some parameters or fields in the protocol carrying the
* COSE message.
*/
static inline enum t_cose_err_t
t_cose_sign1_encode_signature_aad(struct t_cose_sign1_sign_ctx *context,
struct q_useful_buf_c aad,
QCBOREncodeContext *cbor_encode_ctx);
/* ------------------------------------------------------------------------
* Inline implementations of public functions defined above.
*/
static inline void
t_cose_sign1_sign_init(struct t_cose_sign1_sign_ctx *me,
uint32_t option_flags,
int32_t cose_algorithm_id)
{
memset(me, 0, sizeof(*me));
#ifndef T_COSE_DISABLE_CONTENT_TYPE
/* Only member for which 0 is not the empty state */
me->content_type_uint = T_COSE_EMPTY_UINT_CONTENT_TYPE;
#endif
me->cose_algorithm_id = cose_algorithm_id;
me->option_flags = option_flags;
}
static inline void
t_cose_sign1_set_signing_key(struct t_cose_sign1_sign_ctx *me,
struct t_cose_key signing_key,
struct q_useful_buf_c kid)
{
me->kid = kid;
me->signing_key = signing_key;
}
/**
* \brief Semi-private function that ouputs the COSE parameters, startng a
* \c COSE_Sign1 message.
*
* \param[in] context The t_cose signing context.
* \param[in] payload_is_detached If the payload is to be detached, this
* is \c true.
* \param[in] cbor_encode_ctx Encoding context to output to.
*
* \return This returns one of the error codes defined by \ref t_cose_err_t.
*
* This does the actual work for encoding the COSE parameters, but is
* a private function inside the implementation. Call
* t_cose_sign1_encode_parameters() instead of this.
*/
enum t_cose_err_t
t_cose_sign1_encode_parameters_internal(struct t_cose_sign1_sign_ctx *context,
bool payload_is_detached,
QCBOREncodeContext *cbor_encode_ctx);
static inline enum t_cose_err_t
t_cose_sign1_encode_parameters(struct t_cose_sign1_sign_ctx *context,
QCBOREncodeContext *cbor_encode_ctx)
{
return t_cose_sign1_encode_parameters_internal(context,
false,
cbor_encode_ctx);
}
/**
* \brief Semi-private function that ouputs the signature, finishing a
* \c COSE_Sign1 message.
*
* \param[in] context The t_cose signing context.
* \param[in] aad The Additional Authenticated Data or
* \c NULL_Q_USEFUL_BUF_C.
* \param[in] detached_payload The detached payload or \c NULL_Q_USEFUL_BUF_C.
* \param[in] cbor_encode_ctx Encoding context to output to.
*
* \return This returns one of the error codes defined by \ref t_cose_err_t.
*
* This does the actual work for several public methods that output a
* signature. It is internal to the implmentation and
* t_cose_sign1_encode_signature_aad() should be called instead.
*
* If \c detached_payload is \c NULL_Q_USEFUL_BUF_C then the payload
* is to be inline and must have been added by calls to QCBOREncode
* after the call to t_cose_sign1_encode_parameters().
*/
enum t_cose_err_t
t_cose_sign1_encode_signature_aad_internal(struct t_cose_sign1_sign_ctx *context,
struct q_useful_buf_c aad,
struct q_useful_buf_c detached_payload,
QCBOREncodeContext *cbor_encode_ctx);
/**
* \brief Semi-private function that does a complete signing in one call.
*
* \param[in] context The t_cose signing context.
* \param[in] payload_is_detached If \c true, then \c payload is detached.
* \param[in] payload The payload, inline or detached.
* \param[in] aad The Additional Authenticated Data or
* \c NULL_Q_USEFUL_BUF_C.
* \param[in] out_buf Pointer and length of buffer to output to.
* \param[out] result Pointer and length of the resulting
* \c COSE_Sign1.
*
* \return This returns one of the error codes defined by \ref t_cose_err_t.
*
* This is where the work actually gets done for signing that is done
* all in one call with or without AAD and for included or detached
* payloads.
*
* This is a private function internal to the implementation. Call
* t_cose_sign1_sign_aad() instead of this.
*/
enum t_cose_err_t
t_cose_sign1_sign_aad_internal(struct t_cose_sign1_sign_ctx *context,
bool payload_is_detached,
struct q_useful_buf_c aad,
struct q_useful_buf_c payload,
struct q_useful_buf out_buf,
struct q_useful_buf_c *result);
static inline enum t_cose_err_t
t_cose_sign1_sign_aad(struct t_cose_sign1_sign_ctx *me,
struct q_useful_buf_c aad,
struct q_useful_buf_c payload,
struct q_useful_buf out_buf,
struct q_useful_buf_c *result)
{
return t_cose_sign1_sign_aad_internal(me,
false,
aad,
payload,
out_buf,
result);
}
static inline enum t_cose_err_t
t_cose_sign1_sign(struct t_cose_sign1_sign_ctx *me,
struct q_useful_buf_c payload,
struct q_useful_buf out_buf,
struct q_useful_buf_c *result)
{
return t_cose_sign1_sign_aad_internal(me,
false,
payload,
NULL_Q_USEFUL_BUF_C,
out_buf,
result);
}
static inline enum t_cose_err_t
t_cose_sign1_sign_detached(struct t_cose_sign1_sign_ctx *me,
struct q_useful_buf_c aad,
struct q_useful_buf_c detached_payload,
struct q_useful_buf out_buf,
struct q_useful_buf_c *result)
{
return t_cose_sign1_sign_aad_internal(me,
true,
detached_payload,
aad,
out_buf,
result);
}
static inline enum t_cose_err_t
t_cose_sign1_encode_signature_aad(struct t_cose_sign1_sign_ctx *me,
struct q_useful_buf_c aad,
QCBOREncodeContext *cbor_encode_ctx)
{
return t_cose_sign1_encode_signature_aad_internal(me,
aad,
NULL_Q_USEFUL_BUF_C,
cbor_encode_ctx);
}
static inline enum t_cose_err_t
t_cose_sign1_encode_signature(struct t_cose_sign1_sign_ctx *me,
QCBOREncodeContext *cbor_encode_ctx)
{
return t_cose_sign1_encode_signature_aad_internal(me,
NULL_Q_USEFUL_BUF_C,
NULL_Q_USEFUL_BUF_C,
cbor_encode_ctx);
}
#ifndef T_COSE_DISABLE_CONTENT_TYPE
static inline void
t_cose_sign1_set_content_type_uint(struct t_cose_sign1_sign_ctx *me,
uint16_t content_type)
{
me->content_type_uint = content_type;
}
static inline void
t_cose_sign1_set_content_type_tstr(struct t_cose_sign1_sign_ctx *me,
const char *content_type)
{
me->content_type_tstr = content_type;
}
#endif
#ifdef __cplusplus
}
#endif
#endif /* __T_COSE_SIGN1_H__ */

523
3rdparty/exported/t_cose/t_cose/t_cose_sign1_verify.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,523 @@
/*
* t_cose_sign1_verify.h
*
* Copyright 2019-2021, Laurence Lundblade
*
* SPDX-License-Identifier: BSD-3-Clause
*
* See BSD-3-Clause license in README.md
*/
#ifndef __T_COSE_SIGN1_VERIFY_H__
#define __T_COSE_SIGN1_VERIFY_H__
#include <stdint.h>
#include <stdbool.h>
#include "t_cose/q_useful_buf.h"
#include "t_cose/t_cose_common.h"
#include "qcbor/qcbor_common.h"
#ifdef __cplusplus
extern "C" {
#if 0
} /* Keep editor indention formatting happy */
#endif
#endif
#ifndef QCBOR_SPIFFY_DECODE
#error This version of t_cose requires a version of QCBOR that supports spiffy decode
#endif
/**
* \file t_cose_sign1_verify.h
*
* \brief Verify a COSE_Sign1 Message
*
* This verifies a \c COSE_Sign1 message in compliance with [COSE (RFC 8152)]
* (https://tools.ietf.org/html/rfc8152). A \c COSE_Sign1 message is a CBOR
* encoded binary blob that contains header parameters, a payload and a
* signature. Usually the signature is made with an EC signing
* algorithm like ECDSA.
*
* This implementation is intended to be small and portable to
* different OS's and platforms. Its dependencies are:
* - [QCBOR](https://github.com/laurencelundblade/QCBOR)
* - <stdint.h>, <string.h>, <stddef.h>
* - Hash functions like SHA-256
* - Signing functions like ECDSA
*
* There is a cryptographic adaptation layer defined in
* t_cose_crypto.h. An implementation can be made of the functions in
* it for different cryptographic libraries. This means that different
* integrations with different cryptographic libraries may support
* only signing with a particular set of algorithms. Integration with
* [OpenSSL](https://www.openssl.org) is supported. Key ID look up
* also varies by different cryptographic library integrations.
*
* See t_cose_common.h for preprocessor defines to reduce object code
* and stack use by disabling features.
*/
/**
* The result of parsing a set of COSE header parameters. The pointers
* in this are all back into the \c COSE_Sign1 blob passed in to
* t_cose_sign1_verify() as the \c sign1 parameter.
*
* Approximate size on a 64-bit machine is 80 bytes and on a 32-bit
* machine is 40.
*/
struct t_cose_parameters {
/** The algorithm ID. \ref T_COSE_UNSET_ALGORITHM_ID if the algorithm ID
* parameter is not present. String type algorithm IDs are not
* supported. See the
* [IANA COSE Registry](https://www.iana.org/assignments/cose/cose.xhtml)
* for the algorithms corresponding to the integer values.
*/
int32_t cose_algorithm_id;
/** The COSE key ID. \c NULL_Q_USEFUL_BUF_C if parameter is not
* present */
struct q_useful_buf_c kid;
/** The initialization vector. \c NULL_Q_USEFUL_BUF_C if parameter
* is not present */
struct q_useful_buf_c iv;
/** The partial initialization vector. \c NULL_Q_USEFUL_BUF_C if
* parameter is not present */
struct q_useful_buf_c partial_iv;
#ifndef T_COSE_DISABLE_CONTENT_TYPE
/** The content type as a MIME type like
* "text/plain". \c NULL_Q_USEFUL_BUF_C if parameter is not present */
struct q_useful_buf_c content_type_tstr;
/** The content type as a CoAP Content-Format
* integer. \ref T_COSE_EMPTY_UINT_CONTENT_TYPE if parameter is not
* present. Allowed range is 0 to UINT16_MAX per RFC 7252. */
uint32_t content_type_uint;
#endif /* T_COSE_DISABLE_CONTENT_TYPE */
};
/**
* A special COSE algorithm ID that indicates no COSE algorithm ID or an unset
* COSE algorithm ID.
*/
#define T_COSE_UNSET_ALGORITHM_ID 0
/**
* Pass this as \c option_flags to allow verification of short-circuit
* signatures. This should only be used as a test mode as
* short-circuit signatures are not secure.
*
* See also \ref T_COSE_OPT_SHORT_CIRCUIT_SIG.
*/
#define T_COSE_OPT_ALLOW_SHORT_CIRCUIT 0x00000001
/**
* The error \ref T_COSE_ERR_NO_KID is returned if the kid parameter
* is missing. Note that the kid parameter is primarily passed on to
* the crypto layer so the crypto layer can look up the key. If the
* verification key is determined by other than the kid, then it is
* fine if there is no kid.
*/
#define T_COSE_OPT_REQUIRE_KID 0x00000002
/**
* Normally this will decode the CBOR presented as a \c COSE_Sign1
* message whether it is tagged using QCBOR tagging as such or not.
* If this option is set, then \ref T_COSE_ERR_INCORRECTLY_TAGGED is
* returned if it is not a \ref CBOR_TAG_COSE_SIGN1 tag.
*
* See also \ref T_COSE_OPT_TAG_PROHIBITED. If neither this or
* \ref T_COSE_OPT_TAG_PROHIBITED is set then the content can
* either be COSE message (COSE_Sign1 CDDL from RFC 8152) or
* a COSESign1 tagg (COSE_Sign1_Tagged from RFC 8152).
*
* See t_cose_sign1_get_nth_tag() to get further tags that enclose
* the COSE message.
*/
#define T_COSE_OPT_TAG_REQUIRED 0x00000004
/**
* Normally this will decode the CBOR presented as a \c COSE_Sign1
* message whether it is tagged using QCBOR tagging as such or not.
* If this option is set, then \ref T_COSE_ERR_INCORRECTLY_TAGGED is
* returned if a \ref CBOR_TAG_COSE_SIGN1 tag. When this option is set the caller
* knows for certain that a COSE signed message is expected.
*
* See discussion on @ref T_COSE_OPT_TAG_REQUIRED.
*/
#define T_COSE_OPT_TAG_PROHIBITED 0x00000010
/**
* See t_cose_sign1_set_verification_key().
*
* This option disables cryptographic signature verification. With
* this option the \c verification_key is not needed. This is useful
* to decode the \c COSE_Sign1 message to get the kid (key ID). The
* verification key can be looked up or otherwise obtained by the
* caller. Once the key in in hand, t_cose_sign1_verify() can be
* called again to perform the full verification.
*
* The payload will always be returned whether this is option is given
* or not, but it should not be considered secure when this option is
* given.
*/
#define T_COSE_OPT_DECODE_ONLY 0x00000008
/**
* The maximum number of unprocessed tags that can be returned by
* t_cose_sign1_get_nth_tag(). The CWT
* tag is an example of the tags that might returned. The COSE tags
* that are processed, don't count here.
*/
#define T_COSE_MAX_TAGS_TO_RETURN 4
/**
* Context for signature verification. It is about 56 bytes on a
* 64-bit machine and 42 bytes on a 32-bit machine.
*/
struct t_cose_sign1_verify_ctx {
/* Private data structure */
struct t_cose_key verification_key;
uint32_t option_flags;
uint64_t auTags[T_COSE_MAX_TAGS_TO_RETURN];
};
/**
* \brief Initialize for \c COSE_Sign1 message verification.
*
* \param[in,out] context The context to initialize.
* \param[in] option_flags Options controlling the verification.
*
* This must be called before using the verification context.
*/
static void
t_cose_sign1_verify_init(struct t_cose_sign1_verify_ctx *context,
uint32_t option_flags);
/**
* \brief Set key for \c COSE_Sign1 message verification.
*
* \param[in,out] context The t_cose signature verification context.
* \param[in] verification_key The verification key to use.
*
* There are four ways that the verification key is found and
* supplied to t_cose so that t_cose_sign1_verify() succeeds.
*
* -# Look up by kid parameter and set by t_cose_sign1_set_verification_key()
* -# Look up by other and set by t_cose_sign1_set_verification_key()
* -# Determination by kid that short circuit signing is used (test only)
* -# Look up by kid parameter in cryptographic adaptation layer
*
* Note that there is no means where certificates, like X.509
* certificates, are provided in the COSE parameters. Perhaps there
* will be in the future but that is not in common use or supported by
* this implementation.
*
* To use 1, it is necessary to call t_cose_sign1_verify_init() and
* t_cose_sign1_verify() twice. The first time
* t_cose_sign1_verify_init() is called, give the \ref
* T_COSE_OPT_DECODE_ONLY option. Then call t_cose_sign1_verify() and
* the kid will be returned in \c parameters. The caller finds the kid on
* their own. Then call this to set the key. Last call
* t_cose_sign1_verify(), again without the \ref T_COSE_OPT_DECODE_ONLY
* option.
*
* To use 2, the key is somehow determined without the kid and
* t_cose_sign1_set_verification_key() is called with it. Then
* t_cose_sign1_verify() is called. Note that this implementation
* cannot return non-standard header parameters, at least not yet.
*
* To use 3, initialize with \ref T_COSE_OPT_ALLOW_SHORT_CIRCUIT. No
* call to t_cose_sign1_set_verification_key() is necessary. If you do
* call t_cose_sign1_set_verification_key(), the kid for short circuit
* signing will be recognized and the set key will be ignored.
*
* To use 4, first be sure that the cryptographic adapter supports
* look up by kid. There's no API to determine this, so it is
* probably determined by other system documentation (aka source
* code). In this mode, all that is necessary is to call
* t_cose_sign1_verify().
*
* 3 always works no matter what is done in the cryptographic
* adaptation layer because it never calls out to it. The OpenSSL
* adaptor supports 1 and 2.
*/
static void
t_cose_sign1_set_verification_key(struct t_cose_sign1_verify_ctx *context,
struct t_cose_key verification_key);
/**
* \brief Verify a \c COSE_Sign1.
*
* \param[in,out] context The t_cose signature verification context.
* \param[in] sign1 Pointer and length of CBOR encoded \c COSE_Sign1
* message that is to be verified.
* \param[out] payload Pointer and length of the payload.
* \param[out] parameters Place to return parsed parameters. May be \c NULL.
*
* \return This returns one of the error codes defined by \ref t_cose_err_t.
*
* See t_cose_sign1_set_verification_key() for discussion on where
* the verification key comes from.
*
* Verification involves the following steps.
*
* - The CBOR-format \c COSE_Sign1 structure is parsed. This makes
* sure \c COSE_Sign1 is valid CBOR and follows the required structure
* for \c COSE_Sign1.
*
* - The protected header parameters are decoded, particular the algorithm id.
*
* - The unprotected headers parameters are decoded, particularly the kid.
*
* - The payload is identified. The internals of the payload are not decoded.
*
* - The expected hash, the "to-be-signed" bytes are computed. The hash
* algorithm used comes from the signing algorithm. If the algorithm is
* unknown or not supported this will error out.
*
* - Finally, the signature verification is performed.
*
* If verification is successful, the pointer to the CBOR-encoded payload is
* returned. The parameters are returned if requested. All pointers
* returned are to memory in the \c sign1 passed in.
*
* Note that this only handles standard COSE header parameters. There
* are no facilities for custom header parameters, even though they
* are allowed by the COSE standard.
*
* This will recognize the special key ID for short-circuit signing
* and verify it if the \ref T_COSE_OPT_ALLOW_SHORT_CIRCUIT is set.
*
* Indefinite length CBOR strings are not supported by this
* implementation. \ref T_COSE_ERR_SIGN1_FORMAT will be returned if
* they are in the input \c COSE_Sign1 messages. For example, if the
* payload is an indefinite-length byte string, this error will be
* returned.
*/
static enum t_cose_err_t
t_cose_sign1_verify(struct t_cose_sign1_verify_ctx *context,
struct q_useful_buf_c sign1,
struct q_useful_buf_c *payload,
struct t_cose_parameters *parameters);
/**
* \brief Verify a COSE_Sign1 with Additional Authenticated Data.
*
* \param[in,out] context The t_cose signature verification context.
* \param[in] sign1 Pointer and length of CBOR encoded \c COSE_Sign1
* message that is to be verified.
* \param[in] aad The Additional Authenticated Data or \c NULL_Q_USEFUL_BUF_C.
* \param[out] payload Pointer and length of the payload.
* \param[out] parameters Place to return parsed parameters. May be \c NULL.
*
* \return This returns one of the error codes defined by \ref t_cose_err_t.
*
* This is just like t_cose_sign1_verify(), but allows passing AAD
* (Additional Authenticated Data) for verification.
*
* AAD is some additional bytes that are covered by the signature in
* addition to the payload. They may be any bytes, but are often some
* options or commands that are sent along with the \c COSE_Sign1. If
* a \c COSE_Sign1 was created with AAD, that AAD must be passed in
* here to successfully verify the signature. If it is not, a \ref
* T_COSE_ERR_SIG_VERIFY will occur. There is no indication in the \c
* COSE_Sign1 to know whether there was AAD input when it was
* created. It has to be known by context.
*
* Calling this with \c aad as \c NULL_Q_USEFUL_BUF_C is the same as
* calling t_cose_sign1_verify().
*/
static enum t_cose_err_t
t_cose_sign1_verify_aad(struct t_cose_sign1_verify_ctx *context,
struct q_useful_buf_c sign1,
struct q_useful_buf_c aad,
struct q_useful_buf_c *payload,
struct t_cose_parameters *parameters);
/**
* \brief Verify a COSE_Sign1 with detached payload.
*
* \param[in,out] context The t_cose signature verification context.
* \param[in] cose_sign1 Pointer and length of CBOR encoded \c COSE_Sign1
* message that is to be verified.
* \param[in] aad The Additional Authenticated Data or \c NULL_Q_USEFUL_BUF_C.
* \param[in] detached_payload Pointer and length of the payload.
* \param[out] parameters Place to return parsed parameters. May be \c NULL.
*
* \return This returns one of the error codes defined by \ref t_cose_err_t.
*
* A detached payload is one that is not inside the \c COSE_Sign1, but
* is conveyed separately. It is still covered by the signature
* exactly as if it was the payload inside the \c COSE_Sign1.
*
* This function is the same as t_cose_sign1_verify_aad(), but for use
* with a detached payload. Instead of the payload being returned, it
* must be passed in as it must have arrived separately from the
* \c COSE_Sign1. The signature covers it so it must be passed in to
* complete the verification.
*
* \c aad may be \c NULL_Q_USEFUL_BUF_C if there is no AAD.
*/
static inline enum t_cose_err_t
t_cose_sign1_verify_detached(struct t_cose_sign1_verify_ctx *context,
struct q_useful_buf_c cose_sign1,
struct q_useful_buf_c aad,
struct q_useful_buf_c detached_payload,
struct t_cose_parameters *parameters);
/**
* \brief Return unprocessed tags from most recent signature verify.
*
* \param[in] context The t_cose signature verification context.
* \param[in] n Index of the tag to return.
*
* \return The tag value or \ref CBOR_TAG_INVALID64 if there is no tag
* at the index or the index is too large.
*
* The 0th tag is the one for which the COSE message is the content. Loop
* from 0 up until \ref CBOR_TAG_INVALID64 is returned. The maximum
* is \ref T_COSE_MAX_TAGS_TO_RETURN.
*
* It will be necessary to call this for a general implementation
* of a CWT since sometimes the CWT tag is required. This is also
* needed for recursive processing of nested COSE signing and/or
* encryption.
*/
static uint64_t
t_cose_sign1_get_nth_tag(const struct t_cose_sign1_verify_ctx *context,
size_t n);
/* ------------------------------------------------------------------------
* Inline implementations of public functions defined above.
*/
static inline void
t_cose_sign1_verify_init(struct t_cose_sign1_verify_ctx *me,
uint32_t option_flags)
{
me->option_flags = option_flags;
me->verification_key = T_COSE_NULL_KEY;
}
static inline void
t_cose_sign1_set_verification_key(struct t_cose_sign1_verify_ctx *me,
struct t_cose_key verification_key)
{
me->verification_key = verification_key;
}
static inline uint64_t
t_cose_sign1_get_nth_tag(const struct t_cose_sign1_verify_ctx *context,
size_t n)
{
if(n > T_COSE_MAX_TAGS_TO_RETURN) {
return CBOR_TAG_INVALID64;
}
return context->auTags[n];
}
/**
* \brief Semi-private function to verify a COSE_Sign1.
*
* \param[in,out] me The t_cose signature verification context.
* \param[in] sign1 Pointer and length of CBOR encoded \c COSE_Sign1
* message that is to be verified.
* \param[in] aad The Additional Authenticated Data or \c NULL_Q_USEFUL_BUF_C.
* \param[in,out] payload Pointer and length of the payload.
* \param[out] parameters Place to return parsed parameters. May be \c NULL.
* \param[in] is_detached Indicates the payload is detached.
*
* \return This returns one of the error codes defined by \ref t_cose_err_t.
*
* This does the work for t_cose_sign1_verify(),
* t_cose_sign1_verify_aad() and t_cose_sign1_verify_detached(). It is
* a semi-private function which means its interface isn't guaranteed
* so it should not to call it directly.
*/
enum t_cose_err_t
t_cose_sign1_verify_internal(struct t_cose_sign1_verify_ctx *me,
struct q_useful_buf_c sign1,
struct q_useful_buf_c aad,
struct q_useful_buf_c *payload,
struct t_cose_parameters *parameters,
bool is_detached);
static inline enum t_cose_err_t
t_cose_sign1_verify(struct t_cose_sign1_verify_ctx *me,
struct q_useful_buf_c sign1,
struct q_useful_buf_c *payload,
struct t_cose_parameters *parameters)
{
return t_cose_sign1_verify_internal(me,
sign1,
NULL_Q_USEFUL_BUF_C,
payload,
parameters,
false);
}
static inline enum t_cose_err_t
t_cose_sign1_verify_aad(struct t_cose_sign1_verify_ctx *me,
struct q_useful_buf_c cose_sign1,
struct q_useful_buf_c aad,
struct q_useful_buf_c *payload,
struct t_cose_parameters *parameters)
{
return t_cose_sign1_verify_internal(me,
cose_sign1,
aad,
payload,
parameters,
false);
}
static inline enum t_cose_err_t
t_cose_sign1_verify_detached(struct t_cose_sign1_verify_ctx *me,
struct q_useful_buf_c cose_sign1,
struct q_useful_buf_c aad,
struct q_useful_buf_c detached_payload,
struct t_cose_parameters *parameters)
{
return t_cose_sign1_verify_internal(me,
cose_sign1,
aad,
&detached_payload,
parameters,
true);
}
#ifdef __cplusplus
}
#endif
#endif /* __T_COSE_SIGN1_VERIFY_H__ */

15
3rdparty/exported/t_cose/test/keys/README.txt поставляемый Normal file
Просмотреть файл

@ -0,0 +1,15 @@
To list curves:
openssl ecparam -list_curves
To generate an ECDSA key:
openssl ecparam -genkey -name secp384r1 -out k.pem
To print out the ECDSA key:
openssl ec -in k.pem -noout -text
https://kjur.github.io/jsrsasign/sample/sample-ecdsa.html
https://superuser.com/questions/1103401/generate-an-ecdsa-key-and-csr-with-openssl

8
3rdparty/exported/t_cose/test/keys/prime256v1.pem поставляемый Normal file
Просмотреть файл

@ -0,0 +1,8 @@
-----BEGIN EC PARAMETERS-----
BggqhkjOPQMBBw==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIPG3FCNDQC87XecxXqiU+dpc9QP/eTijfKFOsDKGmIRQoAoGCCqGSM49
AwEHoUQDQgAEN6tllV+uBGZnPDopNKNPLw7Cs+7CJBmFV5mPwEv0srSV2XmPJTnJ
DX0QKzu72n/L2w6bWNThrS5hUI2nX4Smew==
-----END EC PRIVATE KEY-----

9
3rdparty/exported/t_cose/test/keys/secp384r1.pem поставляемый Normal file
Просмотреть файл

@ -0,0 +1,9 @@
-----BEGIN EC PARAMETERS-----
BgUrgQQAIg==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MIGkAgEBBDAD3xT0uKQ/2Kt1pgRr0rXqpv0QsrID/Yp415Ft4gqiQes37D1MaT0j
uitPbltm9X+gBwYFK4EEACKhZANiAAS92cP4GMnO8+EeLUDndb6ze8N2aY1xln+T
M3pOAy3/sRtQUGfd20IUtW2bzsWRd+zNirBfUJdZM7mnONkMCwfrlRlWfvkHWAfP
dxOfwf6FYIhRNhE2gGEj7cc1zloD6OQ=
-----END EC PRIVATE KEY-----

10
3rdparty/exported/t_cose/test/keys/secp521r1.pem поставляемый Normal file
Просмотреть файл

@ -0,0 +1,10 @@
-----BEGIN EC PARAMETERS-----
BgUrgQQAIw==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MIHcAgEBBEIARdLRQ5Q1+rMzscbItTTwlpOWrWTV9TXWX2jyoWBlkLsV/VMi/Jek
FsOVdF5yx8hRmMCSGrO46S3ZAbWkIVmtrG2gBwYFK4EEACOhgYkDgYYABADk0lMX
WhQxH8LdSHaHcMtJsHvRXTJ765iqM+YM0BgbF/uPHL8H28hlL/W3tEUsCC4GhsD6
uAiQccvFNxAdNEuUwgHmQk86GNpPIOyr+8hLhGfCF81nBV+l3sf7GuhwgjAsGBPK
pLexzyjZRnfkhvtLMXCX6TB6vbnVAYd3mj0eaCwSPA==
-----END EC PRIVATE KEY-----

317
3rdparty/exported/t_cose/test/run_tests.c поставляемый Normal file
Просмотреть файл

@ -0,0 +1,317 @@
/*==============================================================================
run_tests.c -- test aggregator and results reporting
Copyright (c) 2018-2022, Laurence Lundblade. All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
See BSD-3-Clause license in README.md
Created on 9/30/18
=============================================================================*/
#include "run_tests.h"
#include "qcbor/UsefulBuf.h"
#include <stdbool.h>
#include <stddef.h>
#include "t_cose_test.h"
#include "t_cose_sign_verify_test.h"
/*
Test configuration
*/
typedef int_fast32_t (test_fun_t)(void);
typedef const char * (test_fun2_t)(void);
#define TEST_ENTRY(test_name) {#test_name, test_name, true}
#define TEST_ENTRY_DISABLED(test_name) {#test_name, test_name, false}
typedef struct {
const char *szTestName;
test_fun_t *test_fun;
bool bEnabled;
} test_entry;
#ifdef STRING_RETURNING_TESTS
typedef struct {
const char *szTestName;
test_fun2_t *test_fun;
bool bEnabled;
} test_entry2;
static test_entry2 s_tests2[] = {
};
#endif
static test_entry s_tests[] = {
TEST_ENTRY(sign1_structure_decode_test),
#ifndef T_COSE_DISABLE_SIGN_VERIFY_TESTS
/* Many tests can be run without a crypto library integration and
* provide good test coverage of everything but the signing and
* verification. These tests can't be run with signing and
* verification short circuited. They must have a real crypto
* library integrated. */
TEST_ENTRY(sign_verify_basic_test),
TEST_ENTRY(sign_verify_make_cwt_test),
TEST_ENTRY(sign_verify_sig_fail_test),
TEST_ENTRY(sign_verify_get_size_test),
TEST_ENTRY(known_good_test),
#endif /* T_COSE_DISABLE_SIGN_VERIFY_TESTS */
#ifndef T_COSE_DISABLE_SHORT_CIRCUIT_SIGN
/* These tests can't run if short-circuit signatures are disabled.
* The most critical ones are replicated in the group of tests
* that require a real crypto library. Typically short-circuit
* signing is only disabled for extreme code size savings so these
* tests are typically always run.
*/
TEST_ENTRY(bad_parameters_test),
TEST_ENTRY(crit_parameters_test),
#ifndef T_COSE_DISABLE_CONTENT_TYPE
TEST_ENTRY(content_type_test),
#endif
TEST_ENTRY(all_header_parameters_test),
TEST_ENTRY(cose_example_test),
TEST_ENTRY(short_circuit_signing_error_conditions_test),
TEST_ENTRY(short_circuit_self_test),
TEST_ENTRY(short_circuit_self_detached_content_test),
TEST_ENTRY(short_circuit_decode_only_test),
TEST_ENTRY(short_circuit_make_cwt_test),
TEST_ENTRY(short_circuit_verify_fail_test),
TEST_ENTRY(tags_test),
TEST_ENTRY(get_size_test),
TEST_ENTRY(indef_array_and_map_test),
#ifdef T_COSE_ENABLE_HASH_FAIL_TEST
TEST_ENTRY(short_circuit_hash_fail_test),
#endif /* T_COSE_DISABLE_HASH_FAIL_TEST */
#endif /* T_COSE_DISABLE_SHORT_CIRCUIT_SIGN */
};
/**
\brief Convert number to ASCII string, similar to sprint
\param [in] nNum The 32-bit integer to convert.
\param [in] StringMem The buffer to output to.
\return POinter to NULL-terminated string with result or "XXX" on failure.
Convert a number up to 999999999 to a string. This is so sprintf doesn't
have to be linked in so as to minimized dependencies even in test code.
StringMem should be 12 bytes long, 9 for digits, 1 for minus and
1 for \0 termination.
*/
static const char *NumToString(int32_t nNum, UsefulBuf StringMem)
{
const int32_t nMax = 1000000000;
UsefulOutBuf OutBuf;
UsefulOutBuf_Init(&OutBuf, StringMem);
if(nNum < 0) {
UsefulOutBuf_AppendByte(&OutBuf, '-');
nNum = -nNum;
}
if(nNum > nMax-1) {
return "XXX";
}
bool bDidSomeOutput = false;
for(int32_t n = nMax; n > 0; n/=10) {
int32_t nDigitValue = nNum/n;
if(nDigitValue || bDidSomeOutput){
bDidSomeOutput = true;
UsefulOutBuf_AppendByte(&OutBuf, (uint8_t)('0' + nDigitValue));
nNum -= nDigitValue * n;
}
}
if(!bDidSomeOutput){
UsefulOutBuf_AppendByte(&OutBuf, '0');
}
UsefulOutBuf_AppendByte(&OutBuf, '\0');
return UsefulOutBuf_GetError(&OutBuf) ? "" : StringMem.ptr;
}
/*
Public function. See run_test.h.
*/
int RunTestsTCose(const char *szTestNames[],
OutputStringCB pfOutput,
void *poutCtx,
int *pNumTestsRun)
{
// int (-32767 to 32767 according to C standard) used by conscious choice
int nTestsFailed = 0;
int nTestsRun = 0;
UsefulBuf_MAKE_STACK_UB(StringStorage, 12);
#ifdef STRING_RETURNING_TESTS
test_entry2 *t2;
const test_entry2 *s_tests2_end = s_tests2 + sizeof(s_tests2)/sizeof(test_entry2);
for(t2 = s_tests2; t2 < s_tests2_end; t2++) {
if(szTestNames[0]) {
// Some tests have been named
const char **szRequestedNames;
for(szRequestedNames = szTestNames; *szRequestedNames; szRequestedNames++) {
if(!strcmp(t2->szTestName, *szRequestedNames)) {
break; // Name matched
}
}
if(*szRequestedNames == NULL) {
// Didn't match this test
continue;
}
} else {
// no tests named, but don't run "disabled" tests
if(!t2->bEnabled) {
// Don't run disabled tests when all tests are being run
// as indicated by no specific test names being given
continue;
}
}
const char * szTestResult = (t2->test_fun)();
nTestsRun++;
if(pfOutput) {
(*pfOutput)(t2->szTestName, poutCtx, 0);
}
if(szTestResult) {
if(pfOutput) {
(*pfOutput)(" FAILED (returned ", poutCtx, 0);
(*pfOutput)(szTestResult, poutCtx, 0);
(*pfOutput)(")", poutCtx, 1);
}
nTestsFailed++;
} else {
if(pfOutput) {
(*pfOutput)( " PASSED", poutCtx, 1);
}
}
}
#endif
test_entry *t;
const test_entry *s_tests_end = s_tests + sizeof(s_tests)/sizeof(test_entry);
for(t = s_tests; t < s_tests_end; t++) {
if(szTestNames[0]) {
// Some tests have been named
const char **szRequestedNames;
for(szRequestedNames = szTestNames; *szRequestedNames; szRequestedNames++) {
if(!strcmp(t->szTestName, *szRequestedNames)) {
break; // Name matched
}
}
if(*szRequestedNames == NULL) {
// Didn't match this test
continue;
}
} else {
// no tests named, but don't run "disabled" tests
if(!t->bEnabled) {
// Don't run disabled tests when all tests are being run
// as indicated by no specific test names being given
continue;
}
}
int nTestResult = (t->test_fun)();
nTestsRun++;
if(pfOutput) {
(*pfOutput)(t->szTestName, poutCtx, 0);
}
if(nTestResult) {
if(pfOutput) {
(*pfOutput)(" FAILED (returned ", poutCtx, 0);
(*pfOutput)(NumToString(nTestResult, StringStorage), poutCtx, 0);
(*pfOutput)(")", poutCtx, 1);
}
nTestsFailed++;
} else {
if(pfOutput) {
(*pfOutput)( " PASSED", poutCtx, 1);
}
}
}
if(pNumTestsRun) {
*pNumTestsRun = nTestsRun;
}
if(pfOutput) {
(*pfOutput)( "SUMMARY: ", poutCtx, 0);
(*pfOutput)( NumToString(nTestsRun, StringStorage), poutCtx, 0);
(*pfOutput)( " tests run; ", poutCtx, 0);
(*pfOutput)( NumToString(nTestsFailed, StringStorage), poutCtx, 0);
(*pfOutput)( " tests failed", poutCtx, 1);
}
return nTestsFailed;
}
/*
Public function. See run_test.h.
*/
static void PrintSize(const char *szWhat,
uint32_t uSize,
OutputStringCB pfOutput,
void *pOutCtx)
{
UsefulBuf_MAKE_STACK_UB(buffer, 20);
(*pfOutput)(szWhat, pOutCtx, 0);
(*pfOutput)(" ", pOutCtx, 0);
(*pfOutput)(NumToString((int32_t)uSize, buffer), pOutCtx, 0);
(*pfOutput)("", pOutCtx, 1);
}
#include "t_cose/t_cose_sign1_sign.h" /* For struct size printing */
#include "t_cose/t_cose_sign1_verify.h" /* For struct size printing */
#include "t_cose_crypto.h" /* For struct size printing */
/*
Public function. See run_test.h.
*/
void PrintSizesTCose(OutputStringCB pfOutput, void *pOutCtx)
{
// Type and size of return from sizeof() varies. These will never be large
// so cast is safe.
PrintSize("sizeof(struct t_cose_sign1_ctx)",
(uint32_t)sizeof(struct t_cose_sign1_sign_ctx),
pfOutput, pOutCtx);
PrintSize("sizeof(struct t_cose_signing_key)",
(uint32_t)sizeof(struct t_cose_key),
pfOutput, pOutCtx);
PrintSize("sizeof(struct t_cose_crypto_hash)",
(uint32_t)sizeof(struct t_cose_crypto_hash),
pfOutput, pOutCtx);
PrintSize("sizeof(struct t_cose_parameters)",
(uint32_t)sizeof(struct t_cose_parameters),
pfOutput, pOutCtx);
PrintSize("sizeof(struct t_cose_sign1_verify_ctx)",
(uint32_t)sizeof(struct t_cose_sign1_verify_ctx),
pfOutput, pOutCtx);
(*pfOutput)("", pOutCtx, 1);
}

69
3rdparty/exported/t_cose/test/run_tests.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,69 @@
/*==============================================================================
run_tests.h -- test aggregator and results reporting
Copyright (c) 2018-2020, Laurence Lundblade. All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
See BSD-3-Clause license in README.md
Created 9/30/18
=============================================================================*/
/**
@file run_tests.h
*/
/**
@brief Type for function to output a text string
@param[in] szString The string to output
@param[in] pOutCtx A context pointer; NULL if not needed
@param[in] bNewline If non-zero, output a newline after the string
This is a prototype of a function to be passed to RunTests() to
output text strings.
This can be implemented with stdio (if available) using a straight
call to fputs() where the FILE * is passed as the pOutCtx as shown in
the example code below. This code is for Linux where the newline is
a \\n. Windows usually prefers \\r\\n.
@code
static void fputs_wrapper(const char *szString, void *pOutCtx, int bNewLine)
{
fputs(szString, (FILE *)pOutCtx);
if(bNewLine) {
fputs("\n", pOutCtx);
}
}
@endcode
*/
typedef void (*OutputStringCB)(const char *szString, void *pOutCtx, int bNewline);
/**
@brief Runs the T_COSE tests.
@param[in] szTestNames An argv-style list of test names to run. If
empty, all are run.
@param[in] pfOutput Function that is called to output text strings.
@param[in] pOutCtx Context pointer passed to output function.
@param[out] pNumTestsRun Returns the number of tests run. May be NULL.
@return The number of tests that failed. Zero means overall success.
*/
int RunTestsTCose(const char *szTestNames[],
OutputStringCB pfOutput,
void *pOutCtx,
int *pNumTestsRun);
/**
@brief Print sizes of encoder / decoder contexts.
@param[in] pfOutput Function that is called to output text strings.
@param[in] pOutCtx Context pointer passed to output function.
*/
void PrintSizesTCose(OutputStringCB pfOutput, void *pOutCtx);

166
3rdparty/exported/t_cose/test/t_cose_make_openssl_test_key.c поставляемый Normal file
Просмотреть файл

@ -0,0 +1,166 @@
/*
* t_cose_make_openssl_test_key.c
*
* Copyright 2019-2022, Laurence Lundblade
*
* SPDX-License-Identifier: BSD-3-Clause
*
* See BSD-3-Clause license in README.md
*/
#include "t_cose_make_test_pub_key.h" /* The interface implemented here */
#include "openssl/err.h"
#include "openssl/evp.h"
#include "openssl/x509.h"
/*
* RFC 5915 format EC private key, including the public key. These
* are the same key as in t_cose_make_psa_test_key.c
*
* They are made by:
*
* openssl ecparam -genkey -name prime256v1 -noout -out ec256-key-pair.pem
*
* Edit the PEM headers off so it is just b64
*
* base64 --decode to get the pure DER
*
* xxd -i to turn it into a C variable
*
*
* See also:
* https://stackoverflow.com/
* questions/71890050/
* set-an-evp-pkey-from-ec-raw-points-pem-or-der-in-both-openssl-1-1-1-and-3-0-x/
* 71896633#71896633
*/
static const unsigned char ec256_key_pair[] = {
0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0xd9, 0xb5, 0xe7, 0x1f, 0x77,
0x28, 0xbf, 0xe5, 0x63, 0xa9, 0xdc, 0x93, 0x75, 0x62, 0x27, 0x7e, 0x32,
0x7d, 0x98, 0xd9, 0x94, 0x80, 0xf3, 0xdc, 0x92, 0x41, 0xe5, 0x74, 0x2a,
0xc4, 0x58, 0x89, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x40, 0x41, 0x6c,
0x8c, 0xda, 0xa0, 0xf7, 0xa1, 0x75, 0x69, 0x55, 0x53, 0xc3, 0x27, 0x9c,
0x10, 0x9c, 0xe9, 0x27, 0x7e, 0x53, 0xc5, 0x86, 0x2a, 0xa7, 0x15, 0xed,
0xc6, 0x36, 0xf1, 0x71, 0xca, 0x32, 0xf1, 0x76, 0x43, 0x54, 0x96, 0x15,
0xe5, 0xc8, 0x34, 0x0d, 0x43, 0x32, 0xdd, 0x13, 0x77, 0x8a, 0xec, 0x87,
0x15, 0x76, 0xa3, 0x3c, 0x26, 0x08, 0x6c, 0x32, 0x0c, 0x9f, 0xf3, 0x3f,
0xc7
};
static const unsigned char ec384_key_pair[] = {
0x30, 0x81, 0xa4, 0x02, 0x01, 0x01, 0x04, 0x30, 0x63, 0x88, 0x1c, 0xbf,
0x86, 0x65, 0xec, 0x39, 0x27, 0x33, 0x24, 0x2e, 0x5a, 0xae, 0x63, 0x3a,
0xf5, 0xb1, 0xb4, 0x54, 0xcf, 0x7a, 0x55, 0x7e, 0x44, 0xe5, 0x7c, 0xca,
0xfd, 0xb3, 0x59, 0xf9, 0x72, 0x66, 0xec, 0x48, 0x91, 0xdf, 0x27, 0x79,
0x99, 0xbd, 0x1a, 0xbc, 0x09, 0x36, 0x49, 0x9c, 0xa0, 0x07, 0x06, 0x05,
0x2b, 0x81, 0x04, 0x00, 0x22, 0xa1, 0x64, 0x03, 0x62, 0x00, 0x04, 0x14,
0x2a, 0x78, 0x91, 0x06, 0x9b, 0xbe, 0x43, 0xa9, 0xe8, 0xd2, 0xa7, 0xbd,
0x03, 0xdf, 0xc9, 0x12, 0x62, 0x66, 0xb7, 0x84, 0xe3, 0x33, 0x4a, 0xf2,
0xb5, 0xf9, 0x5e, 0xe0, 0x3f, 0xe5, 0xc7, 0xdc, 0x1d, 0x56, 0xb3, 0x9f,
0x30, 0x6f, 0x97, 0xba, 0x00, 0xd8, 0xcf, 0x41, 0xea, 0x95, 0x5f, 0xeb,
0x55, 0x62, 0xab, 0x7c, 0xb7, 0x58, 0xd0, 0xe8, 0xde, 0xcf, 0x64, 0x69,
0x32, 0x50, 0xb3, 0x06, 0x70, 0xb0, 0xbc, 0x84, 0xcb, 0xa7, 0x1f, 0x2f,
0x1b, 0xf6, 0xad, 0x54, 0x56, 0x0a, 0x75, 0x83, 0xe1, 0xcf, 0xb6, 0x12,
0x2e, 0x0a, 0xde, 0xf9, 0xaa, 0x37, 0x64, 0x1a, 0x51, 0x1c, 0x27
};
static const unsigned char ec521_key_pair[] = {
0x30, 0x81, 0xdc, 0x02, 0x01, 0x01, 0x04, 0x42, 0x00, 0x4b, 0x35, 0x4d,
0xa4, 0xab, 0xf7, 0xa5, 0x4f, 0xac, 0xee, 0x06, 0x49, 0x4a, 0x97, 0x0e,
0xa6, 0x5f, 0x85, 0xf0, 0x6a, 0x2e, 0xfb, 0xf8, 0xdd, 0x60, 0x9a, 0xf1,
0x0b, 0x7a, 0x13, 0xf7, 0x90, 0xf8, 0x9f, 0x49, 0x02, 0xbf, 0x5d, 0x5d,
0x71, 0xa0, 0x90, 0x93, 0x11, 0xfd, 0x0c, 0xda, 0x7b, 0x6a, 0x5f, 0x7b,
0x82, 0x9d, 0x79, 0x61, 0xe1, 0x6b, 0x31, 0x0a, 0x30, 0x6f, 0x4d, 0xf3,
0x8b, 0xe3, 0xa0, 0x07, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23, 0xa1,
0x81, 0x89, 0x03, 0x81, 0x86, 0x00, 0x04, 0x00, 0x64, 0x27, 0x45, 0x07,
0x38, 0xbd, 0xd7, 0x1a, 0x87, 0xea, 0x20, 0xfb, 0x93, 0x6f, 0x1c, 0xde,
0xb3, 0x42, 0xcc, 0xf4, 0x58, 0x87, 0x79, 0x0f, 0x69, 0xaf, 0x5b, 0xff,
0x72, 0x96, 0x35, 0xb9, 0x6e, 0x8a, 0x55, 0x64, 0x00, 0x44, 0xfe, 0x63,
0x20, 0x4f, 0x65, 0x3a, 0x3a, 0x47, 0xcf, 0x3a, 0x7f, 0x60, 0x5d, 0xcb,
0xe6, 0xb4, 0x5a, 0x57, 0x2f, 0xc8, 0x74, 0x62, 0xcf, 0x98, 0x58, 0x33,
0x59, 0x00, 0xb9, 0xd0, 0xbc, 0x76, 0x2a, 0x37, 0x15, 0x3b, 0x9d, 0x3c,
0x62, 0xe9, 0xcc, 0x63, 0x00, 0xab, 0x7b, 0x01, 0xb1, 0x00, 0x77, 0x02,
0x14, 0xdb, 0x5e, 0xb8, 0xda, 0xac, 0x72, 0xf1, 0xd4, 0xa6, 0x17, 0xc5,
0x12, 0x97, 0x95, 0x6b, 0x98, 0x0b, 0xe0, 0x19, 0xf1, 0xf6, 0xd1, 0x0c,
0x09, 0xec, 0x1e, 0x2f, 0x51, 0x7a, 0x87, 0x71, 0x3c, 0x63, 0x25, 0x01,
0x43, 0xc0, 0xa8, 0x52, 0x1f, 0xf9, 0x53
};
/*
* Public function, see t_cose_make_test_pub_key.h
*/
/*
* The key object returned by this is malloced and has to be freed by
* by calling free_ecdsa_key_pair(). This heap use is a part of
* OpenSSL and not t_cose which does not use the heap.
*/
enum t_cose_err_t make_ecdsa_key_pair(int32_t cose_algorithm_id,
struct t_cose_key *key_pair)
{
enum t_cose_err_t return_value;
EVP_PKEY *pkey;
const uint8_t *rfc5915_key;
long rfc5915_key_len;
switch (cose_algorithm_id) {
case T_COSE_ALGORITHM_ES256:
rfc5915_key = ec256_key_pair;
rfc5915_key_len = sizeof(ec256_key_pair);
break;
case T_COSE_ALGORITHM_ES384:
rfc5915_key = ec384_key_pair;
rfc5915_key_len = sizeof(ec384_key_pair);
break;
case T_COSE_ALGORITHM_ES512:
rfc5915_key = ec521_key_pair;
rfc5915_key_len = sizeof(ec521_key_pair);
break;
default:
return T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
}
/* This imports the public key too */
pkey = d2i_PrivateKey(EVP_PKEY_EC, NULL, &rfc5915_key, rfc5915_key_len);
if(pkey == NULL) {
return_value = T_COSE_ERR_FAIL;
goto Done;
}
key_pair->k.key_ptr = pkey;
key_pair->crypto_lib = T_COSE_CRYPTO_LIB_OPENSSL;
return_value = T_COSE_SUCCESS;
Done:
return return_value;
}
/*
* Public function, see t_cose_make_test_pub_key.h
*/
void free_ecdsa_key_pair(struct t_cose_key key_pair)
{
EVP_PKEY_free(key_pair.k.key_ptr);
}
/*
* Public function, see t_cose_make_test_pub_key.h
*/
int check_for_key_pair_leaks()
{
/* So far no good way to do this for OpenSSL or malloc() in general
in a nice portable way. The PSA version does check so there is
some coverage of the code even though there is no check here.
*/
return 0;
}

193
3rdparty/exported/t_cose/test/t_cose_make_psa_test_key.c поставляемый Normal file
Просмотреть файл

@ -0,0 +1,193 @@
/*
* t_cose_make_psa_test_key.c
*
* Copyright 2019-2022, Laurence Lundblade
*
* SPDX-License-Identifier: BSD-3-Clause
*
* See BSD-3-Clause license in README.md
*/
#include "t_cose_make_test_pub_key.h" /* The interface implemented here */
#include "t_cose_standard_constants.h"
#include "psa/crypto.h"
/*
* These are the same keys as in t_cose_make_openssl_test_key.c so that
* messages made with openssl can be verified those made by mbedtls.
* These were made with openssl as detailed in t_cose_make_openssl_test_key.c.
* Then just the private key was pulled out to be put here because
* mbedtls just needs the private key, unlike openssl for which there
* is a full rfc5915 DER structure. These were pulled out of the DER
* by identifying the key with openssl asn1parse and then finding those
* bytes in the C variable holding the rfc5915 (perhaps there is a better
* way, but this works).
*/
#define PRIVATE_KEY_prime256v1 \
0xd9, 0xb5, 0xe7, 0x1f, 0x77, 0x28, 0xbf, 0xe5, 0x63, 0xa9, 0xdc, 0x93, 0x75, \
0x62, 0x27, 0x7e, 0x32, 0x7d, 0x98, 0xd9, 0x94, 0x80, 0xf3, 0xdc, 0x92, 0x41, \
0xe5, 0x74, 0x2a, 0xc4, 0x58, 0x89
#define PRIVATE_KEY_secp384r1 \
0x63, 0x88, 0x1c, 0xbf, \
0x86, 0x65, 0xec, 0x39, 0x27, 0x33, 0x24, 0x2e, 0x5a, 0xae, 0x63, 0x3a, \
0xf5, 0xb1, 0xb4, 0x54, 0xcf, 0x7a, 0x55, 0x7e, 0x44, 0xe5, 0x7c, 0xca, \
0xfd, 0xb3, 0x59, 0xf9, 0x72, 0x66, 0xec, 0x48, 0x91, 0xdf, 0x27, 0x79, \
0x99, 0xbd, 0x1a, 0xbc, 0x09, 0x36, 0x49, 0x9c
#define PRIVATE_KEY_secp521r1 \
0x00, 0x4b, 0x35, 0x4d, \
0xa4, 0xab, 0xf7, 0xa5, 0x4f, 0xac, 0xee, 0x06, 0x49, 0x4a, 0x97, 0x0e, \
0xa6, 0x5f, 0x85, 0xf0, 0x6a, 0x2e, 0xfb, 0xf8, 0xdd, 0x60, 0x9a, 0xf1, \
0x0b, 0x7a, 0x13, 0xf7, 0x90, 0xf8, 0x9f, 0x49, 0x02, 0xbf, 0x5d, 0x5d, \
0x71, 0xa0, 0x90, 0x93, 0x11, 0xfd, 0x0c, 0xda, 0x7b, 0x6a, 0x5f, 0x7b, \
0x82, 0x9d, 0x79, 0x61, 0xe1, 0x6b, 0x31, 0x0a, 0x30, 0x6f, 0x4d, 0xf3, \
0x8b, 0xe3
/*
* Public function, see t_cose_make_test_pub_key.h
*/
enum t_cose_err_t make_ecdsa_key_pair(int32_t cose_algorithm_id,
struct t_cose_key *key_pair)
{
psa_key_type_t key_type;
psa_status_t crypto_result;
mbedtls_svc_key_id_t key_handle;
psa_algorithm_t key_alg;
const uint8_t *private_key;
size_t private_key_len;
psa_key_attributes_t key_attributes;
static const uint8_t private_key_256[] = {PRIVATE_KEY_prime256v1};
static const uint8_t private_key_384[] = {PRIVATE_KEY_secp384r1};
static const uint8_t private_key_521[] = {PRIVATE_KEY_secp521r1};
/* There is not a 1:1 mapping from COSE algorithm to key type, but
* there is usually an obvious curve for an algorithm. That
* is what this does.
*/
switch(cose_algorithm_id) {
case COSE_ALGORITHM_ES256:
private_key = private_key_256;
private_key_len = sizeof(private_key_256);
key_type = PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1);
key_alg = PSA_ALG_ECDSA(PSA_ALG_SHA_256);
break;
case COSE_ALGORITHM_ES384:
private_key = private_key_384;
private_key_len = sizeof(private_key_384);
key_type = PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1);
key_alg = PSA_ALG_ECDSA(PSA_ALG_SHA_384);
break;
case COSE_ALGORITHM_ES512:
private_key = private_key_521;
private_key_len = sizeof(private_key_521);
key_type = PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1);
key_alg = PSA_ALG_ECDSA(PSA_ALG_SHA_512);
break;
default:
return T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
}
/* OK to call this multiple times */
crypto_result = psa_crypto_init();
if(crypto_result != PSA_SUCCESS) {
return T_COSE_ERR_FAIL;
}
/* When importing a key with the PSA API there are two main things
* to do.
*
* First you must tell it what type of key it is as this cannot be
* discovered from the raw data (because the import is not of a format
* like RFC 5915). The variable key_type contains
* that information including the EC curve. This is sufficient for
* psa_import_key() to succeed, but you probably want actually use
* the key.
*
* Second, you must say what algorithm(s) and operations the key
* can be used as the PSA Crypto Library has policy enforcement.
*/
key_attributes = psa_key_attributes_init();
/* The type of key including the EC curve */
psa_set_key_type(&key_attributes, key_type);
/* Say what algorithm and operations the key can be used with/for */
psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH);
psa_set_key_algorithm(&key_attributes, key_alg);
/* Import the private key. psa_import_key() automatically
* generates the public key from the private so no need to import
* more than the private key. With ECDSA the public key is always
* deterministically derivable from the private key.
*/
crypto_result = psa_import_key(&key_attributes,
private_key,
private_key_len,
&key_handle);
if(crypto_result != PSA_SUCCESS) {
return T_COSE_ERR_FAIL;
}
/* This assignment relies on MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER
* not being defined. If it is defined key_handle is a structure.
* This does not seem to be typically defined as it seems that is
* for a PSA implementation architecture as a service rather than
* an linked library. If it is defined, the structure will
* probably be less than 64 bits, so it can still fit in a
* t_cose_key. */
key_pair->k.key_handle = key_handle;
key_pair->crypto_lib = T_COSE_CRYPTO_LIB_PSA;
return T_COSE_SUCCESS;
}
/*
* Public function, see t_cose_make_test_pub_key.h
*/
void free_ecdsa_key_pair(struct t_cose_key key_pair)
{
psa_destroy_key((mbedtls_svc_key_id_t)key_pair.k.key_handle);
}
/*
* Public function, see t_cose_make_test_pub_key.h
*/
int check_for_key_pair_leaks()
{
/* The key allocation counters are private data structures, but
* they are the only way to do the valuable test for key
* deallocation leakage, so they are used. MbedTLS 3 formally
* labeled them private with a macro. */
#if MBEDTLS_VERSION_MAJOR < 3
#define MBEDTLS_PRIVATE(x) x
#endif
mbedtls_psa_stats_t stats;
mbedtls_psa_get_stats(&stats);
return (int)(stats.MBEDTLS_PRIVATE(volatile_slots) +
stats.MBEDTLS_PRIVATE(persistent_slots) +
stats.MBEDTLS_PRIVATE(external_slots) +
stats.MBEDTLS_PRIVATE(half_filled_slots) +
stats.MBEDTLS_PRIVATE(cache_slots));
}

651
3rdparty/exported/t_cose/test/t_cose_make_test_messages.c поставляемый Normal file
Просмотреть файл

@ -0,0 +1,651 @@
/*
* t_cose_make_test_messages.c
*
* Copyright (c) 2019-2022, Laurence Lundblade. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
* See BSD-3-Clause license in README.md
*/
#include "t_cose_make_test_messages.h"
#include "qcbor/qcbor.h"
#include "t_cose_crypto.h"
#include "t_cose_util.h"
/**
* \file t_cose_make_test_messages.c
*
* This makes \c COSE_Sign1 messages of various sorts for testing
* verification. Some of them are badly formed to test various
* verification failures.
*
* This is essentially a hacked-up version of t_cose_sign1_sign.c.
*/
#ifndef T_COSE_DISABLE_SHORT_CIRCUIT_SIGN
/**
* \brief Create a short-circuit signature
*
* \param[in] cose_algorithm_id Algorithm ID. This is used only to make
* the short-circuit signature the same size
* as the real signature would be for the
* particular algorithm.
* \param[in] hash_to_sign The bytes to sign. Typically, a hash of
* a payload.
* \param[in] signature_buffer Pointer and length of buffer into which
* the resulting signature is put.
* \param[in] signature Pointer and length of the signature
* returned.
*
* \return This returns one of the error codes defined by \ref t_cose_err_t.
*
* This creates the short-circuit signature that is a concatenation of
* hashes up to the expected size of the signature. This is a test
* mode only has it has no security value. This is retained in
* commercial production code as a useful test or demo that can run
* even if key material is not set up or accessible.
*/
static inline enum t_cose_err_t
short_circuit_sign(int32_t cose_algorithm_id,
struct q_useful_buf_c hash_to_sign,
struct q_useful_buf signature_buffer,
struct q_useful_buf_c *signature)
{
/* approximate stack use on 32-bit machine: local use: 16 bytes
*/
enum t_cose_err_t return_value;
size_t array_index;
size_t amount_to_copy;
size_t sig_size;
sig_size = cose_algorithm_id == COSE_ALGORITHM_ES256 ? T_COSE_EC_P256_SIG_SIZE :
cose_algorithm_id == COSE_ALGORITHM_ES384 ? T_COSE_EC_P384_SIG_SIZE :
cose_algorithm_id == COSE_ALGORITHM_ES512 ? T_COSE_EC_P512_SIG_SIZE :
0;
/* Check the signature length against buffer size*/
if(sig_size == 0) {
return_value = T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
goto Done;
}
if(sig_size > signature_buffer.len) {
/* Buffer too small for this signature type */
return_value = T_COSE_ERR_SIG_BUFFER_SIZE;
goto Done;
}
/* Loop concatening copies of the hash to fill out to signature size */
for(array_index = 0; array_index < sig_size; array_index += hash_to_sign.len) {
amount_to_copy = sig_size - array_index;
if(amount_to_copy > hash_to_sign.len) {
amount_to_copy = hash_to_sign.len;
}
memcpy((uint8_t *)signature_buffer.ptr + array_index,
hash_to_sign.ptr,
amount_to_copy);
}
signature->ptr = signature_buffer.ptr;
signature->len = sig_size;
return_value = T_COSE_SUCCESS;
Done:
return return_value;
}
#endif /* T_COSE_DISABLE_SHORT_CIRCUIT_SIGN */
/**
* \brief Makes various protected parameters for various tests
*
* \param[in] test_message_options Flags to select test modes.
* \param[in] cose_algorithm_id The algorithm ID to put in the parameters.
* \param[in] buffer_for_protected_parameters Pointer and length into which
* the resulting encoded protected
* parameters is put.
*
* \return The pointer and length of the protected parameters is
* returned, or \c NULL_Q_USEFUL_BUF_C if this fails.
*
* The protected parameters are returned in fully encoded CBOR format as
* they are added to the \c COSE_Sign1 as a binary string. This is
* different from the unprotected parameters which are not handled this
* way.
*
* This returns \c NULL_Q_USEFUL_BUF_C if buffer_for_protected_parameters was
* too small. See also definition of
* \c T_COSE_SIGN1_MAX_SIZE_PROTECTED_PARAMETERS.
*/
static inline struct q_useful_buf_c
encode_protected_parameters(uint32_t test_message_options,
int32_t cose_algorithm_id,
struct q_useful_buf buffer_for_protected_parameters)
{
/* approximate stack use on 32-bit machine:
* local use: 170
* with calls: 210
*/
struct q_useful_buf_c protected_parameters;
QCBORError qcbor_result;
QCBOREncodeContext cbor_encode_ctx;
struct q_useful_buf_c return_value;
if(test_message_options & T_COSE_TEST_EMPTY_PROTECTED_PARAMETERS) {
/* An empty q_useful_buf_c */
return (struct q_useful_buf_c){buffer_for_protected_parameters.ptr, 0};
}
if(test_message_options & T_COSE_TEST_UNCLOSED_PROTECTED) {
*(uint8_t *)(buffer_for_protected_parameters.ptr) = 0xa1;
return (struct q_useful_buf_c){buffer_for_protected_parameters.ptr, 1};
}
QCBOREncode_Init(&cbor_encode_ctx, buffer_for_protected_parameters);
if(test_message_options & T_COSE_TEST_BAD_PROTECTED) {
QCBOREncode_OpenArray(&cbor_encode_ctx);
QCBOREncode_AddInt64(&cbor_encode_ctx, 42);
QCBOREncode_CloseArray(&cbor_encode_ctx);
goto Finish;
}
if(test_message_options & T_COSE_TEST_INDEFINITE_MAPS_ARRAYS) {
QCBOREncode_OpenMapIndefiniteLength(&cbor_encode_ctx);
} else {
QCBOREncode_OpenMap(&cbor_encode_ctx);
}
QCBOREncode_AddInt64ToMapN(&cbor_encode_ctx,
COSE_HEADER_PARAM_ALG,
cose_algorithm_id);
if(test_message_options & T_COSE_TEST_UNKNOWN_CRIT_UINT_PARAMETER) {
/* This is the parameter that will be unknown */
QCBOREncode_AddInt64ToMapN(&cbor_encode_ctx, 42, 43);
/* This is the critical labels parameter */
if(test_message_options & T_COSE_TEST_INDEFINITE_MAPS_ARRAYS) {
QCBOREncode_OpenArrayIndefiniteLengthInMapN(&cbor_encode_ctx, COSE_HEADER_PARAM_CRIT);
} else {
QCBOREncode_OpenArrayInMapN(&cbor_encode_ctx, COSE_HEADER_PARAM_CRIT);
}
QCBOREncode_AddInt64(&cbor_encode_ctx, 42);
QCBOREncode_AddInt64(&cbor_encode_ctx, 43);
QCBOREncode_AddInt64(&cbor_encode_ctx, 44);
if(test_message_options & T_COSE_TEST_INDEFINITE_MAPS_ARRAYS) {
QCBOREncode_CloseArrayIndefiniteLength(&cbor_encode_ctx);
} else {
QCBOREncode_CloseArray(&cbor_encode_ctx);
}
}
if(test_message_options & T_COSE_TEST_UNKNOWN_CRIT_TSTR_PARAMETER) {
/* This is the parameter that will be unknown */
QCBOREncode_AddInt64ToMap(&cbor_encode_ctx, "hh", 43);
/* This is the critical labels parameter */
QCBOREncode_OpenArrayInMapN(&cbor_encode_ctx, COSE_HEADER_PARAM_CRIT);
QCBOREncode_AddSZString(&cbor_encode_ctx, "hh");
QCBOREncode_AddSZString(&cbor_encode_ctx, "h");
QCBOREncode_AddSZString(&cbor_encode_ctx, "hhh");
QCBOREncode_CloseArray(&cbor_encode_ctx);
}
if(test_message_options & T_COSE_TEST_BAD_CRIT_LABEL) {
/* This is the critical labels parameter */
QCBOREncode_OpenArrayInMapN(&cbor_encode_ctx, COSE_HEADER_PARAM_CRIT);
QCBOREncode_AddBool(&cbor_encode_ctx, true);
QCBOREncode_CloseArray(&cbor_encode_ctx);
}
if(test_message_options & T_COSE_TEST_CRIT_PARAMETER_EXIST) {
/* This is the critical labels parameter */
QCBOREncode_OpenArrayInMapN(&cbor_encode_ctx, COSE_HEADER_PARAM_CRIT);
int i;
/* Add the maxium */
for(i = 0; i < T_COSE_PARAMETER_LIST_MAX; i++) {
QCBOREncode_AddInt64(&cbor_encode_ctx, i + 10);
}
QCBOREncode_CloseArray(&cbor_encode_ctx);
}
if(test_message_options & T_COSE_TEST_TOO_MANY_CRIT_PARAMETER_EXIST) {
/* This is the critical labels parameter */
QCBOREncode_OpenArrayInMapN(&cbor_encode_ctx, COSE_HEADER_PARAM_CRIT);
int i;
/* One more than the maximum */
for(i = 0; i < T_COSE_PARAMETER_LIST_MAX+1; i++) {
QCBOREncode_AddInt64(&cbor_encode_ctx, i + 10);
}
QCBOREncode_CloseArray(&cbor_encode_ctx);
}
if(test_message_options & T_COSE_TEST_TOO_MANY_TSTR_CRIT_LABLELS) {
/* This is the critical labels parameter */
QCBOREncode_OpenArrayInMapN(&cbor_encode_ctx, COSE_HEADER_PARAM_CRIT);
int i;
/* One more than the maximum */
for(i = 0; i < T_COSE_PARAMETER_LIST_MAX+1; i++) {
QCBOREncode_AddSZString(&cbor_encode_ctx, "");
}
QCBOREncode_CloseArray(&cbor_encode_ctx);
}
if(test_message_options & T_COSE_TEST_EMPTY_CRIT_PARAMETER) {
QCBOREncode_OpenArrayInMapN(&cbor_encode_ctx, COSE_HEADER_PARAM_CRIT);
QCBOREncode_CloseArray(&cbor_encode_ctx);
}
if(test_message_options & T_COSE_TEST_KID_IN_PROTECTED) {
QCBOREncode_AddBytesToMapN(&cbor_encode_ctx,
COSE_HEADER_PARAM_KID,
Q_USEFUL_BUF_FROM_SZ_LITERAL("kid"));
}
if(test_message_options & T_COSE_TEST_DUP_CONTENT_ID) {
QCBOREncode_AddUInt64ToMapN(&cbor_encode_ctx,
COSE_HEADER_PARAM_CONTENT_TYPE,
3);
}
if(test_message_options & T_COSE_TEST_INDEFINITE_MAPS_ARRAYS) {
QCBOREncode_CloseMapIndefiniteLength(&cbor_encode_ctx);
} else {
QCBOREncode_CloseMap(&cbor_encode_ctx);
}
Finish:
qcbor_result = QCBOREncode_Finish(&cbor_encode_ctx, &protected_parameters);
if(qcbor_result == QCBOR_SUCCESS) {
return_value = protected_parameters;
} else {
return_value = NULL_Q_USEFUL_BUF_C;
}
return return_value;
}
/**
* \brief Add the unprotected parameters to a CBOR encoding context
*
* \param[in] test_message_options Flags to select test modes.
* \param[in] cbor_encode_ctx CBOR encoding context to output to.
* \param[in] kid The key ID to go into the kid parameter.
*
* No error is returned. If an error occurred it will be returned when
* \c QCBOR_Finish() is called on \c cbor_encode_ctx.
*
* The unprotected parameters added by this are the key ID plus
* lots of different test parameters.
*/
static inline void
add_unprotected_parameters(uint32_t test_message_options,
QCBOREncodeContext *cbor_encode_ctx,
struct q_useful_buf_c kid)
{
if(test_message_options & T_COSE_TEST_UNPROTECTED_NOT_MAP) {
QCBOREncode_OpenArray(cbor_encode_ctx);
QCBOREncode_AddBytes(cbor_encode_ctx, kid);
QCBOREncode_CloseArray(cbor_encode_ctx);
return; /* skip the rest for this degenerate test */
}
if(test_message_options & T_COSE_TEST_INDEFINITE_MAPS_ARRAYS) {
QCBOREncode_OpenMapIndefiniteLength(cbor_encode_ctx);
} else {
QCBOREncode_OpenMap(cbor_encode_ctx);
}
if(test_message_options & T_COSE_TEST_NOT_WELL_FORMED_1) {
QCBOREncode_AddEncoded(cbor_encode_ctx,
Q_USEFUL_BUF_FROM_SZ_LITERAL("xxxxxx"));
}
/* Put in a byte string (not a text string) for the parameter label */
if(test_message_options & T_COSE_TEST_PARAMETER_LABEL) {
QCBOREncode_AddBytes(cbor_encode_ctx, kid);
QCBOREncode_AddBytes(cbor_encode_ctx, kid);
}
if(test_message_options & T_COSE_TEST_BAD_CRIT_PARAMETER) {
QCBOREncode_AddSZStringToMapN(cbor_encode_ctx,
COSE_HEADER_PARAM_CRIT, "hi");
}
if(test_message_options & T_COSE_TEST_EXTRA_PARAMETER) {
QCBOREncode_OpenArrayInMapN(cbor_encode_ctx, 55);
QCBOREncode_OpenMap(cbor_encode_ctx);
QCBOREncode_AddSZStringToMapN(cbor_encode_ctx, 66, "hi");
QCBOREncode_CloseMap(cbor_encode_ctx);
QCBOREncode_CloseArray(cbor_encode_ctx);
}
if(test_message_options & T_COSE_TEST_NOT_WELL_FORMED_2) {
QCBOREncode_OpenArrayInMapN(cbor_encode_ctx, 55);
QCBOREncode_OpenMap(cbor_encode_ctx);
QCBOREncode_AddSZStringToMapN(cbor_encode_ctx, 66, "hi");
/* 0xff is a break outside of anything indefinite and thus
* not-well-formed, This test used to use a 0x3d before
* spiffy decode, but spiffy decode can traverse that
* without error because it is not an
* QCBORDecode_IsUnrecoverableError().
* Improvement: add a test case for the 3d error back in
*/
QCBOREncode_AddEncoded(cbor_encode_ctx,
Q_USEFUL_BUF_FROM_SZ_LITERAL("\xff"));
QCBOREncode_AddSZStringToMapN(cbor_encode_ctx, 67, "bye");
QCBOREncode_CloseMap(cbor_encode_ctx);
QCBOREncode_CloseArray(cbor_encode_ctx);
}
if(test_message_options & T_COSE_TEST_CRIT_NOT_PROTECTED) {
/* This is the critical labels parameter */
QCBOREncode_OpenArrayInMapN(cbor_encode_ctx, COSE_HEADER_PARAM_CRIT);
int i;
/* Add the maxium */
for(i = 0; i < T_COSE_PARAMETER_LIST_MAX; i++) {
QCBOREncode_AddInt64(cbor_encode_ctx, i + 100);
QCBOREncode_AddSZString(cbor_encode_ctx, "xxxx");
}
QCBOREncode_CloseArray(cbor_encode_ctx);
}
if(test_message_options & T_COSE_TEST_TOO_MANY_UNKNOWN) {
int i;
for(i = 0; i < T_COSE_PARAMETER_LIST_MAX + 1; i++ ) {
QCBOREncode_AddBoolToMapN(cbor_encode_ctx, i+10, true);
}
}
if(!q_useful_buf_c_is_null_or_empty(kid)) {
QCBOREncode_AddBytesToMapN(cbor_encode_ctx, COSE_HEADER_PARAM_KID, kid);
}
if(test_message_options & T_COSE_TEST_ALL_PARAMETERS) {
QCBOREncode_AddBytesToMapN(cbor_encode_ctx,
COSE_HEADER_PARAM_IV,
Q_USEFUL_BUF_FROM_SZ_LITERAL("iv"));
QCBOREncode_AddBytesToMapN(cbor_encode_ctx,
COSE_HEADER_PARAM_PARTIAL_IV,
Q_USEFUL_BUF_FROM_SZ_LITERAL("partial_iv"));
QCBOREncode_AddInt64ToMapN(cbor_encode_ctx,
COSE_HEADER_PARAM_CONTENT_TYPE,
1);
/* A slighly complex unknown header parameter */
QCBOREncode_OpenArrayInMapN(cbor_encode_ctx, 55);
QCBOREncode_OpenMap(cbor_encode_ctx);
QCBOREncode_AddSZStringToMapN(cbor_encode_ctx, 66, "hi");
QCBOREncode_AddSZStringToMapN(cbor_encode_ctx, 67, "bye");
QCBOREncode_CloseMap(cbor_encode_ctx);
QCBOREncode_OpenArray(cbor_encode_ctx);
QCBOREncode_OpenMap(cbor_encode_ctx);
QCBOREncode_CloseMap(cbor_encode_ctx);
QCBOREncode_CloseArray(cbor_encode_ctx);
QCBOREncode_CloseArray(cbor_encode_ctx);
}
if(test_message_options & T_COSE_TEST_TOO_LARGE_CONTENT_TYPE) {
QCBOREncode_AddInt64ToMapN(cbor_encode_ctx,
COSE_HEADER_PARAM_CONTENT_TYPE,
UINT16_MAX+1);
}
if(test_message_options & T_COSE_TEST_DUP_CONTENT_ID) {
QCBOREncode_AddUInt64ToMapN(cbor_encode_ctx,
COSE_HEADER_PARAM_CONTENT_TYPE,
3);
}
if(test_message_options & T_COSE_TEST_INDEFINITE_MAPS_ARRAYS) {
QCBOREncode_CloseMapIndefiniteLength(cbor_encode_ctx);
} else {
QCBOREncode_CloseMap(cbor_encode_ctx);
}
}
/*
* Buffer for the protected parameters. There used to be a buffer in
* t_cose_sign1_sign_ctx but it was removed when code was improved.
* This needs to be carried between encoding the header and doing
* the signatured, so a buffer is needed. The size is that of the
* largest test protected header and some padding.
*/
static uint8_t s_protected_params[40];
/**
* Replica of t_cose_sign1_encode_parameters() with modifications to
* output various good and bad messages for testing verification.
*/
static enum t_cose_err_t
t_cose_sign1_test_message_encode_parameters(struct t_cose_sign1_sign_ctx *me,
uint32_t test_mess_options,
QCBOREncodeContext *cbor_encode_ctx)
{
enum t_cose_err_t return_value;
struct q_useful_buf_c kid;
int32_t hash_alg_id;
struct q_useful_buf buffer_for_protected_parameters;
/* Check the cose_algorithm_id now by getting the hash alg as an early
* error check even though it is not used until later.
*/
hash_alg_id = hash_alg_id_from_sig_alg_id(me->cose_algorithm_id);
if(hash_alg_id == T_COSE_INVALID_ALGORITHM_ID) {
return T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
}
/* Add the CBOR tag indicating COSE_Sign1 */
if(!(me->option_flags & T_COSE_OPT_OMIT_CBOR_TAG)) {
QCBOREncode_AddTag(cbor_encode_ctx, CBOR_TAG_COSE_SIGN1);
}
/* Get started with the tagged array that holds the four parts of
* a cose single signed message */
if(test_mess_options & T_COSE_TEST_INDEFINITE_MAPS_ARRAYS) {
QCBOREncode_OpenArrayIndefiniteLength(cbor_encode_ctx);
} else {
QCBOREncode_OpenArray(cbor_encode_ctx);
}
/* The protected parameters, which are added as a wrapped bstr */
if( ! (test_mess_options & T_COSE_TEST_NO_PROTECTED_PARAMETERS)) {
buffer_for_protected_parameters = Q_USEFUL_BUF_FROM_BYTE_ARRAY(s_protected_params);
me->protected_parameters = encode_protected_parameters(test_mess_options,
me->cose_algorithm_id,
buffer_for_protected_parameters);
QCBOREncode_AddBytes(cbor_encode_ctx, me->protected_parameters);
}
/* The Unprotected parameters */
/* Get the key id because it goes into the parameters that are about
to be made. */
if(me->option_flags & T_COSE_OPT_SHORT_CIRCUIT_SIG) {
#ifndef T_COSE_DISABLE_SHORT_CIRCUIT_SIGN
kid = get_short_circuit_kid();
#else
return T_COSE_ERR_SHORT_CIRCUIT_SIG_DISABLED;
#endif
} else {
kid = me->kid;
}
if( ! (test_mess_options & T_COSE_TEST_NO_UNPROTECTED_PARAMETERS)) {
add_unprotected_parameters(test_mess_options, cbor_encode_ctx, kid);
}
QCBOREncode_BstrWrap(cbor_encode_ctx);
/* Any failures in CBOR encoding will be caught in finish when the
* CBOR encoding is closed off. No need to track here as the CBOR
* encoder tracks it internally. */
return_value = T_COSE_SUCCESS;
return return_value;
}
/**
* Replica of t_cose_sign1_output_signature() with modifications to
* output various good and bad messages for testing verification.
*/
static enum t_cose_err_t
t_cose_sign1_test_message_output_signature(struct t_cose_sign1_sign_ctx *me,
uint32_t test_mess_options,
QCBOREncodeContext *cbor_encode_ctx)
{
/* approximate stack use on 32-bit machine:
* 32 bytes local use
* 220 to 434 for calls dependin on hash implementation
* 32 to 64 bytes depending on hash alg (SHA256, 384 or 512)
* 64 to 260 depending on EC alg
* 348 to 778 depending on hash and EC alg
* Also add stack use by EC and hash functions
*/
enum t_cose_err_t return_value;
QCBORError cbor_err;
/* pointer and length of the completed tbs hash */
struct q_useful_buf_c tbs_hash;
/* Pointer and length of the completed signature */
struct q_useful_buf_c signature;
/* Buffer for the actual signature */
Q_USEFUL_BUF_MAKE_STACK_UB( buffer_for_signature, T_COSE_MAX_SIG_SIZE);
/* Buffer for the tbs hash. */
Q_USEFUL_BUF_MAKE_STACK_UB( buffer_for_tbs_hash, T_COSE_CRYPTO_MAX_HASH_SIZE);
struct q_useful_buf_c signed_payload;
QCBOREncode_CloseBstrWrap2(cbor_encode_ctx, false, &signed_payload);
/* Check there are no CBOR encoding errors before proceeding with
* hashing and signing. This is not actually necessary as the
* errors will be caught correctly later, but it does make it a
* bit easier for the caller to debug problems.
*/
cbor_err = QCBOREncode_GetErrorState(cbor_encode_ctx);
if(cbor_err == QCBOR_ERR_BUFFER_TOO_SMALL) {
return_value = T_COSE_ERR_TOO_SMALL;
goto Done;
} else if(cbor_err != QCBOR_SUCCESS) {
return_value = T_COSE_ERR_CBOR_FORMATTING;
goto Done;
}
/* Create the hash of the to-be-signed bytes. Inputs to the hash
* are the protected parameters, the payload that is getting signed, the
* cose signature alg from which the hash alg is determined. The
* cose_algorithm_id was checked in t_cose_sign1_init() so it
* doesn't need to be checked here.
*/
return_value = create_tbs_hash(me->cose_algorithm_id,
me->protected_parameters,
NULL_Q_USEFUL_BUF_C,
signed_payload,
buffer_for_tbs_hash,
&tbs_hash);
if(return_value != T_COSE_SUCCESS) {
goto Done;
}
/* Compute the signature using public key crypto. The key selector
* and algorithm ID are passed in to know how and what to sign
* with. The hash of the TBS bytes are what is signed. A buffer in
* which to place the signature is passed in and the signature is
* returned.
*
* Short-circuit signing is invoked if requested. It does no
* public key operation and requires no key. It is just a test
* mode that always works.
*/
if(!(me->option_flags & T_COSE_OPT_SHORT_CIRCUIT_SIG)) {
/* Normal, non-short-circuit signing */
return_value = t_cose_crypto_sign(me->cose_algorithm_id,
me->signing_key,
tbs_hash,
buffer_for_signature,
&signature);
} else {
#ifndef T_COSE_DISABLE_SHORT_CIRCUIT_SIGN
return_value = short_circuit_sign(me->cose_algorithm_id,
tbs_hash,
buffer_for_signature,
&signature);
#endif
}
if(return_value) {
goto Done;
}
/* Add signature to CBOR and close out the array */
QCBOREncode_AddBytes(cbor_encode_ctx, signature);
if(test_mess_options & T_COSE_TEST_INDEFINITE_MAPS_ARRAYS) {
QCBOREncode_CloseArrayIndefiniteLength(cbor_encode_ctx);
} else {
QCBOREncode_CloseArray(cbor_encode_ctx);
}
/* The layer above this must check for and handle CBOR encoding
* errors CBOR encoding errors. Some are detected at the start of
* this function, but they cannot all be deteced there.
*/
Done:
return return_value;
}
/*
* Public function. See t_cose_make_test_messages.h
*/
enum t_cose_err_t
t_cose_test_message_sign1_sign(struct t_cose_sign1_sign_ctx *me,
uint32_t test_message_options,
struct q_useful_buf_c payload,
struct q_useful_buf out_buf,
struct q_useful_buf_c *result)
{
QCBOREncodeContext encode_context;
enum t_cose_err_t return_value;
/* -- Initialize CBOR encoder context with output buffer */
QCBOREncode_Init(&encode_context, out_buf);
/* -- Output the header parameters into the encoder context -- */
return_value = t_cose_sign1_test_message_encode_parameters(me, test_message_options, &encode_context);
if(return_value != T_COSE_SUCCESS) {
goto Done;
}
/* -- Output the payload into the encoder context -- */
/* Payload may or may not actually be CBOR format here. This
* function does the job just fine because it just adds bytes to
* the encoded output without anything extra.
*/
QCBOREncode_AddEncoded(&encode_context, payload);
/* -- Sign and put signature in the encoder context -- */
return_value = t_cose_sign1_test_message_output_signature(me,
test_message_options,
&encode_context);
if(return_value) {
goto Done;
}
/* -- Close off and get the resulting encoded CBOR -- */
if(QCBOREncode_Finish(&encode_context, result)) {
return_value = T_COSE_ERR_CBOR_NOT_WELL_FORMED;
goto Done;
}
Done:
return return_value;
}

153
3rdparty/exported/t_cose/test/t_cose_make_test_messages.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,153 @@
/*
* t_cose_make_test_messages.h
*
* Copyright (c) 2019-2022, Laurence Lundblade. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
* See BSD-3-Clause license in README.md
*/
#ifndef __T_COSE_MAKE_TEST_MESSAGES__
#define __T_COSE_MAKE_TEST_MESSAGES__
#include <stdint.h>
#include <stdbool.h>
#include "qcbor/qcbor.h"
#include "t_cose/t_cose_common.h"
#include "t_cose/t_cose_sign1_sign.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \file t_cose_make_test_messages.h
*
* \brief Create a test \c COSE_Sign1 message for testing the verifier.
*
*/
/**
* Various flags to pass to t_cose_test_message_sign1_sign() to
* make different types of test messages for testing verification
*/
/** Make test message with a bstr label, which is not allowed by
* COSE */
#define T_COSE_TEST_PARAMETER_LABEL 0x80000000U
/** Format of the crit parameter is made invalid */
#define T_COSE_TEST_BAD_CRIT_PARAMETER 0x40000000
/** An extra parameter is added. It has nested structure to be sure
* such are skipped correctly */
#define T_COSE_TEST_EXTRA_PARAMETER 0x20000000
/** The protected parameters bucked is left out of the COSE_Sign1
* message entirely */
#define T_COSE_TEST_NO_PROTECTED_PARAMETERS 0x10000000
/** The unprotected parameters bucked is left out of the COSE_Sign1
* message entirely */
#define T_COSE_TEST_NO_UNPROTECTED_PARAMETERS 0x08000000
/** Simple not-well-formed CBOR is added to the unprotected parameters
* bucket */
#define T_COSE_TEST_NOT_WELL_FORMED_1 0x04000000
/** Not-well-formed CBOR nested in a map is added to the unprotected
* parameters bucket */
#define T_COSE_TEST_NOT_WELL_FORMED_2 0x02000000
/** The crit parameter lists several integer critical labels and the
* labeled parameters exists and they are not understood */
#define T_COSE_TEST_UNKNOWN_CRIT_UINT_PARAMETER 0x01000000
/** The crit parameter lists critical labels, but none of them
* occur */
#define T_COSE_TEST_CRIT_PARAMETER_EXIST 0x00800000
/** Exceed the limit on number of T_COSE_PARAMETER_LIST_MAX on number
* of crit parameters this implementation can handle */
#define T_COSE_TEST_TOO_MANY_CRIT_PARAMETER_EXIST 0x00400000
/** One of the labels in the crit parameter is of the wrong type */
#define T_COSE_TEST_BAD_CRIT_LABEL 0x00200000
/** The crit parameter is in the unprotected bucket */
#define T_COSE_TEST_CRIT_NOT_PROTECTED 0x00100000
/** More than T_COSE_PARAMETER_LIST_MAX unknown parameters occurred */
#define T_COSE_TEST_TOO_MANY_UNKNOWN 0x00080000
/** The crit parameter lists several text string critical labels and
* the labeled parameters exists and they are not understood */
#define T_COSE_TEST_UNKNOWN_CRIT_TSTR_PARAMETER 0x00040000
/** One of each type of parameter the verify handles is added, plus
* some unknown parameters */
#define T_COSE_TEST_ALL_PARAMETERS 0x00020000
/** An invalid CBOR type is in the protected bucket */
#define T_COSE_TEST_BAD_PROTECTED 0x00010000
/** The unprotected header bucket is an array, not a map */
#define T_COSE_TEST_UNPROTECTED_NOT_MAP 0x00008000
/** A kid is added to the protected parameters and is thus a duplicate
* parameter in both protected and unprotected buckets */
#define T_COSE_TEST_KID_IN_PROTECTED 0x00004000
/** The integer CoAP content type is larger than UINT16_MAX, larger
* than it is allowed */
#define T_COSE_TEST_TOO_LARGE_CONTENT_TYPE 0x00002000
/** The protected parameters are not a complete map. Supposed to have
* 1 item, but has zero */
#define T_COSE_TEST_UNCLOSED_PROTECTED 0x00001000
/** The content ID parameter occurs in both protected and unprotected
* bucket */
#define T_COSE_TEST_DUP_CONTENT_ID 0x00000800
/** The bstr wrapped protected parameters is zero length */
#define T_COSE_TEST_EMPTY_PROTECTED_PARAMETERS 0x00000400
/** The list of critical labels parameter is empty. This is not
* allowed by COSE */
#define T_COSE_TEST_EMPTY_CRIT_PARAMETER 0x00000200
/** Exceed the limit on number of T_COSE_PARAMETER_LIST_MAX on number
* of crit parameters this implementation can handle */
#define T_COSE_TEST_TOO_MANY_TSTR_CRIT_LABLELS 0x00000100
/** Encode the COSE maps and arrays with indefinte lengths rather
* than definite. */
#define T_COSE_TEST_INDEFINITE_MAPS_ARRAYS 0x80
/**
* Replica of t_cose_sign1_sign() with modifications to output various
* good and bad messages for testing of t_cose_sign1_verify() .
*
* \c test_message_options is one of \c T_COSE_TEST_XXX
*/
enum t_cose_err_t
t_cose_test_message_sign1_sign(struct t_cose_sign1_sign_ctx *me,
uint32_t test_message_options,
struct q_useful_buf_c payload,
struct q_useful_buf out_buf,
struct q_useful_buf_c *result);
#ifdef __cplusplus
}
#endif
#endif /* __T_COSE_MAKE_TEST_MESSAGES__ */

41
3rdparty/exported/t_cose/test/t_cose_make_test_pub_key.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,41 @@
/*
* t_cose_make_test_pub_key.h
*
* Copyright 2019-2020, Laurence Lundblade
*
* SPDX-License-Identifier: BSD-3-Clause
*
* See BSD-3-Clause license in README.md
*/
#include "t_cose/t_cose_common.h"
#include <stdint.h>
/**
* \file t_cose_make_test_pub_key.h
*
* \brief This defines a simple interface to make keys for tests cases.
*
*/
/**
* \brief make an ECDSA key pair for testing suited to algorim
*
*/
enum t_cose_err_t make_ecdsa_key_pair(int32_t cose_algorithm_id,
struct t_cose_key *key_pair);
void free_ecdsa_key_pair(struct t_cose_key key_pair);
/**
\brief Called by test frame work to see if there were key pair or mem leaks.
\return 0 if no leaks, non-zero if there is a leak.
*/
int check_for_key_pair_leaks(void);

666
3rdparty/exported/t_cose/test/t_cose_sign_verify_test.c поставляемый Normal file
Просмотреть файл

@ -0,0 +1,666 @@
/*
* t_cose_sign_verify_test.c
*
* Copyright 2019-2022, Laurence Lundblade
*
* SPDX-License-Identifier: BSD-3-Clause
*
* See BSD-3-Clause license in README.md
*/
#include "t_cose/t_cose_sign1_sign.h"
#include "t_cose/t_cose_sign1_verify.h"
#include "t_cose/q_useful_buf.h"
#include "t_cose_make_test_pub_key.h"
#include "t_cose_crypto.h" /* Just for t_cose_crypto_sig_size() */
/*
* Public function, see t_cose_sign_verify_test.h
*/
int_fast32_t sign_verify_basic_test_alg(int32_t cose_alg)
{
struct t_cose_sign1_sign_ctx sign_ctx;
int32_t return_value;
enum t_cose_err_t result;
Q_USEFUL_BUF_MAKE_STACK_UB( signed_cose_buffer, 300);
struct q_useful_buf_c signed_cose;
struct t_cose_key key_pair;
struct q_useful_buf_c payload;
struct t_cose_sign1_verify_ctx verify_ctx;
/* -- Get started with context initialization, selecting the alg -- */
t_cose_sign1_sign_init(&sign_ctx, 0, cose_alg);
/* Make an ECDSA key pair that will be used for both signing and
* verification.
*/
result = make_ecdsa_key_pair(cose_alg, &key_pair);
if(result) {
return 1000 + (int32_t)result;
}
t_cose_sign1_set_signing_key(&sign_ctx, key_pair, NULL_Q_USEFUL_BUF_C);
result = t_cose_sign1_sign(&sign_ctx,
Q_USEFUL_BUF_FROM_SZ_LITERAL("payload"),
signed_cose_buffer,
&signed_cose);
if(result) {
return_value = 2000 + (int32_t)result;
goto Done;
}
/* Verification */
t_cose_sign1_verify_init(&verify_ctx, 0);
t_cose_sign1_set_verification_key(&verify_ctx, key_pair);
result = t_cose_sign1_verify(&verify_ctx,
signed_cose, /* COSE to verify */
&payload, /* Payload from signed_cose */
NULL); /* Don't return parameters */
if(result) {
return_value = 5000 + (int32_t)result;
goto Done;
}
/* compare payload output to the one expected */
if(q_useful_buf_compare(payload, Q_USEFUL_BUF_FROM_SZ_LITERAL("payload"))) {
return_value = 6000;
goto Done;
}
return_value = 0;
Done:
/* Many crypto libraries allocate memory, slots, etc for keys */
free_ecdsa_key_pair(key_pair);
return return_value;
}
/*
* Public function, see t_cose_sign_verify_test.h
*/
int_fast32_t sign_verify_basic_test()
{
int_fast32_t return_value;
return_value = sign_verify_basic_test_alg(T_COSE_ALGORITHM_ES256);
if(return_value) {
return 20000 + return_value;
}
#ifndef T_COSE_DISABLE_ES384
return_value = sign_verify_basic_test_alg(T_COSE_ALGORITHM_ES384);
if(return_value) {
return 30000 + return_value;
}
#endif
#ifndef T_COSE_DISABLE_ES512
return_value = sign_verify_basic_test_alg(T_COSE_ALGORITHM_ES512);
if(return_value) {
return 50000 + return_value;
}
#endif
return 0;
}
/*
* Public function, see t_cose_sign_verify_test.h
*/
int_fast32_t sign_verify_sig_fail_test()
{
struct t_cose_sign1_sign_ctx sign_ctx;
QCBOREncodeContext cbor_encode;
int32_t return_value;
enum t_cose_err_t result;
Q_USEFUL_BUF_MAKE_STACK_UB( signed_cose_buffer, 300);
struct q_useful_buf_c signed_cose;
struct t_cose_key key_pair;
struct q_useful_buf_c payload;
QCBORError cbor_error;
struct t_cose_sign1_verify_ctx verify_ctx;
size_t tamper_offset;
/* Make an ECDSA key pair that will be used for both signing and
* verification.
*/
result = make_ecdsa_key_pair(T_COSE_ALGORITHM_ES256, &key_pair);
if(result) {
return 1000 + (int32_t)result;
}
QCBOREncode_Init(&cbor_encode, signed_cose_buffer);
t_cose_sign1_sign_init(&sign_ctx, 0, T_COSE_ALGORITHM_ES256);
t_cose_sign1_set_signing_key(&sign_ctx, key_pair, NULL_Q_USEFUL_BUF_C);
result = t_cose_sign1_encode_parameters(&sign_ctx, &cbor_encode);
if(result) {
return_value = 2000 + (int32_t)result;
goto Done;
}
QCBOREncode_AddSZString(&cbor_encode, "payload");
result = t_cose_sign1_encode_signature(&sign_ctx, &cbor_encode);
if(result) {
return_value = 3000 + (int32_t)result;
goto Done;
}
cbor_error = QCBOREncode_Finish(&cbor_encode, &signed_cose);
if(cbor_error) {
return_value = 4000 + (int32_t)cbor_error;
goto Done;
}
/* tamper with the pay load to see that the signature verification fails */
tamper_offset = q_useful_buf_find_bytes(signed_cose, Q_USEFUL_BUF_FROM_SZ_LITERAL("payload"));
if(tamper_offset == SIZE_MAX) {
return_value = 99;
goto Done;
}
/* Change "payload" to "hayload" */
struct q_useful_buf temp_unconst = q_useful_buf_unconst(signed_cose);
((char *)temp_unconst.ptr)[tamper_offset] = 'h';
t_cose_sign1_verify_init(&verify_ctx, 0);
t_cose_sign1_set_verification_key(&verify_ctx, key_pair);
result = t_cose_sign1_verify(&verify_ctx,
signed_cose, /* COSE to verify */
&payload, /* Payload from signed_cose */
NULL); /* Don't return parameters */
if(result != T_COSE_ERR_SIG_VERIFY) {
return_value = 5000 + (int32_t)result;
}
return_value = 0;
Done:
free_ecdsa_key_pair(key_pair);
return return_value;
}
/*
* Public function, see t_cose_sign_verify_test.h
*/
int_fast32_t sign_verify_make_cwt_test()
{
struct t_cose_sign1_sign_ctx sign_ctx;
QCBOREncodeContext cbor_encode;
int32_t return_value;
enum t_cose_err_t result;
Q_USEFUL_BUF_MAKE_STACK_UB( signed_cose_buffer, 300);
struct q_useful_buf_c signed_cose;
struct t_cose_key key_pair;
struct q_useful_buf_c payload;
QCBORError cbor_error;
struct t_cose_sign1_verify_ctx verify_ctx;
struct q_useful_buf_c expected_rfc8392_first_part;
struct q_useful_buf_c expected_payload;
struct q_useful_buf_c actual_rfc8392_first_part;
/* -- initialize for signing --
* No special options selected
*/
t_cose_sign1_sign_init(&sign_ctx, 0, T_COSE_ALGORITHM_ES256);
/* -- Key and kid --
* The ECDSA key pair made is both for signing and verification.
* The kid comes from RFC 8932
*/
result = make_ecdsa_key_pair(T_COSE_ALGORITHM_ES256, &key_pair);
if(result) {
return 1000 + (int32_t)result;
}
t_cose_sign1_set_signing_key(&sign_ctx,
key_pair,
Q_USEFUL_BUF_FROM_SZ_LITERAL("AsymmetricECDSA256"));
/* -- Encoding context and output of parameters -- */
QCBOREncode_Init(&cbor_encode, signed_cose_buffer);
result = t_cose_sign1_encode_parameters(&sign_ctx, &cbor_encode);
if(result) {
return_value = 2000 + (int32_t)result;
goto Done;
}
/* -- The payload as from RFC 8932 -- */
QCBOREncode_OpenMap(&cbor_encode);
QCBOREncode_AddSZStringToMapN(&cbor_encode, 1, "coap://as.example.com");
QCBOREncode_AddSZStringToMapN(&cbor_encode, 2, "erikw");
QCBOREncode_AddSZStringToMapN(&cbor_encode, 3, "coap://light.example.com");
QCBOREncode_AddInt64ToMapN(&cbor_encode, 4, 1444064944);
QCBOREncode_AddInt64ToMapN(&cbor_encode, 5, 1443944944);
QCBOREncode_AddInt64ToMapN(&cbor_encode, 6, 1443944944);
const uint8_t xx[] = {0x0b, 0x71};
QCBOREncode_AddBytesToMapN(&cbor_encode, 7,
Q_USEFUL_BUF_FROM_BYTE_ARRAY_LITERAL(xx));
QCBOREncode_CloseMap(&cbor_encode);
/* -- Finish up the COSE_Sign1. This is where the signing happens -- */
result = t_cose_sign1_encode_signature(&sign_ctx, &cbor_encode);
if(result) {
return_value = 3000 + (int32_t)result;
goto Done;
}
/* Finally close off the CBOR formatting and get the pointer and length
* of the resulting COSE_Sign1
*/
cbor_error = QCBOREncode_Finish(&cbor_encode, &signed_cose);
if(cbor_error) {
return_value = (int32_t)cbor_error + 4000;
goto Done;
}
/* --- Done making COSE Sign1 object --- */
/* Compare to expected from CWT RFC */
/* The first part, the intro and protected parameters must be the same */
const uint8_t rfc8392_first_part_bytes[] = {
0xd2, 0x84, 0x43, 0xa1, 0x01, 0x26, 0xa1, 0x04, 0x52, 0x41, 0x73, 0x79,
0x6d, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x45, 0x43, 0x44, 0x53, 0x41,
0x32, 0x35, 0x36, 0x58, 0x50, 0xa7, 0x01, 0x75, 0x63, 0x6f, 0x61, 0x70,
0x3a, 0x2f, 0x2f, 0x61, 0x73, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c,
0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x02, 0x65, 0x65, 0x72, 0x69, 0x6b, 0x77,
0x03, 0x78, 0x18, 0x63, 0x6f, 0x61, 0x70, 0x3a, 0x2f, 0x2f, 0x6c, 0x69,
0x67, 0x68, 0x74, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e,
0x63, 0x6f, 0x6d, 0x04, 0x1a, 0x56, 0x12, 0xae, 0xb0, 0x05, 0x1a, 0x56,
0x10, 0xd9, 0xf0, 0x06, 0x1a, 0x56, 0x10, 0xd9, 0xf0, 0x07, 0x42, 0x0b,
0x71};
expected_rfc8392_first_part = Q_USEFUL_BUF_FROM_BYTE_ARRAY_LITERAL(rfc8392_first_part_bytes);
actual_rfc8392_first_part = q_useful_buf_head(signed_cose, sizeof(rfc8392_first_part_bytes));
if(q_useful_buf_compare(actual_rfc8392_first_part, expected_rfc8392_first_part)) {
return_value = -1;
goto Done;
}
/* --- Start verifying the COSE Sign1 object --- */
/* Run the signature verification */
t_cose_sign1_verify_init(&verify_ctx, 0);
t_cose_sign1_set_verification_key(&verify_ctx, key_pair);
result = t_cose_sign1_verify(&verify_ctx,
signed_cose, /* COSE to verify */
&payload, /* Payload from signed_cose */
NULL); /* Don't return parameters */
if(result) {
return_value = 5000 + (int32_t)result;
goto Done;
}
/* Format the expected payload CBOR fragment */
/* Skip the key id, because this has the short-circuit key id */
const size_t kid_encoded_len =
1 +
1 +
1 +
strlen("AsymmetricECDSA256"); // length of short-circuit key id
/* compare payload output to the one expected */
expected_payload = q_useful_buf_tail(expected_rfc8392_first_part, kid_encoded_len + 8);
if(q_useful_buf_compare(payload, expected_payload)) {
return_value = 6000;
}
/* --- Done verifying the COSE Sign1 object --- */
return_value = 0;
Done:
/* Many crypto libraries allocate memory, slots, etc for keys */
free_ecdsa_key_pair(key_pair);
return return_value;
}
/*
* Public function, see t_cose_sign_verify_test.h
*/
static int size_test(int32_t cose_algorithm_id,
struct q_useful_buf_c kid,
struct t_cose_key key_pair)
{
struct t_cose_sign1_sign_ctx sign_ctx;
QCBOREncodeContext cbor_encode;
enum t_cose_err_t return_value;
struct q_useful_buf nil_buf;
size_t calculated_size;
QCBORError cbor_error;
struct q_useful_buf_c actual_signed_cose;
Q_USEFUL_BUF_MAKE_STACK_UB( signed_cose_buffer, 300);
struct q_useful_buf_c payload;
size_t sig_size;
/* ---- Common Set up ---- */
payload = Q_USEFUL_BUF_FROM_SZ_LITERAL("payload");
return_value = t_cose_crypto_sig_size(cose_algorithm_id, key_pair, &sig_size);
/* ---- First calculate the size ----- */
nil_buf = (struct q_useful_buf) {NULL, INT32_MAX};
QCBOREncode_Init(&cbor_encode, nil_buf);
t_cose_sign1_sign_init(&sign_ctx, 0, cose_algorithm_id);
t_cose_sign1_set_signing_key(&sign_ctx, key_pair, kid);
return_value = t_cose_sign1_encode_parameters(&sign_ctx, &cbor_encode);
if(return_value) {
return 2000 + (int32_t)return_value;
}
QCBOREncode_AddEncoded(&cbor_encode, payload);
return_value = t_cose_sign1_encode_signature(&sign_ctx, &cbor_encode);
if(return_value) {
return 3000 + (int32_t)return_value;
}
cbor_error = QCBOREncode_FinishGetSize(&cbor_encode, &calculated_size);
if(cbor_error) {
return 4000 + (int32_t)cbor_error;
}
/* ---- General sanity check ---- */
size_t expected_min = sig_size + payload.len + kid.len;
if(calculated_size < expected_min || calculated_size > expected_min + 30) {
return -1;
}
/* ---- Now make a real COSE_Sign1 and compare the size ---- */
QCBOREncode_Init(&cbor_encode, signed_cose_buffer);
t_cose_sign1_sign_init(&sign_ctx, 0, cose_algorithm_id);
t_cose_sign1_set_signing_key(&sign_ctx, key_pair, kid);
return_value = t_cose_sign1_encode_parameters(&sign_ctx, &cbor_encode);
if(return_value) {
return 2000 + (int32_t)return_value;
}
QCBOREncode_AddEncoded(&cbor_encode, payload);
return_value = t_cose_sign1_encode_signature(&sign_ctx, &cbor_encode);
if(return_value) {
return 3000 + (int32_t)return_value;
}
cbor_error = QCBOREncode_Finish(&cbor_encode, &actual_signed_cose);
if(actual_signed_cose.len != calculated_size) {
return -2;
}
/* ---- Again with one-call API to make COSE_Sign1 ---- */\
t_cose_sign1_sign_init(&sign_ctx, 0, cose_algorithm_id);
t_cose_sign1_set_signing_key(&sign_ctx, key_pair, kid);
return_value = t_cose_sign1_sign(&sign_ctx,
payload,
signed_cose_buffer,
&actual_signed_cose);
if(return_value) {
return 7000 + (int32_t)return_value;
}
if(actual_signed_cose.len != calculated_size) {
return -3;
}
return 0;
}
/*
* Public function, see t_cose_sign_verify_test.h
*/
int_fast32_t sign_verify_get_size_test()
{
enum t_cose_err_t return_value;
struct t_cose_key key_pair;
int32_t result;
return_value = make_ecdsa_key_pair(T_COSE_ALGORITHM_ES256, &key_pair);
if(return_value) {
return 1000 + (int32_t)return_value;
}
result = size_test(T_COSE_ALGORITHM_ES256, NULL_Q_USEFUL_BUF_C, key_pair);
free_ecdsa_key_pair(key_pair);
if(result) {
return 2000 + result;
}
#ifndef T_COSE_DISABLE_ES384
return_value = make_ecdsa_key_pair(T_COSE_ALGORITHM_ES384, &key_pair);
if(return_value) {
return 3000 + (int32_t)return_value;
}
result = size_test(T_COSE_ALGORITHM_ES384, NULL_Q_USEFUL_BUF_C, key_pair);
free_ecdsa_key_pair(key_pair);
if(result) {
return 4000 + result;
}
#endif /* T_COSE_DISABLE_ES384 */
#ifndef T_COSE_DISABLE_ES512
return_value = make_ecdsa_key_pair(T_COSE_ALGORITHM_ES512, &key_pair);
if(return_value) {
return 5000 + (int32_t)return_value;
}
result = size_test(T_COSE_ALGORITHM_ES512, NULL_Q_USEFUL_BUF_C, key_pair);
if(result) {
free_ecdsa_key_pair(key_pair);
return 6000 + result;
}
result = size_test(T_COSE_ALGORITHM_ES512,
Q_USEFUL_BUF_FROM_SZ_LITERAL("greasy kid stuff"),
key_pair);
free_ecdsa_key_pair(key_pair);
if(result) {
return 7000 + result;
}
#endif /* T_COSE_DISABLE_ES512 */
return 0;
}
/* These are complete known-good COSE messages for a verification
* test. The key used to verify them is made by make_ecdsa_key_pair().
* It always makes the same key for both MbedTLS and OpenSSL.
*
* These were made by setting a break point in sign_verify_basic_test()
* and copying the output of the signing.
*/
static const uint8_t signed_cose_made_by_ossl_crypto_256[] = {
0xD2, 0x84, 0x43, 0xA1, 0x01, 0x26, 0xA0, 0x47,
0x70, 0x61, 0x79, 0x6C, 0x6F, 0x61, 0x64, 0x58,
0x40, 0xF2, 0x2B, 0xAE, 0x15, 0xA8, 0xA6, 0x7A,
0x60, 0x6B, 0x0B, 0xEA, 0xCB, 0xB6, 0x21, 0xD0,
0xA0, 0xAC, 0x99, 0xCE, 0x2A, 0xD3, 0xD8, 0x1F,
0xA5, 0x25, 0x77, 0x04, 0x8C, 0x27, 0xF8, 0x7F,
0xF2, 0x25, 0x78, 0xFA, 0xDE, 0xED, 0xB0, 0xFB,
0xC7, 0xB3, 0x31, 0xCF, 0x4F, 0x5C, 0xC8, 0x25,
0xDE, 0xFD, 0x2D, 0xB9, 0xF3, 0x6C, 0xD7, 0xCB,
0x69, 0x53, 0xCB, 0x05, 0xE3, 0x60, 0xAC, 0x98,
0xE6};
#ifndef T_COSE_DISABLE_ES384
static const uint8_t signed_cose_made_by_psa_crypto_384[] = {
0xD2, 0x84, 0x44, 0xA1, 0x01, 0x38, 0x22, 0xA0,
0x47, 0x70, 0x61, 0x79, 0x6C, 0x6F, 0x61, 0x64,
0x58, 0x60, 0x2C, 0x6C, 0x08, 0xF3, 0x36, 0x9E,
0x35, 0x7A, 0x6B, 0xE5, 0xD6, 0x6E, 0xF9, 0x30,
0x06, 0x2B, 0xD8, 0x73, 0xAB, 0x7E, 0x9B, 0x9D,
0x4A, 0x30, 0xDD, 0x62, 0x75, 0xE5, 0xD6, 0x61,
0x39, 0xF7, 0x4D, 0xC3, 0x7C, 0xF0, 0xEB, 0x58,
0x9D, 0x78, 0xCA, 0x70, 0xD3, 0xA2, 0xF9, 0x23,
0x85, 0xE6, 0x45, 0x18, 0x04, 0xBE, 0x9F, 0xA0,
0xE3, 0x97, 0x4A, 0x12, 0x82, 0xF2, 0x87, 0x4F,
0x3B, 0xF6, 0x9D, 0xC3, 0xE2, 0x99, 0xCC, 0x67,
0x69, 0x34, 0xDB, 0x1C, 0xF4, 0xAF, 0x95, 0x83,
0x74, 0x1B, 0x5C, 0xCD, 0xD5, 0x11, 0xC1, 0x07,
0xE2, 0xD9, 0x3B, 0x16, 0x31, 0x5A, 0x55, 0x58,
0x6C, 0xC9};
#endif /* T_COSE_DISABLE_ES384 */
#ifndef T_COSE_DISABLE_ES512
static const uint8_t signed_cose_made_by_openssl_crypto_521[] = {
0xD2, 0x84, 0x44, 0xA1, 0x01, 0x38, 0x23, 0xA0,
0x47, 0x70, 0x61, 0x79, 0x6C, 0x6F, 0x61, 0x64,
0x58, 0x84, 0x01, 0x54, 0x10, 0x66, 0x49, 0x6B,
0x8B, 0xDC, 0xB0, 0xCE, 0x03, 0x73, 0x30, 0x01,
0x92, 0xF1, 0xE3, 0x18, 0x37, 0xF1, 0x91, 0xC1,
0x57, 0xB5, 0x13, 0xB8, 0x30, 0x10, 0xA6, 0xA6,
0x29, 0xDC, 0x74, 0xA0, 0x5E, 0x39, 0xC8, 0x2F,
0x2B, 0x5D, 0x1C, 0xDB, 0x90, 0x47, 0x50, 0xA0,
0x97, 0x47, 0x0E, 0x99, 0x66, 0x6F, 0xC4, 0xA5,
0xBB, 0xD7, 0xF7, 0x99, 0xD3, 0x87, 0x7A, 0x1B,
0x03, 0xCA, 0x6A, 0xDB, 0x01, 0x04, 0xB5, 0x9D,
0xB6, 0x18, 0xE9, 0x2A, 0xD2, 0x0A, 0x32, 0x05,
0x88, 0xDA, 0x7D, 0xB8, 0xAD, 0x7A, 0xCE, 0x5F,
0x49, 0x1F, 0xBD, 0xF3, 0x98, 0xDE, 0x44, 0x05,
0x38, 0xD0, 0x2C, 0x12, 0x83, 0x09, 0x7A, 0xF8,
0xE8, 0x5F, 0xA7, 0x33, 0xA3, 0xE3, 0xE9, 0x35,
0x11, 0x22, 0x48, 0x09, 0xA2, 0x95, 0x6C, 0x9B,
0x97, 0xA9, 0xE9, 0xBF, 0xA8, 0x63, 0x73, 0x88,
0x24, 0xB0, 0x84, 0x46, 0xA8, 0x90};
#endif /* T_COSE_DISABLE_ES512 */
int_fast32_t known_good_test(void)
{
int32_t return_value;
enum t_cose_err_t result;
struct t_cose_key key_pair;
struct q_useful_buf_c payload;
struct t_cose_sign1_verify_ctx verify_ctx;
struct q_useful_buf_c valid_message;
/* Improvement: rewrite this to fetch the algorithm header and
* look up the key from it, so the generalizes to all sorts of
* good known inputs for all sorts of algorithms. (Could do key id
* too...) But for now this accomplishes what is needed.
*/
result = make_ecdsa_key_pair(T_COSE_ALGORITHM_ES256, &key_pair);
if(result) {
return_value = 1000 + (int32_t)result;
goto Done;
}
t_cose_sign1_verify_init(&verify_ctx, 0);
t_cose_sign1_set_verification_key(&verify_ctx, key_pair);
valid_message = Q_USEFUL_BUF_FROM_BYTE_ARRAY_LITERAL(signed_cose_made_by_ossl_crypto_256);
result = t_cose_sign1_verify(&verify_ctx,
valid_message, /* COSE to verify */
&payload, /* Payload from signed_cose */
NULL); /* Don't return parameters */
if(result) {
return_value = 5000 + (int32_t)result;
goto Done;
}
free_ecdsa_key_pair(key_pair);
#ifndef T_COSE_DISABLE_ES384
result = make_ecdsa_key_pair(T_COSE_ALGORITHM_ES384, &key_pair);
if(result) {
return_value = 1100 + (int32_t)result;
goto Done;
}
t_cose_sign1_verify_init(&verify_ctx, 0);
t_cose_sign1_set_verification_key(&verify_ctx, key_pair);
valid_message = Q_USEFUL_BUF_FROM_BYTE_ARRAY_LITERAL(signed_cose_made_by_psa_crypto_384);
result = t_cose_sign1_verify(&verify_ctx,
valid_message, /* COSE to verify */
&payload, /* Payload from signed_cose */
NULL); /* Don't return parameters */
if(result) {
return_value = 5100 + (int32_t)result;
goto Done;
}
free_ecdsa_key_pair(key_pair);
#endif /* T_COSE_DISABLE_ES384 */
#ifndef T_COSE_DISABLE_ES512
result = make_ecdsa_key_pair(T_COSE_ALGORITHM_ES512, &key_pair);
if(result) {
return_value = 1200 + (int32_t)result;
goto Done;
}
t_cose_sign1_verify_init(&verify_ctx, 0);
t_cose_sign1_set_verification_key(&verify_ctx, key_pair);
valid_message = Q_USEFUL_BUF_FROM_BYTE_ARRAY_LITERAL(signed_cose_made_by_openssl_crypto_521);
result = t_cose_sign1_verify(&verify_ctx,
valid_message, /* COSE to verify */
&payload, /* Payload from signed_cose */
NULL); /* Don't return parameters */
if(result) {
return_value = 5200 + (int32_t)result;
goto Done;
}
free_ecdsa_key_pair(key_pair);
#endif /* T_COSE_DISABLE_ES512 */
/* Can't make signed messages and compare them to a known good
* value because ECDSA signature have a random component. They are
* never the same. There are other tests here that evaluate the
* structure of the signed messages and there tests that verify
* messages made by the signing function. */
return_value = 0;
Done:
return return_value;
}

55
3rdparty/exported/t_cose/test/t_cose_sign_verify_test.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,55 @@
/*
* t_cose_sign_verify_test.h
*
* Copyright 2019, 2022, Laurence Lundblade
*
* SPDX-License-Identifier: BSD-3-Clause
*
* See BSD-3-Clause license in README.md
*/
#ifndef t_cose_sign_verify_test_h
#define t_cose_sign_verify_test_h
#include <stdint.h>
/**
* \file t_cose_sign_verify_test.h
*
* \brief Tests that need public key crypto to be implemented
*/
/**
* \brief Self test using integrated crypto.
*
* \return non-zero on failure.
*/
int_fast32_t sign_verify_basic_test(void);
/*
* Sign some data, perturb the data and see that sig validation fails
*/
int_fast32_t sign_verify_sig_fail_test(void);
/*
* Make a CWT and compare it to the one in the CWT RFC
*/
int_fast32_t sign_verify_make_cwt_test(void);
/*
* Test the ability to calculate size of a COSE_Sign1
*/
int_fast32_t sign_verify_get_size_test(void);
/*
* Test against known good messages.
*/
int_fast32_t known_good_test(void);
#endif /* t_cose_sign_verify_test_h */

1658
3rdparty/exported/t_cose/test/t_cose_test.c поставляемый Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

158
3rdparty/exported/t_cose/test/t_cose_test.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,158 @@
/*
* t_cose_test.h
*
* Copyright 2019-2022, Laurence Lundblade
*
* SPDX-License-Identifier: BSD-3-Clause
*
* See BSD-3-Clause license in README.md
*/
#ifndef t_cose_test_h
#define t_cose_test_h
#include <stdint.h>
/**
* \file t_cose_test.h
*
* \brief Entry points for the basic t_cose_tests.
*
* These tests can be performed without any crypto library such as OpenSSL
* integrated with t_cose.
*/
/**
* \brief Minimal message creation test using a short-circuit signature.
*
* \return non-zero on failure.
*
* This test makes a simple COSE_Sign1 and verify it. It uses
* short-circuit signatures so no keys or even integration with public
* key crypto is necessary.
*/
int_fast32_t short_circuit_self_test(void);
/**
* \brief COSE detached content test using a short-circuit signature.
*
* \return non-zero on failure.
*
* This test makes a detached content COSE_Sign1 and verify it. It uses
* short-circuit signatures so no keys or even integration with public
* key crypto is necessary.
*/
int_fast32_t short_circuit_self_detached_content_test(void);
/**
* \brief Test where payload bytes are corrupted and sig fails.
*
* \return non-zero on failure.
*
* This test makes a simple COSE_Sign1 modifies the payload and sees that
* verification fails. It uses short-circuit signatures so no keys or
* even integration with public key crypto is necessary.
*/
int_fast32_t short_circuit_verify_fail_test(void);
/**
* \brief Tests error condidtions for creating COSE_Sign1.
*
* \return non-zero on failure.
*
* It uses short-circuit signatures so no keys or even integration
* with public key crypto is necessary.
*/
int_fast32_t short_circuit_signing_error_conditions_test(void);
/* Make a CWT and see that it compares to the sample in the CWT RFC
*/
int_fast32_t short_circuit_make_cwt_test(void);
/*
* Test the decode only mode, the mode where the
* headers are returned, but the signature is not
* verified.
*/
int_fast32_t short_circuit_decode_only_test(void);
/*
- protected header parameters not well formed CBOR
- unprotected header parameters not well formed CBOR
- unknown algorithm ID
- No algorithm ID parameter
*/
int_fast32_t bad_parameters_test(void);
/* Test that makes a CWT (CBOR Web Token)
*/
int_fast32_t cose_example_test(void);
/*
Various tests involving the crit parameter.
*/
int_fast32_t crit_parameters_test(void);
/*
Check that all types of headers are correctly returned.
*/
int_fast32_t all_header_parameters_test(void);
/*
* Check that setting the content type works
*/
int_fast32_t content_type_test(void);
/*
* Check that setting the content type works
*/
int_fast32_t sign1_structure_decode_test(void);
#ifdef T_COSE_ENABLE_HASH_FAIL_TEST
/*
* This forces / simulates failures in the hash algorithm implementation
* to test t_cose's handling of those condidtions. This test is off
* by default because it needs a hacked version of a hash algorithm.
* It is very hard to get hash algorithms to fail, so this hacked
* version is necessary. This test will not run correctly with
* OpenSSL or Mbed TLS hashes because they aren't (and shouldn't be) hacked.
* It works only with the b_con hash bundled and not intended for
* commercial use (though it is a perfectly fine implementation).
*/
int_fast32_t short_circuit_hash_fail_test(void);
#endif /* T_COSE_ENABLE_HASH_FAIL_TEST*/
/*
* Test tagging of COSE message
*/
int_fast32_t tags_test(void);
int32_t get_size_test(void);
/*
* Test the decoding of COSE messages that use indefinite length
* maps and arrays instead of definite length.
*/
int32_t indef_array_and_map_test(void);
#endif /* t_cose_test_h */

Просмотреть файл

@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Added
- Experimental `ccf::MemberCOSESign1AuthnPolicy` (#3875)
- Add secp256k1 support to `ccf.crypto.generateEcdsaKeyPair()` and `ccf.crypto.verifySignature()` (#4347).
### Deprecated

Просмотреть файл

@ -110,8 +110,8 @@ if("sgx" IN_LIST COMPILE_TARGETS)
)
target_link_libraries(
ccf.enclave PUBLIC quickjs.enclave ccfcrypto.enclave http_parser.enclave
sss.enclave ccf_endpoints.enclave ccf_kv.enclave
ccf.enclave PUBLIC quickjs.enclave http_parser.enclave sss.enclave
ccf_endpoints.enclave ccfcrypto.enclave ccf_kv.enclave
)
target_link_libraries(ccf.enclave PUBLIC nghttp2.enclave)
@ -154,11 +154,11 @@ if("virtual" IN_LIST COMPILE_TARGETS)
ccf.virtual
PUBLIC ${LINK_LIBCXX}
-lgcc
ccfcrypto.host
http_parser.host
quickjs.host
sss.host
ccf_endpoints.host
ccfcrypto.host
ccf_kv.host
openenclave::oehost
${CMAKE_THREAD_LIBS_INIT}
@ -351,7 +351,7 @@ if(BUILD_TESTS)
add_unit_test(js_test ${CMAKE_CURRENT_SOURCE_DIR}/src/js/test/js.cpp)
target_link_libraries(
js_test PRIVATE quickjs.host ccf_kv.host ccf_endpoints.host
http_parser.host
ccfcrypto.host http_parser.host
)
add_unit_test(
@ -429,8 +429,14 @@ if(BUILD_TESTS)
${CCF_DIR}/src/node/quote.cpp
)
target_link_libraries(
frontend_test PRIVATE ${CMAKE_THREAD_LIBS_INIT} http_parser.host sss.host
ccf_endpoints.host ccf_kv.host quickjs.host
frontend_test
PRIVATE ${CMAKE_THREAD_LIBS_INIT}
http_parser.host
sss.host
ccf_endpoints.host
ccfcrypto.host
ccf_kv.host
quickjs.host
)
add_unit_test(
@ -444,8 +450,13 @@ if(BUILD_TESTS)
)
target_link_libraries(
proposal_id_test
PRIVATE ${CMAKE_THREAD_LIBS_INIT} http_parser.host sss.host
ccf_endpoints.host quickjs.host ccf_kv.host
PRIVATE ${CMAKE_THREAD_LIBS_INIT}
http_parser.host
sss.host
ccf_endpoints.host
ccfcrypto.host
quickjs.host
ccf_kv.host
)
add_unit_test(
@ -455,8 +466,13 @@ if(BUILD_TESTS)
)
target_link_libraries(
node_frontend_test
PRIVATE ${CMAKE_THREAD_LIBS_INIT} http_parser.host sss.host
ccf_endpoints.host ccf_kv.host quickjs.host
PRIVATE ${CMAKE_THREAD_LIBS_INIT}
http_parser.host
sss.host
ccf_endpoints.host
ccfcrypto.host
ccf_kv.host
quickjs.host
)
add_unit_test(

Просмотреть файл

@ -144,6 +144,24 @@
"commitHash": "ab840345966d0fa8e7100d771c92a73bfbadd25c"
}
}
},
{
"component": {
"type": "git",
"git": {
"repositoryUrl": "https://github.com/laurencelundblade/QCBOR",
"commitHash": "07653df2bbdb2d090d98d0df514fa019ac23dff3"
}
}
},
{
"component": {
"type": "git",
"git": {
"repositoryUrl": "https://github.com/laurencelundblade/t_cose",
"commitHash": "d5ff4e282d8af34e5756627cf877ab399e7e51af"
}
}
}
],
"Version": 1

Просмотреть файл

@ -175,6 +175,7 @@ set(CCF_ENDPOINTS_SOURCES
${CCF_DIR}/src/endpoints/base_endpoint_registry.cpp
${CCF_DIR}/src/endpoints/common_endpoint_registry.cpp
${CCF_DIR}/src/endpoints/json_handler.cpp
${CCF_DIR}/src/endpoints/authentication/cose_auth.cpp
${CCF_DIR}/src/endpoints/authentication/cert_auth.cpp
${CCF_DIR}/src/endpoints/authentication/empty_auth.cpp
${CCF_DIR}/src/endpoints/authentication/jwt_auth.cpp
@ -194,6 +195,8 @@ include(${CCF_DIR}/cmake/crypto.cmake)
include(${CCF_DIR}/cmake/quickjs.cmake)
include(${CCF_DIR}/cmake/sss.cmake)
include(${CCF_DIR}/cmake/nghttp2.cmake)
include(${CCF_DIR}/cmake/qcbor.cmake)
include(${CCF_DIR}/cmake/t_cose.cmake)
set(MESSAGE_QUIET ON)
include(${CCF_DIR}/cmake/protobuf.cmake)
unset(MESSAGE_QUIET)
@ -343,6 +346,8 @@ install(
# CCF endpoints libs
if("sgx" IN_LIST COMPILE_TARGETS)
add_enclave_library(ccf_endpoints.enclave "${CCF_ENDPOINTS_SOURCES}")
target_link_libraries(ccf_endpoints.enclave PUBLIC qcbor.enclave)
target_link_libraries(ccf_endpoints.enclave PUBLIC t_cose.enclave)
add_warning_checks(ccf_endpoints.enclave)
install(
TARGETS ccf_endpoints.enclave
@ -350,7 +355,10 @@ if("sgx" IN_LIST COMPILE_TARGETS)
DESTINATION lib
)
endif()
add_host_library(ccf_endpoints.host "${CCF_ENDPOINTS_SOURCES}")
target_link_libraries(ccf_endpoints.host PUBLIC qcbor.host)
target_link_libraries(ccf_endpoints.host PUBLIC t_cose.host)
add_san(ccf_endpoints.host)
add_warning_checks(ccf_endpoints.host)
install(

Просмотреть файл

@ -19,10 +19,13 @@ set(CCFCRYPTO_SRC
${CCF_DIR}/src/crypto/openssl/rsa_public_key.cpp
${CCF_DIR}/src/crypto/openssl/rsa_key_pair.cpp
${CCF_DIR}/src/crypto/openssl/verifier.cpp
${CCF_DIR}/src/crypto/openssl/cose_verifier.cpp
)
if("sgx" IN_LIST COMPILE_TARGETS)
add_enclave_library(ccfcrypto.enclave ${CCFCRYPTO_SRC})
target_link_libraries(ccfcrypto.enclave PUBLIC qcbor.enclave)
target_link_libraries(ccfcrypto.enclave PUBLIC t_cose.enclave)
install(
TARGETS ccfcrypto.enclave
@ -35,6 +38,8 @@ add_library(ccfcrypto.host STATIC ${CCFCRYPTO_SRC})
add_san(ccfcrypto.host)
target_compile_options(ccfcrypto.host PUBLIC ${COMPILE_LIBCXX})
target_link_options(ccfcrypto.host PUBLIC ${LINK_LIBCXX})
target_link_libraries(ccfcrypto.host PUBLIC qcbor.host)
target_link_libraries(ccfcrypto.host PUBLIC t_cose.host)
target_link_libraries(ccfcrypto.host PUBLIC crypto)
target_link_libraries(ccfcrypto.host PUBLIC ssl)
set_property(TARGET ccfcrypto.host PROPERTY POSITION_INDEPENDENT_CODE ON)

39
cmake/qcbor.cmake Normal file
Просмотреть файл

@ -0,0 +1,39 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the Apache 2.0 License.
# Build QCBOR
set(QCBOR_DIR "${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/exported/QCBOR")
set(QCBOR_SRC "${QCBOR_DIR}/src")
set(QCBOR_SRCS
"${QCBOR_SRC}/ieee754.c" "${QCBOR_SRC}/qcbor_decode.c"
"${QCBOR_SRC}/qcbor_encode.c" "${QCBOR_SRC}/qcbor_err_to_str.c"
"${QCBOR_SRC}/UsefulBuf.c"
)
if("sgx" IN_LIST COMPILE_TARGETS)
add_enclave_library_c(qcbor.enclave ${QCBOR_SRCS})
target_include_directories(
qcbor.enclave PUBLIC $<BUILD_INTERFACE:${CCF_3RD_PARTY_EXPORTED_DIR}/QCBOR>
$<INSTALL_INTERFACE:include/3rdparty/QCBOR>
)
install(
TARGETS qcbor.enclave
EXPORT ccf
DESTINATION lib
)
endif()
add_library(qcbor.host STATIC ${QCBOR_SRCS})
target_include_directories(
qcbor.host PUBLIC $<BUILD_INTERFACE:${CCF_3RD_PARTY_EXPORTED_DIR}/QCBOR>
$<INSTALL_INTERFACE:include/3rdparty/QCBOR>
)
set_property(TARGET qcbor.host PROPERTY POSITION_INDEPENDENT_CODE ON)
add_san(qcbor.host)
install(
TARGETS qcbor.host
EXPORT ccf
DESTINATION lib
)

59
cmake/t_cose.cmake Normal file
Просмотреть файл

@ -0,0 +1,59 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the Apache 2.0 License.
# Build t_cose
set(T_COSE_DIR "${CCF_3RD_PARTY_EXPORTED_DIR}/t_cose")
set(T_COSE_SRC "${T_COSE_DIR}/src")
set(T_COSE_INC "${T_COSE_DIR}/inc")
set(T_COSE_DEFS -DT_COSE_USE_OPENSSL_CRYPTO=1)
# https://github.com/laurencelundblade/t_cose/issues/50
# set(T_COSE_OPTS_INTERFACE -Wno-c99-extensions)
set(T_COSE_SRCS
"${T_COSE_SRC}/t_cose_parameters.c" "${T_COSE_SRC}/t_cose_sign1_verify.c"
"${T_COSE_SRC}/t_cose_util.c"
"${T_COSE_DIR}/crypto_adapters/t_cose_openssl_crypto.c"
)
if("sgx" IN_LIST COMPILE_TARGETS)
add_enclave_library_c(t_cose.enclave ${T_COSE_SRCS})
target_compile_definitions(t_cose.enclave PRIVATE ${T_COSE_DEFS})
target_compile_options(t_cose.enclave INTERFACE ${T_COSE_OPTS_INTERFACE})
target_include_directories(t_cose.enclave PRIVATE "${T_COSE_SRC}")
target_include_directories(
t_cose.enclave
PUBLIC $<BUILD_INTERFACE:${CCF_3RD_PARTY_EXPORTED_DIR}/t_cose>
$<INSTALL_INTERFACE:include/3rdparty/t_cose>
)
target_link_libraries(t_cose.enclave PUBLIC qcbor.enclave)
# This is needed to get the OpenSSL includes from Open Enclave
target_link_libraries(t_cose.enclave PRIVATE openenclave::oecryptoopenssl)
install(
TARGETS t_cose.enclave
EXPORT ccf
DESTINATION lib
)
endif()
find_package(OpenSSL REQUIRED)
add_library(t_cose.host STATIC ${T_COSE_SRCS})
target_compile_definitions(t_cose.host PRIVATE ${T_COSE_DEFS})
target_compile_options(t_cose.host INTERFACE ${T_COSE_OPTS_INTERFACE})
target_include_directories(t_cose.host PRIVATE "${T_COSE_SRC}")
target_include_directories(
t_cose.host PUBLIC $<BUILD_INTERFACE:${CCF_3RD_PARTY_EXPORTED_DIR}/t_cose>
$<INSTALL_INTERFACE:include/3rdparty/t_cose>
)
target_link_libraries(t_cose.host PUBLIC qcbor.host OpenSSL::Crypto)
set_property(TARGET t_cose.host PROPERTY POSITION_INDEPENDENT_CODE ON)
add_san(t_cose.host)
install(
TARGETS t_cose.host
EXPORT ccf
DESTINATION lib
)

Просмотреть файл

@ -316,6 +316,11 @@
"scheme": "bearer",
"type": "http"
},
"member_cose_sign1": {
"description": "Request payload must be a COSE Sign1 document, with expected protected headers.Signer must be a member identity registered with this service.",
"scheme": "cose_sign1",
"type": "http"
},
"member_signature": {
"description": "Request must be signed according to the HTTP Signature scheme. The signer must be a member identity registered with this service.",
"scheme": "signature",
@ -345,7 +350,7 @@
"info": {
"description": "This CCF sample app implements a simple logging application, securely recording messages at client-specified IDs. It demonstrates most of the features available to CCF apps.",
"title": "CCF Sample Logging App",
"version": "1.12.2"
"version": "1.14.0"
},
"openapi": "3.0.0",
"paths": {
@ -491,6 +496,33 @@
}
}
},
"/app/log/cose_signed_content": {
"post": {
"responses": {
"200": {
"content": {
"text/plain": {
"schema": {
"$ref": "#/components/schemas/string"
}
}
},
"description": "Default response description"
},
"default": {
"$ref": "#/components/responses/default"
}
},
"security": [
{
"member_cose_sign1": []
}
],
"x-ccf-forwarding": {
"$ref": "#/components/x-ccf-forwarding/always"
}
}
},
"/app/log/private": {
"delete": {
"parameters": [

Просмотреть файл

@ -3,6 +3,7 @@
#pragma once
#include "ccf/endpoints/authentication/cert_auth.h"
#include "ccf/endpoints/authentication/cose_auth.h"
#include "ccf/endpoints/authentication/empty_auth.h"
#include "ccf/endpoints/authentication/jwt_auth.h"
#include "ccf/endpoints/authentication/sig_auth.h"
@ -48,6 +49,12 @@ namespace ccf
static std::shared_ptr<JwtAuthnPolicy> jwt_auth_policy =
std::make_shared<JwtAuthnPolicy>();
/** Authenticate using COSE Sign1 payloads, and
* @c public:ccf.gov.members.certs table */
static std::shared_ptr<MemberCOSESign1AuthnPolicy>
member_cose_sign1_auth_policy =
std::make_shared<MemberCOSESign1AuthnPolicy>();
/** A clear name for the empty auth policy, to reduce errors where it is
* accidentally defaulted or unspecified.
*/

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше