[修改] 增加freeRTOS

1. 版本FreeRTOSv202212.01,命名为kernel;
This commit is contained in:
2023-05-06 16:43:01 +00:00
commit a345df017b
20944 changed files with 11094377 additions and 0 deletions

View File

@ -0,0 +1,24 @@
# Emitted when running CBMC proofs
proofs/**/logs
proofs/**/gotos
proofs/**/report
proofs/**/html
proofs/output
# Emitted by CBMC Viewer
TAGS-*
# Emitted by Arpa
arpa_cmake/
arpa-validation-logs/
Makefile.arpa
# Emitted by litani
.ninja_deps
.ninja_log
.litani_cache_dir
# These files should be overwritten whenever prepare.py runs
cbmc-batch.yaml
__pycache__/

View File

@ -0,0 +1,6 @@
CBMC proof include files
========================
This directory contains include files written for CBMC proof. It is
common to write some code to model aspects of the system under test,
and the header files for this code go here.

View File

@ -0,0 +1,49 @@
/*
* SigV4 Library v1.2.0
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file hash_stubs.h
* @brief Declarations for stubs used in sigv4.c.
* Please see sigv4.c for documentation.
*/
#ifndef HASH_STUBS_H_
#define HASH_STUBS_H_
/* Standard includes. */
#include <stdint.h>
#include <stddef.h>
#include <string.h>
int32_t HashInitStub( void * pHashContext );
int32_t HashUpdateStub( void * pHashContext,
const char * pInput,
size_t inputLen );
int32_t HashFinalStub( void * pHashContext,
const char * pInput,
size_t inputLen );
#endif /* ifndef HASH_STUBS_H_ */

View File

@ -0,0 +1,42 @@
/*
* SigV4 Library v1.2.0
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef SIGV4_ANNEX_H_
#define SIGV4_ANNEX_H_
#include "sigv4.h"
#include "sigv4_internal.h"
/*
* These are declarations for the (normally) static functions from sigv4.c.
* Please see sigv4.c for documentation.
*/
SigV4Status_t copyHeaderStringToCanonicalBuffer( const char * pData,
size_t dataLen,
uint32_t flags,
char separator,
CanonicalContext_t * canonicalRequest );
#endif /* ifndef SIGV4_ANNEX_H_ */

View File

@ -0,0 +1,105 @@
/*
* SigV4 Library v1.2.0
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file sigv4_config.h
* @brief The default values for configuration macros used by the SigV4 Library.
*
* @note This file should NOT be modified. If custom values are needed for any
* configuration macros, a sigv4_config.h file should be provided to the SigV4
* Library to override the default values defined in this file. To use
* the custom config file, the preprocessor macro SIGV4_DO_NOT_USE_CUSTOM_CONFIG
* must NOT be set.
*/
#ifndef SIGV4_CONFIG_H_
#define SIGV4_CONFIG_H_
/**
* @brief Macro indicating the largest block size of any hashing
* algorithm used for SigV4 authentication i.e. the maximum of all
* values specified for the hashBlockLen in #SigV4CryptoInterface_t.
* For example, using SHA-512 would require this value to be at least 128.
*
* <b>Possible values:</b> Any positive 32 bit integer. <br>
* <b>Default value:</b> `64`
*/
#define SIGV4_HASH_MAX_BLOCK_LENGTH ( MAX_HASH_BLOCK_LEN - 1U )
/**
* @brief Macro defining the maximum digest length of the specified hash function,
* used to determine the length of the output buffer.
*
* This macro should be updated if using a hashing algorithm other than SHA256
* (32 byte digest length). For example, using SHA512 would require this
* value to be at least 64.
*
* <b>Possible values:</b> Any positive 32 bit integer. <br>
* <b>Default value:</b> `32`
*/
#define SIGV4_HASH_MAX_DIGEST_LENGTH ( MAX_HASH_DIGEST_LEN - 1U )
/**
* @brief Macro defining the size of the internal buffer used for incremental
* canonicalization and hashing.
*
* A buffer of this size in bytes is declared on the stack. It should be be
* large enough for the digest output of the specified hash function.
*
* <b>Possible values:</b> Any positive 32 bit integer. <br>
* <b>Default value:</b> `1024`
*/
#ifndef SIGV4_PROCESSING_BUFFER_LENGTH
#define SIGV4_PROCESSING_BUFFER_LENGTH 60U
#endif
/**
* @brief Macro defining the maximum number of headers in the request, used to
* assist the library in sorting header fields during canonicalization.
*
* This macro should be updated if the number of request headers the application
* wishes to sign is higher or lower than the default value (100).
*
* <b>Possible values:</b> Any positive 32 bit integer. <br>
* <b>Default value:</b> `100`
*/
#ifndef SIGV4_MAX_HTTP_HEADER_COUNT
#define SIGV4_MAX_HTTP_HEADER_COUNT 5U
#endif
/**
* @brief Macro defining the maximum number of query key/value pairs, used to
* assist the library in sorting query keys during canonicalization.
*
* This macro should be updated if the number of query key/value pairs the
* application wishes to sign is higher or lower than the default value (100).
*
* <b>Possible values:</b> Any positive 32 bit integer. <br>
* <b>Default value:</b> `100`
*/
#ifndef SIGV4_MAX_QUERY_PAIR_COUNT
#define SIGV4_MAX_QUERY_PAIR_COUNT 5U
#endif
#endif /* ifndef SIGV4_CONFIG_H_ */

View File

@ -0,0 +1,77 @@
/*
* SigV4 Library v1.2.0
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file sigv4_stubs.h
* @brief Declarations for the (normally) static functions from sigv4.c.
* Please see sigv4.c for documentation.
*/
#ifndef SIGV4_STUBS_H_
#define SIGV4_STUBS_H_
#include <stdbool.h>
#include <sigv4.h>
#include <sigv4_internal.h>
void addToDate( const char formatChar,
int32_t result,
SigV4DateTime_t * pDateElements );
SigV4Status_t scanValue( const char * pDate,
const char formatChar,
size_t readLoc,
size_t lenToRead,
SigV4DateTime_t * pDateElements );
SigV4Status_t writeLineToCanonicalRequest( const char * pLine,
size_t lineLen,
CanonicalContext_t * pCanonicalContext );
SigV4Status_t encodeURI( const char * pUri,
size_t uriLen,
char * pCanonicalURI,
size_t * canonicalURILen,
bool encodeSlash,
bool doubleEncodeEquals );
SigV4Status_t generateCanonicalQuery( const char * pQuery,
size_t queryLen,
CanonicalContext_t * pCanonicalContext );
SigV4Status_t generateCanonicalAndSignedHeaders( const char * pHeaders,
size_t headersLen,
uint32_t flags,
CanonicalContext_t * canonicalRequest,
char ** pSignedHeaders,
size_t * pSignedHeadersLen );
SigV4Status_t copyHeaderStringToCanonicalBuffer( const char * pData,
size_t dataLen,
uint32_t flags,
char separator,
CanonicalContext_t * canonicalRequest );
#endif /* ifndef SIGV4_STUBS_H_ */

View File

@ -0,0 +1,23 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0
HARNESS_ENTRY=harness
DEFINES += -DCBMC_MAX_BUFSIZE=$(CBMC_MAX_BUFSIZE)
ifdef CBMC_MAX_QUERYKEYLENGTH
DEFINES += -DCBMC_MAX_QUERYKEYLENGTH=$(CBMC_MAX_QUERYKEYLENGTH)
endif
INCLUDES += -I$(CBMC_ROOT)/include
PROOF_SOURCES += $(PROOFDIR)/$(HARNESS_FILE).c
PROJECT_SOURCES += $(PROOFDIR)/sigv4.c
PROJECT_SOURCES += $(SRCDIR)/source/sigv4_quicksort.c
CHECKFLAGS += --pointer-primitive-check
include ../Makefile.common
cleanclean: veryclean
-$(RM) $(PROOFDIR)/sigv4.c

View File

@ -0,0 +1,43 @@
# -*- mode: makefile -*-
# The first line sets the emacs major mode to Makefile
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0
################################################################
# Use this file to give project-specific definitions of the command
# line arguments to pass to CBMC tools like goto-cc to build the goto
# binaries and cbmc to do the property and coverage checking.
#
# Use this file to override most default definitions of variables in
# Makefile.common.
################################################################
# Flags to pass to goto-cc for compilation (typically those passed to gcc -c)
# COMPILE_FLAGS =
COMPILE_FLAGS += -fPIC
COMPILE_FLAGS += -std=gnu90
# Flags to pass to goto-cc for linking (typically those passed to gcc)
# LINK_FLAGS =
# Preprocessor include paths -I...
# Consider adding
# INCLUDES += -I$(CBMC_ROOT)/include
# You will want to decide what order that comes in relative to the other
# include directories in your project.
#
# INCLUDES =
INCLUDES += -I$(SRCDIR)/test/cbmc/include
INCLUDES += -I$(SRCDIR)/source/include
INCLUDES += -I$(SRCDIR)/test/include
# Preprocessor definitions -D...
# DEFINES =
DEFINES +=
# Path to arpa executable
# ARPA =
# Flags to pass to cmake for building the project
# ARPA_CMAKE_FLAGS =

View File

@ -0,0 +1,25 @@
# -*- mode: makefile -*-
# The first line sets the emacs major mode to Makefile
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0
################################################################
# Use this file to give project-specific targets, including targets
# that may depend on targets defined in Makefile.common.
################################################################
# Each proof requires sigv4.c to be patched (using sed) and dumped into the
# proof directory. The exact sed invocation differs for each proof. So each
# proof must set the SIGV4_SED_EXPR variable, which this rule uses as the
# argument to sed.
$(PROOFDIR)/sigv4.c: $(SRCDIR)/source/sigv4.c
$(LITANI) add-job \
--command \
"sed -E '$(SIGV4_SED_EXPR)' $^" \
--inputs $^ \
--outputs $@ \
--stdout-file $@ \
--ci-stage build \
--pipeline-name "$(PROOF_UID)" \
--description "$(PROOF_UID): patching sigv4.c"

View File

@ -0,0 +1,11 @@
# -*- mode: makefile -*-
# The first line sets the emacs major mode to Makefile
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0
################################################################
# Use this file to define project-specific targets and definitions for
# unit testing or continuous integration that may depend on targets
# defined in Makefile.common
################################################################

View File

@ -0,0 +1,19 @@
PROOF_ROOT ?= $(abspath .)
# Absolute path to the root of the source tree.
#
SRCDIR ?= $(abspath $(PROOF_ROOT)/../../..)
# Absolute path to the litani script.
#
LITANI ?= litani
# Name of this proof project, displayed in proof reports. For example,
# "s2n" or "Amazon FreeRTOS". For projects with multiple proof roots,
# this may be overridden on the command-line to Make, for example
#
# make PROJECT_NAME="FreeRTOS MQTT" report
#
PROJECT_NAME = "sigv4-for-aws-iot-embedded-sdk"

View File

