├── test
├── cbmc
│ ├── proofs
│ │ ├── lib
│ │ │ ├── __init__.py
│ │ │ ├── print_tool_versions.py
│ │ │ └── summarize.py
│ │ ├── SigV4_AwsIotDateToIso8601
│ │ │ ├── cbmc-proof.txt
│ │ │ ├── cbmc-viewer.json
│ │ │ ├── README.md
│ │ │ ├── Makefile
│ │ │ └── SigV4_AwsIotDateToIso8601_harness.c
│ │ ├── SigV4_GenerateHTTPAuthorization
│ │ │ ├── cbmc-proof.txt
│ │ │ ├── cbmc-viewer.json
│ │ │ ├── README.md
│ │ │ ├── Makefile
│ │ │ └── SigV4_GenerateHTTPAuthorization_harness.c
│ │ ├── copyHeaderStringToCanonicalBuffer
│ │ │ ├── cbmc-proof.txt
│ │ │ ├── cbmc-viewer.json
│ │ │ ├── README.md
│ │ │ ├── Makefile
│ │ │ └── copyHeaderStringToCanonicalBuffer_harness.c
│ │ ├── Makefile-project-testing
│ │ ├── Makefile-template-defines
│ │ ├── Makefile-json.common
│ │ ├── Makefile-project-targets
│ │ ├── README.md
│ │ ├── Makefile-project-defines
│ │ └── run-cbmc-proofs.py
│ ├── sources
│ │ └── README.md
│ ├── include
│ │ ├── README.md
│ │ ├── sigv4_annex.h
│ │ ├── hash_stubs.h
│ │ ├── sigv4_stubs.h
│ │ └── sigv4_config.h
│ ├── stubs
│ │ ├── README.md
│ │ ├── hash_stubs.c
│ │ ├── memmove.c
│ │ ├── memcpy.c
│ │ └── sigv4_stubs.c
│ └── .gitignore
├── unit-test
│ ├── CMakeLists.txt
│ ├── cmock_build.cmake
│ └── sigv4_config.h
├── include
│ └── sigv4_config.h
└── CMakeLists.txt
├── .github
├── links_allowlist.txt
├── workflows
│ ├── doxygen.yml
│ ├── ci.yml
│ └── release.yml
├── memory_statistics_config.json
├── pull_request_template.md
├── .cSpellWords.txt
├── CODEOWNERS
└── CONTRIBUTING.md
├── docs
├── plantuml
│ ├── images
│ │ └── sigv4_design.png
│ └── sigv4_design.pu
└── doxygen
│ ├── include
│ └── size_table.md
│ ├── porting.dox
│ ├── style.css
│ ├── pages.dox
│ └── layout.xml
├── .gitmodules
├── .gitignore
├── SECURITY.md
├── manifest.yml
├── sigv4FilePaths.cmake
├── cspell.config.yaml
├── tools
├── cmock
│ ├── project.yml
│ ├── coverage.cmake
│ └── create_test.cmake
└── coverity
│ ├── misra.config
│ └── README.md
├── LICENSE
├── MISRA.md
├── CMakeLists.txt
├── CHANGELOG.md
├── source
├── include
│ ├── sigv4_quicksort.h
│ ├── sigv4_config_defaults.h
│ └── sigv4_internal.h
└── sigv4_quicksort.c
└── README.md
/test/cbmc/proofs/lib/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.github/links_allowlist.txt:
--------------------------------------------------------------------------------
1 | https://www.somewebsite.com/path/to/item.txt?optionalquery=stuff
2 |
--------------------------------------------------------------------------------
/test/cbmc/proofs/SigV4_AwsIotDateToIso8601/cbmc-proof.txt:
--------------------------------------------------------------------------------
1 | # This file marks this directory as containing a CBMC proof.
2 |
--------------------------------------------------------------------------------
/test/cbmc/proofs/SigV4_GenerateHTTPAuthorization/cbmc-proof.txt:
--------------------------------------------------------------------------------
1 | # This file marks this directory as containing a CBMC proof.
2 |
--------------------------------------------------------------------------------
/test/cbmc/proofs/copyHeaderStringToCanonicalBuffer/cbmc-proof.txt:
--------------------------------------------------------------------------------
1 | # This file marks this directory as containing a CBMC proof.
2 |
--------------------------------------------------------------------------------
/docs/plantuml/images/sigv4_design.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws/SigV4-for-AWS-IoT-embedded-sdk/HEAD/docs/plantuml/images/sigv4_design.png
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "test/unit-test/CMock"]
2 | path = test/unit-test/CMock
3 | url = https://github.com/ThrowTheSwitch/CMock.git
4 | update = none
5 |
--------------------------------------------------------------------------------
/test/cbmc/proofs/SigV4_AwsIotDateToIso8601/cbmc-viewer.json:
--------------------------------------------------------------------------------
1 | { "expected-missing-functions":
2 | [
3 |
4 | ],
5 | "proof-name": "SigV4_AwsIotDateToIso8601",
6 | "proof-root": "test/cbmc/proofs"
7 | }
8 |
--------------------------------------------------------------------------------
/test/cbmc/proofs/SigV4_GenerateHTTPAuthorization/cbmc-viewer.json:
--------------------------------------------------------------------------------
1 | { "expected-missing-functions":
2 | [
3 |
4 | ],
5 | "proof-name": "SigV4_GenerateHTTPAuthorization",
6 | "proof-root": "test/cbmc/proofs"
7 | }
8 |
--------------------------------------------------------------------------------
/test/cbmc/proofs/copyHeaderStringToCanonicalBuffer/cbmc-viewer.json:
--------------------------------------------------------------------------------
1 | { "expected-missing-functions":
2 | [
3 |
4 | ],
5 | "proof-name": "copyHeaderStringToCanonicalBuffer",
6 | "proof-root": "test/cbmc/proofs"
7 | }
8 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Ignore documentation output.
2 | **/docs/**/output/*
3 |
4 | # Ignore CMake build directory.
5 | build/
6 |
7 | # Ignore build artifacts.
8 | *.o
9 |
10 | # Ignore code coverage artifacts.
11 | *.gcda
12 | *.gcno
13 | *.gcov
14 |
--------------------------------------------------------------------------------
/test/cbmc/sources/README.md:
--------------------------------------------------------------------------------
1 | CBMC proof source code
2 | ======================
3 |
4 | This directory contains source code written for CBMC proofs. It is
5 | common to write some code to model aspects of the system under test,
6 | and this code goes here.
7 |
--------------------------------------------------------------------------------
/test/cbmc/include/README.md:
--------------------------------------------------------------------------------
1 | CBMC proof include files
2 | ========================
3 |
4 | This directory contains include files written for CBMC proof. It is
5 | common to write some code to model aspects of the system under test,
6 | and the header files for this code go here.
7 |
--------------------------------------------------------------------------------
/test/cbmc/stubs/README.md:
--------------------------------------------------------------------------------
1 | CBMC proof stubs
2 | ======================
3 |
4 | This directory contains the stubs written for CBMC proofs. It is
5 | common to stub out functionality like network send and receive methods
6 | when writing a CBMC proof, and the code for these stubs goes here.
7 |
--------------------------------------------------------------------------------
/.github/workflows/doxygen.yml:
--------------------------------------------------------------------------------
1 | name: Doxygen Generation
2 | on:
3 | push:
4 | branches: [main]
5 | workflow_dispatch:
6 | jobs:
7 | doxygen-generation:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - name: Doxygen generation
11 | uses: FreeRTOS/CI-CD-Github-Actions/doxygen-generation@main
12 |
--------------------------------------------------------------------------------
/.github/memory_statistics_config.json:
--------------------------------------------------------------------------------
1 | {
2 | "lib_name": "AWS SigV4 library",
3 | "src": [
4 | "source/sigv4.c",
5 | "source/sigv4_quicksort.c"
6 | ],
7 | "include": [
8 | "source/include"
9 | ],
10 | "compiler_flags": [
11 | "SIGV4_DO_NOT_USE_CUSTOM_CONFIG"
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | ## Reporting a Vulnerability
2 |
3 | If you discover a potential security issue in this project, we ask that you notify AWS/Amazon Security
4 | via our [vulnerability reporting page](https://aws.amazon.com/security/vulnerability-reporting/) or directly via email to aws-security@amazon.com.
5 | Please do **not** create a public github issue.
--------------------------------------------------------------------------------
/test/cbmc/proofs/copyHeaderStringToCanonicalBuffer/README.md:
--------------------------------------------------------------------------------
1 | copyHeaderStringToCanonicalBuffer proof
2 | ==============
3 |
4 | This directory contains a memory safety proof for copyHeaderStringToCanonicalBuffer.
5 |
6 | To run the proof.
7 | -------------
8 |
9 | * Add `cbmc`, `goto-cc`, `goto-instrument`, `goto-analyzer`, and `cbmc-viewer`
10 | to your path.
11 | * Run `make`.
12 | * Open html/index.html in a web browser.
--------------------------------------------------------------------------------
/manifest.yml:
--------------------------------------------------------------------------------
1 | name : "SigV4-for-AWS-IoT-embedded-sdk"
2 | version: "v1.3.0"
3 | description: |
4 | "Library used in client authorization over HTTP with AWS IoT, on embedded devices.\n"
5 | license: "MIT"
6 |
7 | dependencies:
8 | - name: "CMock"
9 | version: v2.5.3
10 | license: "MIT"
11 | repository:
12 | type: "git"
13 | url: "https://github.com/ThrowTheSwitch/CMock.git"
14 | path: test/unit-test/CMock
15 |
--------------------------------------------------------------------------------
/test/cbmc/.gitignore:
--------------------------------------------------------------------------------
1 | # Emitted when running CBMC proofs
2 | proofs/**/logs
3 | proofs/**/gotos
4 | proofs/**/report
5 | proofs/**/html
6 | proofs/output
7 |
8 | # Emitted by CBMC Viewer
9 | TAGS-*
10 |
11 | # Emitted by Arpa
12 | arpa_cmake/
13 | arpa-validation-logs/
14 | Makefile.arpa
15 |
16 | # Emitted by litani
17 | .ninja_deps
18 | .ninja_log
19 | .litani_cache_dir
20 |
21 | # These files should be overwritten whenever prepare.py runs
22 | cbmc-batch.yaml
23 |
24 | __pycache__/
25 |
--------------------------------------------------------------------------------
/test/cbmc/proofs/Makefile-project-testing:
--------------------------------------------------------------------------------
1 | # -*- mode: makefile -*-
2 | # The first line sets the emacs major mode to Makefile
3 |
4 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
5 | # SPDX-License-Identifier: MIT-0
6 |
7 | ################################################################
8 | # Use this file to define project-specific targets and definitions for
9 | # unit testing or continuous integration that may depend on targets
10 | # defined in Makefile.common
11 | ################################################################
12 |
--------------------------------------------------------------------------------
/test/cbmc/proofs/Makefile-template-defines:
--------------------------------------------------------------------------------
1 | PROOF_ROOT ?= $(abspath .)
2 |
3 | # Absolute path to the root of the source tree.
4 | #
5 | SRCDIR ?= $(abspath $(PROOF_ROOT)/../../..)
6 |
7 |
8 | # Absolute path to the litani script.
9 | #
10 | LITANI ?= litani
11 |
12 |
13 | # Name of this proof project, displayed in proof reports. For example,
14 | # "s2n" or "Amazon FreeRTOS". For projects with multiple proof roots,
15 | # this may be overridden on the command-line to Make, for example
16 | #
17 | # make PROJECT_NAME="FreeRTOS MQTT" report
18 | #
19 | PROJECT_NAME = "sigv4-for-aws-iot-embedded-sdk"
20 |
--------------------------------------------------------------------------------
/sigv4FilePaths.cmake:
--------------------------------------------------------------------------------
1 | # This file sets source files and include directories to variables so that they
2 | # can be reused from different repositories in their CMake based build system by
3 | # including this file.
4 | #
5 | # Files specific to the repository such as test runner and platform tests are
6 | # not added to the variables.
7 |
8 | # SigV4 library source files.
9 | set( SIGV4_SOURCES
10 | "${CMAKE_CURRENT_LIST_DIR}/source/sigv4.c"
11 | "${CMAKE_CURRENT_LIST_DIR}/source/sigv4_quicksort.c" )
12 |
13 | # SigV4 library public include directories.
14 | set( SIGV4_INCLUDE_PUBLIC_DIRS
15 | "${CMAKE_CURRENT_LIST_DIR}/source/include" )
16 |
--------------------------------------------------------------------------------
/test/cbmc/proofs/Makefile-json.common:
--------------------------------------------------------------------------------
1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | # SPDX-License-Identifier: MIT-0
3 |
4 | HARNESS_ENTRY=harness
5 |
6 | DEFINES += -DCBMC_MAX_BUFSIZE=$(CBMC_MAX_BUFSIZE)
7 | ifdef CBMC_MAX_QUERYKEYLENGTH
8 | DEFINES += -DCBMC_MAX_QUERYKEYLENGTH=$(CBMC_MAX_QUERYKEYLENGTH)
9 | endif
10 |
11 | INCLUDES += -I$(CBMC_ROOT)/include
12 |
13 | PROOF_SOURCES += $(PROOFDIR)/$(HARNESS_FILE).c
14 |
15 | PROJECT_SOURCES += $(PROOFDIR)/sigv4.c
16 | PROJECT_SOURCES += $(SRCDIR)/source/sigv4_quicksort.c
17 |
18 | CHECKFLAGS += --pointer-primitive-check
19 |
20 | include ../Makefile.common
21 |
22 | cleanclean: veryclean
23 | -$(RM) $(PROOFDIR)/sigv4.c
24 |
--------------------------------------------------------------------------------
/cspell.config.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | $schema: https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json
3 | version: '0.2'
4 | # Allows things like stringLength
5 | allowCompoundWords: true
6 |
7 | # Read files not to spell check from the git ignore
8 | useGitignore: true
9 |
10 | # Language settings for C
11 | languageSettings:
12 | - caseSensitive: false
13 | enabled: true
14 | languageId: c
15 | locale: "*"
16 |
17 | # Add a dictionary, and the path to the word list
18 | dictionaryDefinitions:
19 | - name: freertos-words
20 | path: '.github/.cSpellWords.txt'
21 | addWords: true
22 |
23 | dictionaries:
24 | - freertos-words
25 |
26 | # Paths and files to ignore
27 | ignorePaths:
28 | - 'dependency'
29 | - 'docs'
30 | - 'ThirdParty'
31 | - 'History.txt'
32 |
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | Description
4 | -----------
5 |
6 |
7 | Test Steps
8 | -----------
9 |
10 |
11 | Checklist:
12 | ----------
13 |
14 |
15 | - [ ] I have tested my changes. No regression in existing tests.
16 | - [ ] I have modified and/or added unit-tests to cover the code changes in this Pull Request.
17 |
18 | Related Issue
19 | -----------
20 |
21 | By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.
22 |
--------------------------------------------------------------------------------
/docs/doxygen/include/size_table.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | | Code Size of AWS SigV4 library (example generated with GCC for ARM Cortex-M) |
4 |
5 |
6 | | File |
7 | With -O1 Optimization |
8 | With -Os Optimization |
9 |
10 |
11 | | sigv4.c |
12 | 5.4K |
13 | 4.5K |
14 |
15 |
16 | | sigv4_quicksort.c |
17 | 0.4K |
18 | 0.3K |
19 |
20 |
21 | | Total estimates |
22 | 5.8K |
23 | 4.8K |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/tools/cmock/project.yml:
--------------------------------------------------------------------------------
1 | # Taken from amazon-freertos repository
2 | :cmock:
3 | :mock_prefix: mock_
4 | :when_no_prototypes: :warn
5 | :enforce_strict_ordering: TRUE
6 | :plugins:
7 | - :ignore
8 | - :ignore_arg
9 | - :expect_any_args
10 | - :array
11 | - :callback
12 | - :return_thru_ptr
13 | :callback_include_count: true # include a count arg when calling the callback
14 | :callback_after_arg_check: false # check arguments before calling the callback
15 | :treat_as:
16 | uint8: HEX8
17 | uint16: HEX16
18 | uint32: UINT32
19 | int8: INT8
20 | bool: UINT8
21 | :includes: # This will add these includes to each mock.
22 | -
23 | -
24 | :treat_externs: :exclude # Now the extern-ed functions will be mocked.
25 | :weak: __attribute__((weak))
26 | :treat_externs: :include
27 |
--------------------------------------------------------------------------------
/test/cbmc/proofs/SigV4_AwsIotDateToIso8601/README.md:
--------------------------------------------------------------------------------
1 | SigV4_AwsIotDateToIso8601 proof
2 | ==============
3 |
4 | This directory contains a memory safety proof for SigV4_AwsIotDateToIso8601.
5 |
6 | To run the proof.
7 | -------------
8 |
9 | * Add `cbmc`, `goto-cc`, `goto-instrument`, `goto-analyzer`, and `cbmc-viewer`
10 | to your path.
11 | * Run `make`.
12 | * Open html/index.html in a web browser.
13 |
14 | To use [`arpa`](https://awslabs.github.io/aws-proof-build-assistant) to simplify writing Makefiles.
15 | -------------
16 |
17 | * Run `make arpa` to generate a Makefile.arpa that contains relevant build information for the proof.
18 | * Use Makefile.arpa as the starting point for your proof Makefile by:
19 | 1. Modifying Makefile.arpa (if required).
20 | 2. Including Makefile.arpa into the existing proof Makefile (add `sinclude Makefile.arpa` at the bottom of the Makefile, right before `include ../Makefile.common`).
21 |
--------------------------------------------------------------------------------
/test/cbmc/proofs/SigV4_GenerateHTTPAuthorization/README.md:
--------------------------------------------------------------------------------
1 | SigV4_GenerateHTTPAuthorization proof
2 | ==============
3 |
4 | This directory contains a memory safety proof for SigV4_GenerateHTTPAuthorization.
5 |
6 | To run the proof.
7 | -------------
8 |
9 | * Add `cbmc`, `goto-cc`, `goto-instrument`, `goto-analyzer`, and `cbmc-viewer`
10 | to your path.
11 | * Run `make`.
12 | * Open html/index.html in a web browser.
13 |
14 | To use [`arpa`](https://awslabs.github.io/aws-proof-build-assistant) to simplify writing Makefiles.
15 | -------------
16 |
17 | * Run `make arpa` to generate a Makefile.arpa that contains relevant build information for the proof.
18 | * Use Makefile.arpa as the starting point for your proof Makefile by:
19 | 1. Modifying Makefile.arpa (if required).
20 | 2. Including Makefile.arpa into the existing proof Makefile (add `sinclude Makefile.arpa` at the bottom of the Makefile, right before `include ../Makefile.common`).
21 |
--------------------------------------------------------------------------------
/test/cbmc/proofs/Makefile-project-targets:
--------------------------------------------------------------------------------
1 | # -*- mode: makefile -*-
2 | # The first line sets the emacs major mode to Makefile
3 |
4 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
5 | # SPDX-License-Identifier: MIT-0
6 |
7 | ################################################################
8 | # Use this file to give project-specific targets, including targets
9 | # that may depend on targets defined in Makefile.common.
10 | ################################################################
11 |
12 | # Each proof requires sigv4.c to be patched (using sed) and dumped into the
13 | # proof directory. The exact sed invocation differs for each proof. So each
14 | # proof must set the SIGV4_SED_EXPR variable, which this rule uses as the
15 | # argument to sed.
16 | $(PROOFDIR)/sigv4.c: $(SRCDIR)/source/sigv4.c
17 | $(LITANI) add-job \
18 | --command \
19 | "sed -E '$(SIGV4_SED_EXPR)' $^" \
20 | --inputs $^ \
21 | --outputs $@ \
22 | --stdout-file $@ \
23 | --ci-stage build \
24 | --pipeline-name "$(PROOF_UID)" \
25 | --description "$(PROOF_UID): patching sigv4.c"
26 |
--------------------------------------------------------------------------------
/test/cbmc/proofs/README.md:
--------------------------------------------------------------------------------
1 | CBMC proofs
2 | ===========
3 |
4 | This directory contains the CBMC proofs. Each proof is in its own
5 | directory.
6 |
7 | This directory includes four Makefiles.
8 |
9 | One Makefile describes the basic workflow for building and running proofs:
10 |
11 | * Makefile.common:
12 | * make: builds the goto binary, does the cbmc property checking
13 | and coverage checking, and builds the final report.
14 | * make goto: builds the goto binary
15 | * make result: does cbmc property checking
16 | * make coverage: does cbmc coverage checking
17 | * make report: builds the final report
18 |
19 | Three included Makefiles describe project-specific settings and can override
20 | definitions in Makefile.common:
21 |
22 | * Makefile-project-defines: definitions like compiler flags
23 | required to build the goto binaries, and definitions to override
24 | definitions in Makefile.common.
25 | * Makefile-project-targets: other make targets needed for the project
26 | * Makefile-project-testing: other definitions and targets needed for
27 | unit testing or continuous integration.
28 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/test/cbmc/proofs/SigV4_AwsIotDateToIso8601/Makefile:
--------------------------------------------------------------------------------
1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | # SPDX-License-Identifier: MIT-0
3 |
4 | HARNESS_ENTRY = harness
5 | HARNESS_FILE = SigV4_AwsIotDateToIso8601_harness
6 |
7 | # This should be a unique identifier for this proof, and will appear on the
8 | # Litani dashboard. It can be human-readable and contain spaces if you wish.
9 | PROOF_UID = SigV4_AwsIotDateToIso8601
10 |
11 | DEFINES += -DSIGV4_DO_NOT_USE_CUSTOM_CONFIG=1
12 | INCLUDES +=
13 |
14 | MONTH_ASCII_LEN=3
15 | ISO_YEAR_LEN=5
16 | MONTHS_IN_YEAR=12
17 | FORMAT_RFC_5322_LEN=32
18 |
19 | REMOVE_FUNCTION_BODY +=
20 | UNWINDSET += parseDate.0:$(FORMAT_RFC_5322_LEN)
21 | UNWINDSET += scanValue.0:$(ISO_YEAR_LEN)
22 | UNWINDSET += intToAscii.0:$(ISO_YEAR_LEN)
23 |
24 | PROOF_SOURCES += $(PROOFDIR)/$(HARNESS_FILE).c
25 | PROOF_SOURCES += $(SRCDIR)/test/cbmc/stubs/sigv4_stubs.c
26 |
27 | include ../Makefile-json.common
28 |
29 | # Substitution command to pass to sed for patching sigv4.c. The
30 | # characters " and # must be escaped with backslash.
31 | SIGV4_SED_EXPR = 1s/^/\#include \"sigv4_stubs.h\" /; s/^static //; s/SigV4Status_t scanValue\b/&_/
32 |
--------------------------------------------------------------------------------
/tools/coverity/misra.config:
--------------------------------------------------------------------------------
1 | {
2 | "version" : "2.0",
3 | "standard" : "c2012",
4 | "title" : "Coverity MISRA Configuration",
5 | "deviations" : [
6 | {
7 | "deviation" : "Directive 4.9",
8 | "reason" : "Allow inclusion of function like macros. Asserts and logging use function like macros."
9 | },
10 | {
11 | "deviation" : "Rule 2.4",
12 | "reason" : "Allow unused tags. Some compilers warn if types are not tagged."
13 | },
14 | {
15 | "deviation" : "Rule 2.5",
16 | "reason" : "Allow unused macros."
17 | },
18 | {
19 | "deviation" : "Rule 3.1",
20 | "reason" : "Allow nested comments. C++ style `//` comments are used in example code within Doxygen documentation blocks."
21 | },
22 | {
23 | "deviation" : "Rule 8.7",
24 | "reason" : "API functions are not used by the library outside of the files they are defined in; however, they must be externally visible in order to be used by an application."
25 | },
26 | {
27 | "deviation" : "Rule 11.5",
28 | "reason" : "Allow casts from void *. Functions with void * parameters are used while sorting."
29 | }
30 | ]
31 | }
32 |
--------------------------------------------------------------------------------
/.github/.cSpellWords.txt:
--------------------------------------------------------------------------------
1 | Aizca
2 | AKIAIOSFODNN
3 | Ayjrf
4 | Bgza
5 | cbmc
6 | CBMC
7 | cbor
8 | CBOR
9 | chjdsvchjdvhjcdhjsckhdsvchdks
10 | cmock
11 | Cmock
12 | CMock
13 | CMOCK
14 | Cnpb
15 | Cnpbfi
16 | coremqtt
17 | coverity
18 | Coverity
19 | CSDK
20 | ctest
21 | Cuiz
22 | DCMOCK
23 | DDISABLE
24 | decihours
25 | Decihours
26 | DECIHOURS
27 | DNDEBUG
28 | DSIGV
29 | DUNITY
30 | DUNITTEST
31 | Ecjuve
32 | EKHX
33 | getpacketid
34 | GGHU
35 | Gicnak
36 | gjfhjxgxghsgfdwfdfdfdffhfdhdhfhdfhd
37 | HMDL
38 | Hpxdr
39 | isystem
40 | Kcdef
41 | Kced
42 | lcov
43 | Lkec
44 | misra
45 | Misra
46 | MISRA
47 | mlkzxncvlknlkanlkqwlerknlasdflkzxcnvklnlksqwerasdfklqwenrklnfsad
48 | MQTT
49 | mypy
50 | Ndzbbpmap
51 | NGYY
52 | nondet
53 | Nondet
54 | NONDET
55 | opad
56 | OPAD
57 | pasdfghwsshasdfghjk
58 | Pjiyp
59 | Pnpyim
60 | pylint
61 | pytest
62 | pyyaml
63 | Qvpwa
64 | Qwxh
65 | Rajbw
66 | reall
67 | sdgfdfgdshfgsjdhfdhfkhdkfhjdgfgdfgdfg
68 | sdvfdvfhdvfhvdhfvdsfdsgfgdsjfgjdsfqwertyuio
69 | sfdghfdfahgsdhfgjsgfjkgfsdgkdgfdjkgdggdjfsjkgjksgkj
70 | sigv
71 | SIGV
72 | sinclude
73 | Sutzy
74 | Thwgv
75 | Uijcfxv
76 | UNACKED
77 | unpadded
78 | Unpadded
79 | UNPADDED
80 | UNSUB
81 | UNSUBACK
82 | unsubscriptions
83 | utest
84 | Vajgc
85 | vect
86 | Vect
87 | VECT
88 | Vwng
89 | wnqj
90 | Wunused
91 | xchjsd
92 | XLFAUQG
93 | ymxchykldfghiwbdcjhjdddkkgddsdhshdkshdhsskgfkjgfggc
94 | YYYYMMDD'T'HHMMSS'Z'
95 | Zapv
96 |
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | # Each line is a file pattern followed by one or more owners.
2 |
3 | # These owners will be the default owners for everything in
4 | # the repo. Unless a later match takes precedence,
5 | # @global-owner1 and @global-owner2 will be requested for
6 | # review when someone opens a pull request.
7 | * @aws/freertos-pr-bar-raisers
8 |
9 | # Order is important; the last matching pattern takes the most
10 | # precedence. When someone opens a pull request that only
11 | # modifies c files, only @FreeRTOS/pr-bar-raiser and not the
12 | # global owner(s) will be requested for a review.
13 | # *.c FreeRTOS/pr-bar-raiser
14 |
15 | # You can also use email addresses if you prefer. They'll be
16 | # used to look up users just like we do for commit author
17 | # emails.
18 | # *.go docs@example.com
19 |
20 | # In this example, @doctocat owns any files in the build/logs
21 | # directory at the root of the repository and any of its
22 | # subdirectories.
23 | # /build/logs/ @doctocat
24 |
25 | # The `docs/*` pattern will match files like
26 | # `docs/getting-started.md` but not further nested files like
27 | # `docs/build-app/troubleshooting.md`.
28 | # docs/* docs@example.com
29 |
30 | # In this example, @octocat owns any file in an apps directory
31 | # anywhere in your repository.
32 | # apps/ @octocat
33 |
34 | # In this example, @doctocat owns any file in the `/docs`
35 | # directory in the root of your repository and any of its
36 | # subdirectories.
37 | # /docs/ @doctocat
--------------------------------------------------------------------------------
/test/cbmc/proofs/Makefile-project-defines:
--------------------------------------------------------------------------------
1 | # -*- mode: makefile -*-
2 | # The first line sets the emacs major mode to Makefile
3 |
4 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
5 | # SPDX-License-Identifier: MIT-0
6 |
7 | ################################################################
8 | # Use this file to give project-specific definitions of the command
9 | # line arguments to pass to CBMC tools like goto-cc to build the goto
10 | # binaries and cbmc to do the property and coverage checking.
11 | #
12 | # Use this file to override most default definitions of variables in
13 | # Makefile.common.
14 | ################################################################
15 |
16 | # Flags to pass to goto-cc for compilation (typically those passed to gcc -c)
17 | # COMPILE_FLAGS =
18 | COMPILE_FLAGS += -fPIC
19 | COMPILE_FLAGS += -std=gnu90
20 |
21 | # Flags to pass to goto-cc for linking (typically those passed to gcc)
22 | # LINK_FLAGS =
23 |
24 | # Preprocessor include paths -I...
25 | # Consider adding
26 | # INCLUDES += -I$(CBMC_ROOT)/include
27 | # You will want to decide what order that comes in relative to the other
28 | # include directories in your project.
29 | #
30 | # INCLUDES =
31 | INCLUDES += -I$(SRCDIR)/test/cbmc/include
32 | INCLUDES += -I$(SRCDIR)/source/include
33 | INCLUDES += -I$(SRCDIR)/test/include
34 |
35 | # Preprocessor definitions -D...
36 | # DEFINES =
37 | DEFINES +=
38 |
39 | # Path to arpa executable
40 | # ARPA =
41 |
42 | # Flags to pass to cmake for building the project
43 | # ARPA_CMAKE_FLAGS =
44 |
--------------------------------------------------------------------------------
/test/cbmc/proofs/copyHeaderStringToCanonicalBuffer/Makefile:
--------------------------------------------------------------------------------
1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | # SPDX-License-Identifier: MIT-0
3 |
4 | HARNESS_ENTRY = harness
5 | HARNESS_FILE = copyHeaderStringToCanonicalBuffer_harness
6 |
7 | # This should be a unique identifier for this proof, and will appear on the
8 | # Litani dashboard. It can be human-readable and contain spaces if you wish.
9 | PROOF_UID = copyHeaderStringToCanonicalBuffer
10 |
11 | # This value was experimentally chosen to provide 100% coverage
12 | # without tripping unwinding assertions and without exhausting memory.
13 | CBMC_MAX_BUFSIZE=10
14 | MAX_HASH_BLOCK_LEN=17
15 | MAX_HASH_DIGEST_LEN=16
16 |
17 | DEFINES += -DMAX_HASH_BLOCK_LEN=$(MAX_HASH_BLOCK_LEN)
18 | DEFINES += -DCBMC_MAX_BUFSIZE=$(CBMC_MAX_BUFSIZE)
19 | DEFINES += -DMAX_HASH_DIGEST_LEN=$(MAX_HASH_DIGEST_LEN)
20 | INCLUDES +=
21 |
22 | REMOVE_FUNCTION_BODY +=
23 | UNWINDSET +=copyHeaderStringToCanonicalBuffer.0:$(CBMC_MAX_BUFSIZE)
24 |
25 | PROOF_SOURCES += $(PROOFDIR)/$(HARNESS_FILE).c
26 |
27 | # If this proof is found to consume huge amounts of RAM, you can set the
28 | # EXPENSIVE variable. With new enough versions of the proof tools, this will
29 | # restrict the number of EXPENSIVE CBMC jobs running at once. See the
30 | # documentation in Makefile.common under the "Job Pools" heading for details.
31 | # EXPENSIVE = true
32 |
33 | include ../Makefile-json.common
34 |
35 | # Substitution command to pass to sed for patching sigv4.c. The
36 | # characters " and # must be escaped with backslash.
37 | SIGV4_SED_EXPR = s/^static //
38 |
--------------------------------------------------------------------------------
/docs/plantuml/sigv4_design.pu:
--------------------------------------------------------------------------------
1 | @startuml
2 | skinparam dpi 100
3 | skinparam classFontSize 8
4 | skinparam classFontName Helvetica
5 | autonumber
6 |
7 | box "Application" #LightGreen
8 | participant "Application" as application
9 | end box
10 |
11 | box "Library" #LightBlue
12 | participant "SigV4 Library" as sigv4
13 | end box
14 |
15 | box "IoT Server" #Yellow
16 | participant "IoT Server" as server
17 | end box
18 |
19 | box "AWS Server" #Orange
20 | participant "AWS Server" as aws
21 | end box
22 | activate application
23 |
24 | application -> server : Connect to AWS IOT Credential provider to fetch the temporary credentials
25 | server -> application : Connected and retrieved credentials
26 |
27 | application -> application: Parse the temporary credentials
28 |
29 | application -> server : Disconnect from server
30 |
31 | application -> application: Implement crypto interface hash functions.
32 |
33 | application -> sigv4 : Convert the AWS IoT date retrieved from AWS IoT Credential Provider\n to ISO8601 format using (SigV4_AwsIotDateToIso8601) API
34 |
35 | sigv4-> application : Date Converted and written to provided buffer
36 |
37 | application-> aws : Connect to AWS Server for sending the HTTP request
38 |
39 | aws->application : Connected
40 |
41 | application -> sigv4 : Generate Authorization header using (Sigv4_GenerateHTTPAuthorization) API
42 |
43 |
44 | application->application : Add the Authorization Header to the HTTP request to AWS Server.
45 |
46 | application-> aws : Send the HTTP request to AWS Server to perform the desired action
47 |
48 | aws-> application : Receive HTTP Response from AWS Server
49 | application -> aws: Disconnect from AWS server
50 |
51 | deactivate application
52 | @enduml
53 |
54 |
--------------------------------------------------------------------------------
/MISRA.md:
--------------------------------------------------------------------------------
1 | # MISRA Compliance
2 |
3 | The AWS SigV4 Library files conform to the [MISRA C:2012](https://www.misra.org.uk)
4 | guidelines, with some noted exceptions. Compliance is checked with Coverity static analysis.
5 | The specific deviations, suppressed inline, are listed below.
6 |
7 | Additionally, [MISRA configuration file](https://github.com/aws/SigV4-for-AWS-IoT-embedded-sdk/blob/main/tools/coverity/misra.config) contains the project wide deviations.
8 |
9 | ### Suppressed with Coverity Comments
10 | To find the deviation references in the source files run grep on the source code
11 | with ( Assuming rule 5.4 violation; with justification in point 1 ):
12 | ```
13 | grep 'MISRA Ref 5.4.1' . -rI
14 | ```
15 |
16 | #### Rule 5.4
17 | _Ref 5.4.1_
18 |
19 | - MISRA Rule 5.4 flags the following macro's name as ambiguous from the
20 | one postfixed with _LENGTH. The macro highlighted by the deviation is already
21 | in use and changing the name will break existing user projects. Thus, for
22 | backwards compatibility, the macro is not modified and kept as is and the
23 | deviation is suppressed.
24 |
25 | _Ref 18.2.1_
26 |
27 | - MISRA Rule 18.2 states that two pointers may only be subtracted if they point
28 | to elements of the same array. In this library, array of bytes are used to process
29 | data. Functions which fill the arrays with data update an index to an offset.
30 | To know the amount of data added to the array, the beginning address of the array has
31 | to be subtracted from the index. It is manually verified that the index will always be
32 | within bounds of the array. However, Coverity is flagging this as a deviation. Thus, we
33 | are suppressing it.
34 |
--------------------------------------------------------------------------------
/test/unit-test/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Include filepaths for source and include.
2 | include( ${MODULE_ROOT_DIR}/sigv4FilePaths.cmake )
3 |
4 | find_package(OpenSSL REQUIRED)
5 |
6 | # ==================== Define your project name (edit) ========================
7 | set(project_name "sigv4")
8 |
9 | # ===================== Create your mock here (edit) ========================
10 | # ================= Create the library under test here (edit) ==================
11 |
12 | # list the files you would like to test here
13 | list(APPEND real_source_files
14 | ${SIGV4_SOURCES}
15 | )
16 | # list the directories the module under test includes
17 | list(APPEND real_include_directories
18 | .
19 | ${SIGV4_INCLUDE_PUBLIC_DIRS}
20 | "${CMAKE_CURRENT_LIST_DIR}/../include"
21 | )
22 |
23 | # ===================== Create UnitTest Code here (edit) =====================
24 |
25 | # list the directories your test needs to include
26 | list(APPEND test_include_directories
27 | .
28 | ${SIGV4_INCLUDE_PUBLIC_DIRS}
29 | )
30 |
31 | # ============================= (end edit) ===================================
32 |
33 | set(real_name "${project_name}_real")
34 |
35 | create_real_library(${real_name}
36 | "${real_source_files}"
37 | "${real_include_directories}"
38 | "${mock_name}"
39 | )
40 |
41 | list(APPEND utest_link_list
42 | lib${real_name}.a
43 | )
44 |
45 | list(APPEND utest_dep_list
46 | ${real_name}
47 | )
48 |
49 | set(utest_name "${project_name}_utest")
50 | set(utest_source "${project_name}_utest.c")
51 | create_test(${utest_name}
52 | ${utest_source}
53 | "${utest_link_list}"
54 | "${utest_dep_list}"
55 | "${test_include_directories}"
56 | )
57 |
58 | target_link_libraries(${utest_name} OpenSSL::SSL)
59 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Project information.
2 | cmake_minimum_required( VERSION 3.10.0 )
3 | project( "sigv4" LANGUAGES C )
4 |
5 | # Allow the project to be organized into folders.
6 | set_property( GLOBAL PROPERTY USE_FOLDERS ON )
7 |
8 | set( CMAKE_C_STANDARD_REQUIRED ON )
9 |
10 | # Do not allow in-source build.
11 | if( ${PROJECT_SOURCE_DIR} STREQUAL ${PROJECT_BINARY_DIR} )
12 | message( FATAL_ERROR "In-source build is not allowed. Please build in a separate directory, such as ${PROJECT_SOURCE_DIR}/build." )
13 | endif()
14 |
15 | # Set global path variables.
16 | get_filename_component( __MODULE_ROOT_DIR "${CMAKE_CURRENT_LIST_DIR}" ABSOLUTE )
17 | set( MODULE_ROOT_DIR ${__MODULE_ROOT_DIR} CACHE INTERNAL "SigV4 repository root." )
18 |
19 |
20 | # Set output directories.
21 | set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin )
22 | set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib )
23 | set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib )
24 |
25 |
26 | # Include filepaths for source and include.
27 | include( ${MODULE_ROOT_DIR}/sigv4FilePaths.cmake )
28 |
29 | add_library(${PROJECT_NAME})
30 | target_sources(${PROJECT_NAME} PRIVATE ${SIGV4_SOURCES})
31 | target_include_directories(${PROJECT_NAME} PUBLIC
32 | $
33 | $
34 | )
35 |
36 | # `sigv4_config` target defines the path to sigv4_config.h and optionally other based config files
37 | if( NOT TARGET sigv4_config )
38 | target_compile_definitions(${PROJECT_NAME} PRIVATE -DSIGV4_DO_NOT_USE_CUSTOM_CONFIG )
39 | endif()
40 |
41 | include( GNUInstallDirs )
42 |
43 | install( TARGETS ${PROJECT_NAME}
44 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME}
45 | PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}
46 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME}
47 | )
48 |
49 | install( DIRECTORY ${SIGV4_INCLUDE_PUBLIC_DIRS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} )
50 |
--------------------------------------------------------------------------------
/test/cbmc/include/sigv4_annex.h:
--------------------------------------------------------------------------------
1 | /*
2 | * SigV4 Library v1.3.0
3 | * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | *
5 | * SPDX-License-Identifier: MIT
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
8 | * this software and associated documentation files (the "Software"), to deal in
9 | * the Software without restriction, including without limitation the rights to
10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11 | * the Software, and to permit persons to whom the Software is furnished to do so,
12 | * subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in all
15 | * copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 | */
24 |
25 | #ifndef SIGV4_ANNEX_H_
26 | #define SIGV4_ANNEX_H_
27 |
28 | #include "sigv4.h"
29 | #include "sigv4_internal.h"
30 |
31 | /*
32 | * These are declarations for the (normally) static functions from sigv4.c.
33 | * Please see sigv4.c for documentation.
34 | */
35 |
36 | SigV4Status_t copyHeaderStringToCanonicalBuffer( const char * pData,
37 | size_t dataLen,
38 | uint32_t flags,
39 | char separator,
40 | CanonicalContext_t * canonicalRequest );
41 |
42 | #endif /* ifndef SIGV4_ANNEX_H_ */
43 |
--------------------------------------------------------------------------------
/test/cbmc/include/hash_stubs.h:
--------------------------------------------------------------------------------
1 | /*
2 | * SigV4 Library v1.3.0
3 | * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | *
5 | * SPDX-License-Identifier: MIT
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
8 | * this software and associated documentation files (the "Software"), to deal in
9 | * the Software without restriction, including without limitation the rights to
10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11 | * the Software, and to permit persons to whom the Software is furnished to do so,
12 | * subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in all
15 | * copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 | */
24 |
25 | /**
26 | * @file hash_stubs.h
27 | * @brief Declarations for stubs used in sigv4.c.
28 | * Please see sigv4.c for documentation.
29 | */
30 |
31 | #ifndef HASH_STUBS_H_
32 | #define HASH_STUBS_H_
33 |
34 | /* Standard includes. */
35 | #include
36 | #include
37 | #include
38 |
39 | int32_t HashInitStub( void * pHashContext );
40 |
41 | int32_t HashUpdateStub( void * pHashContext,
42 | const char * pInput,
43 | size_t inputLen );
44 |
45 | int32_t HashFinalStub( void * pHashContext,
46 | const char * pInput,
47 | size_t inputLen );
48 |
49 | #endif /* ifndef HASH_STUBS_H_ */
50 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog for AWS SigV4 Library
2 |
3 | ## v1.3.0 (May 2024)
4 |
5 | - [#93](https://github.com/aws/SigV4-for-AWS-IoT-embedded-sdk/pull/93) Update CanonicalContext structure for MISRA compliance
6 | - [#92](https://github.com/aws/SigV4-for-AWS-IoT-embedded-sdk/pull/92) MISRA C:2012 Compliance Update
7 | - [#89](https://github.com/aws/SigV4-for-AWS-IoT-embedded-sdk/pull/89) Support presigned URL signature "UNSIGNED-PAYLOAD" and expose EncodeURI
8 | - [#85](https://github.com/aws/SigV4-for-AWS-IoT-embedded-sdk/pull/85) Fix bugs in generating canonical Query
9 | - [#77](https://github.com/aws/SigV4-for-AWS-IoT-embedded-sdk/pull/77) Update Doxygen version to 1.9.6
10 |
11 | ## v1.2.0 (October 2022)
12 |
13 | - [#71](https://github.com/aws/SigV4-for-AWS-IoT-embedded-sdk/pull/71) MISRA C:2012 Compliance Update
14 | - [#70](https://github.com/aws/SigV4-for-AWS-IoT-embedded-sdk/pull/70) Update CBMC starter kit
15 |
16 | ## v1.1.0 (December 2021)
17 |
18 | - [#63](https://github.com/aws/SigV4-for-AWS-IoT-embedded-sdk/pull/63) Remove extraneous parentheses in isAllowedChar()
19 | - [#62](https://github.com/aws/SigV4-for-AWS-IoT-embedded-sdk/pull/62) Enable logging macros in CI checks for SigV4
20 | - [#59](https://github.com/aws/SigV4-for-AWS-IoT-embedded-sdk/pull/59) Remove superfluous memmove
21 | - [#58](https://github.com/aws/SigV4-for-AWS-IoT-embedded-sdk/pull/58) Utility word removal from Sigv4 Library
22 | - [#57](https://github.com/aws/SigV4-for-AWS-IoT-embedded-sdk/pull/57) SigV4 Porting Guide
23 | - [#56](https://github.com/aws/SigV4-for-AWS-IoT-embedded-sdk/pull/56) Update Doxygen version to 1.9.2
24 | - [#55](https://github.com/aws/SigV4-for-AWS-IoT-embedded-sdk/pull/55) CBMC Proof Failure Fixes
25 | - [#52](https://github.com/aws/SigV4-for-AWS-IoT-embedded-sdk/pull/52) Fix bugs in generating canonical Query and improve functionality coverage in unit tests.
26 | - [#51](https://github.com/aws/SigV4-for-AWS-IoT-embedded-sdk/pull/51) Payload hash optimization
27 |
28 | ## v1.0.0 (August 2021)
29 |
30 | This is the first release of the AWS SigV4 Library.
31 |
--------------------------------------------------------------------------------
/test/cbmc/stubs/hash_stubs.c:
--------------------------------------------------------------------------------
1 | /*
2 | * SigV4 Library v1.3.0
3 | * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | *
5 | * SPDX-License-Identifier: MIT
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
8 | * this software and associated documentation files (the "Software"), to deal in
9 | * the Software without restriction, including without limitation the rights to
10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11 | * the Software, and to permit persons to whom the Software is furnished to do so,
12 | * subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in all
15 | * copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 | */
24 |
25 | /**
26 | * @file hash_stubs.c
27 | * @brief Declarations for stubs used in sigv4.c.
28 | * Please see sigv4.c for documentation.
29 | */
30 |
31 | /* Standard includes. */
32 | #include "hash_stubs.h"
33 |
34 | int32_t HashInitStub( void * pHashContext )
35 | {
36 | int32_t ret;
37 |
38 | return ret;
39 | }
40 |
41 | int32_t HashUpdateStub( void * pHashContext,
42 | const char * pInput,
43 | size_t inputLen )
44 | {
45 | int32_t ret;
46 |
47 | return ret;
48 | }
49 |
50 | int32_t HashFinalStub( void * pHashContext,
51 | const char * pInput,
52 | size_t inputLen )
53 | {
54 | int32_t ret;
55 |
56 | return ret;
57 | }
58 |
--------------------------------------------------------------------------------
/test/cbmc/proofs/lib/print_tool_versions.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | #
3 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | # SPDX-License-Identifier: MIT-0
5 |
6 |
7 | import logging
8 | import pathlib
9 | import shutil
10 | import subprocess
11 |
12 |
13 | _TOOLS = [
14 | "cadical",
15 | "cbmc",
16 | "cbmc-viewer",
17 | "cbmc-starter-kit-update",
18 | "kissat",
19 | "litani",
20 | ]
21 |
22 |
23 | def _format_versions(table):
24 | lines = [
25 | "",
26 | '| Tool Versions |
',
27 | ]
28 | for tool, version in table.items():
29 | if version:
30 | v_str = f'{version}'
31 | else:
32 | v_str = 'not found'
33 | lines.append(
34 | f'| {tool}: | '
36 | f'{v_str} |
')
37 | lines.append("
")
38 | return "\n".join(lines)
39 |
40 |
41 | def _get_tool_versions():
42 | ret = {}
43 | for tool in _TOOLS:
44 | err = f"Could not determine version of {tool}: "
45 | ret[tool] = None
46 | if not shutil.which(tool):
47 | logging.error("%s'%s' not found on $PATH", err, tool)
48 | continue
49 | cmd = [tool, "--version"]
50 | proc = subprocess.Popen(cmd, text=True, stdout=subprocess.PIPE)
51 | try:
52 | out, _ = proc.communicate(timeout=10)
53 | except subprocess.TimeoutExpired:
54 | logging.error("%s'%s --version' timed out", err, tool)
55 | continue
56 | if proc.returncode:
57 | logging.error(
58 | "%s'%s --version' returned %s", err, tool, str(proc.returncode))
59 | continue
60 | ret[tool] = out.strip()
61 | return ret
62 |
63 |
64 | def main():
65 | exe_name = pathlib.Path(__file__).name
66 | logging.basicConfig(format=f"{exe_name}: %(message)s")
67 |
68 | table = _get_tool_versions()
69 | out = _format_versions(table)
70 | print(out)
71 |
72 |
73 | if __name__ == "__main__":
74 | main()
75 |
--------------------------------------------------------------------------------
/test/cbmc/proofs/SigV4_AwsIotDateToIso8601/SigV4_AwsIotDateToIso8601_harness.c:
--------------------------------------------------------------------------------
1 | /*
2 | * SigV4 Library v1.3.0
3 | * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | *
5 | * SPDX-License-Identifier: MIT
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
8 | * this software and associated documentation files (the "Software"), to deal in
9 | * the Software without restriction, including without limitation the rights to
10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11 | * the Software, and to permit persons to whom the Software is furnished to do so,
12 | * subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in all
15 | * copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 | */
24 |
25 | /**
26 | * @file SigV4_AwsIotDateToIso8601_harness.c
27 | * @brief Implements the proof harness for SigV4_AwsIotDateToIso8601 function.
28 | */
29 |
30 | #include "stdlib.h"
31 | #include "sigv4.h"
32 |
33 | void harness()
34 | {
35 | char * pInputDate;
36 | size_t dateLen;
37 | char * pDateISO8601;
38 | size_t dateISO8601Len;
39 | SigV4Status_t status;
40 |
41 | __CPROVER_assume( dateLen == SIGV4_EXPECTED_LEN_RFC_3339 || dateLen == SIGV4_EXPECTED_LEN_RFC_5322 || dateLen == 0 );
42 |
43 | pInputDate = malloc( dateLen );
44 |
45 | __CPROVER_assume( dateISO8601Len < CBMC_MAX_OBJECT_SIZE );
46 |
47 | pDateISO8601 = malloc( dateISO8601Len );
48 |
49 | status = SigV4_AwsIotDateToIso8601( pInputDate, dateLen, pDateISO8601, dateISO8601Len );
50 |
51 | __CPROVER_assert( status == SigV4InvalidParameter || status == SigV4Success || status == SigV4ISOFormattingError, "This is not a valid SigV4 return status" );
52 | }
53 |
--------------------------------------------------------------------------------
/test/include/sigv4_config.h:
--------------------------------------------------------------------------------
1 | /*
2 | * SigV4 Library v1.3.0
3 | * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | *
5 | * SPDX-License-Identifier: MIT
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
8 | * this software and associated documentation files (the "Software"), to deal in
9 | * the Software without restriction, including without limitation the rights to
10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11 | * the Software, and to permit persons to whom the Software is furnished to do so,
12 | * subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in all
15 | * copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 | */
24 |
25 | /**
26 | * @file sigv4_config.h
27 | * @brief Config values for testing the SigV4 for AWS IoT Library.
28 | */
29 |
30 | #ifndef SIGV4_CONFIG_H_
31 | #define SIGV4_CONFIG_H_
32 |
33 | #include
34 |
35 | #ifdef DISABLE_LOGGING
36 | #ifndef LogError
37 | #define LogError( message )
38 | #endif
39 | #ifndef LogWarn
40 | #define LogWarn( message )
41 | #endif
42 |
43 | #ifndef LogInfo
44 | #define LogInfo( message )
45 | #endif
46 |
47 | #ifndef LogDebug
48 | #define LogDebug( message )
49 | #endif
50 |
51 | #else /* ! DISABLE_LOGGING */
52 | #define LogError( message ) printf( "Error: " ); printf message; printf( "\n" )
53 |
54 | #define LogWarn( message ) printf( "Warn: " ); printf message; printf( "\n" )
55 |
56 | #define LogInfo( message ) printf( "Info: " ); printf message; printf( "\n" )
57 |
58 | #define LogDebug( message ) printf( "Debug: " ); printf message; printf( "\n" )
59 | #endif /* DISABLE_LOGGING */
60 |
61 | #endif /* SIGV4_CONFIG_H_ */
62 |
--------------------------------------------------------------------------------
/test/unit-test/cmock_build.cmake:
--------------------------------------------------------------------------------
1 | # Macro utility to clone the CMock submodule.
2 | macro( clone_cmock )
3 | find_package( Git REQUIRED )
4 | message( "Cloning submodule CMock." )
5 | execute_process( COMMAND rm -rf ${CMOCK_DIR}
6 | COMMAND ${GIT_EXECUTABLE} submodule update --checkout --init --recursive ${CMOCK_DIR}
7 | WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
8 | RESULT_VARIABLE CMOCK_CLONE_RESULT )
9 |
10 | if( NOT ${CMOCK_CLONE_RESULT} STREQUAL "0" )
11 | message( FATAL_ERROR "Failed to clone CMock submodule." )
12 | endif()
13 | endmacro()
14 |
15 | # Macro utility to add library targets for Unity and CMock to build configuration.
16 | macro( add_cmock_targets )
17 | # Build Configuration for CMock and Unity libraries.
18 | list( APPEND CMOCK_INCLUDE_DIRS
19 | "${CMOCK_DIR}/vendor/unity/src/"
20 | "${CMOCK_DIR}/vendor/unity/extras/fixture/src"
21 | "${CMOCK_DIR}/vendor/unity/extras/memory/src"
22 | "${CMOCK_DIR}/src"
23 | )
24 |
25 | add_library(cmock STATIC
26 | "${CMOCK_DIR}/src/cmock.c"
27 | )
28 |
29 | set_target_properties(cmock PROPERTIES
30 | ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib
31 | POSITION_INDEPENDENT_CODE ON
32 | COMPILE_FLAGS "-Og"
33 | )
34 |
35 | target_include_directories(cmock PUBLIC
36 | ${CMOCK_DIR}/src
37 | ${CMOCK_DIR}/vendor/unity/src/
38 | ${CMOCK_DIR}/examples
39 | ${CMOCK_INCLUDE_DIRS}
40 | )
41 |
42 | add_library(unity STATIC
43 | "${CMOCK_DIR}/vendor/unity/src/unity.c"
44 | "${CMOCK_DIR}/vendor/unity/extras/fixture/src/unity_fixture.c"
45 | "${CMOCK_DIR}/vendor/unity/extras/memory/src/unity_memory.c"
46 | )
47 |
48 | set_target_properties(unity PROPERTIES
49 | ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib
50 | POSITION_INDEPENDENT_CODE ON
51 | )
52 |
53 | target_include_directories(unity PUBLIC
54 | ${CMOCK_INCLUDE_DIRS}
55 | )
56 |
57 | target_link_libraries(cmock unity)
58 | endmacro()
59 |
--------------------------------------------------------------------------------
/test/cbmc/stubs/memmove.c:
--------------------------------------------------------------------------------
1 | /*
2 | * SigV4 Library v1.3.0
3 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | *
5 | * SPDX-License-Identifier: MIT
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
8 | * this software and associated documentation files (the "Software"), to deal in
9 | * the Software without restriction, including without limitation the rights to
10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11 | * the Software, and to permit persons to whom the Software is furnished to do so,
12 | * subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in all
15 | * copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 | */
24 |
25 | /**
26 | * @file memmove.c
27 | * @brief A stub for memmove so that the proofs for functions that call
28 | * memmove run much faster.
29 | */
30 |
31 | #include
32 |
33 | /* This is a clang macro not available on linux */
34 | #ifndef __has_builtin
35 | #define __has_builtin( x ) 0
36 | #endif
37 |
38 | #if __has_builtin( __builtin___memmove_chk )
39 | void * __builtin___memmove_chk( void * dest,
40 | const void * src,
41 | size_t n,
42 | size_t m )
43 | {
44 | /* Attempting to read or write 0 bytes will make __CPROVER_r/w_ok
45 | * fail. However, per ANSI C specification, memcpy must be able
46 | * to handle a copy length of zero. */
47 | __CPROVER_assert( ( n == 0 ) || __CPROVER_w_ok( dest, n ), "write" );
48 | __CPROVER_assert( ( n == 0 ) || __CPROVER_r_ok( src, n ), "read" );
49 | return dest;
50 | }
51 | #else /* if __has_builtin( __builtin___memmove_chk ) */
52 | void * memmove( void * dest,
53 | const void * src,
54 | size_t n )
55 | {
56 | __CPROVER_assert( __CPROVER_w_ok( dest, n ), "write" );
57 | __CPROVER_assert( __CPROVER_r_ok( src, n ), "read" );
58 | return dest;
59 | }
60 | #endif /* if __has_builtin( __builtin___memmove_chk ) */
61 |
--------------------------------------------------------------------------------
/test/cbmc/stubs/memcpy.c:
--------------------------------------------------------------------------------
1 | /*
2 | * SigV4 Library v1.3.0
3 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | *
5 | * SPDX-License-Identifier: MIT
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
8 | * this software and associated documentation files (the "Software"), to deal in
9 | * the Software without restriction, including without limitation the rights to
10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11 | * the Software, and to permit persons to whom the Software is furnished to do so,
12 | * subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in all
15 | * copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 | */
24 |
25 | /**
26 | * @file memcpy.c
27 | * @brief A stub for memcpy so that the proofs for functions that call memcpy
28 | * run much faster.
29 | */
30 |
31 | #include
32 |
33 | /* This is a clang macro not available on linux */
34 | #ifndef __has_builtin
35 | #define __has_builtin( x ) 0
36 | #endif
37 |
38 | #if __has_builtin( __builtin___memcpy_chk )
39 | void * __builtin___memcpy_chk( void * dest,
40 | const void * src,
41 | size_t n,
42 | size_t m )
43 | {
44 | /* Attempting to read or write 0 bytes will make __CPROVER_r/w_ok
45 | * fail. However, per ANSI C specification, memcpy must be able
46 | * to handle a copy length of zero. */
47 | __CPROVER_assert( ( n == 0 ) || __CPROVER_w_ok( dest, n ), "write" );
48 | __CPROVER_assert( ( n == 0 ) || __CPROVER_r_ok( src, n ), "read" );
49 | return dest;
50 | }
51 | #else /* if __has_builtin( __builtin___memcpy_chk ) */
52 | void * memcpy( void * dest,
53 | const void * src,
54 | size_t n )
55 | {
56 | /* Per ANSI C specification, memcpy must be able to handle a copy length
57 | * of zero. */
58 | __CPROVER_assert( ( n == 0 ) || __CPROVER_w_ok( dest, n ), "write" );
59 | __CPROVER_assert( ( n == 0 ) || __CPROVER_r_ok( src, n ), "read" );
60 | return dest;
61 | }
62 | #endif /* if __has_builtin( __builtin___memcpy_chk ) */
63 |
--------------------------------------------------------------------------------
/test/cbmc/proofs/copyHeaderStringToCanonicalBuffer/copyHeaderStringToCanonicalBuffer_harness.c:
--------------------------------------------------------------------------------
1 | /*
2 | * SigV4 Library v1.3.0
3 | * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | *
5 | * SPDX-License-Identifier: MIT
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
8 | * this software and associated documentation files (the "Software"), to deal in
9 | * the Software without restriction, including without limitation the rights to
10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11 | * the Software, and to permit persons to whom the Software is furnished to do so,
12 | * subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in all
15 | * copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 | */
24 |
25 | /**
26 | * @file copyHeaderStringToCanonicalBuffer_harness.c
27 | * @brief Implements the proof harness for copyHeaderStringToCanonicalBuffer function.
28 | */
29 | #include "stdlib.h"
30 | #include "sigv4_annex.h"
31 |
32 | void harness()
33 | {
34 | const char * pData;
35 | size_t dataLen;
36 | uint32_t flags;
37 | char separator;
38 | CanonicalContext_t * canonicalRequest;
39 | SigV4Status_t sigv4Status;
40 |
41 | canonicalRequest = malloc( sizeof( CanonicalContext_t ) );
42 |
43 | __CPROVER_assume( canonicalRequest != NULL );
44 |
45 |
46 | /* The data to be written is assumed to start at a location within the processing
47 | * buffer and should not end past the length of the processing buffer. */
48 | size_t bytesConsumed;
49 |
50 | __CPROVER_assume( canonicalRequest->bufRemaining < SIGV4_PROCESSING_BUFFER_LENGTH );
51 | bytesConsumed = SIGV4_PROCESSING_BUFFER_LENGTH - canonicalRequest->bufRemaining;
52 | __CPROVER_assume( dataLen > 0U && dataLen < CBMC_MAX_BUFSIZE );
53 | canonicalRequest->uxCursorIndex = bytesConsumed;
54 |
55 | pData = malloc( dataLen );
56 |
57 | __CPROVER_assume( pData != NULL );
58 |
59 | sigv4Status = copyHeaderStringToCanonicalBuffer( pData, dataLen, flags, separator, canonicalRequest );
60 |
61 | __CPROVER_assert( ( sigv4Status == SigV4InvalidParameter || sigv4Status == SigV4Success || sigv4Status == SigV4InsufficientMemory ), "This is not a valid SIGV4 Status." );
62 | }
63 |
--------------------------------------------------------------------------------
/docs/doxygen/porting.dox:
--------------------------------------------------------------------------------
1 | /**
2 | * @page sigv4_porting Porting Guide
3 | * @brief Guide for porting the AWS SigV4 Library to a new
4 | * platform.
5 | *
6 | * To use the AWS SigV4 library, a platform must implement the following
7 | * components:
8 | * 1. [Configuration Macros](@ref sigv4_config_macros)
9 | * 2. [Crypto Interface](@ref sigv4_porting_cryptointerface)
10 | *
11 | * @section sigv4_config_macros Configuration Macros
12 | * @brief Configuration macros that can be set in the config header
13 | * `sigv4_config.h`, or passed in as compiler options.
14 | *
15 | * The following optional logging macros are used throughout the library:
16 | * - @ref LogError
17 | * - @ref LogWarn
18 | * - @ref LogInfo
19 | * - @ref LogDebug
20 | *
21 | * @see [Configurations](@ref sigv4_config) for more information.
22 | *
23 | * @note Regardless of whether the above macros are defined in
24 | * `sigv4_config.h` or passed as compiler options, by default the
25 | * `sigv4_config.h` file is needed to build the AWS SigV4 Library. To disable this requirement and build the library with
26 | * default configuration values, provide
27 | * `SIGV4_DO_NOT_USE_CUSTOM_CONFIG` as a compile time preprocessor
28 | * macro.
29 | *
30 | * @section sigv4_porting_cryptointerface Crypto Interface
31 | * @brief The AWS SigV4 library relies on the implementation of crypto interface
32 | * to provide hash functions used in generating the Authorization header by the library.
33 | *
34 | * A port must implement functions corresponding to the
35 | * following functions pointers:
36 | * - [Hash Initialize]: A function to initialize the Hash Context.
37 | * @code
38 | * int32_t ( * hashInit )( void * pHashContext );
39 | * @endcode
40 | * - [Hash Update]: A function to update the hash to be calculated with more input data.
41 | * @code
42 | * int32_t ( * hashUpdate )( void * pHashContext,
43 | * const uint8_t * pInput,
44 | * size_t inputLen );
45 | * @endcode
46 | * - [Hash Final]: A function to calculate the final binary digest of the hash from the context.
47 | * @code
48 | * int32_t ( * hashFinal )( void * pHashContext,
49 | * uint8_t * pOutput,
50 | * size_t outputLen );
51 | * @endcode
52 | *
53 | * The above three functions take in a pointer to pHashContext which defines the context used
54 | * by the above function in calculating the hash. The HashContext must also be
55 | * defined by the user's implementation and ought to contain any information
56 | * necessary to calculate the hash.
57 | * @code
58 | * void * pHashContext;
59 | * @endcode
60 | *
61 | * A port must also define the following:
62 | * - [Hash Block Length]: The block length of the hash function implemented by the user.
63 | * @code
64 | * size_t hashBlockLen;
65 | * @endcode
66 | *
67 | * - [Hash Digest Length]: The digest length of the hash function implemented by the user.
68 | * @code
69 | * size_t hashDigestLen;
70 | * @endcode
71 | *
72 | */
73 |
--------------------------------------------------------------------------------
/test/cbmc/proofs/SigV4_GenerateHTTPAuthorization/Makefile:
--------------------------------------------------------------------------------
1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | # SPDX-License-Identifier: MIT-0
3 |
4 | HARNESS_ENTRY = harness
5 | HARNESS_FILE = SigV4_GenerateHTTPAuthorization_harness
6 |
7 | # This should be a unique identifier for this proof, and will appear on the
8 | # Litani dashboard. It can be human-readable and contain spaces if you wish.
9 | PROOF_UID = SigV4_GenerateHTTPAuthorization
10 |
11 | # Define constants so as to limit the running time of the proofs.
12 | # Note that these constants are also deliberately chosen so as to attain
13 | # coverage for the SigV4InsufficientMemory cases.
14 | # For the constants below,
15 | # SIGV4_PROCESSING_BUFFER_LENGTH is set specifically to 60.
16 | # It may be easier to attain coverage if the processing buffer is instead
17 | # provided by the user as the length can be variable.
18 | # However, since the length of the processing buffer is fixed,
19 | # these constants must also be fixed in order to match whatever
20 | # SIGV4_PROCESSING_BUFFER_LENGTH is set to in sigv4_config.h.
21 | MAX_QUERY_LEN=6
22 | MAX_HEADERS_LEN=6
23 | MAX_URI_LEN=3
24 | MAX_REQUEST_LEN=16
25 | S3_SERVICE_LEN=2
26 | UNSIGNED_PAYLOAD_LEN=17
27 | MAX_REGION_LEN=30
28 | MAX_SERVICE_LEN=30
29 | MAX_ALGORITHM_LEN=30
30 | MAX_HASH_DIGEST_LEN=16
31 | MAX_HASH_BLOCK_LEN=17
32 | # This is the actual maximum length of an AWS access key ID
33 | MAX_ACCESS_KEY_ID_LEN=128
34 |
35 | DEFINES += -DMAX_QUERY_LEN=$(MAX_QUERY_LEN)
36 | DEFINES += -DMAX_HEADERS_LEN=$(MAX_HEADERS_LEN)
37 | DEFINES += -DMAX_URI_LEN=$(MAX_URI_LEN)
38 | DEFINES += -DMAX_HASH_DIGEST_LEN=$(MAX_HASH_DIGEST_LEN)
39 | DEFINES += -DMAX_HASH_BLOCK_LEN=$(MAX_HASH_BLOCK_LEN)
40 | DEFINES += -DMAX_REGION_LEN=$(MAX_REGION_LEN)
41 | DEFINES += -DMAX_SERVICE_LEN=$(MAX_SERVICE_LEN)
42 | DEFINES += -DMAX_ALGORITHM_LEN=$(MAX_ALGORITHM_LEN)
43 | DEFINES += -DMAX_ACCESS_KEY_ID_LEN=$(MAX_ACCESS_KEY_ID_LEN)
44 | INCLUDES +=
45 |
46 | REMOVE_FUNCTION_BODY += memcpy
47 | REMOVE_FUNCTION_BODY += memmove
48 | UNWINDSET += setQueryStringFieldsAndValues.0:$(MAX_QUERY_LEN)
49 | UNWINDSET += parseHeaderKeyValueEntries.0:$(MAX_HEADERS_LEN)
50 | UNWINDSET += lowercaseHexEncode.0:$(MAX_HASH_DIGEST_LEN)
51 | UNWINDSET += hmacIntermediate.0:$(MAX_HASH_BLOCK_LEN)
52 | UNWINDSET += hmacFinal.0:$(MAX_HASH_BLOCK_LEN)
53 | UNWINDSET += strncmp.0:$(S3_SERVICE_LEN)
54 | UNWINDSET += strlen.0:$(UNSIGNED_PAYLOAD_LEN)
55 |
56 | PROOF_SOURCES += $(PROOFDIR)/$(HARNESS_FILE).c
57 | PROOF_SOURCES += $(SRCDIR)/test/cbmc/stubs/hash_stubs.c
58 | PROOF_SOURCES += $(SRCDIR)/test/cbmc/stubs/memcpy.c
59 | PROOF_SOURCES += $(SRCDIR)/test/cbmc/stubs/memmove.c
60 | PROOF_SOURCES += $(SRCDIR)/test/cbmc/stubs/sigv4_stubs.c
61 |
62 | include ../Makefile-json.common
63 |
64 | # Substitution command to pass to sed for patching sigv4.c. The
65 | # characters " and # must be escaped with backslash.
66 | SIGV4_SED_EXPR = 1s/^/\#include \"sigv4_stubs.h\" /; s/^static //; s/SigV4Status_t (scanValue|SigV4_EncodeURI|generateCanonicalQuery|generateCanonicalAndSignedHeaders|copyHeaderStringToCanonicalBuffer)\b/&_/
67 |
--------------------------------------------------------------------------------
/source/include/sigv4_quicksort.h:
--------------------------------------------------------------------------------
1 | /*
2 | * SigV4 Library v1.3.0
3 | * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | *
5 | * SPDX-License-Identifier: MIT
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
8 | * this software and associated documentation files (the "Software"), to deal in
9 | * the Software without restriction, including without limitation the rights to
10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11 | * the Software, and to permit persons to whom the Software is furnished to do so,
12 | * subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in all
15 | * copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 | */
24 |
25 | /**
26 | * @file sigv4_quicksort.h
27 | * @brief Declaration of Quicksort function for the SigV4 Library.
28 | */
29 |
30 | #ifndef SIGV4_QUICKSORT_H_
31 | #define SIGV4_QUICKSORT_H_
32 |
33 | /* Standard includes. */
34 | #include
35 | #include
36 |
37 | /* *INDENT-OFF* */
38 | #ifdef __cplusplus
39 | extern "C" {
40 | #endif
41 | /* *INDENT-ON* */
42 |
43 | /* SIGV4_DO_NOT_USE_CUSTOM_CONFIG allows building of the SigV4 library without a
44 | * config file. If a config file is provided, the SIGV4_DO_NOT_USE_CUSTOM_CONFIG
45 | * macro must not be defined.
46 | */
47 | #ifndef SIGV4_DO_NOT_USE_CUSTOM_CONFIG
48 | #include "sigv4_config.h"
49 | #endif
50 |
51 | /* Include config defaults header to get default values of configurations not
52 | * defined in sigv4_config.h file. */
53 | #include "sigv4_config_defaults.h"
54 |
55 | /**
56 | * @brief The comparison function used for sorting.
57 | * @param[in] pFirstVal The first value to compare
58 | * @param[in] pSecondVal The second value to compare
59 | *
60 | * @return A value less than 0 if @p pFirstVal is less than
61 | * @p pSecondVal. Otherwise, greater than 0.
62 | */
63 | typedef int32_t ( * ComparisonFunc_t )( const void * pFirstVal,
64 | const void * pSecondVal );
65 |
66 | /**
67 | * @brief Perform quicksort on an array.
68 | *
69 | * @param[in] pArray The array to be sorted.
70 | * @param[in] numItems The number of items in an array.
71 | * @param[in] itemSize The amount of memory per entry in the array.
72 | * @param[out] comparator The comparison function to determine if one item is less than another.
73 | */
74 | void quickSort( void * pArray,
75 | size_t numItems,
76 | size_t itemSize,
77 | ComparisonFunc_t comparator );
78 |
79 | /* *INDENT-OFF* */
80 | #ifdef __cplusplus
81 | }
82 | #endif
83 | /* *INDENT-ON* */
84 |
85 | #endif /* ifndef SIGV4_QUICKSORT_H_ */
86 |
--------------------------------------------------------------------------------
/docs/doxygen/style.css:
--------------------------------------------------------------------------------
1 | /*
2 | * Stylesheet for Doxygen HTML output.
3 | *
4 | * This file defines styles for custom elements in the header/footer and
5 | * overrides some of the default Doxygen styles.
6 | *
7 | * Styles in this file do not affect the treeview sidebar.
8 | */
9 |
10 |
11 | /* Set the margins to place a small amount of whitespace on the left and right
12 | * side of the page. */
13 | div.contents {
14 | margin-left:4em;
15 | margin-right:4em;
16 | }
17 |
18 |
19 | /* Justify text in paragraphs. */
20 | p {
21 | text-align: justify;
22 | }
23 |
24 |
25 | /* Style of section headings. */
26 | h1 {
27 | border-bottom: 1px solid #879ECB;
28 | color: #354C7B;
29 | font-size: 160%;
30 | font-weight: normal;
31 | padding-bottom: 4px;
32 | padding-top: 8px;
33 | }
34 |
35 |
36 | /* Style of subsection headings. */
37 | h2:not(.memtitle):not(.groupheader) {
38 | font-size: 125%;
39 | margin-bottom: 0px;
40 | margin-top: 16px;
41 | padding: 0px;
42 | }
43 |
44 |
45 | /* Style of paragraphs immediately after subsection headings. */
46 | h2 + p {
47 | margin: 0px;
48 | padding: 0px;
49 | }
50 |
51 |
52 | /* Style of subsection headings. */
53 | h3 {
54 | font-size: 100%;
55 | margin-bottom: 0px;
56 | margin-left: 2em;
57 | margin-right: 2em;
58 | }
59 |
60 |
61 | /* Style of paragraphs immediately after subsubsection headings. */
62 | h3 + p {
63 | margin-top: 0px;
64 | margin-left: 2em;
65 | margin-right: 2em;
66 | }
67 |
68 |
69 | /* Style of the prefix "AWS IoT Device SDK C" that appears in the header. */
70 | #csdkprefix {
71 | color: #757575;
72 | }
73 |
74 |
75 | /* Style of the "Return to main page" link that appears in the header. */
76 | #returntomain {
77 | padding: 0.5em;
78 | }
79 |
80 |
81 | /* Style of the dividers on Configuration Settings pages. */
82 | div.configpagedivider {
83 | margin-left: 0px !important;
84 | margin-right: 0px !important;
85 | margin-top: 20px !important;
86 | }
87 |
88 |
89 | /* Style of configuration setting names. */
90 | dl.section.user ~ h1 {
91 | border-bottom: none;
92 | color: #000000;
93 | font-family: monospace, fixed;
94 | font-size: 16px;
95 | margin-bottom: 0px;
96 | margin-left: 2em;
97 | margin-top: 1.5em;
98 | }
99 |
100 |
101 | /* Style of paragraphs on a configuration settings page. */
102 | dl.section.user ~ * {
103 | margin-bottom: 10px;
104 | margin-left: 4em;
105 | margin-right: 4em;
106 | margin-top: 0px;
107 | }
108 |
109 |
110 | /* Hide the configuration setting marker. */
111 | dl.section.user {
112 | display: none;
113 | }
114 |
115 |
116 | /* Overrides for code fragments and lines. */
117 | div.fragment {
118 | background: #ffffff;
119 | border: none;
120 | padding: 5px;
121 | }
122 |
123 |
124 | div.line {
125 | color: #3a3a3a;
126 | }
127 |
128 |
129 | /* Overrides for code syntax highlighting colors. */
130 | span.comment {
131 | color: #008000;
132 | }
133 |
134 |
135 | span.keyword, span.keywordtype, span.keywordflow {
136 | color: #0000ff;
137 | }
138 |
139 |
140 | span.preprocessor {
141 | color: #50015a;
142 | }
143 |
144 |
145 | span.stringliteral, span.charliteral {
146 | color: #800c0c;
147 | }
148 |
149 |
150 | a.code, a.code:visited, a.line, a.line:visited {
151 | color: #496194;
152 | }
153 |
--------------------------------------------------------------------------------
/docs/doxygen/pages.dox:
--------------------------------------------------------------------------------
1 | /**
2 | @mainpage Overview
3 | @anchor sigv4
4 | @brief AWS SigV4 Library
5 |
6 | The AWS SigV4 Library is a standalone library for generating signatures
7 | and authorization headers according to the specifications of the AWS Signature
8 | Version 4 signing process. This library aids applications in sending direct
9 | HTTP requests to AWS services requiring SigV4 authentication. The library is
10 | written in C and designed to be compliant with ISO C90 and MISRA C and has no
11 | dependencies on any additional libraries other than the standard C library.
12 |
13 | @section sigv4_memory_requirements Memory Requirements
14 | @brief Memory requirements of the SigV4 Library.
15 |
16 | @include{doc} size_table.md
17 |
18 | @section sigv4_design Design
19 | @brief SigV4 Library Design
20 |
21 | Memory Usage
22 |
23 | All functions in the SigV4 library operate only on the buffers provided and use only
24 | local variables on the stack.
25 |
26 |
27 | Compliance & Coverage
28 |
29 |
30 | The SIGV4 library is designed to be compliant with ISO C90 and MISRA C:2012.
31 | All functions are written to have low complexity scores. Unit tests and CBMC
32 | proofs are written to cover every path of execution and achieve 100% branch
33 | coverage.
34 |
35 |
36 | The diagram below demonstrates the happy path an application can take to use
37 | the SigV4 library to interact with AWS Services that support SigV4 authentication via HTTP requests.
38 |
39 | @image html sigv4_design.png "SigV4 Library Usage diagram" width=90%
40 |
41 | */
42 |
43 | /**
44 | @page sigv4_config Configurations
45 | @brief Configurations of the AWS SigV4 Library.
46 |
48 | @par configpagestyle
49 |
50 | Configuration settings are C pre-processor constants. They can be set with a
51 | `\#define` in the config file (`sigv4_config.h`) or by using a
52 | compiler option such as -D in gcc.
53 |
54 | @section SIGV4_DO_NOT_USE_CUSTOM_CONFIG
55 | @copydoc SIGV4_DO_NOT_USE_CUSTOM_CONFIG
56 |
57 | @section sigv4_logerror LogError
58 | @copydoc LogError
59 |
60 | @section sigv4_logwarn LogWarn
61 | @copydoc LogWarn
62 |
63 | @section sigv4_loginfo LogInfo
64 | @copydoc LogInfo
65 |
66 | @section sigv4_logdebug LogDebug
67 | @copydoc LogDebug
68 | */
69 |
70 | /**
71 | @page sigv4_functions Functions
72 | @brief Primary functions of the AWS SigV4 library:
73 | @subpage sigV4_generateHTTPAuthorization_function
74 | @subpage sigV4_awsIotDateToIso8601_function
75 | @subpage sigV4_encodeURI_function
76 |
77 | @page sigV4_generateHTTPAuthorization_function SigV4_GenerateHTTPAuthorization
78 | @snippet sigv4.h declare_sigV4_generateHTTPAuthorization_function
79 | @copydoc SigV4_GenerateHTTPAuthorization
80 |
81 | @page sigV4_awsIotDateToIso8601_function SigV4_AwsIotDateToIso8601
82 | @snippet sigv4.h declare_sigV4_awsIotDateToIso8601_function
83 | @copydoc SigV4_AwsIotDateToIso8601
84 |
85 | @page sigV4_encodeURI_function SigV4_EncodeURI
86 | @snippet sigv4.h declare_sigV4_encodeURI_function
87 | @copydoc SigV4_EncodeURI
88 | */
89 |
90 |
91 | /**
92 | @defgroup sigv4_enum_types Enumerated Types
93 | @brief Enumerated types of the SigV4 library
94 |
95 | @defgroup sigv4_struct_types Struct Types
96 | @brief Struct types of the SigV4 library
97 | */
98 |
--------------------------------------------------------------------------------
/tools/cmock/coverage.cmake:
--------------------------------------------------------------------------------
1 | # Taken from amazon-freertos repository
2 | cmake_minimum_required(VERSION 3.13)
3 | set(BINARY_DIR ${CMAKE_BINARY_DIR})
4 | # reset coverage counters
5 | execute_process(
6 | COMMAND lcov --directory ${CMAKE_BINARY_DIR}
7 | --base-directory ${CMAKE_BINARY_DIR}
8 | --zerocounters
9 |
10 | COMMAND mkdir -p ${CMAKE_BINARY_DIR}/coverage
11 | )
12 | # make the initial/baseline capture a zeroed out files
13 | execute_process( COMMAND lcov --directory ${CMAKE_BINARY_DIR}
14 | --base-directory ${CMAKE_BINARY_DIR}
15 | --initial
16 | --capture
17 | --rc branch_coverage=1
18 | --ignore-errors empty
19 | --ignore-errors source
20 | --rc genhtml_branch_coverage=1
21 | --output-file=${CMAKE_BINARY_DIR}/base_coverage.info
22 | --quiet
23 | )
24 | file(GLOB files "${CMAKE_BINARY_DIR}/bin/tests/*")
25 |
26 | set(REPORT_FILE ${CMAKE_BINARY_DIR}/utest_report.txt)
27 | file(WRITE ${REPORT_FILE} "")
28 | # execute all files in bin directory, gathering the output to show it in CI
29 | foreach(testname ${files})
30 | get_filename_component(test
31 | ${testname}
32 | NAME_WLE
33 | )
34 | message("Running ${testname}")
35 | execute_process(COMMAND ${testname} OUTPUT_FILE ${CMAKE_BINARY_DIR}/${test}_out.txt)
36 |
37 | file(READ ${CMAKE_BINARY_DIR}/${test}_out.txt CONTENTS)
38 | file(APPEND ${REPORT_FILE} "${CONTENTS}")
39 | endforeach()
40 |
41 |
42 | # generate Junit style xml output
43 | execute_process(COMMAND ruby
44 | ${CMOCK_DIR}/vendor/unity/auto/parse_output.rb
45 | -xml ${REPORT_FILE}
46 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
47 | )
48 |
49 | # capture data after running the tests
50 | execute_process(
51 | COMMAND lcov --capture
52 | --rc branch_coverage=1
53 | --ignore-errors empty
54 | --ignore-errors source
55 | --rc genhtml_branch_coverage=1
56 | --base-directory ${CMAKE_BINARY_DIR}
57 | --directory ${CMAKE_BINARY_DIR}
58 | --output-file ${CMAKE_BINARY_DIR}/second_coverage.info
59 | --quiet
60 | )
61 |
62 | # combile baseline results (zeros) with the one after running the tests
63 | execute_process(
64 | COMMAND lcov --base-directory ${CMAKE_BINARY_DIR}
65 | --directory ${CMAKE_BINARY_DIR}
66 | --add-tracefile ${CMAKE_BINARY_DIR}/base_coverage.info
67 | --add-tracefile ${CMAKE_BINARY_DIR}/second_coverage.info
68 | --output-file ${CMAKE_BINARY_DIR}/coverage.info
69 | --no-external
70 | --rc branch_coverage=1
71 | --ignore-errors empty
72 | --ignore-errors source
73 | --quiet
74 | )
75 | execute_process(
76 | COMMAND genhtml --rc branch_coverage=1
77 | --ignore-errors empty
78 | --ignore-errors source
79 | --branch-coverage
80 | --output-directory ${CMAKE_BINARY_DIR}/coverage
81 | ${CMAKE_BINARY_DIR}/coverage.info
82 | --quiet
83 | )
84 |
--------------------------------------------------------------------------------
/test/cbmc/include/sigv4_stubs.h:
--------------------------------------------------------------------------------
1 | /*
2 | * SigV4 Library v1.3.0
3 | * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | *
5 | * SPDX-License-Identifier: MIT
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
8 | * this software and associated documentation files (the "Software"), to deal in
9 | * the Software without restriction, including without limitation the rights to
10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11 | * the Software, and to permit persons to whom the Software is furnished to do so,
12 | * subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in all
15 | * copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 | */
24 |
25 | /**
26 | * @file sigv4_stubs.h
27 | * @brief Declarations for the (normally) static functions from sigv4.c.
28 | * Please see sigv4.c for documentation.
29 | */
30 |
31 | #ifndef SIGV4_STUBS_H_
32 | #define SIGV4_STUBS_H_
33 |
34 | #include
35 |
36 | #include
37 | #include
38 |
39 | void addToDate( const char formatChar,
40 | int32_t result,
41 | SigV4DateTime_t * pDateElements );
42 |
43 | SigV4Status_t scanValue( const char * pDate,
44 | const char formatChar,
45 | size_t readLoc,
46 | size_t lenToRead,
47 | SigV4DateTime_t * pDateElements );
48 |
49 | SigV4Status_t writeLineToCanonicalRequest( const char * pLine,
50 | size_t lineLen,
51 | CanonicalContext_t * pCanonicalContext );
52 |
53 | SigV4Status_t SigV4_EncodeURI( const char * pUri,
54 | size_t uriLen,
55 | char * pCanonicalURI,
56 | size_t * canonicalURILen,
57 | bool encodeSlash,
58 | bool doubleEncodeEquals );
59 |
60 | SigV4Status_t generateCanonicalQuery( const char * pQuery,
61 | size_t queryLen,
62 | const bool doubleEncodeEqualsInParmsValues,
63 | CanonicalContext_t * pCanonicalContext );
64 |
65 | SigV4Status_t generateCanonicalAndSignedHeaders( const char * pHeaders,
66 | size_t headersLen,
67 | uint32_t flags,
68 | CanonicalContext_t * canonicalRequest,
69 | char ** pSignedHeaders,
70 | size_t * pSignedHeadersLen );
71 |
72 | SigV4Status_t copyHeaderStringToCanonicalBuffer( const char * pData,
73 | size_t dataLen,
74 | uint32_t flags,
75 | char separator,
76 | CanonicalContext_t * canonicalRequest );
77 |
78 | #endif /* ifndef SIGV4_STUBS_H_ */
79 |
--------------------------------------------------------------------------------
/test/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Project information.
2 | cmake_minimum_required( VERSION 3.13.0 )
3 | project( "SigV4 tests"
4 | VERSION 1.3.0
5 | LANGUAGES C )
6 |
7 | # Allow the project to be organized into folders.
8 | set_property( GLOBAL PROPERTY USE_FOLDERS ON )
9 |
10 | set( CMAKE_C_STANDARD 99 )
11 | set( CMAKE_C_STANDARD_REQUIRED ON )
12 |
13 | # Do not allow in-source build.
14 | if( ${PROJECT_SOURCE_DIR} STREQUAL ${PROJECT_BINARY_DIR} )
15 | message( FATAL_ERROR "In-source build is not allowed. Please build in a separate directory, such as ${PROJECT_SOURCE_DIR}/build." )
16 | endif()
17 |
18 | # Set global path variables.
19 | get_filename_component( __MODULE_ROOT_DIR "${CMAKE_CURRENT_LIST_DIR}/.." ABSOLUTE )
20 | set( MODULE_ROOT_DIR ${__MODULE_ROOT_DIR} CACHE INTERNAL "SigV4 repository root." )
21 |
22 | # Configure options to always show in CMake GUI.
23 | # If no configuration is defined, turn everything on.
24 | if( NOT DEFINED COV_ANALYSIS AND NOT DEFINED UNITTEST )
25 | set( COV_ANALYSIS ON )
26 | set( UNITTEST OFF ) # Default set to OFF for backward compatibility
27 | endif()
28 |
29 | # Set output directories.
30 | set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin )
31 | set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib )
32 | set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib )
33 |
34 | # ====================== Coverity Analysis Configuration ======================
35 | # Include filepaths for source and include.
36 | include( ${MODULE_ROOT_DIR}/sigv4FilePaths.cmake )
37 |
38 | if( COV_ANALYSIS )
39 | # Target for Coverity analysis that builds the library.
40 | add_library( coverity_analysis
41 | ${SIGV4_SOURCES} )
42 |
43 | # Verify ISO C90 compliance of libray.
44 | target_compile_options( coverity_analysis PUBLIC -std=c90 )
45 |
46 | # SigV4 public include path and test config file
47 | target_include_directories( coverity_analysis
48 | PUBLIC
49 | ${SIGV4_INCLUDE_PUBLIC_DIRS}
50 | "${CMAKE_CURRENT_LIST_DIR}/include" )
51 |
52 | # Build without debug enabled when performing static analysis
53 | target_compile_options(coverity_analysis PUBLIC -DNDEBUG -DDISABLE_LOGGING)
54 | endif()
55 |
56 | # ============================ Test Configuration ============================
57 | if( UNITTEST )
58 | # Define a CMock resource path.
59 | set( CMOCK_DIR ${MODULE_ROOT_DIR}/test/unit-test/CMock CACHE INTERNAL "CMock library source directory." )
60 |
61 | # Include CMock build configuration.
62 | include( unit-test/cmock_build.cmake )
63 |
64 | # Check if the CMock source directory exists, and if not present, clone the submodule
65 | # if BUILD_CLONE_SUBMODULES configuration is enabled.
66 | if( NOT EXISTS ${CMOCK_DIR}/src )
67 | # Attempt to clone CMock.
68 | clone_cmock()
69 | endif()
70 |
71 | # Add unit test and coverage configuration.
72 |
73 | # Use CTest utility for managing test runs. This has to be added BEFORE
74 | # defining test targets with add_test()
75 | enable_testing()
76 |
77 | # Add build targets for CMock and Unit, required for unit testing.
78 | add_cmock_targets()
79 |
80 | # Add function to enable CMock based tests and coverage.
81 | include( ${MODULE_ROOT_DIR}/tools/cmock/create_test.cmake )
82 |
83 | # Include build configuration for unit tests.
84 | add_subdirectory( unit-test )
85 |
86 | # ==================== Coverage Analysis configuration ========================
87 |
88 | # Add a target for running coverage on tests.
89 | add_custom_target( coverage
90 | COMMAND ${CMAKE_COMMAND} -DCMOCK_DIR=${CMOCK_DIR}
91 | -P ${MODULE_ROOT_DIR}/tools/cmock/coverage.cmake
92 | DEPENDS cmock unity sigv4_utest
93 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
94 | )
95 | endif()
96 |
--------------------------------------------------------------------------------
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing Guidelines
2 |
3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional
4 | documentation, we greatly value feedback and contributions from our community.
5 |
6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary
7 | information to effectively respond to your bug report or contribution.
8 |
9 |
10 | ## Reporting Bugs/Feature Requests
11 |
12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features.
13 |
14 | When filing an issue, please check [existing open](https://github.com/aws/SigV4-for-AWS-IoT-embedded-sdk/issues), or [recently closed](https://github.com/aws/SigV4-for-AWS-IoT-embedded-sdk/issues?q=is%3Aissue+is%3Aclosed) issues to make sure somebody else hasn't already
15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful:
16 |
17 | * A reproducible test case or series of steps
18 | * The version of our code being used
19 | * Any modifications you've made relevant to the bug
20 | * Anything unusual about your environment or deployment
21 |
22 |
23 | ## Contributing via Pull Requests
24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that:
25 |
26 | 1. You are working against the latest source on the *main* branch.
27 | 1. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already.
28 | 1. You open an issue to discuss any significant work - we would hate for your time to be wasted.
29 |
30 | To send us a pull request, please:
31 |
32 | 1. Fork the repository.
33 | 1. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change.
34 | 1. Ensure that your contributions conform to the [style guide](https://docs.aws.amazon.com/embedded-csdk/202011.00/lib-ref/docs/doxygen/output/html/guide_developer_styleguide.html).
35 | 1. Format your code with uncrustify, using the config available in [FreeRTOS/CI-CD-Github-Actions](https://github.com/FreeRTOS/CI-CD-Github-Actions/blob/main/formatting/uncrustify.cfg).
36 | 1. Ensure local tests pass.
37 | 1. Commit to your fork using clear commit messages.
38 | 1. Send us a pull request, answering any default questions in the pull request interface.
39 | 1. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation.
40 |
41 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and
42 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/).
43 |
44 |
45 | ## Finding contributions to work on
46 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels ((enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/aws/SigV4-for-AWS-IoT-embedded-sdk/labels?q=help+wanted) issues is a great place to start.
47 |
48 |
49 | ## Code of Conduct
50 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
51 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
52 | opensource-codeofconduct@amazon.com with any additional questions or comments.
53 |
54 |
55 | ## Security issue notifications
56 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](https://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public Github issue.
57 |
58 |
59 | ## Licensing
60 |
61 | See the [LICENSE](../LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution.
62 |
63 | We may ask you to sign a [Contributor License Agreement (CLA)](https://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes.
64 |
--------------------------------------------------------------------------------
/test/cbmc/include/sigv4_config.h:
--------------------------------------------------------------------------------
1 | /*
2 | * SigV4 Library v1.3.0
3 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | *
5 | * SPDX-License-Identifier: MIT
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
8 | * this software and associated documentation files (the "Software"), to deal in
9 | * the Software without restriction, including without limitation the rights to
10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11 | * the Software, and to permit persons to whom the Software is furnished to do so,
12 | * subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in all
15 | * copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 | */
24 |
25 | /**
26 | * @file sigv4_config.h
27 | * @brief The default values for configuration macros used by the SigV4 Library.
28 | *
29 | * @note This file should NOT be modified. If custom values are needed for any
30 | * configuration macros, a sigv4_config.h file should be provided to the SigV4
31 | * Library to override the default values defined in this file. To use
32 | * the custom config file, the preprocessor macro SIGV4_DO_NOT_USE_CUSTOM_CONFIG
33 | * must NOT be set.
34 | */
35 |
36 | #ifndef SIGV4_CONFIG_H_
37 | #define SIGV4_CONFIG_H_
38 |
39 | /**
40 | * @brief Macro indicating the largest block size of any hashing
41 | * algorithm used for SigV4 authentication i.e. the maximum of all
42 | * values specified for the hashBlockLen in #SigV4CryptoInterface_t.
43 | * For example, using SHA-512 would require this value to be at least 128.
44 | *
45 | * Possible values: Any positive 32 bit integer.
46 | * Default value: `64`
47 | */
48 | #define SIGV4_HASH_MAX_BLOCK_LENGTH ( MAX_HASH_BLOCK_LEN - 1U )
49 |
50 | /**
51 | * @brief Macro defining the maximum digest length of the specified hash function,
52 | * used to determine the length of the output buffer.
53 | *
54 | * This macro should be updated if using a hashing algorithm other than SHA256
55 | * (32 byte digest length). For example, using SHA512 would require this
56 | * value to be at least 64.
57 | *
58 | * Possible values: Any positive 32 bit integer.
59 | * Default value: `32`
60 | */
61 | #define SIGV4_HASH_MAX_DIGEST_LENGTH ( MAX_HASH_DIGEST_LEN - 1U )
62 |
63 | /**
64 | * @brief Macro defining the size of the internal buffer used for incremental
65 | * canonicalization and hashing.
66 | *
67 | * A buffer of this size in bytes is declared on the stack. It should be be
68 | * large enough for the digest output of the specified hash function.
69 | *
70 | * Possible values: Any positive 32 bit integer.
71 | * Default value: `1024`
72 | */
73 | #ifndef SIGV4_PROCESSING_BUFFER_LENGTH
74 | #define SIGV4_PROCESSING_BUFFER_LENGTH 60U
75 | #endif
76 |
77 | /**
78 | * @brief Macro defining the maximum number of headers in the request, used to
79 | * assist the library in sorting header fields during canonicalization.
80 | *
81 | * This macro should be updated if the number of request headers the application
82 | * wishes to sign is higher or lower than the default value (100).
83 | *
84 | * Possible values: Any positive 32 bit integer.
85 | * Default value: `100`
86 | */
87 | #ifndef SIGV4_MAX_HTTP_HEADER_COUNT
88 | #define SIGV4_MAX_HTTP_HEADER_COUNT 5U
89 | #endif
90 |
91 | /**
92 | * @brief Macro defining the maximum number of query key/value pairs, used to
93 | * assist the library in sorting query keys during canonicalization.
94 | *
95 | * This macro should be updated if the number of query key/value pairs the
96 | * application wishes to sign is higher or lower than the default value (100).
97 | *
98 | * Possible values: Any positive 32 bit integer.
99 | * Default value: `100`
100 | */
101 | #ifndef SIGV4_MAX_QUERY_PAIR_COUNT
102 | #define SIGV4_MAX_QUERY_PAIR_COUNT 5U
103 | #endif
104 |
105 | #endif /* ifndef SIGV4_CONFIG_H_ */
106 |
--------------------------------------------------------------------------------
/tools/coverity/README.md:
--------------------------------------------------------------------------------
1 | # Static code analysis for AWS SigV4 Library
2 | This directory is made for the purpose of statically testing the MISRA C:2012 compliance of AWS SigV4 Library using
3 | [Synopsys Coverity](https://www.synopsys.com/software-integrity/security-testing/static-analysis-sast.html) static analysis tool.
4 | To that end, this directory provides a [configuration file](https://github.com/aws/SigV4-for-AWS-IoT-embedded-sdk/blob/main/tools/coverity/misra.config) to use when
5 | building a binary for the tool to analyze.
6 |
7 | > **Note**
8 | For generating the report as outlined below, we have used Coverity version 2023.6.1.
9 |
10 | For details regarding the suppressed violations in the report (which can be generated using the instructions described below), please
11 | see the [MISRA.md](https://github.com/aws/SigV4-for-AWS-IoT-embedded-sdk/blob/main/MISRA.md) file.
12 |
13 | ## Getting Started
14 | ### Prerequisites
15 | You can run this on a platform supported by Coverity. The list and other details can be found [here](https://sig-docs.synopsys.com/polaris/topics/c_coverity-compatible-platforms.html).
16 | To compile and run the Coverity target successfully, you must have the following:
17 |
18 | 1. CMake version > 3.13.0 (You can check whether you have this by typing `cmake --version`)
19 | 2. GCC compiler
20 | - You can see the downloading and installation instructions [here](https://gcc.gnu.org/install/).
21 | 3. Download the repo and include the submodules using the following commands.
22 | - `git clone --recurse-submodules git@github.com:aws/SigV4-for-AWS-IoT-embedded-sdk.git ./SigV4-for-AWS-IoT-embedded-sdk`
23 | - `cd ./SigV4-for-AWS-IoT-embedded-sdk`
24 | - `git submodule update --checkout --init --recursive`
25 |
26 | ### To build and run coverity:
27 | Go to the root directory of the library and run the following commands in terminal:
28 | 1. Update the compiler configuration in Coverity
29 | ~~~
30 | cov-configure --force --compiler cc --comptype gcc
31 | ~~~
32 | 2. Create the build files using CMake in a `build` directory
33 | ~~~
34 | cmake -B build -S test
35 | ~~~
36 | 3. Go to the build directory and copy the coverity configuration file
37 | ~~~
38 | cd build/
39 | ~~~
40 | 4. Build the static analysis target
41 | ~~~
42 | cov-build --emit-complementary-info --dir cov-out make coverity_analysis
43 | ~~~
44 | 5. Go to the Coverity output directory (`cov-out`) and begin Coverity static analysis
45 | ~~~
46 | cd cov-out/
47 | cov-analyze --dir . --coding-standard-config ../../tools/coverity/misra.config --tu-pattern "file('.*/source/.*')"
48 | ~~~
49 | 6. Format the errors in HTML format so that it is more readable while removing the test and build directory from the report
50 | ~~~
51 | cov-format-errors --dir . --file "source" --exclude-files '(/build/|/test/)' --html-output html-out;
52 | ~~~
53 | 7. Format the errors in JSON format to perform a jq query to get a simplified list of any exceptions.
54 | NOTE: A blank output means there are no defects that aren't being suppressed by the config or inline comments.
55 | ~~~
56 | cov-format-errors --dir . --file "source" --exclude-files '(/build/|/test/)' --json-output-v2 defects.json;
57 | echo -e "\n-------------------------Non-Suppresed Deviations, if any, Listed Below-------------------------\n";
58 | jq '.issues[] | .events[] | .eventTag ' defects.json | sort | uniq -c | sort -nr;
59 | echo -e "\n-------------------------Non-Suppresed Deviations, if any, Listed Above-------------------------\n";
60 | ~~~
61 |
62 | For your convenience the commands above are below to be copy/pasted into a UNIX command friendly terminal.
63 | ~~~
64 | cov-configure --force --compiler cc --comptype gcc;
65 | cmake -B build -S test;
66 | cd build/;
67 | cov-build --emit-complementary-info --dir cov-out make coverity_analysis;
68 | cd cov-out/
69 | cov-analyze --dir . --coding-standard-config ../../tools/coverity/misra.config --tu-pattern "file('.*/source/.*')";
70 | cov-format-errors --dir . --file "source" --exclude-files '(/build/|/test/)' --html-output html-out;
71 | cov-format-errors --dir . --file "source" --exclude-files '(/build/|/test/)' --json-output-v2 defects.json;
72 | echo -e "\n-------------------------Non-Suppresed Deviations, if any, Listed Below-------------------------\n";
73 | jq '.issues[] | .events[] | .eventTag ' defects.json | sort | uniq -c | sort -nr;
74 | echo -e "\n-------------------------Non-Suppresed Deviations, if any, Listed Above-------------------------\n";
75 | cd ../../;
76 | ~~~
77 |
78 | You should now have the HTML formatted violations list in a directory named `build/cov-out/html-output`.
79 | With the current configuration and the provided project, you should not see any deviations.
80 |
--------------------------------------------------------------------------------
/test/unit-test/sigv4_config.h:
--------------------------------------------------------------------------------
1 | /*
2 | * SigV4 Library v1.3.0
3 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | *
5 | * SPDX-License-Identifier: MIT
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
8 | * this software and associated documentation files (the "Software"), to deal in
9 | * the Software without restriction, including without limitation the rights to
10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11 | * the Software, and to permit persons to whom the Software is furnished to do so,
12 | * subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in all
15 | * copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 | */
24 |
25 | /**
26 | * @file sigv4_config.h
27 | * @brief The default values for configuration macros used by the SigV4 Library.
28 | *
29 | * @note This file should NOT be modified. If custom values are needed for any
30 | * configuration macros, a sigv4_config.h file should be provided to the SigV4
31 | * Library to override the default values defined in this file. To use
32 | * the custom config file, the preprocessor macro SIGV4_DO_NOT_USE_CUSTOM_CONFIG
33 | * must NOT be set.
34 | */
35 |
36 | #ifndef SIGV4_CONFIG_H_
37 | #define SIGV4_CONFIG_H_
38 |
39 | /* @[code_example_loggingmacros] */
40 | /************* Define Logging Macros using printf function ***********/
41 |
42 | #define PrintfError( ... ) printf( "[%d] Error: ", __LINE__ ); printf( __VA_ARGS__ ); printf( "\n" )
43 | #define PrintfWarn( ... ) printf( "[%d] Warn: ", __LINE__ ); printf( __VA_ARGS__ ); printf( "\n" )
44 | #define PrintfInfo( ... ) printf( "[%d] Info: ", __LINE__ ); printf( __VA_ARGS__ ); printf( "\n" )
45 | #define PrintfDebug( ... ) printf( "[%d] Debug: ", __LINE__ ); printf( __VA_ARGS__ ); printf( "\n" )
46 |
47 | #ifdef LOGGING_LEVEL_ERROR
48 | #define LogError( message ) PrintfError message
49 | #elif defined( LOGGING_LEVEL_WARNING )
50 | #define LogError( message ) PrintfError message
51 | #define LogWarn( message ) PrintfWarn message
52 | #elif defined( LOGGING_LEVEL_INFO )
53 | #define LogError( message ) PrintfError message
54 | #define LogWarn( message ) PrintfWarn message
55 | #define LogInfo( message ) PrintfInfo message
56 | #elif defined( LOGGING_LEVEL_DEBUG )
57 | #define LogError( message ) PrintfError message
58 | #define LogWarn( message ) PrintfWarn message
59 | #define LogInfo( message ) PrintfInfo message
60 | #define LogDebug( message ) PrintfDebug message
61 | #endif /* ifdef LOGGING_LEVEL_ERROR */
62 |
63 | /**************************************************/
64 | /* @[code_example_loggingmacros] */
65 |
66 | /**
67 | * @brief Macro defining the size of the internal buffer used for incremental
68 | * canonicalization and hashing.
69 | *
70 | * A buffer of this size in bytes is declared on the stack. It should be be
71 | * large enough for the digest output of the specified hash function.
72 | *
73 | * Possible values: Any positive 32 bit integer.
74 | * Default value: `1024`
75 | */
76 | #ifndef SIGV4_PROCESSING_BUFFER_LENGTH
77 | #define SIGV4_PROCESSING_BUFFER_LENGTH 428
78 | #endif
79 |
80 | /**
81 | * @brief Macro defining the maximum number of headers in the request, used to
82 | * assist the library in sorting header fields during canonicalization.
83 | *
84 | * This macro should be updated if the number of request headers the application
85 | * wishes to sign is higher or lower than the default value (100).
86 | *
87 | * Possible values: Any positive 32 bit integer.
88 | * Default value: `100`
89 | */
90 | #ifndef SIGV4_MAX_HTTP_HEADER_COUNT
91 | #define SIGV4_MAX_HTTP_HEADER_COUNT 7U
92 | #endif
93 |
94 | /**
95 | * @brief Macro defining the maximum number of query key/value pairs, used to
96 | * assist the library in sorting query keys during canonicalization.
97 | *
98 | * This macro should be updated if the number of query key/value pairs the
99 | * application wishes to sign is higher or lower than the default value (100).
100 | *
101 | * Possible values: Any positive 32 bit integer.
102 | * Default value: `100`
103 | */
104 | #ifndef SIGV4_MAX_QUERY_PAIR_COUNT
105 | #define SIGV4_MAX_QUERY_PAIR_COUNT 5U
106 | #endif
107 |
108 | #endif /* ifndef SIGV4_CONFIG_H_ */
109 |
--------------------------------------------------------------------------------
/test/cbmc/proofs/lib/summarize.py:
--------------------------------------------------------------------------------
1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | # SPDX-License-Identifier: MIT-0
3 |
4 | import argparse
5 | import json
6 | import logging
7 | import os
8 | import sys
9 |
10 |
11 | DESCRIPTION = """Print 2 tables in GitHub-flavored Markdown that summarize
12 | an execution of CBMC proofs."""
13 |
14 |
15 | def get_args():
16 | """Parse arguments for summarize script."""
17 | parser = argparse.ArgumentParser(description=DESCRIPTION)
18 | for arg in [{
19 | "flags": ["--run-file"],
20 | "help": "path to the Litani run.json file",
21 | "required": True,
22 | }]:
23 | flags = arg.pop("flags")
24 | parser.add_argument(*flags, **arg)
25 | return parser.parse_args()
26 |
27 |
28 | def _get_max_length_per_column_list(data):
29 | ret = [len(item) + 1 for item in data[0]]
30 | for row in data[1:]:
31 | for idx, item in enumerate(row):
32 | ret[idx] = max(ret[idx], len(item) + 1)
33 | return ret
34 |
35 |
36 | def _get_table_header_separator(max_length_per_column_list):
37 | line_sep = ""
38 | for max_length_of_word_in_col in max_length_per_column_list:
39 | line_sep += "|" + "-" * (max_length_of_word_in_col + 1)
40 | line_sep += "|\n"
41 | return line_sep
42 |
43 |
44 | def _get_entries(max_length_per_column_list, row_data):
45 | entries = []
46 | for row in row_data:
47 | entry = ""
48 | for idx, word in enumerate(row):
49 | max_length_of_word_in_col = max_length_per_column_list[idx]
50 | space_formatted_word = (max_length_of_word_in_col - len(word)) * " "
51 | entry += "| " + word + space_formatted_word
52 | entry += "|\n"
53 | entries.append(entry)
54 | return entries
55 |
56 |
57 | def _get_rendered_table(data):
58 | table = []
59 | max_length_per_column_list = _get_max_length_per_column_list(data)
60 | entries = _get_entries(max_length_per_column_list, data)
61 | for idx, entry in enumerate(entries):
62 | if idx == 1:
63 | line_sep = _get_table_header_separator(max_length_per_column_list)
64 | table.append(line_sep)
65 | table.append(entry)
66 | table.append("\n")
67 | return "".join(table)
68 |
69 |
70 | def _get_status_and_proof_summaries(run_dict):
71 | """Parse a dict representing a Litani run and create lists summarizing the
72 | proof results.
73 |
74 | Parameters
75 | ----------
76 | run_dict
77 | A dictionary representing a Litani run.
78 |
79 |
80 | Returns
81 | -------
82 | A list of 2 lists.
83 | The first sub-list maps a status to the number of proofs with that status.
84 | The second sub-list maps each proof to its status.
85 | """
86 | count_statuses = {}
87 | proofs = [["Proof", "Status"]]
88 | for proof_pipeline in run_dict["pipelines"]:
89 | status_pretty_name = proof_pipeline["status"].title().replace("_", " ")
90 | try:
91 | count_statuses[status_pretty_name] += 1
92 | except KeyError:
93 | count_statuses[status_pretty_name] = 1
94 | if proof_pipeline["name"] == "print_tool_versions":
95 | continue
96 | proofs.append([proof_pipeline["name"], status_pretty_name])
97 | statuses = [["Status", "Count"]]
98 | for status, count in count_statuses.items():
99 | statuses.append([status, str(count)])
100 | return [statuses, proofs]
101 |
102 |
103 | def print_proof_results(out_file):
104 | """
105 | Print 2 strings that summarize the proof results.
106 | When printing, each string will render as a GitHub flavored Markdown table.
107 | """
108 | output = "## Summary of CBMC proof results\n\n"
109 | with open(out_file, encoding='utf-8') as run_json:
110 | run_dict = json.load(run_json)
111 | status_table, proof_table = _get_status_and_proof_summaries(run_dict)
112 | for summary in (status_table, proof_table):
113 | output += _get_rendered_table(summary)
114 |
115 | print(output)
116 | sys.stdout.flush()
117 |
118 | github_summary_file = os.getenv("GITHUB_STEP_SUMMARY")
119 | if github_summary_file:
120 | with open(github_summary_file, "a") as handle:
121 | print(output, file=handle)
122 | handle.flush()
123 | else:
124 | logging.warning(
125 | "$GITHUB_STEP_SUMMARY not set, not writing summary file")
126 |
127 | msg = (
128 | "Click the 'Summary' button to view a Markdown table "
129 | "summarizing all proof results")
130 | if run_dict["status"] != "success":
131 | logging.error("Not all proofs passed.")
132 | logging.error(msg)
133 | sys.exit(1)
134 | logging.info(msg)
135 |
136 |
137 | if __name__ == '__main__':
138 | args = get_args()
139 | logging.basicConfig(format="%(levelname)s: %(message)s")
140 | try:
141 | print_proof_results(args.run_file)
142 | except Exception as ex: # pylint: disable=broad-except
143 | logging.critical("Could not print results. Exception: %s", str(ex))
144 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AWS SigV4 Library
2 |
3 | **[API Documentation Pages for current and previous releases of this library can be found here](https://aws.github.io/SigV4-for-AWS-IoT-embedded-sdk/)**
4 |
5 | The AWS SigV4 Library is a standalone library for generating authorization
6 | headers and signatures according to the specifications of the
7 | [Signature Version 4](https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html)
8 | signing process. Authorization headers are required for authentication when
9 | sending HTTP requests to AWS. This library can optionally be used by
10 | applications sending direct HTTP requests to AWS services requiring SigV4
11 | authentication. This library has no dependencies on any additional libraries
12 | other than the standard C library. This library is distributed under the MIT
13 | Open Source License.
14 |
15 | This library has gone through code quality checks including verification that no
16 | function has a GNU Complexity score over 8, and checks against deviations from
17 | mandatory rules in the MISRA coding standard. Deviations from the MISRA C:2012
18 | guidelines are documented under MISRA Deviations. This library has also
19 | undergone static code analysis using Coverity static analysis, and validation of
20 | memory safety through the CBMC automated reasoning tool.
21 |
22 | See memory requirements for this library [here][memory_table].
23 |
24 | [memory_table]: ./docs/doxygen/include/size_table.md
25 |
26 | **AWS SigV4 v1.3.0
27 | [source code](https://github.com/aws/Sigv4-for-AWS-IoT-embedded-sdk/tree/v1.3.0/source)
28 | is part of the
29 | [FreeRTOS 202406.00 LTS](https://github.com/FreeRTOS/FreeRTOS-LTS/tree/202406.00-LTS)
30 | release.**
31 |
32 | ## AWS SigV4 Library Config File
33 |
34 | The AWS SigV4 library exposes build configuration macros that are required for
35 | building the library. A list of all the configurations and their default values
36 | are defined in [sigv4_config_defaults.h][default_config]. To provide custom
37 | values for the configuration macros, a config file named `sigv4_config.h` can be
38 | provided by the application to the library.
39 |
40 | [default_config]: source/include/sigv4_config_defaults.h
41 |
42 | By default, a `sigv4_config.h` config file is required to build the library. To
43 | disable this requirement and build the library with default configuration
44 | values, provide `SIGV4_DO_NOT_USE_CUSTOM_CONFIG` as a compile time preprocessor
45 | macro.
46 |
47 | **Thus, the SigV4 library can be built by either**:
48 |
49 | - Defining a `sigv4_config.h` file in the application, and adding it to the
50 | include directories list of the library.
51 |
52 | **OR**
53 |
54 | - Defining the `SIGV4_DO_NOT_USE_CUSTOM_CONFIG` preprocessor macro for the
55 | library build.
56 |
57 | ## Building the SigV4 Library
58 |
59 | The [sigv4FilePaths.cmake](sigv4FilePaths.cmake) file contains information of
60 | all the source files and header include paths required to build the SigV4
61 | library.
62 |
63 | As mentioned in the previous section, either a custom config file (i.e.
64 | `sigv4_config.h`) or `SIGV4_DO_NOT_USE_CUSTOM_CONFIG` macro needs to be provided
65 | to build the SigV4 library.
66 |
67 | To use CMake, please refer to the
68 | [sigV4FilePaths.cmake](https://github.com/aws/SigV4-for-AWS-IoT-embedded-sdk/blob/main/sigv4FilePaths.cmake)
69 | file, which contains the relevant information regarding source files and header
70 | include paths required to build this library.
71 |
72 | ## Building Unit Tests
73 |
74 | ### Platform Prerequisites
75 |
76 | - For running unit tests:
77 | - **C90 compiler** like gcc.
78 | - **CMake 3.13.0 or later**.
79 | - **Ruby 2.0.0 or later** is additionally required for the CMock test
80 | framework (that we use).
81 | - For running the coverage target, **gcov** and **lcov** are additionally
82 | required.
83 |
84 | ### Steps to build **Unit Tests**
85 |
86 | 1. Go to the root directory of this repository.
87 |
88 | 1. Run the _cmake_ command: `cmake -S test -B build -DUNITTEST=ON`.
89 |
90 | 1. Run this command to build the library and unit tests: `make -C build all`.
91 |
92 | 1. The generated test executables will be present in `build/bin/tests` folder.
93 |
94 | 1. Run `cd build && ctest` to execute all tests and view the test run summary.
95 |
96 | ## CBMC
97 |
98 | To learn more about CBMC and proofs specifically, review the training material
99 | [here](https://model-checking.github.io/cbmc-training).
100 |
101 | The `test/cbmc/proofs` directory contains CBMC proofs.
102 |
103 | In order to run these proofs you will need to install CBMC and other tools by
104 | following the instructions
105 | [here](https://model-checking.github.io/cbmc-training/installation.html).
106 |
107 | ## Reference examples
108 |
109 | The AWS IoT Embedded C-SDK repository contains
110 | [HTTP demos](https://github.com/aws/aws-iot-device-sdk-embedded-C/tree/main/demos/http)
111 | showing the use of the AWS SigV4 Library on a POSIX platform to authenticate
112 | HTTP requests to AWS S3 service.
113 |
114 | ## Generating documentation
115 |
116 | The Doxygen references found in this repository were created using Doxygen
117 | version 1.9.6. To generate these Doxygen pages, please run the following command
118 | from the root of this repository:
119 |
120 | ```shell
121 | doxygen docs/doxygen/config.doxyfile
122 | ```
123 |
124 | ## Contributing
125 |
126 | See [CONTRIBUTING.md](.github/CONTRIBUTING.md) for information on contributing.
127 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI Checks
2 |
3 | on:
4 | push:
5 | branches: ["**"]
6 | pull_request:
7 | branches: [main]
8 | workflow_dispatch:
9 |
10 | jobs:
11 | build-check-library:
12 | runs-on: ubuntu-latest
13 | steps:
14 | - name: Clone This Repo
15 | uses: actions/checkout@v3
16 |
17 | - name: Build in Release Mode
18 | run: |
19 | cmake -S test -B build/ \
20 | -G "Unix Makefiles" \
21 | -DCMAKE_BUILD_TYPE=Debug \
22 | -DCMAKE_C_FLAGS='-Wall -Wextra -Werror'
23 | make -C build/ all
24 |
25 | unittest:
26 | runs-on: ubuntu-latest
27 | steps:
28 | - name: Clone This Repo
29 | uses: actions/checkout@v3
30 |
31 | - name: Build
32 | run: |
33 | sudo apt-get install -y lcov
34 | cmake -S test -B build/ \
35 | -G "Unix Makefiles" \
36 | -DCMAKE_BUILD_TYPE=Debug \
37 | -DUNITTEST=ON \
38 | -DCMAKE_C_FLAGS='--coverage -Wall -Wextra -DNDEBUG'
39 | make -C build/ all
40 |
41 | - name: Test
42 | run: |
43 | cd build/
44 | ctest -E system --output-on-failure
45 | cd ..
46 |
47 | - name: Run Coverage
48 | run: |
49 | make -C build/ coverage
50 | declare -a EXCLUDE=("\*test\*" "\*CMakeCCompilerId.c")
51 | echo ${EXCLUDE[@]} | xargs lcov --rc branch_coverage=1 --ignore-errors empty --ignore-errors source -r build/coverage.info -o build/coverage.info
52 | lcov --rc branch_coverage=1 --ignore-errors empty --ignore-errors source --list build/coverage.info
53 |
54 | - name: Check Coverage
55 | uses: FreeRTOS/CI-CD-Github-Actions/coverage-cop@main
56 | with:
57 | coverage-file: ./build/coverage.info
58 |
59 | build-with-default-config:
60 | runs-on: ubuntu-latest
61 | steps:
62 | - name: Clone This Repo
63 | uses: actions/checkout@v3
64 |
65 | - name: Build
66 | run: |
67 | cmake -S test -B build/ \
68 | -G "Unix Makefiles" \
69 | -DCMAKE_BUILD_TYPE=Debug \
70 | -DCMAKE_C_FLAGS='-Wall -Wextra -Werror -DSIGV4_DO_NOT_USE_CUSTOM_CONFIG'
71 | make -C build/ all
72 |
73 | complexity:
74 | runs-on: ubuntu-latest
75 | steps:
76 | - uses: actions/checkout@v3
77 |
78 | - name: Check complexity
79 | uses: FreeRTOS/CI-CD-Github-Actions/complexity@main
80 | with:
81 | path: ./
82 |
83 | doxygen:
84 | runs-on: ubuntu-latest
85 | steps:
86 | - uses: actions/checkout@v3
87 |
88 | - name: Run doxygen build
89 | uses: FreeRTOS/CI-CD-Github-Actions/doxygen@main
90 | with:
91 | path: ./
92 |
93 | spell-check:
94 | runs-on: ubuntu-latest
95 | steps:
96 |
97 | - name: Clone This Repo
98 | uses: actions/checkout@v3
99 |
100 | - name: Run spellings check
101 | uses: FreeRTOS/CI-CD-Github-Actions/spellings@main
102 | with:
103 | path: ./
104 |
105 | formatting:
106 | runs-on: ubuntu-latest
107 | steps:
108 | - uses: actions/checkout@v3
109 |
110 | - name: Check formatting
111 | uses: FreeRTOS/CI-CD-Github-Actions/formatting@main
112 | with:
113 | path: ./
114 |
115 | git-secrets:
116 | runs-on: ubuntu-latest
117 | steps:
118 | - uses: actions/checkout@v3
119 |
120 | - name: Checkout awslabs/git-secrets
121 | uses: actions/checkout@v3
122 | with:
123 | repository: awslabs/git-secrets
124 | ref: master
125 | path: git-secrets
126 |
127 | - name: Install git-secrets
128 | run: cd git-secrets && sudo make install && cd ..
129 |
130 | - name: Run git-secrets
131 | run: |
132 | git-secrets --register-aws
133 | git-secrets --scan
134 |
135 | memory_statistics:
136 | runs-on: ubuntu-latest
137 | steps:
138 | - uses: actions/checkout@v3
139 | with:
140 | submodules: "recursive"
141 |
142 | - name: Install Python3
143 | uses: actions/setup-python@v3
144 | with:
145 | python-version: "3.11.0"
146 |
147 | - name: Measure sizes
148 | uses: FreeRTOS/CI-CD-Github-Actions/memory_statistics@main
149 | with:
150 | config: .github/memory_statistics_config.json
151 | check_against: docs/doxygen/include/size_table.md
152 |
153 | link-verifier:
154 | runs-on: ubuntu-latest
155 | steps:
156 | - uses: actions/checkout@v3
157 | - name: Check Links
158 | env:
159 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
160 | uses: FreeRTOS/CI-CD-Github-Actions/link-verifier@main
161 |
162 | verify-manifest:
163 | runs-on: ubuntu-latest
164 | steps:
165 | - uses: actions/checkout@v3
166 | with:
167 | submodules: true
168 | fetch-depth: 0
169 |
170 | # At time of writing the gitmodules are set not to pull
171 | # Even when using fetch submodules. Need to run this command
172 | # To force it to grab them.
173 | - name: Perform Recursive Clone
174 | shell: bash
175 | run: git submodule update --checkout --init --recursive
176 |
177 | - name: Run manifest verifier
178 | uses: FreeRTOS/CI-CD-GitHub-Actions/manifest-verifier@main
179 | with:
180 | path: ./
181 | fail-on-incorrect-version: true
182 |
183 | proof_ci:
184 | if: ${{ github.event.pull_request }}
185 | runs-on: cbmc_ubuntu-latest_32-core
186 | steps:
187 | - name: Set up CBMC runner
188 | uses: FreeRTOS/CI-CD-Github-Actions/set_up_cbmc_runner@main
189 | with:
190 | cbmc_version: "6.1.1"
191 |
192 | - name: Run CBMC
193 | uses: FreeRTOS/CI-CD-Github-Actions/run_cbmc@main
194 | with:
195 | proofs_dir: test/cbmc/proofs
196 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release automation
2 |
3 | on:
4 | workflow_dispatch:
5 | inputs:
6 | commit_id:
7 | description: 'Commit ID to tag and create a release for'
8 | required: true
9 | version_number:
10 | description: 'Release Version Number (Eg, v1.0.0)'
11 | required: true
12 |
13 | jobs:
14 | tag-commit:
15 | name: Generate SBOM and tag commit
16 | runs-on: ubuntu-latest
17 | steps:
18 | - name: Checkout code
19 | uses: actions/checkout@v4
20 | with:
21 | ref: ${{ github.event.inputs.commit_id }}
22 | - name: Configure git identity
23 | run: |
24 | git config --global user.name ${{ github.actor }}
25 | git config --global user.email ${{ github.actor }}@users.noreply.github.com
26 | - name: create a new branch that references commit id
27 | run: git checkout -b ${{ github.event.inputs.version_number }} ${{ github.event.inputs.commit_id }}
28 | - name: Generate SBOM
29 | uses: FreeRTOS/CI-CD-Github-Actions/sbom-generator@main
30 | with:
31 | repo_path: ./
32 | source_path: ./source
33 | - name: commit SBOM file
34 | run: |
35 | git add .
36 | git commit -m 'Update SBOM'
37 | git push -u origin ${{ github.event.inputs.version_number }}
38 | - name: Tag Commit and Push to remote
39 | run: |
40 | git tag ${{ github.event.inputs.version_number }} -a -m "AWS IoT SigV4 ${{ github.event.inputs.version_number }}"
41 | git push origin --tags
42 | - name: Verify tag on remote
43 | run: |
44 | git tag -d ${{ github.event.inputs.version_number }}
45 | git remote update
46 | git checkout tags/${{ github.event.inputs.version_number }}
47 | git diff ${{ github.event.inputs.commit_id }} tags/${{ github.event.inputs.version_number }}
48 | create-zip:
49 | needs: tag-commit
50 | name: Create ZIP and verify package for release asset.
51 | runs-on: ubuntu-latest
52 | steps:
53 | - name: Install ZIP tools
54 | run: sudo apt-get install zip unzip
55 | - name: Checkout code
56 | uses: actions/checkout@v4
57 | with:
58 | ref: ${{ github.event.inputs.commit_id }}
59 | path: SigV4-for-AWS-IoT-embedded-sdk
60 | submodules: recursive
61 | - name: Checkout disabled submodules
62 | run: |
63 | cd SigV4-for-AWS-IoT-embedded-sdk
64 | git submodule update --init --checkout --recursive
65 | - name: Create ZIP
66 | run: |
67 | zip -r SigV4-for-AWS-IoT-embedded-sdk-${{ github.event.inputs.version_number }}.zip SigV4-for-AWS-IoT-embedded-sdk -x "*.git*"
68 | ls ./
69 | - name: Validate created ZIP
70 | run: |
71 | mkdir zip-check
72 | mv SigV4-for-AWS-IoT-embedded-sdk-${{ github.event.inputs.version_number }}.zip zip-check
73 | cd zip-check
74 | unzip SigV4-for-AWS-IoT-embedded-sdk-${{ github.event.inputs.version_number }}.zip -d SigV4-for-AWS-IoT-embedded-sdk-${{ github.event.inputs.version_number }}
75 | ls SigV4-for-AWS-IoT-embedded-sdk-${{ github.event.inputs.version_number }}
76 | diff -r -x "*.git*" SigV4-for-AWS-IoT-embedded-sdk-${{ github.event.inputs.version_number }}/SigV4-for-AWS-IoT-embedded-sdk/ ../SigV4-for-AWS-IoT-embedded-sdk/
77 | cd ../
78 | - name: Build
79 | run: |
80 | cd zip-check/SigV4-for-AWS-IoT-embedded-sdk-${{ github.event.inputs.version_number }}/SigV4-for-AWS-IoT-embedded-sdk
81 | sudo apt-get install -y lcov
82 | cmake -S test -B build/ \
83 | -G "Unix Makefiles" \
84 | -DCMAKE_BUILD_TYPE=Debug \
85 | -DBUILD_CLONE_SUBMODULES=ON \
86 | -DCMAKE_C_FLAGS='--coverage -Wall -Wextra -Werror -DNDEBUG'
87 | make -C build/ all
88 | - name: Test
89 | run: |
90 | cd zip-check/SigV4-for-AWS-IoT-embedded-sdk-${{ github.event.inputs.version_number }}/SigV4-for-AWS-IoT-embedded-sdk/build/
91 | ctest -E system --output-on-failure
92 | cd ..
93 | - name: Create artifact of ZIP
94 | uses: actions/upload-artifact@v4
95 | with:
96 | name: SigV4-for-AWS-IoT-embedded-sdk-${{ github.event.inputs.version_number }}.zip
97 | path: zip-check/SigV4-for-AWS-IoT-embedded-sdk-${{ github.event.inputs.version_number }}.zip
98 | deploy-doxygen:
99 | needs: tag-commit
100 | name: Deploy doxygen documentation
101 | runs-on: ubuntu-latest
102 | steps:
103 | - name: Doxygen generation
104 | uses: FreeRTOS/CI-CD-Github-Actions/doxygen-generation@main
105 | with:
106 | ref: ${{ github.event.inputs.version_number }}
107 | add_release: "true"
108 | create-release:
109 | permissions:
110 | id-token: write
111 | needs:
112 | - create-zip
113 | - deploy-doxygen
114 | name: Create Release and Upload Release Asset
115 | runs-on: ubuntu-latest
116 | steps:
117 | - name: Create Release
118 | id: create_release
119 | uses: actions/create-release@v1
120 | env:
121 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
122 | with:
123 | tag_name: ${{ github.event.inputs.version_number }}
124 | release_name: ${{ github.event.inputs.version_number }}
125 | body: Release ${{ github.event.inputs.version_number }} of AWS IoT SigV4.
126 | draft: false
127 | prerelease: false
128 | - name: Download ZIP artifact
129 | uses: actions/download-artifact@v4
130 | with:
131 | name: SigV4-for-AWS-IoT-embedded-sdk-${{ github.event.inputs.version_number }}.zip
132 | - name: Upload Release Asset
133 | id: upload-release-asset
134 | uses: actions/upload-release-asset@v1
135 | env:
136 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
137 | with:
138 | upload_url: ${{ steps.create_release.outputs.upload_url }}
139 | asset_path: ./SigV4-for-AWS-IoT-embedded-sdk-${{ github.event.inputs.version_number }}.zip
140 | asset_name: SigV4-for-AWS-IoT-embedded-sdk-${{ github.event.inputs.version_number }}.zip
141 | asset_content_type: application/zip
142 | - name: Backup Release Asset
143 | uses: FreeRTOS/CI-CD-Github-Actions/artifact-backup@main
144 | with:
145 | artifact_path: ./SigV4-for-AWS-IoT-embedded-sdk-${{ github.event.inputs.version_number }}.zip
146 | release_tag: ${{ github.event.inputs.version_number }}
147 |
--------------------------------------------------------------------------------
/test/cbmc/proofs/SigV4_GenerateHTTPAuthorization/SigV4_GenerateHTTPAuthorization_harness.c:
--------------------------------------------------------------------------------
1 | /*
2 | * SigV4 Library v1.3.0
3 | * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | *
5 | * SPDX-License-Identifier: MIT
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
8 | * this software and associated documentation files (the "Software"), to deal in
9 | * the Software without restriction, including without limitation the rights to
10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11 | * the Software, and to permit persons to whom the Software is furnished to do so,
12 | * subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in all
15 | * copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 | */
24 |
25 | /**
26 | * @file SigV4_GenerateHTTPAuthorization_harness.c
27 | * @brief Implements the proof harness for the SigV4_GenerateHTTPAuthorization function.
28 | */
29 |
30 | /* Include paths for public enums, structures, and macros. */
31 | #include "stdlib.h"
32 | #include "sigv4.h"
33 | #include "sigv4_internal.h"
34 | #include "hash_stubs.h"
35 |
36 | void harness()
37 | {
38 | SigV4Parameters_t * pSigV4Params;
39 | SigV4HttpParameters_t * pHttpParams;
40 | SigV4CryptoInterface_t * pCryptoInterface;
41 | SigV4Credentials_t * pCredentials;
42 | char * pAuthBuf;
43 | size_t * authBufLen;
44 | char * pSignature;
45 | size_t signatureLen;
46 | SigV4Status_t status;
47 |
48 | pHttpParams = malloc( sizeof( SigV4HttpParameters_t ) );
49 | pSigV4Params = malloc( sizeof( SigV4Parameters_t ) );
50 | pCryptoInterface = malloc( sizeof( SigV4CryptoInterface_t ) );
51 | pCredentials = malloc( sizeof( SigV4Credentials_t ) );
52 |
53 | /* This property applies to all hash functions. */
54 | if( pCryptoInterface != NULL )
55 | {
56 | __CPROVER_assume( SIGV4_HMAC_SIGNING_KEY_PREFIX_LEN < pCryptoInterface->hashBlockLen && pCryptoInterface->hashBlockLen <= MAX_HASH_BLOCK_LEN );
57 | __CPROVER_assume( 0U < pCryptoInterface->hashDigestLen && pCryptoInterface->hashDigestLen <= MAX_HASH_DIGEST_LEN );
58 | __CPROVER_assume( pCryptoInterface->hashDigestLen <= pCryptoInterface->hashBlockLen );
59 | pCryptoInterface->hashInit = nondet_bool() ? NULL : HashInitStub;
60 | pCryptoInterface->hashUpdate = nondet_bool() ? NULL : HashUpdateStub;
61 | pCryptoInterface->hashFinal = nondet_bool() ? NULL : HashFinalStub;
62 | }
63 |
64 | if( pCredentials != NULL )
65 | {
66 | /* Make size assumptions for string-like types. */
67 | __CPROVER_assume( pCredentials->accessKeyIdLen <= MAX_ACCESS_KEY_ID_LEN );
68 | __CPROVER_assume( pCredentials->secretAccessKeyLen < CBMC_MAX_OBJECT_SIZE );
69 | pCredentials->pAccessKeyId = malloc( pCredentials->accessKeyIdLen );
70 | pCredentials->pSecretAccessKey = malloc( pCredentials->secretAccessKeyLen );
71 | }
72 |
73 | if( pHttpParams != NULL )
74 | {
75 | /* Make size assumptions for string-like types. */
76 | __CPROVER_assume( pHttpParams->payloadLen < CBMC_MAX_OBJECT_SIZE );
77 | __CPROVER_assume( pHttpParams->httpMethodLen < CBMC_MAX_OBJECT_SIZE );
78 | __CPROVER_assume( pHttpParams->pathLen < MAX_URI_LEN );
79 | __CPROVER_assume( pHttpParams->queryLen < MAX_QUERY_LEN );
80 | __CPROVER_assume( pHttpParams->headersLen < MAX_HEADERS_LEN );
81 | pHttpParams->pPayload = malloc( pHttpParams->payloadLen );
82 | pHttpParams->pHttpMethod = malloc( pHttpParams->httpMethodLen );
83 | pHttpParams->pPath = malloc( pHttpParams->pathLen );
84 | pHttpParams->pQuery = malloc( pHttpParams->queryLen );
85 | pHttpParams->pHeaders = malloc( pHttpParams->headersLen );
86 | }
87 |
88 | if( pSigV4Params != NULL )
89 | {
90 | /* Make size assumptions for string-like types. */
91 | __CPROVER_assume( pSigV4Params->regionLen < MAX_REGION_LEN );
92 | __CPROVER_assume( pSigV4Params->serviceLen < MAX_SERVICE_LEN );
93 | __CPROVER_assume( pSigV4Params->algorithmLen < MAX_ALGORITHM_LEN );
94 | pSigV4Params->pRegion = malloc( pSigV4Params->regionLen );
95 | pSigV4Params->pService = malloc( pSigV4Params->serviceLen );
96 | pSigV4Params->pAlgorithm = malloc( pSigV4Params->algorithmLen );
97 |
98 | /* The ISO date has a fixed length. */
99 | pSigV4Params->pDateIso8601 = malloc( SIGV4_ISO_STRING_LEN );
100 |
101 | /* Set other structs within SigV4Parameters_t. */
102 | pSigV4Params->pCredentials = pCredentials;
103 | pSigV4Params->pCryptoInterface = pCryptoInterface;
104 | pSigV4Params->pHttpParameters = pHttpParams;
105 | }
106 |
107 | authBufLen = malloc( sizeof( size_t ) );
108 |
109 | if( authBufLen != NULL )
110 | {
111 | __CPROVER_assume( *authBufLen < CBMC_MAX_OBJECT_SIZE );
112 | pAuthBuf = malloc( *authBufLen );
113 | }
114 |
115 | status = SigV4_GenerateHTTPAuthorization( pSigV4Params,
116 | pAuthBuf,
117 | authBufLen,
118 | nondet_bool() ? NULL : &pSignature,
119 | nondet_bool() ? NULL : &signatureLen );
120 | __CPROVER_assert( status == SigV4InvalidParameter || status == SigV4Success || status == SigV4HashError || status == SigV4InsufficientMemory || status == SigV4MaxHeaderPairCountExceeded || status == SigV4MaxQueryPairCountExceeded, "This is not a valid SigV4 return status" );
121 |
122 | if( status == SigV4Success )
123 | {
124 | /* The signature must start at a location within pAuthBuf and
125 | * should not end past the length of pAuthBuf. */
126 | __CPROVER_assert( pAuthBuf <= pSignature,
127 | "Signature does not start at a location within pAuthBuf." );
128 | __CPROVER_assert( pSignature + signatureLen <= pAuthBuf + *authBufLen,
129 | "Signature ends past the length of pAuthBuf." );
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/tools/cmock/create_test.cmake:
--------------------------------------------------------------------------------
1 | # Taken from amazon-freertos repository
2 |
3 | #function to create the test executable
4 | function(create_test test_name
5 | test_src
6 | link_list
7 | dep_list
8 | include_list)
9 | set(mocks_dir "${CMAKE_CURRENT_BINARY_DIR}/mocks")
10 | include (CTest)
11 | get_filename_component(test_src_absolute ${test_src} ABSOLUTE)
12 | add_custom_command(OUTPUT ${test_name}_runner.c
13 | COMMAND ruby
14 | ${CMOCK_DIR}/vendor/unity/auto/generate_test_runner.rb
15 | ${MODULE_ROOT_DIR}/tools/cmock/project.yml
16 | ${test_src_absolute}
17 | ${test_name}_runner.c
18 | DEPENDS ${test_src}
19 | )
20 | add_executable(${test_name} ${test_src} ${test_name}_runner.c)
21 | set_target_properties(${test_name} PROPERTIES
22 | COMPILE_FLAG "-O0 -ggdb"
23 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/tests"
24 | INSTALL_RPATH_USE_LINK_PATH TRUE
25 | LINK_FLAGS " \
26 | -Wl,-rpath,${CMAKE_BINARY_DIR}/lib \
27 | -Wl,-rpath,${CMAKE_CURRENT_BINARY_DIR}/lib"
28 | )
29 | target_include_directories(${test_name} PUBLIC
30 | ${mocks_dir}
31 | ${include_list}
32 | )
33 |
34 | target_link_directories(${test_name} PUBLIC
35 | ${CMAKE_CURRENT_BINARY_DIR}
36 | )
37 |
38 | # link all libraries sent through parameters
39 | foreach(link IN LISTS link_list)
40 | target_link_libraries(${test_name} ${link})
41 | endforeach()
42 |
43 | # add dependency to all the dep_list parameter
44 | foreach(dependency IN LISTS dep_list)
45 | add_dependencies(${test_name} ${dependency})
46 | target_link_libraries(${test_name} ${dependency})
47 | endforeach()
48 | target_link_libraries(${test_name} -lgcov unity)
49 | target_link_directories(${test_name} PUBLIC
50 | ${CMAKE_CURRENT_BINARY_DIR}/lib
51 | )
52 | add_test(NAME ${test_name}
53 | COMMAND ${CMAKE_BINARY_DIR}/bin/tests/${test_name}
54 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
55 | )
56 | endfunction()
57 |
58 | # Run the C preprocessor on target files.
59 | # Takes a CMAKE list of arguments to pass to the C compiler
60 | function(preprocess_mock_list mock_name file_list compiler_args)
61 | set_property(GLOBAL PROPERTY ${mock_name}_processed TRUE)
62 | foreach (target_file IN LISTS file_list)
63 | # Has to be TARGET ALL so the file is pre-processed before CMOCK
64 | # is executed on the file.
65 | add_custom_command(OUTPUT ${target_file}.backup
66 | COMMAND scp ${target_file} ${target_file}.backup
67 | VERBATIM COMMAND ${CMAKE_C_COMPILER} -E ${compiler_args} ${target_file} > ${target_file}.out
68 | )
69 | add_custom_target(pre_${mock_name}
70 | COMMAND mv ${target_file}.out ${target_file}
71 | DEPENDS ${target_file}.backup
72 | )
73 | endforeach()
74 |
75 | # Clean up temporary files that were created.
76 | # First we test to see if the backup file still exists. If it does we revert
77 | # the change made to the original file.
78 | foreach (target_file IN LISTS file_list)
79 | add_custom_command(TARGET ${mock_name}
80 | POST_BUILD
81 | COMMAND test ! -e ${target_file}.backup || mv ${target_file}.backup ${target_file}
82 | )
83 | endforeach()
84 | endfunction()
85 |
86 | # Generates a mock library based on a module's header file
87 | # places the generated source file in the build directory
88 | # @param mock_name: name of the target name
89 | # @param mock_list list of header files to mock
90 | # @param cmock_config configuration file of the cmock framework
91 | # @param mock_include_list include list for the target
92 | # @param mock_define_list special definitions to control compilation
93 | function(create_mock_list mock_name
94 | mock_list
95 | cmock_config
96 | mock_include_list
97 | mock_define_list)
98 | set(mocks_dir "${CMAKE_CURRENT_BINARY_DIR}/mocks")
99 | add_library(${mock_name} SHARED)
100 | foreach (mock_file IN LISTS mock_list)
101 | get_filename_component(mock_file_abs
102 | ${mock_file}
103 | ABSOLUTE
104 | )
105 | get_filename_component(mock_file_name
106 | ${mock_file}
107 | NAME_WLE
108 | )
109 | get_filename_component(mock_file_dir
110 | ${mock_file}
111 | DIRECTORY
112 | )
113 | add_custom_command (
114 | OUTPUT ${mocks_dir}/mock_${mock_file_name}.c
115 | COMMAND ruby
116 | ${CMOCK_DIR}/lib/cmock.rb
117 | -o${cmock_config} ${mock_file_abs}
118 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
119 | )
120 | target_sources(${mock_name} PUBLIC
121 | ${mocks_dir}/mock_${mock_file_name}.c
122 | )
123 |
124 | target_include_directories(${mock_name} PUBLIC
125 | ${mock_file_dir}
126 | )
127 | endforeach()
128 | target_include_directories(${mock_name} PUBLIC
129 | ${mocks_dir}
130 | ${mock_include_list}
131 | )
132 | set_target_properties(${mock_name} PROPERTIES
133 | LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib
134 | POSITION_INDEPENDENT_CODE ON
135 | )
136 | target_compile_definitions(${mock_name} PUBLIC
137 | ${mock_define_list}
138 | )
139 | target_link_libraries(${mock_name} cmock unity)
140 | endfunction()
141 |
142 |
143 | function(create_real_library target
144 | src_file
145 | real_include_list
146 | mock_name)
147 | add_library(${target} STATIC
148 | ${src_file}
149 | )
150 | target_include_directories(${target} PUBLIC
151 | ${real_include_list}
152 | )
153 | set_target_properties(${target} PROPERTIES
154 | COMPILE_FLAGS "-Wextra -Wpedantic \
155 | -fprofile-arcs -ftest-coverage -fprofile-generate \
156 | -Wno-unused-but-set-variable"
157 | LINK_FLAGS "-fprofile-arcs -ftest-coverage \
158 | -fprofile-generate "
159 | ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/lib
160 | )
161 | if(NOT(mock_name STREQUAL ""))
162 | add_dependencies(${target} ${mock_name})
163 | target_link_libraries(${target}
164 | -l${mock_name}
165 | -lgcov
166 | )
167 | endif()
168 | endfunction()
169 |
--------------------------------------------------------------------------------
/docs/doxygen/layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
--------------------------------------------------------------------------------
/test/cbmc/stubs/sigv4_stubs.c:
--------------------------------------------------------------------------------
1 | /*
2 | * SigV4 Library v1.3.0
3 | * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | *
5 | * SPDX-License-Identifier: MIT
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
8 | * this software and associated documentation files (the "Software"), to deal in
9 | * the Software without restriction, including without limitation the rights to
10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11 | * the Software, and to permit persons to whom the Software is furnished to do so,
12 | * subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in all
15 | * copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 | */
24 |
25 | /**
26 | * @file sigv4_stubs.c
27 | * @brief Implements the functions declared in sigv4_stubs.h
28 | */
29 |
30 | #include
31 | #include
32 | #include
33 |
34 | SigV4Status_t scanValue( const char * pDate,
35 | const char formatChar,
36 | size_t readLoc,
37 | size_t lenToRead,
38 | SigV4DateTime_t * pDateElements )
39 | {
40 | SigV4Status_t returnStatus = SigV4InvalidParameter;
41 | const char * pMonthNames[] = MONTH_NAMES;
42 | const char * pLoc = pDate + readLoc;
43 | size_t remainingLenToRead = lenToRead;
44 | int32_t result = 0;
45 | static flag = 0;
46 |
47 | assert( pDate != NULL );
48 | assert( pDateElements != NULL );
49 |
50 | if( formatChar == '*' )
51 | {
52 | remainingLenToRead = 0U;
53 | }
54 |
55 | /* Determine if month value is non-numeric. */
56 | if( ( formatChar == 'M' ) && ( remainingLenToRead == MONTH_ASCII_LEN ) )
57 | {
58 | returnStatus = SigV4Success;
59 |
60 | remainingLenToRead = 0U;
61 | }
62 |
63 | /* Interpret integer value of numeric representation. */
64 | while( ( remainingLenToRead > 0U ) && ( *pLoc >= '0' ) && ( *pLoc <= '9' ) )
65 | {
66 | result = ( result * 10 ) + ( int32_t ) ( *pLoc - '0' );
67 | remainingLenToRead--;
68 | pLoc += 1;
69 | }
70 |
71 | if( remainingLenToRead != 0U )
72 | {
73 | LogError( ( "Parsing Error: Expected numerical string of type '%%%d%c', "
74 | "but received '%.*s'.",
75 | ( int ) lenToRead,
76 | formatChar,
77 | ( int ) lenToRead,
78 | pLoc ) );
79 | returnStatus = SigV4ISOFormattingError;
80 | }
81 |
82 | if( returnStatus != SigV4ISOFormattingError )
83 | {
84 | addToDate( formatChar,
85 | result,
86 | pDateElements );
87 | }
88 |
89 | return returnStatus;
90 | }
91 |
92 | void addToDate( const char formatChar,
93 | int32_t result,
94 | SigV4DateTime_t * pDateElements )
95 | {
96 | assert( pDateElements != NULL );
97 | assert( result >= 0 );
98 |
99 | switch( formatChar )
100 | {
101 | case 'Y':
102 | pDateElements->year = result;
103 | break;
104 |
105 | case 'M':
106 | pDateElements->mon = result;
107 | break;
108 |
109 | case 'D':
110 | pDateElements->mday = result;
111 | break;
112 |
113 | case 'h':
114 | pDateElements->hour = result;
115 | break;
116 |
117 | case 'm':
118 | pDateElements->min = result;
119 | break;
120 |
121 | case 's':
122 | pDateElements->sec = result;
123 | break;
124 |
125 | default:
126 |
127 | /* Do not assign values for skipped characters ('*'), or
128 | * unrecognized format specifiers. */
129 | break;
130 | }
131 | }
132 |
133 | SigV4Status_t writeLineToCanonicalRequest( const char * pLine,
134 | size_t lineLen,
135 | CanonicalContext_t * pCanonicalContext )
136 | {
137 | SigV4Status_t ret = SigV4InsufficientMemory;
138 |
139 | assert( pCanonicalContext != NULL );
140 |
141 | if( pCanonicalContext->bufRemaining >= ( lineLen + 1U ) )
142 | {
143 | assert( __CPROVER_w_ok( &( pCanonicalContext->pBufProcessing[ pCanonicalContext->uxCursorIndex ] ), ( lineLen + 1U ) ) );
144 | ret = SigV4Success;
145 | }
146 |
147 | return ret;
148 | }
149 |
150 | SigV4Status_t SigV4_EncodeURI( const char * pUri,
151 | size_t uriLen,
152 | char * pCanonicalURI,
153 | size_t * canonicalURILen,
154 | bool encodeSlash,
155 | bool doubleEncodeEquals )
156 | {
157 | SigV4Status_t returnStatus = SigV4Success;
158 |
159 | assert( pUri != NULL );
160 | assert( pCanonicalURI != NULL );
161 | assert( canonicalURILen != NULL );
162 |
163 | if( nondet_bool() )
164 | {
165 | returnStatus = SigV4Success;
166 | }
167 | else
168 | {
169 | returnStatus = SigV4InsufficientMemory;
170 | }
171 |
172 | return returnStatus;
173 | }
174 |
175 | SigV4Status_t generateCanonicalQuery( const char * pQuery,
176 | size_t queryLen,
177 | const bool doubleEncodeEqualsInParmsValues,
178 | CanonicalContext_t * pCanonicalContext )
179 | {
180 | SigV4Status_t returnStatus = SigV4InsufficientMemory;
181 |
182 | assert( pCanonicalContext != NULL );
183 |
184 | if( nondet_bool() )
185 | {
186 | __CPROVER_assume( pCanonicalContext->bufRemaining < SIGV4_PROCESSING_BUFFER_LENGTH );
187 | returnStatus = SigV4Success;
188 | }
189 | else
190 | {
191 | returnStatus = SigV4InsufficientMemory;
192 | }
193 |
194 | return returnStatus;
195 | }
196 |
197 | SigV4Status_t generateCanonicalAndSignedHeaders( const char * pHeaders,
198 | size_t headersLen,
199 | uint32_t flags,
200 | CanonicalContext_t * pCanonicalContext,
201 | char ** pSignedHeaders,
202 | size_t * pSignedHeadersLen )
203 | {
204 | SigV4Status_t returnStatus = SigV4InsufficientMemory;
205 |
206 | assert( pHeaders != NULL );
207 | assert( pCanonicalContext != NULL );
208 | assert( pSignedHeaders != NULL );
209 | assert( pSignedHeadersLen != NULL );
210 |
211 | if( nondet_bool() )
212 | {
213 | /* The signed headers are assumed to start at a location within the processing
214 | * buffer and should not end past the length of the processing buffer. */
215 | size_t headersLen, headerOffset, bytesConsumed;
216 | char * pHeaders = NULL;
217 | __CPROVER_assume( pCanonicalContext->bufRemaining < SIGV4_PROCESSING_BUFFER_LENGTH );
218 | bytesConsumed = SIGV4_PROCESSING_BUFFER_LENGTH - pCanonicalContext->bufRemaining;
219 | __CPROVER_assume( headerOffset < bytesConsumed );
220 | __CPROVER_assume( headersLen > 0U && headersLen <= bytesConsumed - headerOffset );
221 | pHeaders = ( char * ) pCanonicalContext->pBufProcessing + headerOffset;
222 |
223 | *pSignedHeadersLen = headersLen;
224 | *pSignedHeaders = pHeaders;
225 | returnStatus = SigV4Success;
226 | }
227 | else
228 | {
229 | returnStatus = SigV4InsufficientMemory;
230 | }
231 |
232 | return returnStatus;
233 | }
234 |
235 | SigV4Status_t copyHeaderStringToCanonicalBuffer( const char * pData,
236 | size_t dataLen,
237 | uint32_t flags,
238 | char separator,
239 | CanonicalContext_t * canonicalRequest )
240 | {
241 | SigV4Status_t returnStatus = SigV4Success;
242 | size_t buffRemaining;
243 |
244 | __CPROVER_assume( pData != NULL );
245 | __CPROVER_assume( dataLen > 0 );
246 | __CPROVER_assume( dataLen < CBMC_MAX_OBJECT_SIZE );
247 |
248 | assert( ( pData != NULL ) && ( dataLen > 0 ) );
249 | assert( canonicalRequest != NULL );
250 |
251 | buffRemaining = canonicalRequest->bufRemaining;
252 |
253 | if( buffRemaining < dataLen )
254 | {
255 | returnStatus = SigV4InsufficientMemory;
256 | }
257 |
258 | return returnStatus;
259 | }
260 |
--------------------------------------------------------------------------------
/source/sigv4_quicksort.c:
--------------------------------------------------------------------------------
1 | /*
2 | * SigV4 Library v1.3.0
3 | * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | *
5 | * SPDX-License-Identifier: MIT
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
8 | * this software and associated documentation files (the "Software"), to deal in
9 | * the Software without restriction, including without limitation the rights to
10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11 | * the Software, and to permit persons to whom the Software is furnished to do so,
12 | * subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in all
15 | * copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 | */
24 |
25 | /**
26 | * @file sigv4_quicksort.c
27 | * @brief Implements an Iterative Quicksort Algorithm for the SigV4 Library.
28 | */
29 |
30 | #include "sigv4_quicksort.h"
31 |
32 | #include
33 | #include
34 |
35 | /**
36 | * @brief Push a value to the stack.
37 | */
38 | #define PUSH_STACK( valueToPush, stack, index ) \
39 | { \
40 | ( stack )[ ( index ) ] = ( valueToPush ); \
41 | ++( index ); \
42 | }
43 |
44 | /**
45 | * @brief Pop a value from the stack.
46 | */
47 | #define POP_STACK( valueToPop, stack, index ) \
48 | { \
49 | --( index ); \
50 | ( valueToPop ) = ( stack )[ ( index ) ]; \
51 | }
52 |
53 | /*-----------------------------------------------------------*/
54 |
55 | /**
56 | * @brief A helper function to swap the value of two pointers
57 | * given their sizes.
58 | *
59 | * @param[in] pFirstItem The item to swap with @p pSecondItem.
60 | * @param[in] pSecondItem The item to swap with @p pFirstItem.
61 | * @param[in] itemSize The amount of memory per entry in the array.
62 | */
63 | static void swap( void * pFirstItem,
64 | void * pSecondItem,
65 | size_t itemSize );
66 |
67 | /**
68 | * @brief A helper function to perform quicksort on a subarray.
69 | *
70 | * @param[in] pArray The array to be sorted.
71 | * @param[in] low The low index of the array.
72 | * @param[in] high The high index of the array.
73 | * @param[in] itemSize The amount of memory per entry in the array.
74 | * @param[out] comparator The comparison function to determine if one item is less than another.
75 | */
76 | static void quickSortHelper( void * pArray,
77 | size_t low,
78 | size_t high,
79 | size_t itemSize,
80 | ComparisonFunc_t comparator );
81 |
82 | /**
83 | * @brief A helper function to partition a subarray using the last element
84 | * of the array as the pivot. All items smaller than the pivot end up
85 | * at its left while all items greater than end up at its right.
86 | *
87 | * @param[in] pArray The array to be sorted.
88 | * @param[in] low The low index of the array.
89 | * @param[in] high The high index of the array.
90 | * @param[in] itemSize The amount of memory per entry in the array.
91 | * @param[out] comparator The comparison function to determine if one item is less than another.
92 | *
93 | * @return The index of the pivot
94 | */
95 | static size_t partition( void * pArray,
96 | size_t low,
97 | size_t high,
98 | size_t itemSize,
99 | ComparisonFunc_t comparator );
100 |
101 | /*-----------------------------------------------------------*/
102 |
103 | static void swap( void * pFirstItem,
104 | void * pSecondItem,
105 | size_t itemSize )
106 | {
107 | uint8_t * pFirstByte = pFirstItem;
108 | uint8_t * pSecondByte = pSecondItem;
109 | size_t dataSize = itemSize;
110 |
111 | assert( pFirstItem != NULL );
112 | assert( pSecondItem != NULL );
113 |
114 | /* Swap one byte at a time. */
115 | while( dataSize-- > 0U )
116 | {
117 | uint8_t tmp = *pFirstByte;
118 | *pFirstByte = *pSecondByte;
119 | ++pFirstByte;
120 | *pSecondByte = tmp;
121 | ++pSecondByte;
122 | }
123 | }
124 |
125 | static void quickSortHelper( void * pArray,
126 | size_t low,
127 | size_t high,
128 | size_t itemSize,
129 | ComparisonFunc_t comparator )
130 | {
131 | size_t stack[ SIGV4_WORST_CASE_SORT_STACK_SIZE ];
132 |
133 | /* Low and high are first two items on the stack. Note
134 | * that we use an intermediary variable for MISRA compliance. */
135 | size_t top = 0U, lo = low, hi = high;
136 |
137 | PUSH_STACK( lo, stack, top );
138 | PUSH_STACK( hi, stack, top );
139 |
140 | while( top > 0U )
141 | {
142 | size_t partitionIndex;
143 | size_t len1, len2;
144 | POP_STACK( hi, stack, top );
145 | POP_STACK( lo, stack, top );
146 |
147 | partitionIndex = partition( pArray, lo, hi, itemSize, comparator );
148 |
149 | /* Calculate length of the left partition containing items smaller
150 | * than the pivot element.
151 | * The length is zero if either:
152 | * 1. The pivoted item is the smallest in the the array before partitioning.
153 | * OR
154 | * 2. The left partition is only of single length which can be treated as
155 | * sorted, and thus, of zero length for avoided adding to the stack. */
156 | len1 = ( ( partitionIndex != 0U ) && ( ( partitionIndex - 1U ) > lo ) ) ? ( partitionIndex - lo ) : 0U;
157 |
158 | /* Calculate length of the right partition containing items greater than
159 | * or equal to the pivot item.
160 | * The calculated length is zero if either:
161 | * 1. The pivoted item is the greatest in the the array before partitioning.
162 | * OR
163 | * 2. The right partition contains only a single length which can be treated as
164 | * sorted, and thereby, of zero length to avoid adding to the stack. */
165 | len2 = ( ( partitionIndex + 1U ) < hi ) ? ( hi - partitionIndex ) : 0U;
166 |
167 | /* Push the information of the left and right partitions to the stack.
168 | * Note: For stack space optimization, the larger of the partitions is pushed
169 | * first and the smaller is pushed later so that the smaller part of the tree
170 | * is completed first without increasing stack space usage before coming back
171 | * to the larger partition. */
172 | if( len1 > len2 )
173 | {
174 | PUSH_STACK( lo, stack, top );
175 | PUSH_STACK( partitionIndex - 1U, stack, top );
176 |
177 | if( len2 > 0U )
178 | {
179 | PUSH_STACK( partitionIndex + 1U, stack, top );
180 | PUSH_STACK( hi, stack, top );
181 | }
182 | }
183 | else
184 | {
185 | if( len2 > 0U )
186 | {
187 | PUSH_STACK( partitionIndex + 1U, stack, top );
188 | PUSH_STACK( hi, stack, top );
189 | }
190 |
191 | if( len1 > 0U )
192 | {
193 | PUSH_STACK( lo, stack, top );
194 | PUSH_STACK( partitionIndex - 1U, stack, top );
195 | }
196 | }
197 | }
198 | }
199 |
200 | static size_t partition( void * pArray,
201 | size_t low,
202 | size_t high,
203 | size_t itemSize,
204 | ComparisonFunc_t comparator )
205 | {
206 | uint8_t * pivot;
207 | uint8_t * pArrayLocal = ( uint8_t * ) pArray;
208 | size_t i = low - 1U, j = low;
209 |
210 | assert( pArray != NULL );
211 | assert( comparator != NULL );
212 |
213 | /* Choose pivot as the highest indexed item in the current partition. */
214 | pivot = &( pArrayLocal[ high * itemSize ] );
215 |
216 | /* Iterate over all elements of the current array to partition it
217 | * in comparison to the chosen pivot with smaller items on the left
218 | * and larger or equal to items on the right. */
219 | for( ; j < high; j++ )
220 | {
221 | /* Use comparator function to check current element is smaller than the pivot */
222 | if( comparator( &( pArrayLocal[ j * itemSize ] ), pivot ) < 0 )
223 | {
224 | ++i;
225 | swap( &( pArrayLocal[ i * itemSize ] ), &( pArrayLocal[ j * itemSize ] ), itemSize );
226 | }
227 | }
228 |
229 | /* Place the pivot between the smaller and larger item chunks of
230 | * the array. This represents the 2 partitions of the array. */
231 | swap( &( pArrayLocal[ ( i + 1U ) * itemSize ] ), pivot, itemSize );
232 |
233 | /* Return the pivot item's index. */
234 | return i + 1U;
235 | }
236 |
237 | void quickSort( void * pArray,
238 | size_t numItems,
239 | size_t itemSize,
240 | ComparisonFunc_t comparator )
241 | {
242 | assert( pArray != NULL );
243 | assert( numItems > 0U );
244 | assert( itemSize > 0U );
245 | assert( comparator != NULL );
246 |
247 | quickSortHelper( pArray, 0U, numItems - 1U, itemSize, comparator );
248 | }
249 |
--------------------------------------------------------------------------------
/source/include/sigv4_config_defaults.h:
--------------------------------------------------------------------------------
1 | /*
2 | * SigV4 Library v1.3.0
3 | * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | *
5 | * SPDX-License-Identifier: MIT
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
8 | * this software and associated documentation files (the "Software"), to deal in
9 | * the Software without restriction, including without limitation the rights to
10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11 | * the Software, and to permit persons to whom the Software is furnished to do so,
12 | * subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in all
15 | * copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 | */
24 |
25 | /**
26 | * @file sigv4_config_defaults.h
27 | * @brief The default values for configuration macros used by the SigV4 Library.
28 | *
29 | * @note This file should NOT be modified. If custom values are needed for any
30 | * configuration macros, a sigv4_config.h file should be provided to the SigV4
31 | * Library to override the default values defined in this file. To use the custom
32 | * config file, the preprocessor macro SIGV4_DO_NOT_USE_CUSTOM_CONFIG
33 | * must NOT be set.
34 | */
35 |
36 | #ifndef SIGV4_CONFIG_DEFAULTS_H_
37 | #define SIGV4_CONFIG_DEFAULTS_H_
38 |
39 | /* *INDENT-OFF* */
40 | #ifdef __cplusplus
41 | extern "C" {
42 | #endif
43 | /* *INDENT-ON* */
44 |
45 | /* The macro definition for SIGV4_DO_NOT_USE_CUSTOM_CONFIG is for Doxygen
46 | * documentation only. */
47 |
48 | /**
49 | * @brief Define this macro to build the AWS IoT SigV4 Library without the
50 | * custom config file sigv4_config.h.
51 | *
52 | * Without the custom config, the the AWS IoT SigV4 Library builds with default
53 | * values of config macros defined in the sigv4_config_defaults.h file.
54 | *
55 | * If a custom config file is provided, then
56 | * SIGV4_DO_NOT_USE_CUSTOM_CONFIG must not be defined.
57 | *
58 | * Default value: SIGV4_DO_NOT_USE_CUSTOM_CONFIG is
59 | * not defined by default and the library expects a
60 | * sigv4_config.h file.
61 | */
62 | #ifdef DOXYGEN
63 | #define SIGV4_DO_NOT_USE_CUSTOM_CONFIG
64 | #endif
65 |
66 | /**
67 | * @brief Macro defining the size of the internal buffer used for incremental
68 | * canonicalization and hashing.
69 | *
70 | * A buffer of this size in bytes is declared on the stack. It should be be
71 | * large enough for the digest output of the specified hash function.
72 | *
73 | * Possible values: Any positive 32 bit integer.
74 | * Default value: `1024`
75 | */
76 | #ifndef SIGV4_PROCESSING_BUFFER_LENGTH
77 | #define SIGV4_PROCESSING_BUFFER_LENGTH 1024U
78 | #endif
79 |
80 | /**
81 | * @brief Macro defining the maximum number of headers in the request, used to
82 | * assist the library in sorting header fields during canonicalization.
83 | *
84 | * This macro should be updated if the number of request headers the application
85 | * wishes to sign is higher or lower than the default value (100).
86 | *
87 | * Possible values: Any positive 32 bit integer.
88 | * Default value: `100`
89 | */
90 | #ifndef SIGV4_MAX_HTTP_HEADER_COUNT
91 | #define SIGV4_MAX_HTTP_HEADER_COUNT 100U
92 | #endif
93 |
94 | /**
95 | * @brief Macro defining the maximum number of query key/value pairs, used to
96 | * assist the library in sorting query keys during canonicalization.
97 | *
98 | * This macro should be updated if the number of query key/value pairs the
99 | * application wishes to sign is higher or lower than the default value (100).
100 | *
101 | * Possible values: Any positive 32 bit integer.
102 | * Default value: `100`
103 | */
104 | #ifndef SIGV4_MAX_QUERY_PAIR_COUNT
105 | #define SIGV4_MAX_QUERY_PAIR_COUNT 100U
106 | #endif
107 |
108 | /**
109 | * @brief Macro used to compute the worst-case stack size when sorting elements
110 | * associated with #SIGV4_MAX_QUERY_PAIR_COUNT or #SIGV4_MAX_HTTP_HEADER_COUNT.
111 | * Suppose the max of the two aforementioned macros is X, then the macro
112 | * below must be set to 2 * ceiling(log(X)/log(2)) where ceiling rounds up
113 | * the ones digit if the decimal is greater than 0.
114 | * @note If updating #SIGV4_MAX_QUERY_PAIR_COUNT or #SIGV4_MAX_HTTP_HEADER_COUNT,
115 | * be sure to update this value based on the formula above.
116 | */
117 | #ifndef SIGV4_WORST_CASE_SORT_STACK_SIZE
118 | #define SIGV4_WORST_CASE_SORT_STACK_SIZE 14U
119 | #endif
120 |
121 | /**
122 | * @brief Macro indicating the largest block size of any hashing
123 | * algorithm used for SigV4 authentication i.e. the maximum of all
124 | * values specified for the hashBlockLen in #SigV4CryptoInterface_t.
125 | * For example, using SHA-512 would require this value to be at least 128.
126 | *
127 | * Possible values: Any positive 32 bit integer.
128 | * Default value: `64`
129 | */
130 | #ifndef SIGV4_HASH_MAX_BLOCK_LENGTH
131 | #define SIGV4_HASH_MAX_BLOCK_LENGTH 64U
132 | #endif
133 |
134 | /**
135 | * @brief Macro defining the maximum digest length of the specified hash function,
136 | * used to determine the length of the output buffer.
137 | *
138 | * This macro should be updated if using a hashing algorithm other than SHA256
139 | * (32 byte digest length). For example, using SHA512 would require this
140 | * value to be at least 64.
141 | *
142 | * Possible values: Any positive 32 bit integer.
143 | * Default value: `32`
144 | */
145 | #ifndef SIGV4_HASH_MAX_DIGEST_LENGTH
146 | #define SIGV4_HASH_MAX_DIGEST_LENGTH 32U
147 | #endif
148 |
149 | /**
150 | * @brief Macro to statically enable support for canonicalizing the URI,
151 | * headers, and query in this library.
152 | *
153 | * Set this to one to enable the encoding functions used to create the canonical
154 | * request.
155 | *
156 | * Possible values: 0 or 1
157 | * Default value: `1`
158 | */
159 | #ifndef SIGV4_USE_CANONICAL_SUPPORT
160 | #define SIGV4_USE_CANONICAL_SUPPORT 1
161 | #endif
162 |
163 | /**
164 | * @brief Macro called by the SigV4 library for logging "Error" level
165 | * messages.
166 | *
167 | * To enable error level logging in the SigV4 library, this macro should
168 | * be mapped to the application-specific logging implementation that supports
169 | * error logging.
170 | *
171 | * @note This logging macro is called in the SigV4 library with
172 | * parameters wrapped in double parentheses to be ISO C89/C90 standard
173 | * compliant. For a reference POSIX implementation of the logging macros, refer
174 | * to sigv4_config.h files, and the logging-stack in demos folder of the [AWS
175 | * IoT Embedded C SDK
176 | * repository](https://github.com/aws/aws-iot-device-sdk-embedded-C).
177 | *
178 | * Default value: Error logging is turned off, and no code is generated
179 | * for calls to the macro in the SigV4 library on compilation.
180 | */
181 | #ifndef LogError
182 | #define LogError( message )
183 | #endif
184 |
185 | /**
186 | * @brief Macro called by the the SigV4 library for logging "Warning"
187 | * level messages.
188 | *
189 | * To enable warning level logging in the SigV4 library, this macro
190 | * should be mapped to the application-specific logging implementation that
191 | * supports warning logging.
192 | *
193 | * @note This logging macro is called in the SigV4 library with
194 | * parameters wrapped in double parentheses to be ISO C89/C90 standard
195 | * compliant. For a reference POSIX implementation of the logging macros, refer
196 | * to sigv4_config.h files, and the logging-stack in demos folder of the [AWS
197 | * IoT Embedded C SDK
198 | * repository](https://github.com/aws/aws-iot-device-sdk-embedded-C).
199 | *
200 | * Default value: Warning logs are turned off, and no code is generated
201 | * for calls to the macro in the SigV4 library on compilation.
202 | */
203 | #ifndef LogWarn
204 | #define LogWarn( message )
205 | #endif
206 |
207 | /**
208 | * @brief Macro called by the the SigV4 library for logging "Info" level
209 | * messages.
210 | *
211 | * To enable info level logging in the SigV4 library, this macro should
212 | * be mapped to the application-specific logging implementation that supports
213 | * info logging.
214 | *
215 | * @note This logging macro is called in the SigV4 library with
216 | * parameters wrapped in double parentheses to be ISO C89/C90 standard
217 | * compliant. For a reference POSIX implementation of the logging macros, refer
218 | * to sigv4_config.h files, and the logging-stack in demos folder of the [AWS
219 | * IoT Embedded C SDK
220 | * repository](https://github.com/aws/aws-iot-device-sdk-embedded-C).
221 | *
222 | * Default value: Info logging is turned off, and no code is generated
223 | * for calls to the macro in the SigV4 library on compilation.
224 | */
225 | #ifndef LogInfo
226 | #define LogInfo( message )
227 | #endif
228 |
229 | /**
230 | * @brief Macro called by the the SigV4 library for logging "Debug"
231 | * level messages.
232 | *
233 | * To enable debug level logging from SigV4 library, this macro should
234 | * be mapped to the application-specific logging implementation that supports
235 | * debug logging.
236 | *
237 | * @note This logging macro is called in the SigV4 library with
238 | * parameters wrapped in double parentheses to be ISO C89/C90 standard
239 | * compliant. For a reference POSIX implementation of the logging macros, refer
240 | * to sigv4_config.h files, and the logging-stack in demos folder of the [AWS
241 | * IoT Embedded C SDK
242 | * repository](https://github.com/aws/aws-iot-device-sdk-embedded-C).
243 | *
244 | * Default value: Debug logging is turned off, and no code is generated
245 | * for calls to the macro in the SigV4 library on compilation.
246 | */
247 | #ifndef LogDebug
248 | #define LogDebug( message )
249 | #endif
250 |
251 | /* *INDENT-OFF* */
252 | #ifdef __cplusplus
253 | }
254 | #endif
255 | /* *INDENT-ON* */
256 |
257 | #endif /* ifndef SIGV4_CONFIG_DEFAULTS_H_ */
258 |
--------------------------------------------------------------------------------
/source/include/sigv4_internal.h:
--------------------------------------------------------------------------------
1 | /*
2 | * SigV4 Library v1.3.0
3 | * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | *
5 | * SPDX-License-Identifier: MIT
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of
8 | * this software and associated documentation files (the "Software"), to deal in
9 | * the Software without restriction, including without limitation the rights to
10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11 | * the Software, and to permit persons to whom the Software is furnished to do so,
12 | * subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in all
15 | * copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 | */
24 |
25 | /**
26 | * @file sigv4_internal.h
27 | * @brief Internal definitions for the SigV4 Library.
28 | */
29 |
30 | #ifndef SIGV4_INTERNAL_H_
31 | #define SIGV4_INTERNAL_H_
32 |
33 | /* *INDENT-OFF* */
34 | #ifdef __cplusplus
35 | extern "C" {
36 | #endif
37 | /* *INDENT-ON* */
38 |
39 | /* SIGV4_DO_NOT_USE_CUSTOM_CONFIG allows building of the SigV4 library without a
40 | * config file. If a config file is provided, the SIGV4_DO_NOT_USE_CUSTOM_CONFIG
41 | * macro must not be defined.
42 | */
43 | #ifndef SIGV4_DO_NOT_USE_CUSTOM_CONFIG
44 | #include "sigv4_config.h"
45 | #endif
46 |
47 | /* Include config defaults header to get default values of configurations not
48 | * defined in sigv4_config.h file. */
49 | #include "sigv4_config_defaults.h"
50 |
51 | /* Constants for date verification. */
52 | #define YEAR_MIN 1900L /**< Earliest year accepted. */
53 | #define MONTH_ASCII_LEN 3U /**< Length of month abbreviations. */
54 |
55 | /**
56 | * @brief Month name abbreviations for RFC 5322 date parsing.
57 | */
58 | #define MONTH_NAMES { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }
59 |
60 | /**
61 | * @brief Number of days in each respective month.
62 | */
63 | #define MONTH_DAYS { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
64 |
65 | #define FORMAT_RFC_3339 "%4Y-%2M-%2DT%2h:%2m:%2sZ" /**< Format string to parse RFC 3339 date. */
66 | #define FORMAT_RFC_3339_LEN sizeof( FORMAT_RFC_3339 ) - 1U /**< Length of the RFC 3339 format string. */
67 |
68 | #define FORMAT_RFC_5322 "%3*, %2D %3M %4Y %2h:%2m:%2s GMT" /**< Format string to parse RFC 5322 date. */
69 | #define FORMAT_RFC_5322_LEN sizeof( FORMAT_RFC_5322 ) - 1U /**< Length of the RFC 3339 format string. */
70 |
71 | #define ISO_YEAR_LEN 4U /**< Length of year value in ISO 8601 date. */
72 | #define ISO_NON_YEAR_LEN 2U /**< Length of non-year values in ISO 8601 date. */
73 |
74 | #define ISO_DATE_SCOPE_LEN 8U /**< Length of date substring used in credential scope. */
75 |
76 | /* SigV4 related string literals and lengths. */
77 |
78 | /**
79 | * @brief The separator between each component of the credential scope.
80 | */
81 | #define CREDENTIAL_SCOPE_SEPARATOR '/'
82 | #define CREDENTIAL_SCOPE_SEPARATOR_LEN 1U /**< The length of #CREDENTIAL_SCOPE_SEPARATOR. */
83 |
84 | /**
85 | * @brief The last component that terminates the credential scope.
86 | */
87 | #define CREDENTIAL_SCOPE_TERMINATOR "aws4_request"
88 | #define CREDENTIAL_SCOPE_TERMINATOR_LEN ( sizeof( CREDENTIAL_SCOPE_TERMINATOR ) - 1U ) /**< The length of #CREDENTIAL_SCOPE_TERMINATOR. */
89 |
90 | /**
91 | * @brief Default value when HttpParameters_t.pPath == NULL.
92 | */
93 | #define HTTP_EMPTY_PATH "/"
94 | #define HTTP_EMPTY_PATH_LEN ( sizeof( HTTP_EMPTY_PATH ) - 1U ) /**< The length of #HTTP_EMPTY_PATH. */
95 |
96 | #define URI_ENCODED_SPECIAL_CHAR_SIZE 3U /**< The size of an encoded URI special character. */
97 | #define URI_DOUBLE_ENCODED_EQUALS_CHAR_SIZE 5U /**< The size of the double-encoded "=" character. */
98 |
99 | #define LINEFEED_CHAR '\n' /**< A linefeed character used to build the canonical request. */
100 | #define LINEFEED_CHAR_LEN 1U /**< The length of #LINEFEED_CHAR. */
101 |
102 | #define HTTP_REQUEST_LINE_ENDING "\r\n" /**< The string used in non-canonicalized HTTP headers to separate header entries in HTTP request. */
103 | #define HTTP_REQUEST_LINE_ENDING_LEN ( sizeof( HTTP_REQUEST_LINE_ENDING ) - 1U ) /**< The length of #HTTP_REQUEST_LINE_ENDING. */
104 |
105 | #define SPACE_CHAR ' ' /**< A linefeed character used to build the Authorization header value. */
106 | #define SPACE_CHAR_LEN 1U /**< The length of #SPACE_CHAR. */
107 |
108 | #define S3_SERVICE_NAME "s3" /**< S3 is the only service where the URI must only be encoded once. */
109 | #define S3_SERVICE_NAME_LEN ( sizeof( S3_SERVICE_NAME ) - 1U ) /**< The length of #S3_SERVICE_NAME. */
110 |
111 | #define SIGV4_HMAC_SIGNING_KEY_PREFIX "AWS4" /**< HMAC signing key prefix. */
112 | #define SIGV4_HMAC_SIGNING_KEY_PREFIX_LEN ( sizeof( SIGV4_HMAC_SIGNING_KEY_PREFIX ) - 1U ) /**< The length of #SIGV4_HMAC_SIGNING_KEY_PREFIX. */
113 |
114 | #define AUTH_CREDENTIAL_PREFIX "Credential=" /**< The prefix that goes before the credential value in the Authorization header value. */
115 | #define AUTH_CREDENTIAL_PREFIX_LEN ( sizeof( AUTH_CREDENTIAL_PREFIX ) - 1U ) /**< The length of #AUTH_CREDENTIAL_PREFIX. */
116 | #define AUTH_SEPARATOR ", " /**< The separator between each component in the Authorization header value. */
117 | #define AUTH_SEPARATOR_LEN ( sizeof( AUTH_SEPARATOR ) - 1U ) /**< The length of #AUTH_SEPARATOR. */
118 | #define AUTH_SIGNED_HEADERS_PREFIX "SignedHeaders=" /**< The prefix that goes before the signed headers in the Authorization header value. */
119 | #define AUTH_SIGNED_HEADERS_PREFIX_LEN ( sizeof( AUTH_SIGNED_HEADERS_PREFIX ) - 1U ) /**< The length of #AUTH_SIGNED_HEADERS_PREFIX. */
120 | #define AUTH_SIGNATURE_PREFIX "Signature=" /**< The prefix that goes before the signature in the Authorization header value. */
121 | #define AUTH_SIGNATURE_PREFIX_LEN ( sizeof( AUTH_SIGNATURE_PREFIX ) - 1U ) /**< The length of #AUTH_SIGNATURE_PREFIX. */
122 |
123 | #define HMAC_INNER_PAD_BYTE ( 0x36U ) /**< The "ipad" byte used for generating the inner key in the HMAC calculation process. */
124 | #define HMAC_OUTER_PAD_BYTE ( 0x5CU ) /**< The "opad" byte used for generating the outer key in the HMAC calculation process. */
125 | #define HMAX_IPAD_XOR_OPAD_BYTE ( 0x6AU ) /**< The XOR of the "ipad" and "opad" bytes to extract outer key from inner key. */
126 |
127 | /**
128 | * @brief A helper macro to print insufficient memory errors.
129 | */
130 | #define LOG_INSUFFICIENT_MEMORY_ERROR( purposeOfWrite, bytesExceeded ) \
131 | { \
132 | LogError( ( "Unable to " purposeOfWrite ": Insufficient memory configured in SIGV4_PROCESSING_BUFFER_LENGTH macro. BytesExceeded=%lu", \
133 | ( unsigned long ) ( bytesExceeded ) ) ); \
134 | }
135 |
136 | /**
137 | * @brief A helper macro to test if a flag is set.
138 | */
139 | #define FLAG_IS_SET( bits, flag ) ( ( ( bits ) & ( flag ) ) == ( flag ) )
140 |
141 | /**
142 | * @brief A helper macro to determine if a character is whitespace.
143 | * @note The ctype function isspace() returns true for the following characters:
144 | * ` `, `\t`, `\n`, `\v`, `\f`, `\r`. However, according to RFC5234:
145 | * https://datatracker.ietf.org/doc/html/rfc5234#appendix-B.1
146 | * the only whitespace characters in an HTTP header are spaces and
147 | * horizontal tabs.
148 | */
149 | #define isWhitespace( c ) ( ( ( c ) == ' ' ) || ( ( c ) == '\t' ) )
150 |
151 | /**
152 | * @brief An aggregator representing the individually parsed elements of the
153 | * user-provided date parameter. This is used to verify the complete date
154 | * representation, and construct the final ISO 8601 string.
155 | */
156 | typedef struct SigV4DateTime
157 | {
158 | int32_t year; /**< Year (1900 or later) */
159 | int32_t mon; /**< Month (1 to 12) */
160 | int32_t mday; /**< Day of Month (1 to 28/29/30/31) */
161 | int32_t hour; /**< Hour (0 to 23) */
162 | int32_t min; /**< Minutes (0 to 59) */
163 | int32_t sec; /**< Seconds (0 to 60) */
164 | } SigV4DateTime_t;
165 |
166 | /**
167 | * @brief A library structure holding the string and length values of parameters to
168 | * be sorted and standardized. This allows for a layer of abstraction during the
169 | * canonicalization step of the V4 signing process.
170 | */
171 | typedef struct SigV4String
172 | {
173 | char * pData; /**< SigV4 string data */
174 | size_t dataLen; /**< Length of pData */
175 | } SigV4String_t;
176 |
177 | /**
178 | * @brief A library structure holding the string and length values of parameters to
179 | * be sorted and standardized. This allows for a layer of abstraction during the
180 | * canonicalization step of the V4 signing process.
181 | */
182 | typedef struct SigV4ConstString
183 | {
184 | const char * pData; /**< SigV4 string data */
185 | size_t dataLen; /**< Length of pData */
186 | } SigV4ConstString_t;
187 |
188 | /**
189 | * @brief A key-value pair data structure that allows for sorting of SigV4
190 | * string values using internal comparison functions, and provides additional
191 | * stability to quickSort(), to comply with Misra rule 21.9.
192 | */
193 | typedef struct SigV4KeyValuePair
194 | {
195 | SigV4ConstString_t key; /**< SigV4 string identifier */
196 | SigV4ConstString_t value; /**< SigV4 data */
197 | } SigV4KeyValuePair_t;
198 |
199 | /**
200 | * @brief An aggregator to maintain the internal state of canonicalization
201 | * during intermediate calculations.
202 | */
203 | typedef struct CanonicalContext
204 | {
205 | SigV4KeyValuePair_t pQueryLoc[ SIGV4_MAX_QUERY_PAIR_COUNT ]; /**< Query pointers used during sorting. */
206 | SigV4KeyValuePair_t pHeadersLoc[ SIGV4_MAX_HTTP_HEADER_COUNT ]; /**< Header pointers used during sorting. */
207 |
208 | uint8_t pBufProcessing[ SIGV4_PROCESSING_BUFFER_LENGTH ]; /**< Internal calculation buffer used during canonicalization. */
209 | size_t uxCursorIndex; /**< pBufProcessing cursor. */
210 | size_t bufRemaining; /**< pBufProcessing value used during internal calculation. */
211 | const char * pHashPayloadLoc; /**< Pointer used to store the location of hashed HTTP request payload. */
212 | size_t hashPayloadLen; /**< Length of hashed HTTP request payload. */
213 | } CanonicalContext_t;
214 |
215 | /**
216 | * @brief An aggregator to maintain the internal state of HMAC
217 | * calculations.
218 | */
219 | typedef struct HmacContext
220 | {
221 | /**
222 | * @brief The cryptography interface.
223 | */
224 | const SigV4CryptoInterface_t * pCryptoInterface;
225 |
226 | /**
227 | * @brief All accumulated key data.
228 | */
229 | uint8_t key[ SIGV4_HASH_MAX_BLOCK_LENGTH ];
230 |
231 | /**
232 | * @brief The length of the accumulated key data.
233 | */
234 | size_t keyLen;
235 | } HmacContext_t;
236 |
237 | /* *INDENT-OFF* */
238 | #ifdef __cplusplus
239 | }
240 | #endif
241 | /* *INDENT-ON* */
242 |
243 | #endif /* ifndef SIGV4_INTERNAL_H_ */
244 |
--------------------------------------------------------------------------------
/test/cbmc/proofs/run-cbmc-proofs.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | #
3 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 | # SPDX-License-Identifier: MIT-0
5 |
6 |
7 | import argparse
8 | import asyncio
9 | import json
10 | import logging
11 | import math
12 | import os
13 | import pathlib
14 | import re
15 | import subprocess
16 | import sys
17 | import tempfile
18 |
19 | from lib.summarize import print_proof_results
20 |
21 |
22 | DESCRIPTION = "Configure and run all CBMC proofs in parallel"
23 |
24 | # Keep the epilog hard-wrapped at 70 characters, as it gets printed
25 | # verbatim in the terminal. 70 characters stops here --------------> |
26 | EPILOG = """
27 | This tool automates the process of running `make report` in each of
28 | the CBMC proof directories. The tool calculates the dependency graph
29 | of all tasks needed to build, run, and report on all the proofs, and
30 | executes these tasks in parallel.
31 |
32 | The tool is roughly equivalent to doing this:
33 |
34 | litani init --project "my-cool-project";
35 |
36 | find . -name cbmc-proof.txt | while read -r proof; do
37 | pushd $(dirname ${proof});
38 |
39 | # The `make _report` rule adds a single proof to litani
40 | # without running it
41 | make _report;
42 |
43 | popd;
44 | done
45 |
46 | litani run-build;
47 |
48 | except that it is much faster and provides some convenience options.
49 | The CBMC CI runs this script with no arguments to build and run all
50 | proofs in parallel. The value of "my-cool-project" is taken from the
51 | PROJECT_NAME variable in Makefile-project-defines.
52 |
53 | The --no-standalone argument omits the `litani init` and `litani
54 | run-build`; use it when you want to add additional proof jobs, not
55 | just the CBMC ones. In that case, you would run `litani init`
56 | yourself; then run `run-cbmc-proofs --no-standalone`; add any
57 | additional jobs that you want to execute with `litani add-job`; and
58 | finally run `litani run-build`.
59 |
60 | The litani dashboard will be written under the `output` directory; the
61 | cbmc-viewer reports remain in the `$PROOF_DIR/report` directory. The
62 | HTML dashboard from the latest Litani run will always be symlinked to
63 | `output/latest/html/index.html`, so you can keep that page open in
64 | your browser and reload the page whenever you re-run this script.
65 | """
66 | # 70 characters stops here ----------------------------------------> |
67 |
68 |
69 | def get_project_name():
70 | cmd = [
71 | "make",
72 | "--no-print-directory",
73 | "-f", "Makefile.common",
74 | "echo-project-name",
75 | ]
76 | logging.debug(" ".join(cmd))
77 | proc = subprocess.run(cmd, universal_newlines=True, stdout=subprocess.PIPE, check=False)
78 | if proc.returncode:
79 | logging.critical("could not run make to determine project name")
80 | sys.exit(1)
81 | if not proc.stdout.strip():
82 | logging.warning(
83 | "project name has not been set; using generic name instead. "
84 | "Set the PROJECT_NAME value in Makefile-project-defines to "
85 | "remove this warning")
86 | return ""
87 | return proc.stdout.strip()
88 |
89 |
90 | def get_args():
91 | pars = argparse.ArgumentParser(
92 | description=DESCRIPTION, epilog=EPILOG,
93 | formatter_class=argparse.RawDescriptionHelpFormatter)
94 | for arg in [{
95 | "flags": ["-j", "--parallel-jobs"],
96 | "type": int,
97 | "metavar": "N",
98 | "help": "run at most N proof jobs in parallel",
99 | }, {
100 | "flags": ["--fail-on-proof-failure"],
101 | "action": "store_true",
102 | "help": "exit with return code `10' if any proof failed"
103 | " (default: exit 0)",
104 | }, {
105 | "flags": ["--no-standalone"],
106 | "action": "store_true",
107 | "help": "only configure proofs: do not initialize nor run",
108 | }, {
109 | "flags": ["-p", "--proofs"],
110 | "nargs": "+",
111 | "metavar": "DIR",
112 | "help": "only run proof in directory DIR (can pass more than one)",
113 | }, {
114 | "flags": ["--project-name"],
115 | "metavar": "NAME",
116 | "default": get_project_name(),
117 | "help": "project name for report. Default: %(default)s",
118 | }, {
119 | "flags": ["--marker-file"],
120 | "metavar": "FILE",
121 | "default": "cbmc-proof.txt",
122 | "help": (
123 | "name of file that marks proof directories. Default: "
124 | "%(default)s"),
125 | }, {
126 | "flags": ["--no-memory-profile"],
127 | "action": "store_true",
128 | "help": "disable memory profiling, even if Litani supports it"
129 | }, {
130 | "flags": ["--no-expensive-limit"],
131 | "action": "store_true",
132 | "help": "do not limit parallelism of 'EXPENSIVE' jobs",
133 | }, {
134 | "flags": ["--expensive-jobs-parallelism"],
135 | "metavar": "N",
136 | "default": 1,
137 | "type": int,
138 | "help": (
139 | "how many proof jobs marked 'EXPENSIVE' to run in parallel. "
140 | "Default: %(default)s"),
141 | }, {
142 | "flags": ["--verbose"],
143 | "action": "store_true",
144 | "help": "verbose output",
145 | }, {
146 | "flags": ["--debug"],
147 | "action": "store_true",
148 | "help": "debug output",
149 | }, {
150 | "flags": ["--summarize"],
151 | "action": "store_true",
152 | "help": "summarize proof results with two tables on stdout",
153 | }, {
154 | "flags": ["--version"],
155 | "action": "version",
156 | "version": "CBMC starter kit 2.5",
157 | "help": "display version and exit"
158 | }]:
159 | flags = arg.pop("flags")
160 | pars.add_argument(*flags, **arg)
161 | return pars.parse_args()
162 |
163 |
164 | def set_up_logging(verbose):
165 | if verbose:
166 | level = logging.DEBUG
167 | else:
168 | level = logging.WARNING
169 | logging.basicConfig(
170 | format="run-cbmc-proofs: %(message)s", level=level)
171 |
172 |
173 | def task_pool_size():
174 | ret = os.cpu_count()
175 | if ret is None or ret < 3:
176 | return 1
177 | return ret - 2
178 |
179 |
180 | def print_counter(counter):
181 | # pylint: disable=consider-using-f-string
182 | print("\rConfiguring CBMC proofs: "
183 | "{complete:{width}} / {total:{width}}".format(**counter), end="", file=sys.stderr)
184 |
185 |
186 | def get_proof_dirs(proof_root, proof_list, marker_file):
187 | if proof_list is not None:
188 | proofs_remaining = list(proof_list)
189 | else:
190 | proofs_remaining = []
191 |
192 | for root, _, fyles in os.walk(proof_root):
193 | proof_name = str(pathlib.Path(root).name)
194 | if root != str(proof_root) and ".litani_cache_dir" in fyles:
195 | pathlib.Path(f"{root}/.litani_cache_dir").unlink()
196 | if proof_list and proof_name not in proof_list:
197 | continue
198 | if proof_list and proof_name in proofs_remaining:
199 | proofs_remaining.remove(proof_name)
200 | if marker_file in fyles:
201 | yield root
202 |
203 | if proofs_remaining:
204 | logging.critical(
205 | "The following proofs were not found: %s",
206 | ", ".join(proofs_remaining))
207 | sys.exit(1)
208 |
209 |
210 | def run_build(litani, jobs, fail_on_proof_failure, summarize):
211 | cmd = [str(litani), "run-build"]
212 | if jobs:
213 | cmd.extend(["-j", str(jobs)])
214 | if fail_on_proof_failure:
215 | cmd.append("--fail-on-pipeline-failure")
216 | if summarize:
217 | out_file = pathlib.Path(tempfile.gettempdir(), "run.json").resolve()
218 | cmd.extend(["--out-file", str(out_file)])
219 |
220 | logging.debug(" ".join(cmd))
221 | proc = subprocess.run(cmd, check=False)
222 |
223 | if proc.returncode and not fail_on_proof_failure:
224 | logging.critical("Failed to run litani run-build")
225 | sys.exit(1)
226 |
227 | if summarize:
228 | print_proof_results(out_file)
229 | out_file.unlink()
230 |
231 | if proc.returncode:
232 | logging.error("One or more proofs failed")
233 | sys.exit(10)
234 |
235 | def get_litani_path(proof_root):
236 | cmd = [
237 | "make",
238 | "--no-print-directory",
239 | f"PROOF_ROOT={proof_root}",
240 | "-f", "Makefile.common",
241 | "litani-path",
242 | ]
243 | logging.debug(" ".join(cmd))
244 | proc = subprocess.run(cmd, universal_newlines=True, stdout=subprocess.PIPE, check=False)
245 | if proc.returncode:
246 | logging.critical("Could not determine path to litani")
247 | sys.exit(1)
248 | return proc.stdout.strip()
249 |
250 |
251 | def get_litani_capabilities(litani_path):
252 | cmd = [litani_path, "print-capabilities"]
253 | proc = subprocess.run(
254 | cmd, text=True, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, check=False)
255 | if proc.returncode:
256 | return []
257 | try:
258 | return json.loads(proc.stdout)
259 | except RuntimeError:
260 | logging.warning("Could not load litani capabilities: '%s'", proc.stdout)
261 | return []
262 |
263 |
264 | def check_uid_uniqueness(proof_dir, proof_uids):
265 | with (pathlib.Path(proof_dir) / "Makefile").open() as handle:
266 | for line in handle:
267 | match = re.match(r"^PROOF_UID\s*=\s*(?P\w+)", line)
268 | if not match:
269 | continue
270 | if match["uid"] not in proof_uids:
271 | proof_uids[match["uid"]] = proof_dir
272 | return
273 |
274 | logging.critical(
275 | "The Makefile in directory '%s' should have a different "
276 | "PROOF_UID than the Makefile in directory '%s'",
277 | proof_dir, proof_uids[match["uid"]])
278 | sys.exit(1)
279 |
280 | logging.critical(
281 | "The Makefile in directory '%s' should contain a line like", proof_dir)
282 | logging.critical("PROOF_UID = ...")
283 | logging.critical("with a unique identifier for the proof.")
284 | sys.exit(1)
285 |
286 |
287 | def should_enable_memory_profiling(litani_caps, args):
288 | if args.no_memory_profile:
289 | return False
290 | return "memory_profile" in litani_caps
291 |
292 |
293 | def should_enable_pools(litani_caps, args):
294 | if args.no_expensive_limit:
295 | return False
296 | return "pools" in litani_caps
297 |
298 |
299 | async def configure_proof_dirs( # pylint: disable=too-many-arguments
300 | queue, counter, proof_uids, enable_pools, enable_memory_profiling, debug):
301 | while True:
302 | print_counter(counter)
303 | path = str(await queue.get())
304 |
305 | check_uid_uniqueness(path, proof_uids)
306 |
307 | pools = ["ENABLE_POOLS=true"] if enable_pools else []
308 | profiling = [
309 | "ENABLE_MEMORY_PROFILING=true"] if enable_memory_profiling else []
310 |
311 | # Allow interactive tasks to preempt proof configuration
312 | proc = await asyncio.create_subprocess_exec(
313 | "nice", "-n", "15", "make", *pools,
314 | *profiling, "-B", "_report", "" if debug else "--quiet", cwd=path,
315 | stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE)
316 | stdout, stderr = await proc.communicate()
317 | logging.debug("returncode: %s", str(proc.returncode))
318 | logging.debug("stdout:")
319 | for line in stdout.decode().splitlines():
320 | logging.debug(line)
321 | logging.debug("stderr:")
322 | for line in stderr.decode().splitlines():
323 | logging.debug(line)
324 |
325 | counter["fail" if proc.returncode else "pass"].append(path)
326 | counter["complete"] += 1
327 |
328 | print_counter(counter)
329 | queue.task_done()
330 |
331 |
332 | async def main(): # pylint: disable=too-many-locals
333 | args = get_args()
334 | set_up_logging(args.verbose)
335 |
336 | proof_root = pathlib.Path(os.getcwd())
337 | litani = get_litani_path(proof_root)
338 |
339 | litani_caps = get_litani_capabilities(litani)
340 | enable_pools = should_enable_pools(litani_caps, args)
341 | init_pools = [
342 | "--pools", f"expensive:{args.expensive_jobs_parallelism}"
343 | ] if enable_pools else []
344 |
345 | if not args.no_standalone:
346 | cmd = [
347 | str(litani), "init", *init_pools, "--project", args.project_name,
348 | "--no-print-out-dir",
349 | ]
350 |
351 | if "output_directory_flags" in litani_caps:
352 | out_prefix = proof_root / "output"
353 | out_symlink = out_prefix / "latest"
354 | out_index = out_symlink / "html" / "index.html"
355 | cmd.extend([
356 | "--output-prefix", str(out_prefix),
357 | "--output-symlink", str(out_symlink),
358 | ])
359 | print(
360 | "\nFor your convenience, the output of this run will be symbolically linked to ",
361 | out_index, "\n")
362 |
363 | logging.debug(" ".join(cmd))
364 | proc = subprocess.run(cmd, check=False)
365 | if proc.returncode:
366 | logging.critical("Failed to run litani init")
367 | sys.exit(1)
368 |
369 | proof_dirs = list(get_proof_dirs(
370 | proof_root, args.proofs, args.marker_file))
371 | if not proof_dirs:
372 | logging.critical("No proof directories found")
373 | sys.exit(1)
374 |
375 | proof_queue = asyncio.Queue()
376 | for proof_dir in proof_dirs:
377 | proof_queue.put_nowait(proof_dir)
378 |
379 | counter = {
380 | "pass": [],
381 | "fail": [],
382 | "complete": 0,
383 | "total": len(proof_dirs),
384 | "width": int(math.log10(len(proof_dirs))) + 1
385 | }
386 |
387 | proof_uids = {}
388 | tasks = []
389 |
390 | enable_memory_profiling = should_enable_memory_profiling(litani_caps, args)
391 |
392 | for _ in range(task_pool_size()):
393 | task = asyncio.create_task(configure_proof_dirs(
394 | proof_queue, counter, proof_uids, enable_pools,
395 | enable_memory_profiling, args.debug))
396 | tasks.append(task)
397 |
398 | await proof_queue.join()
399 |
400 | print_counter(counter)
401 | print("", file=sys.stderr)
402 |
403 | if counter["fail"]:
404 | logging.critical(
405 | "Failed to configure the following proofs:\n%s", "\n".join(
406 | [str(f) for f in counter["fail"]]))
407 | sys.exit(1)
408 |
409 | if not args.no_standalone:
410 | run_build(litani, args.parallel_jobs, args.fail_on_proof_failure, args.summarize)
411 |
412 |
413 | if __name__ == "__main__":
414 | asyncio.run(main())
415 |
--------------------------------------------------------------------------------