@ -0,0 +1,999 @@
# -*- mode: makefile -*-
# The first line sets the emacs major mode to Makefile
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0
CBMC_STARTER_KIT_VERSION = CBMC starter kit 2.5
################################################################
# The CBMC Starter Kit depends on the files Makefile.common and
# run-cbmc-proofs.py. They are installed by the setup script
# cbmc-starter-kit-setup and updated to the latest version by the
# update script cbmc-starter-kit-update. For more information about
# the starter kit and these files and these scripts, see
# https://model-checking.github.io/cbmc-starter-kit
#
# Makefile.common implements what we consider to be some best
# practices for using cbmc for software verification.
#
# Section I gives default values for a large number of Makefile
# variables that control
# * how your code is built (include paths, etc),
# * what program transformations are applied to your code (loop
# unwinding, etc), and
# * what properties cbmc checks for in your code (memory safety, etc).
#
# These variables are defined below with definitions of the form
# VARIABLE ?= DEFAULT_VALUE
# meaning VARIABLE is set to DEFAULT_VALUE if VARIABLE has not already
# been given a value.
#
# For your project, you can override these default values with
# project-specific definitions in Makefile-project-defines.
#
# For any individual proof, you can override these default values and
# project-specific values with proof-specific definitions in the
# Makefile for your proof.
#
# The definitions in the proof Makefile override definitions in the
# project Makefile-project-defines which override definitions in this
# Makefile.common.
#
# Section II uses the values defined in Section I to build your code, run
# your proof, and build a report of your results. You should not need
# to modify or override anything in Section II, but you may want to
# read it to understand how the values defined in Section I control
# things.
#
# To use Makefile.common, set variables as described above as needed,
# and then for each proof,
#
# * Create a subdirectory <DIR>.
# * Write a proof harness (a function) with the name <HARNESS_ENTRY>
# in a file with the name <DIR>/<HARNESS_FILE>.c
# * Write a makefile with the name <DIR>/Makefile that looks
# something like
#
# HARNESS_FILE=<HARNESS_FILE>
# HARNESS_ENTRY=<HARNESS_ENTRY>
# PROOF_UID=<PROOF_UID>
#
# PROJECT_SOURCES += $(SRCDIR)/libraries/api_1.c
# PROJECT_SOURCES += $(SRCDIR)/libraries/api_2.c
#
# PROOF_SOURCES += $(PROOFDIR)/harness.c
# PROOF_SOURCES += $(SRCDIR)/cbmc/proofs/stub_a.c
# PROOF_SOURCES += $(SRCDIR)/cbmc/proofs/stub_b.c
#
# UNWINDSET += foo.0:3
# UNWINDSET += bar.1:6
#
# REMOVE_FUNCTION_BODY += api_stub_a
# REMOVE_FUNCTION_BODY += api_stub_b
#
# DEFINES = -DDEBUG=0
#
# include ../Makefile.common
#
# * Change directory to <DIR> and run make
#
# The proof setup script cbmc-starter-kit-setup-proof from the CBMC
# Starter Kit will do most of this for, creating a directory and
# writing a basic Makefile and proof harness into it that you can edit
# as described above.
#
# Warning: If you get results that are hard to explain, consider
# running "make clean" or "make veryclean" before "make" if you get
# results that are hard to explain. Dependency handling in this
# Makefile.common may not be perfect.
SHELL=/bin/bash
default: report
################################################################
################################################################
## Section I: This section gives common variable definitions.
##
## Override these definitions in Makefile-project-defines or
## your proof Makefile.
##
## Remember that Makefile.common and Makefile-project-defines are
## included into the proof Makefile in your proof directory, so all
## relative pathnames defined there should be relative to your proof
## directory.
################################################################
# Define the layout of the source tree and the proof subtree
#
# Generally speaking,
#
# SRCDIR = the root of the repository
# CBMC_ROOT = /srcdir/cbmc
# PROOF_ROOT = /srcdir/cbmc/proofs
# PROOF_SOURCE = /srcdir/cbmc/sources
# PROOF_INCLUDE = /srcdir/cbmc/include
# PROOF_STUB = /srcdir/cbmc/stubs
# PROOFDIR = the directory containing the Makefile for your proof
#
# The path /srcdir/cbmc used in the example above is determined by the
# setup script cbmc-starter-kit-setup. Projects usually create a cbmc
# directory somewhere in the source tree, and run the setup script in
# that directory. The value of CBMC_ROOT becomes the absolute path to
# that directory.
#
# The location of that cbmc directory in the source tree affects the
# definition of SRCDIR, which is defined in terms of the relative path
# from a proof directory to the repository root. The definition is
# usually determined by the setup script cbmc-starter-kit-setup and
# written to Makefile-template-defines, but you can override it for a
# project in Makefile-project-defines and for a specific proof in the
# Makefile for the proof.
# Absolute path to the directory containing this Makefile.common
# See https://ftp.gnu.org/old-gnu/Manuals/make-3.80/html_node/make_17.html
#
# Note: We compute the absolute paths to the makefiles in MAKEFILE_LIST
# before we filter the list of makefiles for %/Makefile.common.
# Otherwise an invocation of the form "make -f Makefile.common" will set
# MAKEFILE_LIST to "Makefile.common" which will fail to match the
# pattern %/Makefile.common.
#
MAKEFILE_PATHS = $(foreach makefile,$(MAKEFILE_LIST),$(abspath $(makefile)))
PROOF_ROOT = $(dir $(filter %/Makefile.common,$(MAKEFILE_PATHS)))
CBMC_ROOT = $(shell dirname $(PROOF_ROOT))
PROOF_SOURCE = $(CBMC_ROOT)/sources
PROOF_INCLUDE = $(CBMC_ROOT)/include
PROOF_STUB = $(CBMC_ROOT)/stubs
# Project-specific definitions to override default definitions below
# * Makefile-project-defines will never be overwritten
# * Makefile-template-defines may be overwritten when the starter
# kit is updated
sinclude $(PROOF_ROOT)/Makefile-project-defines
sinclude $(PROOF_ROOT)/Makefile-template-defines
# SRCDIR is the path to the root of the source tree
# This is a default definition that is frequently overridden in
# another Makefile, see the discussion of SRCDIR above.
SRCDIR ?= $(abspath ../..)
# PROOFDIR is the path to the directory containing the proof harness
PROOFDIR ?= $(abspath .)
################################################################
# Define how to run CBMC
# Do property checking with the external SAT solver given by
# EXTERNAL_SAT_SOLVER. Do coverage checking with the default solver,
# since coverage checking requires the use of an incremental solver.
# The EXTERNAL_SAT_SOLVER variable is typically set (if it is at all)
# as an environment variable or as a makefile variable in
# Makefile-project-defines.
#
# For a particular proof, if the default solver is faster, do property
# checking with the default solver by including this definition in the
# proof Makefile:
# USE_EXTERNAL_SAT_SOLVER =
#
ifneq ($(strip $(EXTERNAL_SAT_SOLVER)),)
USE_EXTERNAL_SAT_SOLVER ?= --external-sat-solver $(EXTERNAL_SAT_SOLVER)
endif
CHECKFLAGS += $(USE_EXTERNAL_SAT_SOLVER)
# Job pools
# For version of Litani that are new enough (where `litani print-capabilities`
# prints "pools"), proofs for which `EXPENSIVE = true` is set can be added to a
# "job pool" that restricts how many expensive proofs are run at a time. All
# other proofs will be built in parallel as usual.
#
# In more detail: all compilation, instrumentation, and report jobs are run with
# full parallelism as usual, even for expensive proofs. The CBMC jobs for
# non-expensive proofs are also run in parallel. The only difference is that the
# CBMC safety checks and coverage checks for expensive proofs are run with a
# restricted parallelism level. At any one time, only N of these jobs are run at
# once, amongst all the proofs.
#
# To configure N, Litani needs to be initialized with a pool called "expensive".
# For example, to only run two CBMC safety/coverage jobs at a time from amongst
# all the proofs, you would initialize litani like
# litani init --pools expensive:2
# The run-cbmc-proofs.py script takes care of this initialization through the
# --expensive-jobs-parallelism flag.
#
# To enable this feature, set
# the ENABLE_POOLS variable when running Make, like
# `make ENABLE_POOLS=true report`
# The run-cbmc-proofs.py script takes care of this through the
# --restrict-expensive-jobs flag.
ifeq ($(strip $(ENABLE_POOLS)),)
POOL =
else ifeq ($(strip $(EXPENSIVE)),)
POOL =
else
POOL = --pool expensive
endif
# Similar to the pool feature above. If Litani is new enough, enable
# profiling CBMC's memory use.
ifeq ($(strip $(ENABLE_MEMORY_PROFILING)),)
MEMORY_PROFILING =
else
MEMORY_PROFILING = --profile-memory
endif
# Property checking flags
#
# Each variable below controls a specific property checking flag
# within CBMC. If desired, a property flag can be disabled within
# a particular proof by nulling the corresponding variable. For
# instance, the following line:
#
# CHECK_FLAG_POINTER_CHECK =
#
# would disable the --pointer-check CBMC flag within:
# * an entire project when added to Makefile-project-defines
# * a specific proof when added to the harness Makefile
CBMC_FLAG_MALLOC_MAY_FAIL ?= --malloc-may-fail
CBMC_FLAG_MALLOC_FAIL_NULL ?= --malloc-fail-null
CBMC_FLAG_BOUNDS_CHECK ?= --bounds-check
CBMC_FLAG_CONVERSION_CHECK ?= --conversion-check
CBMC_FLAG_DIV_BY_ZERO_CHECK ?= --div-by-zero-check
CBMC_FLAG_FLOAT_OVERFLOW_CHECK ?= --float-overflow-check
CBMC_FLAG_NAN_CHECK ?= --nan-check
CBMC_FLAG_POINTER_CHECK ?= --pointer-check
CBMC_FLAG_POINTER_OVERFLOW_CHECK ?= --pointer-overflow-check
CBMC_FLAG_POINTER_PRIMITIVE_CHECK ?= --pointer-primitive-check
CBMC_FLAG_SIGNED_OVERFLOW_CHECK ?= --signed-overflow-check
CBMC_FLAG_UNDEFINED_SHIFT_CHECK ?= --undefined-shift-check
CBMC_FLAG_UNSIGNED_OVERFLOW_CHECK ?= --unsigned-overflow-check
CBMC_FLAG_UNWINDING_ASSERTIONS ?= --unwinding-assertions
CBMC_FLAG_UNWIND ?= --unwind 1
CBMC_FLAG_FLUSH ?= --flush
# CBMC flags used for property checking and coverage checking
CBMCFLAGS += $(CBMC_FLAG_UNWIND) $(CBMC_UNWINDSET) $(CBMC_FLAG_FLUSH)
# CBMC flags used for property checking
CHECKFLAGS += $(CBMC_FLAG_MALLOC_MAY_FAIL)
CHECKFLAGS += $(CBMC_FLAG_MALLOC_FAIL_NULL)
CHECKFLAGS += $(CBMC_FLAG_BOUNDS_CHECK)
CHECKFLAGS += $(CBMC_FLAG_CONVERSION_CHECK)
CHECKFLAGS += $(CBMC_FLAG_DIV_BY_ZERO_CHECK)
CHECKFLAGS += $(CBMC_FLAG_FLOAT_OVERFLOW_CHECK)
CHECKFLAGS += $(CBMC_FLAG_NAN_CHECK)
CHECKFLAGS += $(CBMC_FLAG_POINTER_CHECK)
CHECKFLAGS += $(CBMC_FLAG_POINTER_OVERFLOW_CHECK)
CHECKFLAGS += $(CBMC_FLAG_POINTER_PRIMITIVE_CHECK)
CHECKFLAGS += $(CBMC_FLAG_SIGNED_OVERFLOW_CHECK)
CHECKFLAGS += $(CBMC_FLAG_UNDEFINED_SHIFT_CHECK)
CHECKFLAGS += $(CBMC_FLAG_UNSIGNED_OVERFLOW_CHECK)
CHECKFLAGS += $(CBMC_FLAG_UNWINDING_ASSERTIONS)
# CBMC flags used for coverage checking
COVERFLAGS += $(CBMC_FLAG_MALLOC_MAY_FAIL)
COVERFLAGS += $(CBMC_FLAG_MALLOC_FAIL_NULL)
# Additional CBMC flag to CBMC control verbosity.
#
# Meaningful values are
# 0 none
# 1 only errors
# 2 + warnings
# 4 + results
# 6 + status/phase information
# 8 + statistical information
# 9 + progress information
# 10 + debug info
#
# Uncomment the following line or set in Makefile-project-defines
# CBMC_VERBOSITY ?= --verbosity 4
# Additional CBMC flag to control how CBMC treats static variables.
#
# NONDET_STATIC is a list of flags of the form --nondet-static
# and --nondet-static-exclude VAR. The --nondet-static flag causes
# CBMC to initialize static variables with unconstrained value
# (ignoring initializers and default zero-initialization). The
# --nondet-static-exclude VAR excludes VAR for the variables
# initialized with unconstrained values.
NONDET_STATIC ?=
# Flags to pass to goto-cc for compilation and linking
COMPILE_FLAGS ?= -Wall
LINK_FLAGS ?= -Wall
EXPORT_FILE_LOCAL_SYMBOLS ?= --export-file-local-symbols
# Preprocessor include paths -I...
INCLUDES ?=
# Preprocessor definitions -D...
DEFINES ?=
# CBMC object model
#
# CBMC_OBJECT_BITS is the number of bits in a pointer CBMC uses for
# the id of the object to which a pointer is pointing. CBMC uses 8
# bits for the object id by default. The remaining bits in the pointer
# are used for offset into the object. This limits the size of the
# objects that CBMC can model. This Makefile defines this bound on
# object size to be CBMC_MAX_OBJECT_SIZE. You are likely to get
# unexpected results if you try to malloc an object larger than this
# bound.
CBMC_OBJECT_BITS ?= 8
# CBMC loop unwinding (Normally set in the proof Makefile)
#
# UNWINDSET is a list of pairs of the form foo.1:4 meaning that
# CBMC should unwind loop 1 in function foo no more than 4 times.
# For historical reasons, the number 4 is one more than the number
# of times CBMC actually unwinds the loop.
UNWINDSET ?=
# CBMC early loop unwinding (Normally set in the proof Makefile)
#
# Most users can ignore this variable.
#
# This variable exists to support the use of loop and function
# contracts, two features under development for CBMC. Checking the
# assigns clause for function contracts and loop invariants currently
# assumes loop-free bodies for loops and functions with contracts
# (possibly after replacing nested loops with their own loop
# contracts). To satisfy this requirement, it may be necessary to
# unwind some loops before the function contract and loop invariant
# transformations are applied to the goto program. This variable
# EARLY_UNWINDSET is identical to UNWINDSET, and we assume that the
# loops mentioned in EARLY_UNWINDSET and UNWINDSET are disjoint.
EARLY_UNWINDSET ?=
# CBMC function removal (Normally set set in the proof Makefile)
#
# REMOVE_FUNCTION_BODY is a list of function names. CBMC will "undefine"
# the function, and CBMC will treat the function as having no side effects
# and returning an unconstrained value of the appropriate return type.
# The list should include the names of functions being stubbed out.
REMOVE_FUNCTION_BODY ?=
# CBMC function pointer restriction (Normally set in the proof Makefile)
#
# RESTRICT_FUNCTION_POINTER is a list of function pointer restriction
# instructions of the form:
#
# <fun_id>.function_pointer_call.<N>/<fun_id>[,<fun_id>]*
#
# The function pointer call number <N> in the specified function gets
# rewritten to a case switch over a finite list of functions.
# If some possible target functions are omitted from the list a counter
# example trace will be found by CBMC, i.e. the transformation is sound.
# If the target functions are file-local symbols, then mangled names must
# be used.
RESTRICT_FUNCTION_POINTER ?=
# The project source files (Normally set set in the proof Makefile)
#
# PROJECT_SOURCES is the list of project source files to compile,
# including the source file defining the function under test.
PROJECT_SOURCES ?=
# The proof source files (Normally set in the proof Makefile)
#
# PROOF_SOURCES is the list of proof source files to compile, including
# the proof harness, and including any function stubs being used.
PROOF_SOURCES ?=
# The number of seconds that CBMC should be allowed to run for before
# being forcefully terminated. Currently, this is set to be less than
# the time limit for a CodeBuild job, which is eight hours. If a proof
# run takes longer than the time limit of the CI environment, the
# environment will halt the proof run without updating the Litani
# report, making the proof run appear to "hang".
CBMC_TIMEOUT ?= 21600
# Proof writers could add function contracts in their source code.
# These contracts are ignored by default, but may be enabled in two distinct
# contexts using the following two variables:
# 1. To check whether one or more function contracts are sound with respect to
# the function implementation, CHECK_FUNCTION_CONTRACTS should be a list of
# function names.
# 2. To replace calls to certain functions with their correspondent function
# contracts, USE_FUNCTION_CONTRACTS should be a list of function names.
# One must check separately whether a function contract is sound before
# replacing it in calling contexts.
CHECK_FUNCTION_CONTRACTS ?=
CBMC_CHECK_FUNCTION_CONTRACTS := $(patsubst %,--enforce-contract %, $(CHECK_FUNCTION_CONTRACTS))
USE_FUNCTION_CONTRACTS ?=
CBMC_USE_FUNCTION_CONTRACTS := $(patsubst %,--replace-call-with-contract %, $(USE_FUNCTION_CONTRACTS))
# Similarly, proof writers could also add loop contracts in their source code
# to obtain unbounded correctness proofs. Unlike function contracts, loop
# contracts are not reusable and thus are checked and used simultaneously.
# These contracts are also ignored by default, but may be enabled by setting
# the APPLY_LOOP_CONTRACTS variable to 1.
APPLY_LOOP_CONTRACTS ?= 0
ifeq ($(APPLY_LOOP_CONTRACTS),1)
CBMC_APPLY_LOOP_CONTRACTS ?= --apply-loop-contracts
endif
# Silence makefile output (eg, long litani commands) unless VERBOSE is set.
ifndef VERBOSE
MAKEFLAGS := $(MAKEFLAGS) -s
endif
################################################################
################################################################
## Section II: This section defines the process of running a proof
##
## There should be no reason to edit anything below this line.
################################################################
# Paths
CBMC ?= cbmc
GOTO_ANALYZER ?= goto-analyzer
GOTO_CC ?= goto-cc
GOTO_INSTRUMENT ?= goto-instrument
CRANGLER ?= crangler
VIEWER ?= cbmc-viewer
MAKE_SOURCE ?= make-source
VIEWER2 ?= cbmc-viewer
CMAKE ?= cmake
GOTODIR ?= $(PROOFDIR)/gotos
LOGDIR ?= $(PROOFDIR)/logs
PROJECT ?= project
PROOF ?= proof
HARNESS_GOTO ?= $(GOTODIR)/$(HARNESS_FILE)
PROJECT_GOTO ?= $(GOTODIR)/$(PROJECT)
PROOF_GOTO ?= $(GOTODIR)/$(PROOF)
################################################################
# Useful macros for values that are hard to reference
SPACE :=$() $()
COMMA :=,
################################################################
# Set C compiler defines
CBMCFLAGS += --object-bits $(CBMC_OBJECT_BITS)
COMPILE_FLAGS += --object-bits $(CBMC_OBJECT_BITS)
DEFINES += -DCBMC=1
DEFINES += -DCBMC_OBJECT_BITS=$(CBMC_OBJECT_BITS)
DEFINES += -DCBMC_MAX_OBJECT_SIZE="(SIZE_MAX>>(CBMC_OBJECT_BITS+1))"
# CI currently assumes cbmc invocation has at most one --unwindset
ifdef UNWINDSET
ifneq ($(strip $(UNWINDSET)),"")
CBMC_UNWINDSET := --unwindset $(subst $(SPACE),$(COMMA),$(strip $(UNWINDSET)))
endif
endif
ifdef EARLY_UNWINDSET
ifneq ($(strip $(EARLY_UNWINDSET)),"")
CBMC_EARLY_UNWINDSET := --unwindset $(subst $(SPACE),$(COMMA),$(strip $(EARLY_UNWINDSET)))
endif
endif
CBMC_REMOVE_FUNCTION_BODY := $(patsubst %,--remove-function-body %, $(REMOVE_FUNCTION_BODY))
CBMC_RESTRICT_FUNCTION_POINTER := $(patsubst %,--restrict-function-pointer %, $(RESTRICT_FUNCTION_POINTER))
################################################################
# Targets for rewriting source files with crangler
# Construct crangler configuration files
#
# REWRITTEN_SOURCES is a list of crangler output files source.i.
# This target assumes that for each source.i
# * source.i_SOURCE is the path to a source file,
# * source.i_FUNCTIONS is a list of functions (may be empty)
# * source.i_OBJECTS is a list of variables (may be empty)
# This target constructs the crangler configuration file source.i.json
# of the form
# {
# "sources": [ "/proj/code.c" ],
# "includes": [ "/proj/include" ],
# "defines": [ "VAR=1" ],
# "functions": [ {"function_name": ["remove static"]} ],
# "objects": [ {"variable_name": ["remove static"]} ],
# "output": "source.i"
# }
# to remove the static attribute from function_name and variable_name
# in the source file source.c and write the result to source.i.
#
# This target assumes that filenames include no spaces and that
# the INCLUDES and DEFINES variables include no spaces after -I
# and -D. For example, use "-DVAR=1" and not "-D VAR=1".
#
# Define *_SOURCE, *_FUNCTIONS, and *_OBJECTS in the proof Makefile.
# The string source.i is usually an absolute path $(PROOFDIR)/code.i
# to a file in the proof directory that contains the proof Makefile.
# The proof Makefile usually includes the definitions
# $(PROOFDIR)/code.i_SOURCE = /proj/code.c
# $(PROOFDIR)/code.i_FUNCTIONS = function_name
# $(PROOFDIR)/code.i_OBJECTS = variable_name
# Because these definitions refer to PROOFDIR that is defined in this
# Makefile.common, these definitions must appear after the inclusion
# of Makefile.common in the proof Makefile.
#
$(foreach rs,$(REWRITTEN_SOURCES),$(eval $(rs).json: $($(rs)_SOURCE)))
$(foreach rs,$(REWRITTEN_SOURCES),$(rs).json):
echo '{'\
'"sources": ['\
'"$($(@:.json=)_SOURCE)"'\
'],'\
'"includes": ['\
'$(subst $(SPACE),$(COMMA),$(patsubst -I%,"%",$(strip $(INCLUDES))))' \
'],'\
'"defines": ['\
'$(subst $(SPACE),$(COMMA),$(patsubst -D%,"%",$(subst ",\",$(strip $(DEFINES)))))' \
'],'\
'"functions": ['\
'{'\
'$(subst ~, ,$(subst $(SPACE),$(COMMA),$(patsubst %,"%":["remove~static"],$($(@:.json=)_FUNCTIONS))))' \
'}'\
'],'\
'"objects": ['\
'{'\
'$(subst ~, ,$(subst $(SPACE),$(COMMA),$(patsubst %,"%":["remove~static"],$($(@:.json=)_OBJECTS))))' \
'}'\
'],'\
'"output": "$(@:.json=)"'\
'}' > $@
# Rewrite source files with crangler
#
$(foreach rs,$(REWRITTEN_SOURCES),$(eval $(rs): $(rs).json))
$(REWRITTEN_SOURCES):
$(LITANI) add-job \
--command \
'$(CRANGLER) $@.json' \
--inputs $($@_SOURCE) \
--outputs $@ \
--stdout-file $(LOGDIR)/crangler-$(subst /,_,$(subst .,_,$@))-log.txt \
--interleave-stdout-stderr \
--pipeline-name "$(PROOF_UID)" \
--ci-stage build \
--description "$(PROOF_UID): removing static"
################################################################
# Build targets that make the relevant .goto files
# Compile project sources
$(PROJECT_GOTO)1.goto: $(PROJECT_SOURCES) $(REWRITTEN_SOURCES)
$(LITANI) add-job \
--command \
'$(GOTO_CC) $(CBMC_VERBOSITY) $(COMPILE_FLAGS) $(EXPORT_FILE_LOCAL_SYMBOLS) $(INCLUDES) $(DEFINES) $^ -o $@' \
--inputs $^ \
--outputs $@ \
--stdout-file $(LOGDIR)/project_sources-log.txt \
--pipeline-name "$(PROOF_UID)" \
--ci-stage build \
--description "$(PROOF_UID): building project binary"
# Compile proof sources
$(PROOF_GOTO)1.goto: $(PROOF_SOURCES)
$(LITANI) add-job \
--command \
'$(GOTO_CC) $(CBMC_VERBOSITY) $(COMPILE_FLAGS) $(EXPORT_FILE_LOCAL_SYMBOLS) $(INCLUDES) $(DEFINES) $^ -o $@' \
--inputs $^ \
--outputs $@ \
--stdout-file $(LOGDIR)/proof_sources-log.txt \
--pipeline-name "$(PROOF_UID)" \
--ci-stage build \
--description "$(PROOF_UID): building proof binary"
# Remove function bodies from project sources
$(PROJECT_GOTO)2.goto: $(PROJECT_GOTO)1.goto
$(LITANI) add-job \
--command \
'$(GOTO_INSTRUMENT) $(CBMC_VERBOSITY) $(CBMC_REMOVE_FUNCTION_BODY) $^ $@' \
--inputs $^ \
--outputs $@ \
--stdout-file $(LOGDIR)/remove_function_body-log.txt \
--pipeline-name "$(PROOF_UID)" \
--ci-stage build \
--description "$(PROOF_UID): removing function bodies from project sources"
# Link project and proof sources into the proof harness
$(HARNESS_GOTO)1.goto: $(PROOF_GOTO)1.goto $(PROJECT_GOTO)2.goto
$(LITANI) add-job \
--command '$(GOTO_CC) $(CBMC_VERBOSITY) --function $(HARNESS_ENTRY) $^ $(LINK_FLAGS) -o $@' \
--inputs $^ \
--outputs $@ \
--stdout-file $(LOGDIR)/link_proof_project-log.txt \
--pipeline-name "$(PROOF_UID)" \
--ci-stage build \
--description "$(PROOF_UID): linking project to proof"
# Restrict function pointers
$(HARNESS_GOTO)2.goto: $(HARNESS_GOTO)1.goto
$(LITANI) add-job \
--command \
'$(GOTO_INSTRUMENT) $(CBMC_VERBOSITY) $(CBMC_RESTRICT_FUNCTION_POINTER) $^ $@' \
--inputs $^ \
--outputs $@ \
--stdout-file $(LOGDIR)/restrict_function_pointer-log.txt \
--pipeline-name "$(PROOF_UID)" \
--ci-stage build \
--description "$(PROOF_UID): restricting function pointers in project sources"
# Fill static variable with unconstrained values
$(HARNESS_GOTO)3.goto: $(HARNESS_GOTO)2.goto
$(LITANI) add-job \
--command \
'$(GOTO_INSTRUMENT) $(CBMC_VERBOSITY) $(NONDET_STATIC) $^ $@' \
--inputs $^ \
--outputs $@ \
--stdout-file $(LOGDIR)/nondet_static-log.txt \
--pipeline-name "$(PROOF_UID)" \
--ci-stage build \
--description "$(PROOF_UID): setting static variables to nondet"
# Omit unused functions (sharpens coverage calculations)
$(HARNESS_GOTO)4.goto: $(HARNESS_GOTO)3.goto
$(LITANI) add-job \
--command \
'$(GOTO_INSTRUMENT) $(CBMC_VERBOSITY) --drop-unused-functions $^ $@' \
--inputs $^ \
--outputs $@ \
--stdout-file $(LOGDIR)/drop_unused_functions-log.txt \
--pipeline-name "$(PROOF_UID)" \
--ci-stage build \
--description "$(PROOF_UID): dropping unused functions"
# Omit initialization of unused global variables (reduces problem size)
$(HARNESS_GOTO)5.goto: $(HARNESS_GOTO)4.goto
$(LITANI) add-job \
--command \
'$(GOTO_INSTRUMENT) $(CBMC_VERBOSITY) --slice-global-inits $^ $@' \
--inputs $^ \
--outputs $@ \
--stdout-file $(LOGDIR)/slice_global_inits-log.txt \
--pipeline-name "$(PROOF_UID)" \
--ci-stage build \
--description "$(PROOF_UID): slicing global initializations"
# Replace function calls with function contracts
# This must be done before enforcing function contracts,
# since contract enforcement inlines all function calls.
$(HARNESS_GOTO)6.goto: $(HARNESS_GOTO)5.goto
$(LITANI) add-job \
--command \
'$(GOTO_INSTRUMENT) $(CBMC_VERBOSITY) $(CBMC_USE_FUNCTION_CONTRACTS) $^ $@' \
--inputs $^ \
--outputs $@ \
--stdout-file $(LOGDIR)/use_function_contracts-log.txt \
--pipeline-name "$(PROOF_UID)" \
--ci-stage build \
--description "$(PROOF_UID): replacing function calls with function contracts"
# Unwind loops for loop and function contracts
$(HARNESS_GOTO)7.goto: $(HARNESS_GOTO)6.goto
$(LITANI) add-job \
--command \
'$(GOTO_INSTRUMENT) $(CBMC_VERBOSITY) $(CBMC_EARLY_UNWINDSET) $(CBMC_FLAG_UNWINDING_ASSERTIONS) $^ $@' \
--inputs $^ \
--outputs $@ \
--stdout-file $(LOGDIR)/unwind_loops-log.txt \
--pipeline-name "$(PROOF_UID)" \
--ci-stage build \
--description "$(PROOF_UID): unwinding loops"
# Apply loop contracts
$(HARNESS_GOTO)8.goto: $(HARNESS_GOTO)7.goto
$(LITANI) add-job \
--command \
'$(GOTO_INSTRUMENT) $(CBMC_VERBOSITY) $(CBMC_APPLY_LOOP_CONTRACTS) $^ $@' \
--inputs $^ \
--outputs $@ \
--stdout-file $(LOGDIR)/apply_loop_contracts-log.txt \
--pipeline-name "$(PROOF_UID)" \
--ci-stage build \
--description "$(PROOF_UID): applying loop contracts"
# Check function contracts
$(HARNESS_GOTO)9.goto: $(HARNESS_GOTO)8.goto
$(LITANI) add-job \
--command \
'$(GOTO_INSTRUMENT) $(CBMC_VERBOSITY) $(CBMC_CHECK_FUNCTION_CONTRACTS) $^ $@' \
--inputs $^ \
--outputs $@ \
--stdout-file $(LOGDIR)/check_function_contracts-log.txt \
--pipeline-name "$(PROOF_UID)" \
--ci-stage build \
--description "$(PROOF_UID): checking function contracts"
# Final name for proof harness
$(HARNESS_GOTO).goto: $(HARNESS_GOTO)9.goto
$(LITANI) add-job \
--command 'cp $< $@' \
--inputs $^ \
--outputs $@ \
--pipeline-name "$(PROOF_UID)" \
--ci-stage build \
--description "$(PROOF_UID): copying final goto-binary"
################################################################
# Targets to run the analysis commands
$(LOGDIR)/result.txt: $(HARNESS_GOTO).goto
$(LITANI) add-job \
$(POOL) \
--command \
'$(CBMC) $(CBMC_VERBOSITY) $(CBMCFLAGS) $(CBMC_FLAG_UNWINDING_ASSERTIONS) $(CHECKFLAGS) --trace $<' \
--inputs $^ \
--outputs $@ \
--ci-stage test \
--stdout-file $@ \
$(MEMORY_PROFILING) \
--ignore-returns 10 \
--timeout $(CBMC_TIMEOUT) \
--pipeline-name "$(PROOF_UID)" \
--tags "stats-group:safety checks" \
--stderr-file $(LOGDIR)/result-err-log.txt \
--description "$(PROOF_UID): checking safety properties"
$(LOGDIR)/result.xml: $(HARNESS_GOTO).goto
$(LITANI) add-job \
$(POOL) \
--command \
'$(CBMC) $(CBMC_VERBOSITY) $(CBMCFLAGS) $(CBMC_FLAG_UNWINDING_ASSERTIONS) $(CHECKFLAGS) --trace --xml-ui $<' \
--inputs $^ \
--outputs $@ \
--ci-stage test \
--stdout-file $@ \
$(MEMORY_PROFILING) \
--ignore-returns 10 \
--timeout $(CBMC_TIMEOUT) \
--pipeline-name "$(PROOF_UID)" \
--tags "stats-group:safety checks" \
--stderr-file $(LOGDIR)/result-err-log.txt \
--description "$(PROOF_UID): checking safety properties"
$(LOGDIR)/property.xml: $(HARNESS_GOTO).goto
$(LITANI) add-job \
--command \
'$(CBMC) $(CBMC_VERBOSITY) $(CBMCFLAGS) $(CBMC_FLAG_UNWINDING_ASSERTIONS) $(CHECKFLAGS) --show-properties --xml-ui $<' \
--inputs $^ \
--outputs $@ \
--ci-stage test \
--stdout-file $@ \
--ignore-returns 10 \
--pipeline-name "$(PROOF_UID)" \
--stderr-file $(LOGDIR)/property-err-log.txt \
--description "$(PROOF_UID): printing safety properties"
$(LOGDIR)/coverage.xml: $(HARNESS_GOTO).goto
$(LITANI) add-job \
$(POOL) \
--command \
'$(CBMC) $(CBMC_VERBOSITY) $(CBMCFLAGS) $(COVERFLAGS) --cover location --xml-ui $<' \
--inputs $^ \
--outputs $@ \
--ci-stage test \
--stdout-file $@ \
$(MEMORY_PROFILING) \
--ignore-returns 10 \
--timeout $(CBMC_TIMEOUT) \
--pipeline-name "$(PROOF_UID)" \
--tags "stats-group:coverage computation" \
--stderr-file $(LOGDIR)/coverage-err-log.txt \
--description "$(PROOF_UID): calculating coverage"
define VIEWER_CMD
$(VIEWER) \
--result $(LOGDIR)/result.txt \
--block $(LOGDIR)/coverage.xml \
--property $(LOGDIR)/property.xml \
--srcdir $(SRCDIR) \
--goto $(HARNESS_GOTO).goto \
--htmldir $(PROOFDIR)/html
endef
export VIEWER_CMD
$(PROOFDIR)/html: $(LOGDIR)/result.txt $(LOGDIR)/property.xml $(LOGDIR)/coverage.xml
$(LITANI) add-job \
--command "$$VIEWER_CMD" \
--inputs $^ \
--outputs $(PROOFDIR)/html \
--pipeline-name "$(PROOF_UID)" \
--ci-stage report \
--stdout-file $(LOGDIR)/viewer-log.txt \
--description "$(PROOF_UID): generating report"
# Caution: run make-source before running property and coverage checking
# The current make-source script removes the goto binary
$(LOGDIR)/source.json:
mkdir -p $(dir $@)
$(RM) -r $(GOTODIR)
$(MAKE_SOURCE) --srcdir $(SRCDIR) --wkdir $(PROOFDIR) > $@
$(RM) -r $(GOTODIR)
define VIEWER2_CMD
$(VIEWER2) \
--result $(LOGDIR)/result.xml \
--coverage $(LOGDIR)/coverage.xml \
--property $(LOGDIR)/property.xml \
--srcdir $(SRCDIR) \
--goto $(HARNESS_GOTO).goto \
--reportdir $(PROOFDIR)/report \
--config $(PROOFDIR)/cbmc-viewer.json
endef
export VIEWER2_CMD
# Omit logs/source.json from report generation until make-sources
# works correctly with Makefiles that invoke the compiler with
# mutliple source files at once.
$(PROOFDIR)/report: $(LOGDIR)/result.xml $(LOGDIR)/property.xml $(LOGDIR)/coverage.xml
$(LITANI) add-job \
--command "$$VIEWER2_CMD" \
--inputs $^ \
--outputs $(PROOFDIR)/report \
--pipeline-name "$(PROOF_UID)" \
--stdout-file $(LOGDIR)/viewer-log.txt \
--ci-stage report \
--description "$(PROOF_UID): generating report"
litani-path:
@echo $(LITANI)
# ##############################################################
# Phony Rules
#
# These rules provide a convenient way to run a single proof up to a
# certain stage. Users can browse into a proof directory and run
# "make -Bj 3 report" to generate a report for just that proof, or
# "make goto" to build the goto binary. Under the hood, this runs litani
# for just that proof.
_goto: $(HARNESS_GOTO).goto
goto:
@ echo Running 'litani init'
$(LITANI) init --project $(PROJECT_NAME)
@ echo Running 'litani add-job'
$(MAKE) -B _goto
@ echo Running 'litani build'
$(LITANI) run-build
_result: $(LOGDIR)/result.txt
result:
@ echo Running 'litani init'
$(LITANI) init --project $(PROJECT_NAME)
@ echo Running 'litani add-job'
$(MAKE) -B _result
@ echo Running 'litani build'
$(LITANI) run-build
_property: $(LOGDIR)/property.xml
property:
@ echo Running 'litani init'
$(LITANI) init --project $(PROJECT_NAME)
@ echo Running 'litani add-job'
$(MAKE) -B _property
@ echo Running 'litani build'
$(LITANI) run-build
_coverage: $(LOGDIR)/coverage.xml
coverage:
@ echo Running 'litani init'
$(LITANI) init --project $(PROJECT_NAME)
@ echo Running 'litani add-job'
$(MAKE) -B _coverage
@ echo Running 'litani build'
$(LITANI) run-build
# Choose the invocation of cbmc-viewer depending on which version of
# cbmc-viewer is installed. The --version flag is not implemented in
# version 1 --- it is an "unrecognized argument" --- but it is
# implemented in version 2.
_report1: $(PROOFDIR)/html
_report2: $(PROOFDIR)/report
_report:
(cbmc-viewer --version 2>&1 | grep "unrecognized argument" > /dev/null) && \
$(MAKE) -B _report1 || $(MAKE) -B _report2
report report1 report2:
@ echo Running 'litani init'
$(LITANI) init --project $(PROJECT_NAME)
@ echo Running 'litani add-job'
$(MAKE) -B _report
@ echo Running 'litani build'
$(LITANI) run-build
################################################################
# Targets to clean up after ourselves
clean:
-$(RM) $(DEPENDENT_GOTOS)
-$(RM) TAGS*
-$(RM) *~ \#*
-$(RM) $(REWRITTEN_SOURCES) $(foreach rs,$(REWRITTEN_SOURCES),$(rs).json)
veryclean: clean
-$(RM) -r html report
-$(RM) -r $(LOGDIR) $(GOTODIR)
.PHONY: \
_coverage \
_goto \
_property \
_report \
_report2 \
_result \
clean \
coverage \
goto \
litani-path \
property \
report \
report2 \
result \
setup_dependencies \
testdeps \
veryclean \
#
################################################################
# Rule for generating cbmc-batch.yaml, used by the CI at
# https://github.com/awslabs/aws-batch-cbmc/
JOB_OS ?= ubuntu16
JOB_MEMORY ?= 32000
# Proofs that are expected to fail should set EXPECTED to
# "FAILED" in their Makefile. Values other than SUCCESSFUL
# or FAILED will cause a CI error.
EXPECTED ?= SUCCESSFUL
define yaml_encode_options
"$(shell echo $(1) | sed 's/ ,/ /g' | sed 's/ /;/g')"
endef
CI_FLAGS = $(CBMCFLAGS) $(CHECKFLAGS) $(COVERFLAGS)
cbmc-batch.yaml:
@$(RM) $@
@echo 'build_memory: $(JOB_MEMORY)' > $@
@echo 'cbmcflags: $(strip $(call yaml_encode_options,$(CI_FLAGS)))' >> $@
@echo 'coverage_memory: $(JOB_MEMORY)' >> $@
@echo 'expected: $(EXPECTED)' >> $@
@echo 'goto: $(HARNESS_GOTO).goto' >> $@
@echo 'jobos: $(JOB_OS)' >> $@
@echo 'property_memory: $(JOB_MEMORY)' >> $@
@echo 'report_memory: $(JOB_MEMORY)' >> $@
.PHONY: cbmc-batch.yaml
################################################################
# Run "make echo-proof-uid" to print the proof ID of a proof. This can be
# used by scripts to ensure that every proof has an ID, that there are
# no duplicates, etc.
.PHONY: echo-proof-uid
echo-proof-uid:
@echo $(PROOF_UID)
.PHONY: echo-project-name
echo-project-name:
@echo $(PROJECT_NAME)
################################################################
# Project-specific targets requiring values defined above
sinclude $(PROOF_ROOT)/Makefile-project-targets
# CI-specific targets to drive cbmc in CI
sinclude $(PROOF_ROOT)/Makefile-project-testing
################################################################

View File

@ -0,0 +1,27 @@
CBMC proofs
===========
This directory contains the CBMC proofs. Each proof is in its own
directory.
This directory includes four Makefiles.
One Makefile describes the basic workflow for building and running proofs:
* Makefile.common:
* make: builds the goto binary, does the cbmc property checking
and coverage checking, and builds the final report.
* make goto: builds the goto binary
* make result: does cbmc property checking
* make coverage: does cbmc coverage checking
* make report: builds the final report
Three included Makefiles describe project-specific settings and can override
definitions in Makefile.common:
* Makefile-project-defines: definitions like compiler flags
required to build the goto binaries, and definitions to override
definitions in Makefile.common.
* Makefile-project-targets: other make targets needed for the project
* Makefile-project-testing: other definitions and targets needed for
unit testing or continuous integration.

View File

@ -0,0 +1,31 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0
HARNESS_ENTRY = harness
HARNESS_FILE = SigV4_AwsIotDateToIso8601_harness
# This should be a unique identifier for this proof, and will appear on the
# Litani dashboard. It can be human-readable and contain spaces if you wish.
PROOF_UID = SigV4_AwsIotDateToIso8601
DEFINES += -DSIGV4_DO_NOT_USE_CUSTOM_CONFIG=1
INCLUDES +=
MONTH_ASCII_LEN=3
ISO_YEAR_LEN=5
MONTHS_IN_YEAR=12
FORMAT_RFC_5322_LEN=32
REMOVE_FUNCTION_BODY +=
UNWINDSET += parseDate.0:$(FORMAT_RFC_5322_LEN)
UNWINDSET += scanValue.0:$(ISO_YEAR_LEN)
UNWINDSET += intToAscii.0:$(ISO_YEAR_LEN)
PROOF_SOURCES += $(PROOFDIR)/$(HARNESS_FILE).c
PROOF_SOURCES += $(SRCDIR)/test/cbmc/stubs/sigv4_stubs.c
include ../Makefile-json.common
# Substitution command to pass to sed for patching sigv4.c. The
# characters " and # must be escaped with backslash.
SIGV4_SED_EXPR = 1s/^/\#include \"sigv4_stubs.h\" /; s/^static //; s/SigV4Status_t scanValue\b/&_/

View File

@ -0,0 +1,20 @@
SigV4_AwsIotDateToIso8601 proof
==============
This directory contains a memory safety proof for SigV4_AwsIotDateToIso8601.
To run the proof.
-------------
* Add `cbmc`, `goto-cc`, `goto-instrument`, `goto-analyzer`, and `cbmc-viewer`
to your path.
* Run `make`.
* Open html/index.html in a web browser.
To use [`arpa`](https://github.com/awslabs/aws-proof-build-assistant) to simplify writing Makefiles.
-------------
* Run `make arpa` to generate a Makefile.arpa that contains relevant build information for the proof.
* Use Makefile.arpa as the starting point for your proof Makefile by:
1. Modifying Makefile.arpa (if required).
2. Including Makefile.arpa into the existing proof Makefile (add `sinclude Makefile.arpa` at the bottom of the Makefile, right before `include ../Makefile.common`).

View File

@ -0,0 +1,52 @@
/*
* SigV4 Library v1.2.0
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file SigV4_AwsIotDateToIso8601_harness.c
* @brief Implements the proof harness for SigV4_AwsIotDateToIso8601 function.
*/
#include "stdlib.h"
#include "sigv4.h"
void harness()
{
char * pInputDate;
size_t dateLen;
char * pDateISO8601;
size_t dateISO8601Len;
SigV4Status_t status;
__CPROVER_assume( dateLen == SIGV4_EXPECTED_LEN_RFC_3339 || dateLen == SIGV4_EXPECTED_LEN_RFC_5322 || dateLen == 0 );
pInputDate = malloc( dateLen );
__CPROVER_assume( dateISO8601Len < CBMC_MAX_OBJECT_SIZE );
pDateISO8601 = malloc( dateISO8601Len );
status = SigV4_AwsIotDateToIso8601( pInputDate, dateLen, pDateISO8601, dateISO8601Len );
__CPROVER_assert( status == SigV4InvalidParameter || status == SigV4Success || status == SigV4ISOFormattingError, "This is not a valid SigV4 return status" );
}

View File

@ -0,0 +1 @@
# This file marks this directory as containing a CBMC proof.

View File

@ -0,0 +1,7 @@
{ "expected-missing-functions":
[
],
"proof-name": "SigV4_AwsIotDateToIso8601",
"proof-root": "test/cbmc/proofs"
}

View File

@ -0,0 +1,64 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0
HARNESS_ENTRY = harness
HARNESS_FILE = SigV4_GenerateHTTPAuthorization_harness
# This should be a unique identifier for this proof, and will appear on the
# Litani dashboard. It can be human-readable and contain spaces if you wish.
PROOF_UID = SigV4_GenerateHTTPAuthorization
# Define constants so as to limit the running time of the proofs.
# Note that these constants are also deliberately chosen so as to attain
# coverage for the SigV4InsufficientMemory cases.
# For the constants below,
# SIGV4_PROCESSING_BUFFER_LENGTH is set specifically to 60.
# It may be easier to attain coverage if the processing buffer is instead
# provided by the user as the length can be variable.
# However, since the length of the processing buffer is fixed,
# these constants must also be fixed in order to match whatever
# SIGV4_PROCESSING_BUFFER_LENGTH is set to in sigv4_config.h.
MAX_QUERY_LEN=6
MAX_HEADERS_LEN=6
MAX_URI_LEN=3
MAX_REQUEST_LEN=16
S3_SERVICE_LEN=2
MAX_REGION_LEN=30
MAX_SERVICE_LEN=30
MAX_ALGORITHM_LEN=30
MAX_HASH_DIGEST_LEN=16
MAX_HASH_BLOCK_LEN=17
# This is the actual maximum length of an AWS access key ID
MAX_ACCESS_KEY_ID_LEN=128
DEFINES += -DMAX_QUERY_LEN=$(MAX_QUERY_LEN)
DEFINES += -DMAX_HEADERS_LEN=$(MAX_HEADERS_LEN)
DEFINES += -DMAX_URI_LEN=$(MAX_URI_LEN)
DEFINES += -DMAX_HASH_DIGEST_LEN=$(MAX_HASH_DIGEST_LEN)
DEFINES += -DMAX_HASH_BLOCK_LEN=$(MAX_HASH_BLOCK_LEN)
DEFINES += -DMAX_REGION_LEN=$(MAX_REGION_LEN)
DEFINES += -DMAX_SERVICE_LEN=$(MAX_SERVICE_LEN)
DEFINES += -DMAX_ALGORITHM_LEN=$(MAX_ALGORITHM_LEN)
DEFINES += -DMAX_ACCESS_KEY_ID_LEN=$(MAX_ACCESS_KEY_ID_LEN)
INCLUDES +=
REMOVE_FUNCTION_BODY += memcpy
REMOVE_FUNCTION_BODY += memmove
UNWINDSET += setQueryStringFieldsAndValues.0:$(MAX_QUERY_LEN)
UNWINDSET += parseHeaderKeyValueEntries.0:$(MAX_HEADERS_LEN)
UNWINDSET += lowercaseHexEncode.0:$(MAX_HASH_DIGEST_LEN)
UNWINDSET += hmacIntermediate.0:$(MAX_HASH_BLOCK_LEN)
UNWINDSET += hmacFinal.0:$(MAX_HASH_BLOCK_LEN)
UNWINDSET += strncmp.0:$(S3_SERVICE_LEN)
PROOF_SOURCES += $(PROOFDIR)/$(HARNESS_FILE).c
PROOF_SOURCES += $(SRCDIR)/test/cbmc/stubs/hash_stubs.c
PROOF_SOURCES += $(SRCDIR)/test/cbmc/stubs/memcpy.c
PROOF_SOURCES += $(SRCDIR)/test/cbmc/stubs/memmove.c
PROOF_SOURCES += $(SRCDIR)/test/cbmc/stubs/sigv4_stubs.c
include ../Makefile-json.common
# Substitution command to pass to sed for patching sigv4.c. The
# characters " and # must be escaped with backslash.
SIGV4_SED_EXPR = 1s/^/\#include \"sigv4_stubs.h\" /; s/^static //; s/SigV4Status_t (scanValue|encodeURI|generateCanonicalQuery|generateCanonicalAndSignedHeaders|copyHeaderStringToCanonicalBuffer)\b/&_/

View File

@ -0,0 +1,20 @@
SigV4_GenerateHTTPAuthorization proof
==============
This directory contains a memory safety proof for SigV4_GenerateHTTPAuthorization.
To run the proof.
-------------
* Add `cbmc`, `goto-cc`, `goto-instrument`, `goto-analyzer`, and `cbmc-viewer`
to your path.
* Run `make`.
* Open html/index.html in a web browser.
To use [`arpa`](https://github.com/awslabs/aws-proof-build-assistant) to simplify writing Makefiles.
-------------
* Run `make arpa` to generate a Makefile.arpa that contains relevant build information for the proof.
* Use Makefile.arpa as the starting point for your proof Makefile by:
1. Modifying Makefile.arpa (if required).
2. Including Makefile.arpa into the existing proof Makefile (add `sinclude Makefile.arpa` at the bottom of the Makefile, right before `include ../Makefile.common`).

View File

@ -0,0 +1,131 @@
/*
* SigV4 Library v1.2.0
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file SigV4_GenerateHTTPAuthorization_harness.c
* @brief Implements the proof harness for the SigV4_GenerateHTTPAuthorization function.
*/
/* Include paths for public enums, structures, and macros. */
#include "stdlib.h"
#include "sigv4.h"
#include "sigv4_internal.h"
#include "hash_stubs.h"
void harness()
{
SigV4Parameters_t * pSigV4Params;
SigV4HttpParameters_t * pHttpParams;
SigV4CryptoInterface_t * pCryptoInterface;
SigV4Credentials_t * pCredentials;
char * pAuthBuf;
size_t * authBufLen;
char * pSignature;
size_t signatureLen;
SigV4Status_t status;
pHttpParams = malloc( sizeof( SigV4HttpParameters_t ) );
pSigV4Params = malloc( sizeof( SigV4Parameters_t ) );
pCryptoInterface = malloc( sizeof( SigV4CryptoInterface_t ) );
pCredentials = malloc( sizeof( SigV4Credentials_t ) );
/* This property applies to all hash functions. */
if( pCryptoInterface != NULL )
{
__CPROVER_assume( SIGV4_HMAC_SIGNING_KEY_PREFIX_LEN < pCryptoInterface->hashBlockLen && pCryptoInterface->hashBlockLen <= MAX_HASH_BLOCK_LEN );
__CPROVER_assume( 0U < pCryptoInterface->hashDigestLen && pCryptoInterface->hashDigestLen <= MAX_HASH_DIGEST_LEN );
__CPROVER_assume( pCryptoInterface->hashDigestLen <= pCryptoInterface->hashBlockLen );
pCryptoInterface->hashInit = nondet_bool() ? NULL : HashInitStub;
pCryptoInterface->hashUpdate = nondet_bool() ? NULL : HashUpdateStub;
pCryptoInterface->hashFinal = nondet_bool() ? NULL : HashFinalStub;
}
if( pCredentials != NULL )
{
/* Make size assumptions for string-like types. */
__CPROVER_assume( pCredentials->accessKeyIdLen <= MAX_ACCESS_KEY_ID_LEN );
__CPROVER_assume( pCredentials->secretAccessKeyLen < CBMC_MAX_OBJECT_SIZE );
pCredentials->pAccessKeyId = malloc( pCredentials->accessKeyIdLen );
pCredentials->pSecretAccessKey = malloc( pCredentials->secretAccessKeyLen );
}
if( pHttpParams != NULL )
{
/* Make size assumptions for string-like types. */
__CPROVER_assume( pHttpParams->payloadLen < CBMC_MAX_OBJECT_SIZE );
__CPROVER_assume( pHttpParams->httpMethodLen < CBMC_MAX_OBJECT_SIZE );
__CPROVER_assume( pHttpParams->pathLen < MAX_URI_LEN );
__CPROVER_assume( pHttpParams->queryLen < MAX_QUERY_LEN );
__CPROVER_assume( pHttpParams->headersLen < MAX_HEADERS_LEN );
pHttpParams->pPayload = malloc( pHttpParams->payloadLen );
pHttpParams->pHttpMethod = malloc( pHttpParams->httpMethodLen );
pHttpParams->pPath = malloc( pHttpParams->pathLen );
pHttpParams->pQuery = malloc( pHttpParams->queryLen );
pHttpParams->pHeaders = malloc( pHttpParams->headersLen );
}
if( pSigV4Params != NULL )
{
/* Make size assumptions for string-like types. */
__CPROVER_assume( pSigV4Params->regionLen < MAX_REGION_LEN );
__CPROVER_assume( pSigV4Params->serviceLen < MAX_SERVICE_LEN );
__CPROVER_assume( pSigV4Params->algorithmLen < MAX_ALGORITHM_LEN );
pSigV4Params->pRegion = malloc( pSigV4Params->regionLen );
pSigV4Params->pService = malloc( pSigV4Params->serviceLen );
pSigV4Params->pAlgorithm = malloc( pSigV4Params->algorithmLen );
/* The ISO date has a fixed length. */
pSigV4Params->pDateIso8601 = malloc( SIGV4_ISO_STRING_LEN );
/* Set other structs within SigV4Parameters_t. */
pSigV4Params->pCredentials = pCredentials;
pSigV4Params->pCryptoInterface = pCryptoInterface;
pSigV4Params->pHttpParameters = pHttpParams;
}
authBufLen = malloc( sizeof( size_t ) );
if( authBufLen != NULL )
{
__CPROVER_assume( *authBufLen < CBMC_MAX_OBJECT_SIZE );
pAuthBuf = malloc( *authBufLen );
}
status = SigV4_GenerateHTTPAuthorization( pSigV4Params,
pAuthBuf,
authBufLen,
nondet_bool() ? NULL : &pSignature,
nondet_bool() ? NULL : &signatureLen );
__CPROVER_assert( status == SigV4InvalidParameter || status == SigV4Success || status == SigV4HashError || status == SigV4InsufficientMemory || status == SigV4MaxHeaderPairCountExceeded || status == SigV4MaxQueryPairCountExceeded, "This is not a valid SigV4 return status" );
if( status == SigV4Success )
{
/* The signature must start at a location within pAuthBuf and
* should not end past the length of pAuthBuf. */
__CPROVER_assert( pAuthBuf <= pSignature,
"Signature does not start at a location within pAuthBuf." );
__CPROVER_assert( pSignature + signatureLen <= pAuthBuf + *authBufLen,
"Signature ends past the length of pAuthBuf." );
}
}

View File

@ -0,0 +1 @@
# This file marks this directory as containing a CBMC proof.

View File

@ -0,0 +1,7 @@
{ "expected-missing-functions":
[
],
"proof-name": "SigV4_GenerateHTTPAuthorization",
"proof-root": "test/cbmc/proofs"
}

View File

@ -0,0 +1,37 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0
HARNESS_ENTRY = harness
HARNESS_FILE = copyHeaderStringToCanonicalBuffer_harness
# This should be a unique identifier for this proof, and will appear on the
# Litani dashboard. It can be human-readable and contain spaces if you wish.
PROOF_UID = copyHeaderStringToCanonicalBuffer
# This value was experimentally chosen to provide 100% coverage
# without tripping unwinding assertions and without exhausting memory.
CBMC_MAX_BUFSIZE=10
MAX_HASH_BLOCK_LEN=17
MAX_HASH_DIGEST_LEN=16
DEFINES += -DMAX_HASH_BLOCK_LEN=$(MAX_HASH_BLOCK_LEN)
DEFINES += -DCBMC_MAX_BUFSIZE=$(CBMC_MAX_BUFSIZE)
DEFINES += -DMAX_HASH_DIGEST_LEN=$(MAX_HASH_DIGEST_LEN)
INCLUDES +=
REMOVE_FUNCTION_BODY +=
UNWINDSET +=copyHeaderStringToCanonicalBuffer.0:$(CBMC_MAX_BUFSIZE)
PROOF_SOURCES += $(PROOFDIR)/$(HARNESS_FILE).c
# If this proof is found to consume huge amounts of RAM, you can set the
# EXPENSIVE variable. With new enough versions of the proof tools, this will
# restrict the number of EXPENSIVE CBMC jobs running at once. See the
# documentation in Makefile.common under the "Job Pools" heading for details.
# EXPENSIVE = true
include ../Makefile-json.common
# Substitution command to pass to sed for patching sigv4.c. The
# characters " and # must be escaped with backslash.
SIGV4_SED_EXPR = s/^static //

View File

@ -0,0 +1,12 @@
copyHeaderStringToCanonicalBuffer proof
==============
This directory contains a memory safety proof for copyHeaderStringToCanonicalBuffer.
To run the proof.
-------------
* Add `cbmc`, `goto-cc`, `goto-instrument`, `goto-analyzer`, and `cbmc-viewer`
to your path.
* Run `make`.
* Open html/index.html in a web browser.

View File

@ -0,0 +1 @@
# This file marks this directory as containing a CBMC proof.

View File

@ -0,0 +1,7 @@
{ "expected-missing-functions":
[
],
"proof-name": "copyHeaderStringToCanonicalBuffer",
"proof-root": "test/cbmc/proofs"
}

View File

@ -0,0 +1,62 @@
/*
* SigV4 Library v1.2.0
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file copyHeaderStringToCanonicalBuffer_harness.c
* @brief Implements the proof harness for copyHeaderStringToCanonicalBuffer function.
*/
#include "stdlib.h"
#include "sigv4_annex.h"
void harness()
{
const char * pData;
size_t dataLen;
uint32_t flags;
char separator;
CanonicalContext_t * canonicalRequest;
SigV4Status_t sigv4Status;
canonicalRequest = malloc( sizeof( CanonicalContext_t ) );
__CPROVER_assume( canonicalRequest != NULL );
/* The data to be written is assumed to start at a location within the processing
* buffer and should not end past the length of the processing buffer. */
size_t bytesConsumed;
__CPROVER_assume( canonicalRequest->bufRemaining < SIGV4_PROCESSING_BUFFER_LENGTH );
bytesConsumed = SIGV4_PROCESSING_BUFFER_LENGTH - canonicalRequest->bufRemaining;
__CPROVER_assume( dataLen > 0U && dataLen < CBMC_MAX_BUFSIZE );
canonicalRequest->pBufCur = ( char * ) canonicalRequest->pBufProcessing + bytesConsumed;
pData = malloc( dataLen );
__CPROVER_assume( pData != NULL );
sigv4Status = copyHeaderStringToCanonicalBuffer( pData, dataLen, flags, separator, canonicalRequest );
__CPROVER_assert( ( sigv4Status == SigV4InvalidParameter || sigv4Status == SigV4Success || sigv4Status == SigV4InsufficientMemory ), "This is not a valid SIGV4 Status." );
}

View File

@ -0,0 +1,92 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0
import json
import logging
def _get_max_length_per_column_list(data):
ret = [len(item) + 1 for item in data[0]]
for row in data[1:]:
for idx, item in enumerate(row):
ret[idx] = max(ret[idx], len(item) + 1)
return ret
def _get_table_header_separator(max_length_per_column_list):
line_sep = ""
for max_length_of_word_in_col in max_length_per_column_list:
line_sep += "|" + "-" * (max_length_of_word_in_col + 1)
line_sep += "|\n"
return line_sep
def _get_entries(max_length_per_column_list, row_data):
entries = []
for row in row_data:
entry = ""
for idx, word in enumerate(row):
max_length_of_word_in_col = max_length_per_column_list[idx]
space_formatted_word = (max_length_of_word_in_col - len(word)) * " "
entry += "| " + word + space_formatted_word
entry += "|\n"
entries.append(entry)
return entries
def _get_rendered_table(data):
table = []
max_length_per_column_list = _get_max_length_per_column_list(data)
entries = _get_entries(max_length_per_column_list, data)
for idx, entry in enumerate(entries):
if idx == 1:
line_sep = _get_table_header_separator(max_length_per_column_list)
table.append(line_sep)
table.append(entry)
table.append("\n")
return "".join(table)
def _get_status_and_proof_summaries(run_dict):
"""Parse a dict representing a Litani run and create lists summarizing the
proof results.
Parameters
----------
run_dict
A dictionary representing a Litani run.
Returns
-------
A list of 2 lists.
The first sub-list maps a status to the number of proofs with that status.
The second sub-list maps each proof to its status.
"""
count_statuses = {}
proofs = [["Proof", "Status"]]
for proof_pipeline in run_dict["pipelines"]:
status_pretty_name = proof_pipeline["status"].title().replace("_", " ")
try:
count_statuses[status_pretty_name] += 1
except KeyError:
count_statuses[status_pretty_name] = 1
proof = proof_pipeline["name"]
proofs.append([proof, status_pretty_name])
statuses = [["Status", "Count"]]
for status, count in count_statuses.items():
statuses.append([status, str(count)])
return [statuses, proofs]
def print_proof_results(out_file):
"""
Print 2 strings that summarize the proof results.
When printing, each string will render as a GitHub flavored Markdown table.
"""
try:
with open(out_file, encoding='utf-8') as run_json:
run_dict = json.load(run_json)
for summary in _get_status_and_proof_summaries(run_dict):
print(_get_rendered_table(summary))
except Exception as ex: # pylint: disable=broad-except
logging.critical("Could not print results. Exception: %s", str(ex))

View File

@ -0,0 +1,414 @@
#!/usr/bin/env python3
#
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0
import argparse
import asyncio
import json
import logging
import math
import os
import pathlib
import re
import subprocess
import sys
import tempfile
from lib.summarize import print_proof_results
DESCRIPTION = "Configure and run all CBMC proofs in parallel"
# Keep the epilog hard-wrapped at 70 characters, as it gets printed
# verbatim in the terminal. 70 characters stops here --------------> |
EPILOG = """
This tool automates the process of running `make report` in each of
the CBMC proof directories. The tool calculates the dependency graph
of all tasks needed to build, run, and report on all the proofs, and
executes these tasks in parallel.
The tool is roughly equivalent to doing this:
litani init --project "my-cool-project";
find . -name cbmc-proof.txt | while read -r proof; do
pushd $(dirname ${proof});
# The `make _report` rule adds a single proof to litani
# without running it
make _report;
popd;
done
litani run-build;
except that it is much faster and provides some convenience options.
The CBMC CI runs this script with no arguments to build and run all
proofs in parallel. The value of "my-cool-project" is taken from the
PROJECT_NAME variable in Makefile-project-defines.
The --no-standalone argument omits the `litani init` and `litani
run-build`; use it when you want to add additional proof jobs, not
just the CBMC ones. In that case, you would run `litani init`
yourself; then run `run-cbmc-proofs --no-standalone`; add any
additional jobs that you want to execute with `litani add-job`; and
finally run `litani run-build`.
The litani dashboard will be written under the `output` directory; the
cbmc-viewer reports remain in the `$PROOF_DIR/report` directory. The
HTML dashboard from the latest Litani run will always be symlinked to
`output/latest/html/index.html`, so you can keep that page open in
your browser and reload the page whenever you re-run this script.
"""
# 70 characters stops here ----------------------------------------> |
def get_project_name():
cmd = [
"make",
"--no-print-directory",
"-f", "Makefile.common",
"echo-project-name",
]
logging.debug(" ".join(cmd))
proc = subprocess.run(cmd, universal_newlines=True, stdout=subprocess.PIPE, check=False)
if proc.returncode:
logging.critical("could not run make to determine project name")
sys.exit(1)
if not proc.stdout.strip():
logging.warning(
"project name has not been set; using generic name instead. "
"Set the PROJECT_NAME value in Makefile-project-defines to "
"remove this warning")
return "<PROJECT NAME HERE>"
return proc.stdout.strip()
def get_args():
pars = argparse.ArgumentParser(
description=DESCRIPTION, epilog=EPILOG,
formatter_class=argparse.RawDescriptionHelpFormatter)
for arg in [{
"flags": ["-j", "--parallel-jobs"],
"type": int,
"metavar": "N",
"help": "run at most N proof jobs in parallel",
}, {
"flags": ["--fail-on-proof-failure"],
"action": "store_true",
"help": "exit with return code `10' if any proof failed"
" (default: exit 0)",
}, {
"flags": ["--no-standalone"],
"action": "store_true",
"help": "only configure proofs: do not initialize nor run",
}, {
"flags": ["-p", "--proofs"],
"nargs": "+",
"metavar": "DIR",
"help": "only run proof in directory DIR (can pass more than one)",
}, {
"flags": ["--project-name"],
"metavar": "NAME",
"default": get_project_name(),
"help": "project name for report. Default: %(default)s",
}, {
"flags": ["--marker-file"],
"metavar": "FILE",
"default": "cbmc-proof.txt",
"help": (
"name of file that marks proof directories. Default: "
"%(default)s"),
}, {
"flags": ["--no-memory-profile"],
"action": "store_true",
"help": "disable memory profiling, even if Litani supports it"
}, {
"flags": ["--no-expensive-limit"],
"action": "store_true",
"help": "do not limit parallelism of 'EXPENSIVE' jobs",
}, {
"flags": ["--expensive-jobs-parallelism"],
"metavar": "N",
"default": 1,
"type": int,
"help": (
"how many proof jobs marked 'EXPENSIVE' to run in parallel. "
"Default: %(default)s"),
}, {
"flags": ["--verbose"],
"action": "store_true",
"help": "verbose output",
}, {
"flags": ["--debug"],
"action": "store_true",
"help": "debug output",
}, {
"flags": ["--summarize"],
"action": "store_true",
"help": "summarize proof results with two tables on stdout",
}, {
"flags": ["--version"],
"action": "version",
"version": "CBMC starter kit 2.5",
"help": "display version and exit"
}]:
flags = arg.pop("flags")
pars.add_argument(*flags, **arg)
return pars.parse_args()
def set_up_logging(verbose):
if verbose:
level = logging.DEBUG
else:
level = logging.WARNING
logging.basicConfig(
format="run-cbmc-proofs: %(message)s", level=level)
def task_pool_size():
ret = os.cpu_count()
if ret is None or ret < 3:
return 1
return ret - 2
def print_counter(counter):
# pylint: disable=consider-using-f-string
print("\rConfiguring CBMC proofs: "
"{complete:{width}} / {total:{width}}".format(**counter), end="", file=sys.stderr)
def get_proof_dirs(proof_root, proof_list, marker_file):
if proof_list is not None:
proofs_remaining = list(proof_list)
else:
proofs_remaining = []
for root, _, fyles in os.walk(proof_root):
proof_name = str(pathlib.Path(root).name)
if root != str(proof_root) and ".litani_cache_dir" in fyles:
pathlib.Path(f"{root}/.litani_cache_dir").unlink()
if proof_list and proof_name not in proof_list:
continue
if proof_list and proof_name in proofs_remaining:
proofs_remaining.remove(proof_name)
if marker_file in fyles:
yield root
if proofs_remaining:
logging.critical(
"The following proofs were not found: %s",
", ".join(proofs_remaining))
sys.exit(1)
def run_build(litani, jobs, fail_on_proof_failure, summarize):
cmd = [str(litani), "run-build"]
if jobs:
cmd.extend(["-j", str(jobs)])
if fail_on_proof_failure:
cmd.append("--fail-on-pipeline-failure")
if summarize:
out_file = pathlib.Path(tempfile.gettempdir(), "run.json").resolve()
cmd.extend(["--out-file", str(out_file)])
logging.debug(" ".join(cmd))
proc = subprocess.run(cmd, check=False)
if proc.returncode and not fail_on_proof_failure:
logging.critical("Failed to run litani run-build")
sys.exit(1)
if summarize:
print_proof_results(out_file)
out_file.unlink()
if proc.returncode:
logging.error("One or more proofs failed")
sys.exit(10)
def get_litani_path(proof_root):
cmd = [
"make",
"--no-print-directory",
f"PROOF_ROOT={proof_root}",
"-f", "Makefile.common",
"litani-path",
]
logging.debug(" ".join(cmd))
proc = subprocess.run(cmd, universal_newlines=True, stdout=subprocess.PIPE, check=False)
if proc.returncode:
logging.critical("Could not determine path to litani")
sys.exit(1)
return proc.stdout.strip()
def get_litani_capabilities(litani_path):
cmd = [litani_path, "print-capabilities"]
proc = subprocess.run(
cmd, text=True, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL, check=False)
if proc.returncode:
return []
try:
return json.loads(proc.stdout)
except RuntimeError:
logging.warning("Could not load litani capabilities: '%s'", proc.stdout)
return []
def check_uid_uniqueness(proof_dir, proof_uids):
with (pathlib.Path(proof_dir) / "Makefile").open() as handle:
for line in handle:
match = re.match(r"^PROOF_UID\s*=\s*(?P<uid>\w+)", line)
if not match:
continue
if match["uid"] not in proof_uids:
proof_uids[match["uid"]] = proof_dir
return
logging.critical(
"The Makefile in directory '%s' should have a different "
"PROOF_UID than the Makefile in directory '%s'",
proof_dir, proof_uids[match["uid"]])
sys.exit(1)
logging.critical(
"The Makefile in directory '%s' should contain a line like", proof_dir)
logging.critical("PROOF_UID = ...")
logging.critical("with a unique identifier for the proof.")
sys.exit(1)
def should_enable_memory_profiling(litani_caps, args):
if args.no_memory_profile:
return False
return "memory_profile" in litani_caps
def should_enable_pools(litani_caps, args):
if args.no_expensive_limit:
return False
return "pools" in litani_caps
async def configure_proof_dirs( # pylint: disable=too-many-arguments
queue, counter, proof_uids, enable_pools, enable_memory_profiling, debug):
while True:
print_counter(counter)
path = str(await queue.get())
check_uid_uniqueness(path, proof_uids)
pools = ["ENABLE_POOLS=true"] if enable_pools else []
profiling = [
"ENABLE_MEMORY_PROFILING=true"] if enable_memory_profiling else []
# Allow interactive tasks to preempt proof configuration
proc = await asyncio.create_subprocess_exec(
"nice", "-n", "15", "make", *pools,
*profiling, "-B", "_report", "" if debug else "--quiet", cwd=path,
stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE)
stdout, stderr = await proc.communicate()
logging.debug("returncode: %s", str(proc.returncode))
logging.debug("stdout:")
for line in stdout.decode().splitlines():
logging.debug(line)
logging.debug("stderr:")
for line in stderr.decode().splitlines():
logging.debug(line)
counter["fail" if proc.returncode else "pass"].append(path)
counter["complete"] += 1
print_counter(counter)
queue.task_done()
async def main(): # pylint: disable=too-many-locals
args = get_args()
set_up_logging(args.verbose)
proof_root = pathlib.Path(os.getcwd())
litani = get_litani_path(proof_root)
litani_caps = get_litani_capabilities(litani)
enable_pools = should_enable_pools(litani_caps, args)
init_pools = [
"--pools", f"expensive:{args.expensive_jobs_parallelism}"
] if enable_pools else []
if not args.no_standalone:
cmd = [
str(litani), "init", *init_pools, "--project", args.project_name,
"--no-print-out-dir",
]
if "output_directory_flags" in litani_caps:
out_prefix = proof_root / "output"
out_symlink = out_prefix / "latest"
out_index = out_symlink / "html" / "index.html"
cmd.extend([
"--output-prefix", str(out_prefix),
"--output-symlink", str(out_symlink),
])
print(
"\nFor your convenience, the output of this run will be symbolically linked to ",
out_index, "\n")
logging.debug(" ".join(cmd))
proc = subprocess.run(cmd, check=False)
if proc.returncode:
logging.critical("Failed to run litani init")
sys.exit(1)
proof_dirs = list(get_proof_dirs(
proof_root, args.proofs, args.marker_file))
if not proof_dirs:
logging.critical("No proof directories found")
sys.exit(1)
proof_queue = asyncio.Queue()
for proof_dir in proof_dirs:
proof_queue.put_nowait(proof_dir)
counter = {
"pass": [],
"fail": [],
"complete": 0,
"total": len(proof_dirs),
"width": int(math.log10(len(proof_dirs))) + 1
}
proof_uids = {}
tasks = []
enable_memory_profiling = should_enable_memory_profiling(litani_caps, args)
for _ in range(task_pool_size()):
task = asyncio.create_task(configure_proof_dirs(
proof_queue, counter, proof_uids, enable_pools,
enable_memory_profiling, args.debug))
tasks.append(task)
await proof_queue.join()
print_counter(counter)
print("", file=sys.stderr)
if counter["fail"]:
logging.critical(
"Failed to configure the following proofs:\n%s", "\n".join(
[str(f) for f in counter["fail"]]))
sys.exit(1)
if not args.no_standalone:
run_build(litani, args.parallel_jobs, args.fail_on_proof_failure, args.summarize)
if __name__ == "__main__":
asyncio.run(main())

View File

@ -0,0 +1,6 @@
CBMC proof source code
======================
This directory contains source code written for CBMC proofs. It is
common to write some code to model aspects of the system under test,
and this code goes here.

View File

@ -0,0 +1,6 @@
CBMC proof stubs
======================
This directory contains the stubs written for CBMC proofs. It is
common to stub out functionality like network send and receive methods
when writing a CBMC proof, and the code for these stubs goes here.

View File

@ -0,0 +1,57 @@
/*
* SigV4 Library v1.2.0
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file hash_stubs.c
* @brief Declarations for stubs used in sigv4.c.
* Please see sigv4.c for documentation.
*/
/* Standard includes. */
#include "hash_stubs.h"
int32_t HashInitStub( void * pHashContext )
{
int32_t ret;
return ret;
}
int32_t HashUpdateStub( void * pHashContext,
const char * pInput,
size_t inputLen )
{
int32_t ret;
return ret;
}
int32_t HashFinalStub( void * pHashContext,
const char * pInput,
size_t inputLen )
{
int32_t ret;
return ret;
}

View File

@ -0,0 +1,62 @@
/*
* SigV4 Library v1.2.0
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file memcpy.c
* @brief A stub for memcpy so that the proofs for functions that call memcpy
* run much faster.
*/
#include <string.h>
/* This is a clang macro not available on linux */
#ifndef __has_builtin
#define __has_builtin( x ) 0
#endif
#if __has_builtin( __builtin___memcpy_chk )
void * __builtin___memcpy_chk( void * dest,
const void * src,
size_t n,
size_t m )
{
/* Attempting to read or write 0 bytes will make __CPROVER_r/w_ok
* fail. However, per ANSI C specification, memcpy must be able
* to handle a copy length of zero. */
__CPROVER_assert( ( n == 0 ) || __CPROVER_w_ok( dest, n ), "write" );
__CPROVER_assert( ( n == 0 ) || __CPROVER_r_ok( src, n ), "read" );
return dest;
}
#else /* if __has_builtin( __builtin___memcpy_chk ) */
void * memcpy( void * dest,
const void * src,
size_t n )
{
/* Per ANSI C specification, memcpy must be able to handle a copy length
* of zero. */
__CPROVER_assert( ( n == 0 ) || __CPROVER_w_ok( dest, n ), "write" );
__CPROVER_assert( ( n == 0 ) || __CPROVER_r_ok( src, n ), "read" );
return dest;
}
#endif /* if __has_builtin( __builtin___memcpy_chk ) */

View File

@ -0,0 +1,60 @@
/*
* SigV4 Library v1.2.0
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file memmove.c
* @brief A stub for memmove so that the proofs for functions that call
* memmove run much faster.
*/
#include <string.h>
/* This is a clang macro not available on linux */
#ifndef __has_builtin
#define __has_builtin( x ) 0
#endif
#if __has_builtin( __builtin___memmove_chk )
void * __builtin___memmove_chk( void * dest,
const void * src,
size_t n,
size_t m )
{
/* Attempting to read or write 0 bytes will make __CPROVER_r/w_ok
* fail. However, per ANSI C specification, memcpy must be able
* to handle a copy length of zero. */
__CPROVER_assert( ( n == 0 ) || __CPROVER_w_ok( dest, n ), "write" );
__CPROVER_assert( ( n == 0 ) || __CPROVER_r_ok( src, n ), "read" );
return dest;
}
#else /* if __has_builtin( __builtin___memmove_chk ) */
void * memmove( void * dest,
const void * src,
size_t n )
{
__CPROVER_assert( __CPROVER_w_ok( dest, n ), "write" );
__CPROVER_assert( __CPROVER_r_ok( src, n ), "read" );
return dest;
}
#endif /* if __has_builtin( __builtin___memmove_chk ) */

View File

@ -0,0 +1,260 @@
/*
* SigV4 Library v1.2.0
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file sigv4_stubs.c
* @brief Implements the functions declared in sigv4_stubs.h
*/
#include <sigv4.h>
#include <sigv4_internal.h>
#include <sigv4_stubs.h>
SigV4Status_t scanValue( const char * pDate,
const char formatChar,
size_t readLoc,
size_t lenToRead,
SigV4DateTime_t * pDateElements )
{
SigV4Status_t returnStatus = SigV4InvalidParameter;
const char * pMonthNames[] = MONTH_NAMES;
const char * pLoc = pDate + readLoc;
size_t remainingLenToRead = lenToRead;
int32_t result = 0;
static flag = 0;
assert( pDate != NULL );
assert( pDateElements != NULL );
if( formatChar == '*' )
{
remainingLenToRead = 0U;
}
/* Determine if month value is non-numeric. */
if( ( formatChar == 'M' ) && ( remainingLenToRead == MONTH_ASCII_LEN ) )
{
returnStatus = SigV4Success;
remainingLenToRead = 0U;
}
/* Interpret integer value of numeric representation. */
while( ( remainingLenToRead > 0U ) && ( *pLoc >= '0' ) && ( *pLoc <= '9' ) )
{
result = ( result * 10 ) + ( int32_t ) ( *pLoc - '0' );
remainingLenToRead--;
pLoc += 1;
}
if( remainingLenToRead != 0U )
{
LogError( ( "Parsing Error: Expected numerical string of type '%%%d%c', "
"but received '%.*s'.",
( int ) lenToRead,
formatChar,
( int ) lenToRead,
pLoc ) );
returnStatus = SigV4ISOFormattingError;
}
if( returnStatus != SigV4ISOFormattingError )
{
addToDate( formatChar,
result,
pDateElements );
}
return returnStatus;
}
void addToDate( const char formatChar,
int32_t result,
SigV4DateTime_t * pDateElements )
{
assert( pDateElements != NULL );
assert( result >= 0 );
switch( formatChar )
{
case 'Y':
pDateElements->tm_year = result;
break;
case 'M':
pDateElements->tm_mon = result;
break;
case 'D':
pDateElements->tm_mday = result;
break;
case 'h':
pDateElements->tm_hour = result;
break;
case 'm':
pDateElements->tm_min = result;
break;
case 's':
pDateElements->tm_sec = result;
break;
default:
/* Do not assign values for skipped characters ('*'), or
* unrecognized format specifiers. */
break;
}
}
SigV4Status_t writeLineToCanonicalRequest( const char * pLine,
size_t lineLen,
CanonicalContext_t * pCanonicalContext )
{
SigV4Status_t ret = SigV4InsufficientMemory;
assert( ( pCanonicalContext != NULL ) && ( pCanonicalContext->pBufCur != NULL ) );
if( pCanonicalContext->bufRemaining >= ( lineLen + 1U ) )
{
assert( __CPROVER_w_ok( pCanonicalContext->pBufCur, ( lineLen + 1U ) ) );
ret = SigV4Success;
}
return ret;
}
SigV4Status_t encodeURI( const char * pUri,
size_t uriLen,
char * pCanonicalURI,
size_t * canonicalURILen,
bool encodeSlash,
bool doubleEncodeEquals )
{
SigV4Status_t returnStatus = SigV4Success;
assert( pUri != NULL );
assert( pCanonicalURI != NULL );
assert( canonicalURILen != NULL );
if( nondet_bool() )
{
returnStatus = SigV4Success;
}
else
{
returnStatus = SigV4InsufficientMemory;
}
return returnStatus;
}
SigV4Status_t generateCanonicalQuery( const char * pQuery,
size_t queryLen,
CanonicalContext_t * pCanonicalContext )
{
SigV4Status_t returnStatus = SigV4InsufficientMemory;
assert( ( pCanonicalContext != NULL ) && ( pCanonicalContext->pBufCur != NULL ) );
if( nondet_bool() )
{
__CPROVER_assume( pCanonicalContext->bufRemaining < SIGV4_PROCESSING_BUFFER_LENGTH );
returnStatus = SigV4Success;
}
else
{
returnStatus = SigV4InsufficientMemory;
}
return returnStatus;
}
SigV4Status_t generateCanonicalAndSignedHeaders( const char * pHeaders,
size_t headersLen,
uint32_t flags,
CanonicalContext_t * pCanonicalContext,
char ** pSignedHeaders,
size_t * pSignedHeadersLen )
{
SigV4Status_t returnStatus = SigV4InsufficientMemory;
assert( pHeaders != NULL );
assert( pCanonicalContext != NULL );
assert( pCanonicalContext->pBufCur != NULL );
assert( pSignedHeaders != NULL );
assert( pSignedHeadersLen != NULL );
if( nondet_bool() )
{
/* The signed headers are assumed to start at a location within the processing
* buffer and should not end past the length of the processing buffer. */
size_t headersLen, headerOffset, bytesConsumed;
char * pHeaders = NULL;
__CPROVER_assume( pCanonicalContext->bufRemaining < SIGV4_PROCESSING_BUFFER_LENGTH );
bytesConsumed = SIGV4_PROCESSING_BUFFER_LENGTH - pCanonicalContext->bufRemaining;
__CPROVER_assume( headerOffset < bytesConsumed );
__CPROVER_assume( headersLen > 0U && headersLen <= bytesConsumed - headerOffset );
pHeaders = ( char * ) pCanonicalContext->pBufProcessing + headerOffset;
*pSignedHeadersLen = headersLen;
*pSignedHeaders = pHeaders;
returnStatus = SigV4Success;
}
else
{
returnStatus = SigV4InsufficientMemory;
}
return returnStatus;
}
SigV4Status_t copyHeaderStringToCanonicalBuffer( const char * pData,
size_t dataLen,
uint32_t flags,
char separator,
CanonicalContext_t * canonicalRequest )
{
SigV4Status_t returnStatus = SigV4Success;
size_t buffRemaining;
__CPROVER_assume( pData != NULL );
__CPROVER_assume( dataLen > 0 );
__CPROVER_assume( dataLen < CBMC_MAX_OBJECT_SIZE );
assert( ( pData != NULL ) && ( dataLen > 0 ) );
assert( canonicalRequest != NULL );
assert( canonicalRequest->pBufCur != NULL );
buffRemaining = canonicalRequest->bufRemaining;
if( buffRemaining < dataLen )
{
returnStatus = SigV4InsufficientMemory;
}
return returnStatus;
}