Initial insecure reference design release
This commit is contained in:
340
.gitignore
vendored
Normal file
340
.gitignore
vendored
Normal file
@@ -0,0 +1,340 @@
|
||||
## Project .gitignore ##
|
||||
|
||||
.DS_Store
|
||||
.vscode/
|
||||
**/gcc
|
||||
|
||||
!device/lib
|
||||
|
||||
## Begin Generic .gitignore ##
|
||||
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/python,c,c++,git,pycharm
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=python,c,c++,git,pycharm
|
||||
|
||||
### C ###
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Object files
|
||||
*.o
|
||||
*.ko
|
||||
*.obj
|
||||
*.elf
|
||||
|
||||
# Linker output
|
||||
*.ilk
|
||||
*.map
|
||||
*.exp
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Libraries
|
||||
*.lib
|
||||
*.a
|
||||
*.la
|
||||
*.lo
|
||||
|
||||
# Shared objects (inc. Windows DLLs)
|
||||
*.dll
|
||||
*.so
|
||||
*.so.*
|
||||
*.dylib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
*.i*86
|
||||
*.x86_64
|
||||
*.hex
|
||||
*.bin
|
||||
|
||||
# Debug files
|
||||
*.dSYM/
|
||||
*.su
|
||||
*.idb
|
||||
*.pdb
|
||||
|
||||
# Kernel Module Compile Results
|
||||
*.mod*
|
||||
*.cmd
|
||||
.tmp_versions/
|
||||
modules.order
|
||||
Module.symvers
|
||||
Mkfile.old
|
||||
dkms.conf
|
||||
|
||||
### C++ ###
|
||||
# Prerequisites
|
||||
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
|
||||
# Precompiled Headers
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
*.smod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
|
||||
# Executables
|
||||
|
||||
### Git ###
|
||||
# Created by git for backups. To disable backups in Git:
|
||||
# $ git config --global mergetool.keepBackup false
|
||||
*.orig
|
||||
|
||||
# Created by git when using merge tools for conflicts
|
||||
*.BACKUP.*
|
||||
*.BASE.*
|
||||
*.LOCAL.*
|
||||
*.REMOTE.*
|
||||
*_BACKUP_*.txt
|
||||
*_BASE_*.txt
|
||||
*_LOCAL_*.txt
|
||||
*_REMOTE_*.txt
|
||||
|
||||
### PyCharm ###
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff
|
||||
.idea
|
||||
|
||||
# CMake
|
||||
cmake-build-*/
|
||||
|
||||
# Mongo Explorer plugin
|
||||
.idea/**/mongoSettings.xml
|
||||
|
||||
# File-based project format
|
||||
*.iws
|
||||
|
||||
# IntelliJ
|
||||
out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Cursive Clojure plugin
|
||||
.idea/replstate.xml
|
||||
|
||||
# SonarLint plugin
|
||||
.idea/sonarlint/
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
||||
# Editor-based Rest Client
|
||||
.idea/httpRequests
|
||||
|
||||
# Android studio 3.1+ serialized cache file
|
||||
.idea/caches/build_file_checksums.ser
|
||||
|
||||
### PyCharm Patch ###
|
||||
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
|
||||
|
||||
# *.iml
|
||||
# modules.xml
|
||||
# .idea/misc.xml
|
||||
# *.ipr
|
||||
|
||||
# Sonarlint plugin
|
||||
# https://plugins.jetbrains.com/plugin/7973-sonarlint
|
||||
.idea/**/sonarlint/
|
||||
|
||||
# SonarQube Plugin
|
||||
# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin
|
||||
.idea/**/sonarIssues.xml
|
||||
|
||||
# Markdown Navigator plugin
|
||||
# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced
|
||||
.idea/**/markdown-navigator.xml
|
||||
.idea/**/markdown-navigator-enh.xml
|
||||
.idea/**/markdown-navigator/
|
||||
|
||||
# Cache file creation bug
|
||||
# See https://youtrack.jetbrains.com/issue/JBR-2257
|
||||
.idea/$CACHE_FILE$
|
||||
|
||||
# CodeStream plugin
|
||||
# https://plugins.jetbrains.com/plugin/12206-codestream
|
||||
.idea/codestream.xml
|
||||
|
||||
### Python ###
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# poetry
|
||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||
#poetry.lock
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv*
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# WolfSSL
|
||||
wolfssl/
|
||||
|
||||
# PyCharm
|
||||
# JetBrains specific template is maintainted in a separate JetBrains.gitignore that can
|
||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
#.idea/
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/python,c,c++,git,pycharm
|
||||
|
||||
## Project Post-.gitignore ##
|
||||
|
||||
!device/lib
|
||||
*.secrets
|
||||
*.secrets.txt
|
||||
**/secrets.h
|
||||
uv.lock
|
||||
202
LICENSE.txt
Normal file
202
LICENSE.txt
Normal file
@@ -0,0 +1,202 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2026 The MITRE Corporation. All rights reserved
|
||||
Approved for Public Release; Distribution Unlimited. Case Number 25-03257-Code
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
25
Makefile
Normal file
25
Makefile
Normal file
@@ -0,0 +1,25 @@
|
||||
# This file is a helper script to make repetitive build actions easier
|
||||
# Invoking `make docker` will build the docker image.
|
||||
# `make docker-nc` will build the docker image without using the Docker cache.
|
||||
# `make secrets` will generate secrets for group 1234.
|
||||
# `make firmware` will make the firmware image.
|
||||
# `make clean` will remove build artifacts, both in the firmware
|
||||
# directory and the final output directory.
|
||||
|
||||
docker:
|
||||
docker build -t build-hsm ./firmware/
|
||||
|
||||
docker-nc:
|
||||
docker build --no-cache -t build-hsm ./firmware/
|
||||
|
||||
global.secrets:
|
||||
@if [ -z "${GROUPS}" ]; then echo 'Must pass valid groups like:\r\n\tmake global.secrets GROUPS=1234\r\nor, if multiple groups defined:\r\n\tmake global.secrets GROUPS="1234 5678"' && false; fi
|
||||
uvx --with-editable ./ectf26_design --from ectf26_design secrets global.secrets $(GROUPS)
|
||||
|
||||
%.hsm:
|
||||
@if [ ! -f global.secrets ]; then echo 'Must generate global secrets first with\r\n\tmake global.secrets' && false; fi
|
||||
@if [ -z "${PIN}" ] || [ -z "${PERMS}" ]; then echo "Must provide PIN and permissions for HSM. For example:\r\n\tmake $@ PIN=123456 PERMS='1234=RWC'" && false; fi
|
||||
docker run --rm -v ./firmware:/hsm -v ./global.secrets:/secrets/global.secrets:ro -v ./$@:/out -e HSM_PIN=${PIN} -e PERMISSIONS='${PERMS}' build-hsm $(BUILDDIR)
|
||||
|
||||
clean:
|
||||
rm -rfI *.hsm/ global.secrets
|
||||
21
README.md
Normal file
21
README.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# eCTF Insecure Example
|
||||
|
||||
This repository holds the insecure example design for an eCTF Hardware Security Module.
|
||||
The rules for the 2026 eCTF can be found here: https://rules.ectf.mitre.org/. Your team
|
||||
should **NOT fork this repo**. Instead clone it and push to a new __private__ repo.
|
||||
|
||||
## Layout
|
||||
|
||||
- `firmware/` - Source code to build the firmware
|
||||
- `Makefile` - This makefile is invoked by the eCTF tools when creating an HSM.
|
||||
- `Dockerfile` - Describes the build environment used by eCTF build tools.
|
||||
- `secrets_to_c_header.py` - Python file to convert from global secrets to firmware-parsable header file
|
||||
- `inc/` - Directory with c header files
|
||||
- `src/` - Directory with c source files
|
||||
- `wolfssl/` - Location to place wolfssl library for included Crypto Example
|
||||
- `firmware.ld` - Defines memory layout of built firmware
|
||||
- `ectf26_design/` - Pip-installable module for generating secrets
|
||||
- `src/` - Secrets gen source code
|
||||
- `gen_secrets.py` - Generates shared secrets
|
||||
- `pyproject.toml` - File that tells pip how to install this module
|
||||
- `Makefile` - Helper script to simplify repetitive build steps
|
||||
33
ectf26_design/pyproject.toml
Normal file
33
ectf26_design/pyproject.toml
Normal file
@@ -0,0 +1,33 @@
|
||||
[build-system]
|
||||
requires = ["setuptools>=61.0"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "ectf26_design"
|
||||
version = "2026.0+example"
|
||||
requires-python = ">=3.12"
|
||||
|
||||
# TODO: add your custom dependencies to this list
|
||||
dependencies = [
|
||||
"loguru",
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
secrets = "gen_secrets:main"
|
||||
|
||||
|
||||
[tool.black]
|
||||
include = '\.pyi?$'
|
||||
exclude = '''
|
||||
/(
|
||||
\.git
|
||||
| \.hg
|
||||
| \.mypy_cache
|
||||
| \.tox
|
||||
| \.venv
|
||||
| _build
|
||||
| buck-out
|
||||
| build
|
||||
| dist
|
||||
)/
|
||||
'''
|
||||
0
ectf26_design/src/__init__.py
Normal file
0
ectf26_design/src/__init__.py
Normal file
103
ectf26_design/src/gen_secrets.py
Normal file
103
ectf26_design/src/gen_secrets.py
Normal file
@@ -0,0 +1,103 @@
|
||||
"""
|
||||
Author: Ben Janis
|
||||
Date: 2026
|
||||
|
||||
This source file is part of an example system for MITRE's 2026 Embedded CTF
|
||||
(eCTF). This code is being provided only for educational purposes for the 2026 MITRE
|
||||
eCTF competition, and may not meet MITRE standards for quality. Use this code at your
|
||||
own risk!
|
||||
|
||||
Copyright: Copyright (c) 2026 The MITRE Corporation
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from loguru import logger
|
||||
|
||||
|
||||
def gen_secrets(groups: list[int]) -> bytes:
|
||||
"""Generate the contents secrets file
|
||||
|
||||
This will be passed to the Encoder, ectf26_design.gen_secrets,
|
||||
and the build process of the firmware
|
||||
|
||||
NOTE: you should NOT write to secrets files within this function.
|
||||
All generated secrets must be contained in the returned bytes
|
||||
object.
|
||||
|
||||
:param groups: List of permission groups that will be valid in this
|
||||
deployment.
|
||||
|
||||
:returns: Contents of the secrets file
|
||||
"""
|
||||
# TODO: Update this function to generate any system-wide secrets needed by
|
||||
# your design
|
||||
|
||||
# Create the secrets object
|
||||
# You can change this to generate any secret material
|
||||
# The secrets file will never be shared with attackers
|
||||
secrets = {
|
||||
"groups": groups,
|
||||
"some_secrets": "EXAMPLE",
|
||||
}
|
||||
|
||||
# NOTE: if you choose to use JSON for your file type, you will not
|
||||
# be able to store binary data, and must either use a different file
|
||||
# type or encode the binary data to hex, base64, or another type of
|
||||
# ASCII-only encoding
|
||||
return json.dumps(secrets).encode()
|
||||
|
||||
|
||||
def parse_args():
|
||||
"""Define and parse the command line arguments
|
||||
"""
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
"--force",
|
||||
"-f",
|
||||
action="store_true",
|
||||
help="Force creation of secrets file, overwriting existing file",
|
||||
)
|
||||
parser.add_argument(
|
||||
"secrets_file",
|
||||
type=Path,
|
||||
help="Path to the secrets file to be created",
|
||||
)
|
||||
parser.add_argument(
|
||||
"groups",
|
||||
nargs="+",
|
||||
type=lambda x: int(x, 0),
|
||||
help="Supported group IDs",
|
||||
)
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def main():
|
||||
"""Main function of gen_secrets
|
||||
|
||||
You will likely not have to change this function
|
||||
"""
|
||||
# Parse the command line arguments
|
||||
args = parse_args()
|
||||
|
||||
secrets = gen_secrets(args.groups)
|
||||
|
||||
# Print the generated secrets for your own debugging
|
||||
# Attackers will NOT have access to the output of this, but feel free to remove
|
||||
#
|
||||
# NOTE: Printing sensitive data is generally not good security practice
|
||||
logger.debug(f"Generated secrets: {secrets}")
|
||||
|
||||
# Open the file, erroring if the file exists unless the --force arg is provided
|
||||
with open(args.secrets_file, "wb" if args.force else "xb") as f:
|
||||
# Dump the secrets to the file
|
||||
f.write(secrets)
|
||||
|
||||
# For your own debugging. Feel free to remove
|
||||
logger.success(f"Wrote secrets to {str(args.secrets_file.absolute())}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
45
firmware/Dockerfile
Normal file
45
firmware/Dockerfile
Normal file
@@ -0,0 +1,45 @@
|
||||
# Dockerfile for the 2026 eCTF
|
||||
# Make any changes here to set up your build environment (e.g., installing crypto
|
||||
# libraries, dependencies, the compiler for a different language)
|
||||
|
||||
FROM ubuntu:24.04
|
||||
|
||||
LABEL version="0.2"
|
||||
LABEL description="Example HSM Docker Container for the 2026 eCTF"
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
WORKDIR /root
|
||||
|
||||
# Install Requisite Packages
|
||||
# do this first because it takes the longest
|
||||
RUN apt-get update && apt-get upgrade -y && apt-get install -y \
|
||||
python3 \
|
||||
make \
|
||||
wget \
|
||||
build-essential \
|
||||
unzip
|
||||
|
||||
ENV MSPM0_SDK_INSTALL_DIR=/opt/mspm0-sdk-mspm0_sdk_2_06_00_05
|
||||
ENV TICLANG_ARMCOMPILER=/opt/ti-cgt-armllvm_4.0.3.LTS
|
||||
|
||||
# Install MSPM0 SDK
|
||||
RUN wget https://github.com/TexasInstruments/mspm0-sdk/archive/refs/tags/mspm0_sdk_2_06_00_05.zip && \
|
||||
unzip mspm0_sdk_2_06_00_05.zip -d /opt && \
|
||||
rm -f -r mspm0_sdk_2_06_00_05.zip ${MSPM0_SDK_INSTALL_DIR}/docs ${MSPM0_SDK_INSTALL_DIR}/examples
|
||||
|
||||
# Install TI-Clang for curr machine's arch
|
||||
RUN if [ $(uname -m) = "x86_64" ]; then \
|
||||
wget -O ti_cgt_armllvm_4.0.3.LTS_linux_installer.bin https://dr-download.ti.com/software-development/ide-configuration-compiler-or-debugger/MD-ayxs93eZNN/4.0.3.LTS/ti_cgt_armllvm_4.0.3.LTS_linux-x64_installer.bin --ca-certificate=SSLCerts/mitre-chain.pem; \
|
||||
elif [ $(uname -m) = "aarch64" ] || [ $(uname -m) = "arm64" ]; then \
|
||||
wget -O ti_cgt_armllvm_4.0.3.LTS_linux_installer.bin https://dr-download.ti.com/software-development/ide-configuration-compiler-or-debugger/MD-ayxs93eZNN/4.0.3.LTS/ti_cgt_armllvm_4.0.3.LTS_linux-arm64_installer.bin --ca-certificate=SSLCerts/mitre-chain.pem; \
|
||||
else \
|
||||
$(false); \
|
||||
fi && \
|
||||
chmod +x ti_cgt_armllvm_4.0.3.LTS_linux_installer.bin && \
|
||||
./ti_cgt_armllvm_4.0.3.LTS_linux_installer.bin --mode unattended --prefix /opt && \
|
||||
rm -f ti_cgt_armllvm_4.0.3.LTS_linux_installer.bin
|
||||
|
||||
WORKDIR /hsm
|
||||
|
||||
ENTRYPOINT ["bash", "/hsm/build.sh"]
|
||||
|
||||
106
firmware/Makefile
Normal file
106
firmware/Makefile
Normal file
@@ -0,0 +1,106 @@
|
||||
MSPM0_SDK_INSTALL_DIR ?= $(abspath ../../../../../..)
|
||||
|
||||
include $(MSPM0_SDK_INSTALL_DIR)/tools/imports_mak/imports.mak.linux
|
||||
|
||||
CC = "$(TICLANG_ARMCOMPILER)/bin/tiarmclang"
|
||||
LNK = "$(TICLANG_ARMCOMPILER)/bin/tiarmclang"
|
||||
OBJCOPY = "$(TICLANG_ARMCOMPILER)/bin/tiarmobjcopy"
|
||||
BUILDDIR ?= /tmp/build
|
||||
VPATH = "src"
|
||||
LINKERFILE = "firmware.ld"
|
||||
|
||||
# to download wolfssl for the simple crypto example, `cd ./firmware/ && git clone https://github.com/wolfSSL/wolfssl`
|
||||
# then set this variable to 1
|
||||
CRYPTO_EXAMPLE = 0
|
||||
|
||||
OBJECTS = $(BUILDDIR)/HSM.so \
|
||||
$(BUILDDIR)/simple_uart.so \
|
||||
$(BUILDDIR)/ti_msp_dl_config.so \
|
||||
$(BUILDDIR)/startup_mspm0l222x_ticlang.so \
|
||||
$(BUILDDIR)/simple_flash.so \
|
||||
$(BUILDDIR)/host_messaging.so \
|
||||
$(BUILDDIR)/security.so \
|
||||
$(BUILDDIR)/filesystem.so \
|
||||
$(BUILDDIR)/commands.so
|
||||
|
||||
ifeq ($(CRYPTO_EXAMPLE), 1)
|
||||
OBJECTS += $(BUILDDIR)/simple_crypto.so
|
||||
|
||||
# change C flags
|
||||
CFLAGS += -DCRYPTO_EXAMPLE=1
|
||||
CFLAGS += -DNO_WOLFSSL_DIR
|
||||
CFLAGS += -DWOLFSSL_AES_DIRECT
|
||||
CFLAGS += -DSINGLE_THREADED
|
||||
# From https://www.wolfssl.com/documentation/manuals/wolfssl/chapter02.html#building-with-gcc-arm
|
||||
CFLAGS += -DHAVE_PK_CALLBACKS
|
||||
CFLAGS += -DWOLFSSL_USER_IO
|
||||
CFLAGS += -DNO_WRITEV -DTIME_T_NOT_64BIT
|
||||
CFLAGS += -DNO_FILESYSTEM
|
||||
# tells wolfssl that we will handle RNG on the baremetal target
|
||||
# user will need to implement the callbacks
|
||||
CFLAGS += -DNO_DEV_RANDOM
|
||||
CFLAGS += -DWC_NO_DEFAULT_DEVID
|
||||
CFLAGS += -DWOLF_CRYPTO_CB
|
||||
|
||||
WOLFSSL_INC = wolfssl/wolfcrypt/src
|
||||
CFLAGS += -I./wolfssl
|
||||
|
||||
# we need to build these objects for the simple crypto example
|
||||
OBJECTS += $(WOLFSSL_INC)/aes.o $(WOLFSSL_INC)/hash.o
|
||||
OBJECTS += $(WOLFSSL_INC)/md5.o $(WOLFSSL_INC)/cryptocb.o
|
||||
endif
|
||||
|
||||
NAME = hsm
|
||||
|
||||
CFLAGS += -I.. \
|
||||
-D__MSPM0L2228__ \
|
||||
-O2 \
|
||||
"-I$(MSPM0_SDK_INSTALL_DIR)/source/third_party/CMSIS/Core/Include" \
|
||||
"-I$(MSPM0_SDK_INSTALL_DIR)/source" \
|
||||
"-I./inc" \
|
||||
-gdwarf-3 \
|
||||
-mcpu=cortex-m0plus \
|
||||
-march=thumbv6m \
|
||||
-mfloat-abi=soft \
|
||||
-mthumb
|
||||
|
||||
LFLAGS += "-l$(MSPM0_SDK_INSTALL_DIR)/source/ti/drivers/lib/ticlang/m0p/drivers_mspm0l122x_l222x.a" \
|
||||
"-l$(MSPM0_SDK_INSTALL_DIR)/kernel/nortos/lib/ticlang/m0p/nortos_mspm0l122x_l222x.a" \
|
||||
"-l$(MSPM0_SDK_INSTALL_DIR)/source/ti/driverlib/lib/ticlang/m0p/mspm0l122x_l222x/driverlib.a" \
|
||||
"-L$(MSPM0_SDK_INSTALL_DIR)/source" \
|
||||
-L.. \
|
||||
./$(LINKERFILE) \
|
||||
"-Wl,-m,$(BUILDDIR)/$(NAME).map" \
|
||||
-Wl,--rom_model \
|
||||
-Wl,--warn_sections \
|
||||
"-L$(TICLANG_ARMCOMPILER)/lib" \
|
||||
-llibc.a
|
||||
|
||||
all: $(BUILDDIR)/$(NAME).elf $(BUILDDIR)/$(NAME).bin
|
||||
|
||||
$(BUILDDIR):
|
||||
@ mkdir -p $(BUILDDIR)
|
||||
|
||||
$(BUILDDIR)/%.so: ./src/%.c | $(BUILDDIR)
|
||||
@ echo Building $@
|
||||
@ $(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
# if compiling with the crypto example, compile all crypto objects
|
||||
ifeq ($(CRYPTO_EXAMPLE), 1)
|
||||
$(WOLFSSL_INC)/%.o: $(WOLFSSL_INC)/%.c
|
||||
@ echo Building $@
|
||||
@ $(CC) $(CFLAGS) -c $< -o $@
|
||||
endif
|
||||
|
||||
$(BUILDDIR)/$(NAME).elf: $(OBJECTS)
|
||||
@ echo linking $@
|
||||
@ $(LNK) -Wl,-u,_c_int00 $(OBJECTS) $(LFLAGS) -o $(BUILDDIR)/$(NAME).elf
|
||||
|
||||
$(BUILDDIR)/$(NAME).bin: $(BUILDDIR)/$(NAME).elf
|
||||
@ $(OBJCOPY) -O binary $(BUILDDIR)/$(NAME).elf $(BUILDDIR)/$(NAME).bin
|
||||
|
||||
clean:
|
||||
@ echo Cleaning...
|
||||
@ $(RM) $(OBJECTS) > $(DEVNULL) 2>&1
|
||||
@ $(RM) $(NAME).elf > $(DEVNULL) 2>&1
|
||||
@ $(RM) $(NAME).map > $(DEVNULL) 2>&1
|
||||
4
firmware/build.sh
Normal file
4
firmware/build.sh
Normal file
@@ -0,0 +1,4 @@
|
||||
BUILDDIR=${1:-/tmp/build}
|
||||
python3 secrets_to_c_header.py /secrets/global.secrets ${HSM_PIN} ${PERMISSIONS}
|
||||
make BUILDDIR=${BUILDDIR}
|
||||
cp ${BUILDDIR}/hsm.elf ${BUILDDIR}/hsm.bin /out
|
||||
74
firmware/firmware.ld
Normal file
74
firmware/firmware.ld
Normal file
@@ -0,0 +1,74 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com/
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
Neither the name of Texas Instruments Incorporated nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*****************************************************************************/
|
||||
-uinterruptVectors
|
||||
--stack_size=256
|
||||
|
||||
#define FLASH_BASE 0x6000
|
||||
|
||||
MEMORY
|
||||
{
|
||||
/* Divide this in half and allocate the first half to user space and the second reserved */
|
||||
BOOTLOADER (RX) : origin = 0x00000000, length = 0x00006000 /* Bootloader flash */
|
||||
FLASH (RX) : origin = 0x00006000, length = 0x00034000 /* Location of team firmware */
|
||||
FAT (RW) : origin = 0x0003A000, length = 0x00000400 /* Used to store tag, length, pointer values for files */
|
||||
APP2 (RX) : origin = 0x0003A400, length = 0x00005c00 /* Location of team firmware */
|
||||
SRAM (RWX) : origin = 0x20200000, length = 0x00008000
|
||||
BCR_CONFIG (R) : origin = 0x41C00000, length = 0x000000FF
|
||||
BSL_CONFIG (R) : origin = 0x41C00100, length = 0x00000080
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.intvecs: > FLASH_BASE
|
||||
.text : palign(8) {} > FLASH
|
||||
.const : palign(8) {} > FLASH
|
||||
.cinit : palign(8) {} > FLASH
|
||||
.pinit : palign(8) {} > FLASH
|
||||
.rodata : palign(8) {} > FLASH
|
||||
.ARM.exidx : palign(8) {} > FLASH
|
||||
.init_array : palign(8) {} > FLASH
|
||||
.binit : palign(8) {} > FLASH
|
||||
.files : palign(8)
|
||||
.TI.ramfunc : load = FLASH, palign(8), run=SRAM, table(BINIT)
|
||||
|
||||
.vtable : > SRAM
|
||||
.args : > SRAM
|
||||
.data : > SRAM
|
||||
.bss : > SRAM
|
||||
.sysmem : > SRAM
|
||||
.stack : > SRAM (HIGH)
|
||||
|
||||
.BCRConfig : {} > BCR_CONFIG
|
||||
.BSLConfig : {} > BSL_CONFIG
|
||||
}
|
||||
162
firmware/inc/commands.h
Normal file
162
firmware/inc/commands.h
Normal file
@@ -0,0 +1,162 @@
|
||||
/**
|
||||
* @file commands.h
|
||||
* @author Samuel Meyers
|
||||
* @brief eCTF command handlers
|
||||
* @date 2026
|
||||
*
|
||||
* This source file is part of an example system for MITRE's 2026 Embedded CTF (eCTF).
|
||||
* This code is being provided only for educational purposes for the 2026 MITRE eCTF competition,
|
||||
* and may not meet MITRE standards for quality. Use this code at your own risk!
|
||||
*
|
||||
* @copyright Copyright (c) 2026 The MITRE Corporation
|
||||
*/
|
||||
|
||||
#ifndef __COMMANDS_H__
|
||||
#define __COMMANDS_H__
|
||||
|
||||
#include "security.h"
|
||||
#include "stdint.h"
|
||||
#include "simple_flash.h"
|
||||
#include "filesystem.h"
|
||||
#include "secrets.h"
|
||||
|
||||
#define pkt_len_t uint16_t
|
||||
|
||||
// Pin will be 6 hex characters 0-9,a-f
|
||||
typedef unsigned char pin_t[6];
|
||||
|
||||
#define MAX_MSG_SIZE sizeof(write_command_t)
|
||||
|
||||
// calculates the length of a list packet based on the number of files listed
|
||||
#define LIST_PKT_LEN(num_files) (sizeof(num_files) + ((MAX_NAME_SIZE + sizeof(group_id_t) + sizeof(slot_t)) * num_files))
|
||||
|
||||
#pragma pack(push, 1) // Tells the compiler not to pad the struct members
|
||||
// for more information on what struct padding does, see:
|
||||
// https://www.gnu.org/software/c-intro-and-ref/manual/html_node/Structure-Layout.html
|
||||
|
||||
/**********************************************************
|
||||
******************** FILE STRUCTS ************************
|
||||
**********************************************************/
|
||||
|
||||
typedef struct {
|
||||
slot_t slot;
|
||||
group_id_t group_id;
|
||||
char name[MAX_NAME_SIZE];
|
||||
} file_metadata_t;
|
||||
|
||||
/**********************************************************
|
||||
******************** COMMAND STRUCTS *********************
|
||||
**********************************************************/
|
||||
|
||||
typedef struct {
|
||||
pin_t pin;
|
||||
} list_command_t;
|
||||
|
||||
typedef struct {
|
||||
pin_t pin;
|
||||
slot_t slot;
|
||||
} read_command_t;
|
||||
|
||||
typedef struct {
|
||||
pin_t pin;
|
||||
slot_t slot;
|
||||
group_id_t group_id;
|
||||
char name[MAX_NAME_SIZE];
|
||||
uint8_t uuid[UUID_SIZE];
|
||||
uint16_t contents_len;
|
||||
uint8_t contents[MAX_CONTENTS_SIZE];
|
||||
} write_command_t;
|
||||
|
||||
typedef struct {
|
||||
pin_t pin;
|
||||
slot_t read_slot;
|
||||
slot_t write_slot;
|
||||
} receive_command_t;
|
||||
|
||||
typedef struct {
|
||||
slot_t slot;
|
||||
group_permission_t permissions[MAX_PERMS];
|
||||
} receive_request_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t uuid[UUID_SIZE];
|
||||
file_t file;
|
||||
} receive_response_t;
|
||||
|
||||
typedef struct {
|
||||
pin_t pin;
|
||||
} interrogate_command_t;
|
||||
|
||||
/**********************************************************
|
||||
******************** RESPONSE STRUCTS ********************
|
||||
**********************************************************/
|
||||
|
||||
typedef struct {
|
||||
uint32_t n_files;
|
||||
file_metadata_t metadata[MAX_FILE_COUNT];
|
||||
} list_response_t;
|
||||
|
||||
typedef struct {
|
||||
char name[MAX_NAME_SIZE];
|
||||
uint8_t contents[MAX_CONTENTS_SIZE];
|
||||
} read_response_t;
|
||||
|
||||
#pragma pack(pop) // Tells the compiler to resume padding struct members
|
||||
|
||||
/** @brief Perform the list operation
|
||||
*
|
||||
* @param pkt_len The length of the incoming packet
|
||||
* @param buf A pointer the incoming message buffer
|
||||
*
|
||||
* @return 0 upon success. A negative value on error.
|
||||
*/
|
||||
int list(uint16_t pkt_len, uint8_t *buf);
|
||||
|
||||
|
||||
/** @brief Perform the read operation
|
||||
*
|
||||
* @param pkt_len The length of the incoming packet
|
||||
* @param buf A pointer the incoming message buffer
|
||||
*
|
||||
* @return 0 upon success. A negative value on error.
|
||||
*/
|
||||
int read(uint16_t pkt_len, uint8_t *buf);
|
||||
|
||||
|
||||
/** @brief Perform the write operation
|
||||
*
|
||||
* @param pkt_len The length of the incoming packet
|
||||
* @param buf A pointer the incoming message buffer
|
||||
*
|
||||
* @return 0 upon success. A negative value on error.
|
||||
*/
|
||||
int write(uint16_t pkt_len, uint8_t *buf);
|
||||
|
||||
|
||||
/** @brief Perform the receive operation
|
||||
*
|
||||
* @param pkt_len The length of the incoming packet
|
||||
* @param buf A pointer the incoming message buffer
|
||||
*
|
||||
* @return 0 upon success. A negative value on error.
|
||||
*/
|
||||
int receive(uint16_t pkt_len, uint8_t *buf);
|
||||
|
||||
|
||||
/** @brief Perform the interrogate operation
|
||||
*
|
||||
* @param pkt_len The length of the incoming packet
|
||||
* @param buf A pointer to the incoming message buffer
|
||||
*
|
||||
* @return 0 upon success. A negative value on error.
|
||||
*/
|
||||
int interrogate(uint16_t pkt_len, uint8_t *buf);
|
||||
|
||||
|
||||
/** @brief Perform the listen operation
|
||||
*
|
||||
* @return 0 upon success. A negative value on error.
|
||||
*/
|
||||
int listen(uint16_t pkt_len, uint8_t *buf);
|
||||
|
||||
#endif // __COMMANDS_H__
|
||||
152
firmware/inc/filesystem.h
Normal file
152
firmware/inc/filesystem.h
Normal file
@@ -0,0 +1,152 @@
|
||||
/**
|
||||
* @file filesystem.h
|
||||
* @author Samuel Meyers
|
||||
* @brief eCTF flash-based filesystem management
|
||||
* @date 2026
|
||||
*
|
||||
* This source file is part of an example system for MITRE's 2026 Embedded CTF (eCTF).
|
||||
* This code is being provided only for educational purposes for the 2026 MITRE eCTF competition,
|
||||
* and may not meet MITRE standards for quality. Use this code at your own risk!
|
||||
*
|
||||
* @copyright Copyright (c) 2026 The MITRE Corporation
|
||||
*/
|
||||
|
||||
#ifndef __FILESYSTEM__
|
||||
#define __FILESYSTEM__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "simple_flash.h"
|
||||
|
||||
// #include "commands.h"
|
||||
|
||||
typedef unsigned char slot_t;
|
||||
typedef uint16_t group_id_t;
|
||||
|
||||
|
||||
/**********************************************************
|
||||
********** BEGIN FUNCTIONALLY DEFINED ELEMENTS ***********
|
||||
**********************************************************/
|
||||
|
||||
// Everything in this section is defined by the functional requirements. Your design may
|
||||
// not change the FAT scheme, address, or size of the elements. You may change the
|
||||
// implementation to utilize the FAT however you like, and you may use any allocation
|
||||
// scheme to determine where to store files. The pointers to files, along with their
|
||||
// UUIDs MUST be at this location in flash or your design will not be functionally
|
||||
// compliant.
|
||||
|
||||
#define MAX_FILE_COUNT 8
|
||||
#define MAX_NAME_SIZE 32
|
||||
#define MAX_CONTENTS_SIZE 8192
|
||||
|
||||
// _FLASH_FAT_START is defined by the functional specs to be the start of where the FAT
|
||||
// will be stored. It is address 0x0003a000, the last flash page. Your team may NOT
|
||||
// change this location as the data structure location must be known by the secure
|
||||
// bootloader.
|
||||
#define _FLASH_FAT_START 0x0003a000
|
||||
|
||||
// size of file UUID
|
||||
#define UUID_SIZE 16
|
||||
|
||||
// This struct is functionally defined
|
||||
typedef struct {
|
||||
char uuid[UUID_SIZE];
|
||||
uint16_t length;
|
||||
uint16_t padding;
|
||||
unsigned int flash_addr;
|
||||
} filesystem_entry_t;
|
||||
|
||||
static filesystem_entry_t FILE_ALLOCATION_TABLE[MAX_FILE_COUNT];
|
||||
|
||||
/**********************************************************
|
||||
*********** END FUNCTIONALLY DEFINED ELEMENTS ************
|
||||
**********************************************************/
|
||||
|
||||
|
||||
/*
|
||||
The reference design allocates files for each slot as follows:
|
||||
0: 0x10000-0x12400
|
||||
1: 0x12400-0x14800
|
||||
2: 0x14800-0x16c00
|
||||
3: 0x16c00-0x19000
|
||||
4: 0x19000-0x1b400
|
||||
5: 0x1b400-0x1d800
|
||||
6: 0x1d800-0x1fc00
|
||||
7: 0x1fc00-0x22000
|
||||
*/
|
||||
// Calculate the flash address for a given file slot. 9 pages are allocated for each
|
||||
// file.
|
||||
#define FILE_START_PAGE_FROM_SLOT(slot) FILES_START_ADDR + (STORED_FILE_SIZE*slot)
|
||||
|
||||
// Calculate the total size of a file in flash, including its metadata
|
||||
#define FILE_TOTAL_SIZE(len) len + offsetof(file_t, contents)
|
||||
|
||||
// Each file will be 9 pages in size. 8 pages for the file contents + 1 page for
|
||||
// metadata
|
||||
#define FILE_PAGE_COUNT 9
|
||||
#define STORED_FILE_SIZE FLASH_PAGE_SIZE*FILE_PAGE_COUNT
|
||||
|
||||
// first flash address for files
|
||||
#define FILES_START_ADDR 0x10000
|
||||
|
||||
#define FILE_IN_USE 0xdeadbeef
|
||||
// used to actually define the file object
|
||||
typedef struct {
|
||||
uint32_t in_use; // FILE_IN_USE if in use
|
||||
group_id_t group_id;
|
||||
char name[MAX_NAME_SIZE];
|
||||
uint16_t contents_len;
|
||||
uint8_t contents[MAX_CONTENTS_SIZE];
|
||||
} file_t;
|
||||
|
||||
/** @brief Initialize the filesystem
|
||||
*
|
||||
*
|
||||
* @return 0 upon success. A negative value on error.
|
||||
*/
|
||||
int init_fs();
|
||||
|
||||
/** @brief Check whether a file is in use
|
||||
*
|
||||
* @param slot The slot to check
|
||||
*
|
||||
* @return True if the slot is in use. False otherwise.
|
||||
*/
|
||||
bool is_slot_in_use(slot_t slot);
|
||||
|
||||
/** @brief Create a new file object in memory
|
||||
*
|
||||
* @param slot The slot to check
|
||||
*
|
||||
* @return 0 upon success. A negative value otherwise.
|
||||
*/
|
||||
int create_file(file_t *dest, group_id_t group_id, char *name, uint16_t contents_len, uint8_t *contents);
|
||||
|
||||
/** @brief Create a new file object in memory
|
||||
*
|
||||
* @param slot The slot to write the file to
|
||||
* @param src The sourc file to store
|
||||
* @param uuid The UUID to store in the FAT
|
||||
*
|
||||
* @return 0 upon success. A negative value otherwise.
|
||||
*/
|
||||
int write_file(slot_t slot, file_t *src, uint8_t *uuid);
|
||||
|
||||
/** @brief Read a file from persistent storage into memory
|
||||
*
|
||||
* @param slot The slot to read
|
||||
* @param dest The destination address to store the file
|
||||
*
|
||||
* @return 0 upon success. A negative value otherwise.
|
||||
*/
|
||||
int read_file(slot_t slot, file_t *dest);
|
||||
|
||||
|
||||
/** @brief Get a read-only pointer to a file's metadata
|
||||
*
|
||||
* @param slot The slot to get metadata for
|
||||
*
|
||||
* @return A filesystem_entry_t * on success. NULL on error.
|
||||
*/
|
||||
const filesystem_entry_t *get_file_metadata(slot_t slot);
|
||||
|
||||
#endif
|
||||
102
firmware/inc/host_messaging.h
Normal file
102
firmware/inc/host_messaging.h
Normal file
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* @file host_messaging.h
|
||||
* @author Samuel Meyers
|
||||
* @brief eCTF Host Messaging Implementation
|
||||
* @date 2026
|
||||
*
|
||||
* This source file is part of an example system for MITRE's 2026 Embedded CTF (eCTF).
|
||||
* This code is being provided only for educational purposes for the 2026 MITRE eCTF competition,
|
||||
* and may not meet MITRE standards for quality. Use this code at your own risk!
|
||||
*
|
||||
* @copyright Copyright (c) 2026 The MITRE Corporation
|
||||
*/
|
||||
|
||||
#ifndef __HOST_MESSAGING__
|
||||
#define __HOST_MESSAGING__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "simple_uart.h"
|
||||
|
||||
#define CMD_TYPE_LEN sizeof(char)
|
||||
#define CMD_LEN_LEN sizeof(uint16_t)
|
||||
#define MSG_MAGIC '%' // '%' - 0x25
|
||||
|
||||
typedef enum {
|
||||
LIST_MSG = 'L', // 'L' - 0x4c
|
||||
READ_MSG = 'R', // 'R' - 0x52
|
||||
WRITE_MSG = 'W', // 'W' - 0x57
|
||||
RECEIVE_MSG = 'C', // 'C' - 0x43
|
||||
INTERROGATE_MSG = 'I', // 'I' - 0x49
|
||||
LISTEN_MSG = 'N', // 'N' - 0x4e
|
||||
ACK_MSG = 'A', // 'A' - 0x41
|
||||
DEBUG_MSG = 'D', // 'D' - 0x44
|
||||
ERROR_MSG = 'E', // 'E' - 0x45
|
||||
} msg_type_t;
|
||||
|
||||
#pragma pack(push, 1) // Tells the compiler not to pad the struct members
|
||||
typedef struct {
|
||||
char magic; // Should be MSG_MAGIC
|
||||
char cmd; // msg_type_t
|
||||
uint16_t len;
|
||||
} msg_header_t;
|
||||
#pragma pack(pop) // Tells the compiler to resume padding struct members
|
||||
|
||||
typedef enum {
|
||||
MSG_OK = 0,
|
||||
MSG_BAD_PTR,
|
||||
MSG_NO_ACK,
|
||||
MSG_BAD_LEN,
|
||||
// <0 is UART error
|
||||
} msg_status_t;
|
||||
|
||||
#define MSG_HEADER_SIZE sizeof(msg_header_t)
|
||||
|
||||
int write_bytes(int uart_id, const void *buf, uint16_t len, bool should_ack);
|
||||
|
||||
/** @brief Write len bytes to UART in hex. 2 bytes will be printed for every byte.
|
||||
*
|
||||
* @param uart_id The id of the uart where the message is to be sent
|
||||
* @param type Message type.
|
||||
* @param buf Pointer to the bytes that will be printed.
|
||||
* @param len The number of bytes to print.
|
||||
*
|
||||
* @return 0 on success. A negative value on error.
|
||||
*/
|
||||
int write_hex(int uart_id, msg_type_t type, const void *buf, size_t len);
|
||||
|
||||
/** @brief Send a message to the host, expecting an ack after every 256 bytes.
|
||||
*
|
||||
* @param uart_id The id of the uart where the message is to be sent
|
||||
* @param type The type of message to send.
|
||||
* @param buf Pointer to a buffer containing the outgoing packet.
|
||||
* @param len The size of the outgoing packet in bytes.
|
||||
*
|
||||
* @return 0 on success. A negative value on failure.
|
||||
*/
|
||||
int write_packet(int uart_id, msg_type_t type, const void *buf, uint16_t len);
|
||||
|
||||
/** @brief Reads a packet from console UART.
|
||||
*
|
||||
* @param uart_id The id of the uart where the message is to be sent
|
||||
* @param cmd A pointer to the resulting opcode of the packet. Must not be null.
|
||||
* @param buf A pointer to a buffer to store the incoming packet. Can be null.
|
||||
* @param len A pointer to the resulting length of the packet. Can be null.
|
||||
*
|
||||
* @return 0 on success, a negative number on failure
|
||||
*/
|
||||
int read_packet(int uart_id, msg_type_t* cmd, void *buf, uint16_t *len);
|
||||
|
||||
// Macro definitions to print the specified format for error messages
|
||||
#define print_error(msg) write_packet(CONTROL_INTERFACE, ERROR_MSG, msg, strlen(msg))
|
||||
|
||||
// Macro definitions to print the specified format for debug messages
|
||||
#define print_debug(msg) write_packet(CONTROL_INTERFACE, DEBUG_MSG, msg, strlen(msg))
|
||||
#define print_hex_debug(msg, len) write_hex(CONTROL_INTERFACE, DEBUG_MSG, msg, len)
|
||||
|
||||
// Macro definitions to write ack message
|
||||
#define write_ack(uart_id) write_packet(uart_id, ACK_MSG, NULL, 0)
|
||||
|
||||
#endif
|
||||
52
firmware/inc/security.h
Normal file
52
firmware/inc/security.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* @file security.h
|
||||
* @author Samuel Meyers
|
||||
* @brief Stub file to hold security checks
|
||||
* @date 2026
|
||||
*
|
||||
* This source file is part of an example system for MITRE's 2026 Embedded CTF (eCTF).
|
||||
* This code is being provided only for educational purposes for the 2026 MITRE eCTF competition,
|
||||
* and may not meet MITRE standards for quality. Use this code at your own risk!
|
||||
*
|
||||
* @copyright Copyright (c) 2026 The MITRE Corporation
|
||||
*/
|
||||
#ifndef __SECURITY_H__
|
||||
#define __SECURITY_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define MAX_PERMS 8
|
||||
#define PIN_LENGTH 6
|
||||
|
||||
typedef enum {
|
||||
PERM_READ = 'R',
|
||||
PERM_WRITE = 'W',
|
||||
PERM_RECEIVE = 'C',
|
||||
} permission_enum_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t group_id;
|
||||
bool read;
|
||||
bool write;
|
||||
bool receive;
|
||||
} group_permission_t;
|
||||
|
||||
/** @brief Validate a pin against the HSM's pin
|
||||
*
|
||||
* @param pin Requested pin to validate.
|
||||
*
|
||||
* @return True if the pin is valid. False if not.
|
||||
*/
|
||||
bool check_pin(unsigned char *pin);
|
||||
|
||||
/** @brief Ensure the HSM has the requested permission
|
||||
*
|
||||
* @param group_id Group ID.
|
||||
* @param perm Permission type.
|
||||
*
|
||||
* @return True if the HSM has the correct permission. False if not.
|
||||
*/
|
||||
bool validate_permission(uint16_t group_id, permission_enum_t perm);
|
||||
|
||||
#endif // __SECURITY_H__
|
||||
72
firmware/inc/simple_crypto.h
Normal file
72
firmware/inc/simple_crypto.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* @file "simple_crypto.h"
|
||||
* @author Ben Janis
|
||||
* @brief Simplified Crypto API Header
|
||||
* @date 2026
|
||||
*
|
||||
* This source file is part of an example system for MITRE's 2026 Embedded CTF (eCTF).
|
||||
* This code is being provided only for educational purposes for the 2026 MITRE eCTF competition,
|
||||
* and may not meet MITRE standards for quality. Use this code at your own risk!
|
||||
*
|
||||
* @copyright Copyright (c) 2026 The MITRE Corporation
|
||||
*/
|
||||
|
||||
#if CRYPTO_EXAMPLE
|
||||
#ifndef ECTF_CRYPTO_H
|
||||
#define ECTF_CRYPTO_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "wolfssl/wolfcrypt/aes.h"
|
||||
#include "wolfssl/wolfcrypt/hash.h"
|
||||
|
||||
/******************************** MACRO DEFINITIONS ********************************/
|
||||
#define BLOCK_SIZE AES_BLOCK_SIZE
|
||||
#define KEY_SIZE 16
|
||||
#define HASH_SIZE MD5_DIGEST_SIZE
|
||||
|
||||
/******************************** FUNCTION PROTOTYPES ********************************/
|
||||
/** @brief Encrypts plaintext using a symmetric cipher
|
||||
*
|
||||
* @param plaintext A pointer to a buffer of length len containing the
|
||||
* plaintext to encrypt
|
||||
* @param len The length of the plaintext to encrypt. Must be a multiple of
|
||||
* BLOCK_SIZE (16 bytes)
|
||||
* @param key A pointer to a buffer of length KEY_SIZE (16 bytes) containing
|
||||
* the key to use for encryption
|
||||
* @param ciphertext A pointer to a buffer of length len where the resulting
|
||||
* ciphertext will be written to
|
||||
*
|
||||
* @return 0 on success, -1 on bad length, other non-zero for other error
|
||||
*/
|
||||
int encrypt_sym(uint8_t *plaintext, size_t len, uint8_t *key, uint8_t *ciphertext);
|
||||
|
||||
/** @brief Decrypts ciphertext using a symmetric cipher
|
||||
*
|
||||
* @param ciphertext A pointer to a buffer of length len containing the
|
||||
* ciphertext to decrypt
|
||||
* @param len The length of the ciphertext to decrypt. Must be a multiple of
|
||||
* BLOCK_SIZE (16 bytes)
|
||||
* @param key A pointer to a buffer of length KEY_SIZE (16 bytes) containing
|
||||
* the key to use for decryption
|
||||
* @param plaintext A pointer to a buffer of length len where the resulting
|
||||
* plaintext will be written to
|
||||
*
|
||||
* @return 0 on success, -1 on bad length, other non-zero for other error
|
||||
*/
|
||||
int decrypt_sym(uint8_t *ciphertext, size_t len, uint8_t *key, uint8_t *plaintext);
|
||||
|
||||
/** @brief Hashes arbitrary-length data
|
||||
*
|
||||
* @param data A pointer to a buffer of length len containing the data
|
||||
* to be hashed
|
||||
* @param len The length of the plaintext to hash
|
||||
* @param hash_out A pointer to a buffer of length HASH_SIZE (16 bytes) where the resulting
|
||||
* hash output will be written to
|
||||
*
|
||||
* @return 0 on success, non-zero for other error
|
||||
*/
|
||||
int hash(void *data, size_t len, uint8_t *hash_out);
|
||||
|
||||
#endif // CRYPTO_EXAMPLE
|
||||
#endif // ECTF_CRYPTO_H
|
||||
66
firmware/inc/simple_flash.h
Normal file
66
firmware/inc/simple_flash.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* @file "simple_flash.h"
|
||||
* @author Samuel Meyers
|
||||
* @brief Simple Flash Interface Header
|
||||
* @date 2026
|
||||
*
|
||||
* This source file is part of an example system for MITRE's 2026 Embedded CTF (eCTF).
|
||||
* This code is being provided only for educational purposes for the 2026 MITRE eCTF competition,
|
||||
* and may not meet MITRE standards for quality. Use this code at your own risk!
|
||||
*
|
||||
* @copyright Copyright (c) 2026 The MITRE Corporation
|
||||
*/
|
||||
|
||||
#ifndef __SIMPLE_FLASH__
|
||||
#define __SIMPLE_FLASH__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <ti/devices/msp/msp.h>
|
||||
#include <ti/driverlib/driverlib.h>
|
||||
#include <ti/driverlib/m0p/dl_core.h>
|
||||
|
||||
#define FLASH_PAGE_SIZE DL_FLASHCTL_SECTOR_SIZE /* 1024 */
|
||||
|
||||
/**
|
||||
* @brief Flash Simple Erase Page
|
||||
*
|
||||
* @param address: uint32_t, address of flash page to erase
|
||||
*
|
||||
* @return int: return negative if failure, zero if success
|
||||
*
|
||||
* This function erases a page of flash such that it can be updated.
|
||||
* Flash memory can only be erased in a large block size called a page.
|
||||
* Once erased, memory can only be written one way e.g. 1->0.
|
||||
* In order to be re-written the entire page must be erased.
|
||||
*/
|
||||
int flash_simple_erase_page(uint32_t address);
|
||||
/**
|
||||
* @brief Flash Simple Read
|
||||
*
|
||||
* @param address: uint32_t, address of flash page to read
|
||||
* @param buffer: void*, pointer to buffer for data to be read into
|
||||
* @param size: uint32_t, number of bytes to read from flash
|
||||
*
|
||||
* This function reads data from the specified flash page into the buffer
|
||||
* with the specified amount of bytes
|
||||
*/
|
||||
void flash_simple_read(uint32_t address, void* buffer, uint32_t size);
|
||||
/**
|
||||
* @brief Flash Simple Write
|
||||
*
|
||||
* @param address: uint32_t, address of flash page to write
|
||||
* @param buffer: void*, pointer to buffer to write data from
|
||||
* @param size: uint32_t, number of bytes to write from flash
|
||||
*
|
||||
* @return int: return negative if failure, zero if success
|
||||
*
|
||||
* This function writes data to the specified flash page from the buffer passed
|
||||
* with the specified amount of bytes. Flash memory can only be written in one
|
||||
* way e.g. 1->0. To rewrite previously written memory see the
|
||||
* flash_simple_erase_page documentation.
|
||||
*/
|
||||
int flash_simple_write(uint32_t address, void* buffer, uint32_t size);
|
||||
|
||||
#endif
|
||||
51
firmware/inc/simple_uart.h
Normal file
51
firmware/inc/simple_uart.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* @file "simple_uart.h"
|
||||
* @author Samuel Meyers
|
||||
* @brief Simple UART Interface Header
|
||||
* @date 2026
|
||||
*
|
||||
* This source file is part of an example system for MITRE's 2026 Embedded CTF (eCTF).
|
||||
* This code is being provided only for educational purposes for the 2026 MITRE eCTF competition,
|
||||
* and may not meet MITRE standards for quality. Use this code at your own risk!
|
||||
*
|
||||
* @copyright Copyright (c) 2026 The MITRE Corporation
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __SIMPLE_UART__
|
||||
#define __SIMPLE_UART__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "host_messaging.h"
|
||||
|
||||
#include <ti/devices/msp/msp.h>
|
||||
#include <ti/driverlib/dl_gpio.h>
|
||||
#include "ti_msp_dl_config.h"
|
||||
|
||||
/******************************** MACRO DEFINITIONS ********************************/
|
||||
#define UART_BAUD 115200
|
||||
#define CONTROL_INTERFACE 0
|
||||
#define TRANSFER_INTERFACE 1
|
||||
|
||||
#define CONFIG_UART_COUNT 2
|
||||
|
||||
/******************************** FUNCTION PROTOTYPES ******************************/
|
||||
|
||||
/** @brief Reads the next available character from UART.
|
||||
*
|
||||
* @param uart_id The index of UART to use
|
||||
* @return The character read. Otherwise see MAX78000 Error Codes for
|
||||
* a list of return codes.
|
||||
*/
|
||||
int uart_readbyte(int uart_id);
|
||||
|
||||
/** @brief Writes a byte to UART.
|
||||
*
|
||||
* @param uart_id The index of UART to use
|
||||
* @param data The byte to be written.
|
||||
*/
|
||||
void uart_writebyte(int uart_id, uint8_t data);
|
||||
|
||||
#endif // __SIMPLE_UART__
|
||||
22
firmware/inc/status_led.h
Normal file
22
firmware/inc/status_led.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* @file status_led.h
|
||||
* @author Samuel Meyers
|
||||
* @brief eCTF Status LED Implementation
|
||||
* @date 2026
|
||||
*
|
||||
* This source file is part of an example system for MITRE's 2026 Embedded CTF (eCTF).
|
||||
* This code is being provided only for educational purposes for the 2026 MITRE eCTF competition,
|
||||
* and may not meet MITRE standards for quality. Use this code at your own risk!
|
||||
*
|
||||
* @copyright Copyright (c) 2026 The MITRE Corporation
|
||||
*/
|
||||
|
||||
#ifndef __STATUS_LED__
|
||||
#define __STATUS_LED__
|
||||
|
||||
#include "ti_msp_dl_config.h"
|
||||
|
||||
#define STATUS_LED_ON(void) DL_GPIO_setPins(LEDS_PORT, LEDS_STATUS_LED_PIN)
|
||||
#define STATUS_LED_OFF(void) DL_GPIO_clearPins(LEDS_PORT, LEDS_STATUS_LED_PIN)
|
||||
|
||||
#endif // __STATUS_LED__
|
||||
146
firmware/inc/ti_msp_dl_config.h
Normal file
146
firmware/inc/ti_msp_dl_config.h
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Texas Instruments Incorporated - http://www.ti.com
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of Texas Instruments Incorporated nor the names of
|
||||
* its contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ============ ti_msp_dl_config.h =============
|
||||
* Configured MSPM0 DriverLib module declarations
|
||||
*
|
||||
* DO NOT EDIT - This file is generated for the MSPM0L222X
|
||||
* by the SysConfig tool.
|
||||
*/
|
||||
#ifndef ti_msp_dl_config_h
|
||||
#define ti_msp_dl_config_h
|
||||
|
||||
#define CONFIG_MSPM0L222X
|
||||
#define CONFIG_MSPM0L2228
|
||||
|
||||
#if defined(__ti_version__) || defined(__TI_COMPILER_VERSION__)
|
||||
#define SYSCONFIG_WEAK __attribute__((weak))
|
||||
#elif defined(__IAR_SYSTEMS_ICC__)
|
||||
#define SYSCONFIG_WEAK __weak
|
||||
#elif defined(__GNUC__)
|
||||
#define SYSCONFIG_WEAK __attribute__((weak))
|
||||
#endif
|
||||
|
||||
#include <ti/devices/msp/msp.h>
|
||||
#include <ti/driverlib/driverlib.h>
|
||||
#include <ti/driverlib/m0p/dl_core.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ======== SYSCFG_DL_init ========
|
||||
* Perform all required MSP DL initialization
|
||||
*
|
||||
* This function should be called once at a point before any use of
|
||||
* MSP DL.
|
||||
*/
|
||||
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
#define POWER_STARTUP_DELAY (16)
|
||||
|
||||
|
||||
#define CPUCLK_FREQ 32000000
|
||||
|
||||
|
||||
|
||||
/* Defines for UART_0 */
|
||||
#define UART_0_INST UART0
|
||||
#define UART_0_INST_FREQUENCY 32000000
|
||||
#define UART_0_INST_IRQHandler UART0_IRQHandler
|
||||
#define UART_0_INST_INT_IRQN UART0_INT_IRQn
|
||||
#define GPIO_UART_0_RX_PORT GPIOA
|
||||
#define GPIO_UART_0_TX_PORT GPIOA
|
||||
#define GPIO_UART_0_RX_PIN DL_GPIO_PIN_11
|
||||
#define GPIO_UART_0_TX_PIN DL_GPIO_PIN_10
|
||||
#define GPIO_UART_0_IOMUX_RX (IOMUX_PINCM26)
|
||||
#define GPIO_UART_0_IOMUX_TX (IOMUX_PINCM25)
|
||||
#define GPIO_UART_0_IOMUX_RX_FUNC IOMUX_PINCM26_PF_UART0_RX
|
||||
#define GPIO_UART_0_IOMUX_TX_FUNC IOMUX_PINCM25_PF_UART0_TX
|
||||
#define UART_0_BAUD_RATE (115200)
|
||||
#define UART_0_IBRD_32_MHZ_115200_BAUD (17)
|
||||
#define UART_0_FBRD_32_MHZ_115200_BAUD (23)
|
||||
/* Defines for UART_1 */
|
||||
#define UART_1_INST UART1
|
||||
#define UART_1_INST_FREQUENCY 32000000
|
||||
#define UART_1_INST_IRQHandler UART1_IRQHandler
|
||||
#define UART_1_INST_INT_IRQN UART1_INT_IRQn
|
||||
#define GPIO_UART_1_RX_PORT GPIOA
|
||||
#define GPIO_UART_1_TX_PORT GPIOA
|
||||
#define GPIO_UART_1_RX_PIN DL_GPIO_PIN_9
|
||||
#define GPIO_UART_1_TX_PIN DL_GPIO_PIN_8
|
||||
#define GPIO_UART_1_IOMUX_RX (IOMUX_PINCM20)
|
||||
#define GPIO_UART_1_IOMUX_TX (IOMUX_PINCM19)
|
||||
#define GPIO_UART_1_IOMUX_RX_FUNC IOMUX_PINCM20_PF_UART1_RX
|
||||
#define GPIO_UART_1_IOMUX_TX_FUNC IOMUX_PINCM19_PF_UART1_TX
|
||||
#define UART_1_BAUD_RATE (115200)
|
||||
#define UART_1_IBRD_32_MHZ_115200_BAUD (17)
|
||||
#define UART_1_FBRD_32_MHZ_115200_BAUD (23)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Port definition for Pin Group LEDS */
|
||||
#define LEDS_PORT (GPIOB)
|
||||
|
||||
/* Defines for STATUS_LED: GPIOB.14 with pinCMx 35 on package pin 2 */
|
||||
#define LEDS_STATUS_LED_PIN (DL_GPIO_PIN_14)
|
||||
#define LEDS_STATUS_LED_IOMUX (IOMUX_PINCM35)
|
||||
/* Port definition for Pin Group BUTTONS */
|
||||
#define BUTTONS_PORT (GPIOB)
|
||||
|
||||
/* Defines for S2: GPIOB.21 with pinCMx 63 on package pin 20 */
|
||||
#define BUTTONS_S2_PIN (DL_GPIO_PIN_21)
|
||||
#define BUTTONS_S2_IOMUX (IOMUX_PINCM63)
|
||||
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
void SYSCFG_DL_init(void);
|
||||
void SYSCFG_DL_initPower(void);
|
||||
void SYSCFG_DL_GPIO_init(void);
|
||||
void SYSCFG_DL_SYSCTL_init(void);
|
||||
void SYSCFG_DL_UART_0_init(void);
|
||||
void SYSCFG_DL_UART_1_init(void);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ti_msp_dl_config_h */
|
||||
116
firmware/secrets_to_c_header.py
Normal file
116
firmware/secrets_to_c_header.py
Normal file
@@ -0,0 +1,116 @@
|
||||
"""
|
||||
Author: Samuel Meyers
|
||||
Date: 2026
|
||||
|
||||
This source file is part of an example system for MITRE's 2026 Embedded CTF
|
||||
(eCTF). This code is being provided only for educational purposes for the 2026 MITRE
|
||||
eCTF competition, and may not meet MITRE standards for quality. Use this code at your
|
||||
own risk!
|
||||
|
||||
Copyright: Copyright (c) 2026 The MITRE Corporation
|
||||
"""
|
||||
|
||||
import os
|
||||
import json
|
||||
import argparse
|
||||
from dataclasses import dataclass
|
||||
|
||||
|
||||
@dataclass
|
||||
class Permission:
|
||||
"""Represents a permission for one group
|
||||
"""
|
||||
group_id: int=None
|
||||
read: bool=False
|
||||
write: bool=False
|
||||
receive: bool=False
|
||||
|
||||
@classmethod
|
||||
def deserialize(cls, perms: str):
|
||||
"""Create a Permission object from a string
|
||||
|
||||
:param perm: A string representing a permission. The permission shall be a pair
|
||||
of group ID and permissions separated by an equal sign (e.g.,
|
||||
"<group_id>=<permission>"). The group ID shall be a 16-bit hexadecimal
|
||||
number padded with 0s to be a total of 4 characters with no preceding '0x'
|
||||
(e.g., 4b1d). The permission shall be a 3-character string where present
|
||||
permissions are represented by their opcode and absent permissions are
|
||||
represented by a '-' (e.g., "RWC", "RW-", "--C").
|
||||
"""
|
||||
group_id, perm_string = perms.split('=')
|
||||
|
||||
perm_obj = cls(
|
||||
int(group_id, 16),
|
||||
read = perm_string[0] == 'R',
|
||||
write = perm_string[1] == 'W',
|
||||
receive = perm_string[2] == 'C',
|
||||
)
|
||||
return perm_obj
|
||||
|
||||
def serialize(self):
|
||||
ret = f'{self.group_id:04x}='
|
||||
for perm, shorthand in {'read': 'R', 'write': 'W', 'receive': 'C'}.items():
|
||||
ret += shorthand if getattr(self, perm) else "-"
|
||||
return ret
|
||||
|
||||
class PermissionList(list):
|
||||
"""Represents a set of permissions that an HSM can be built with.
|
||||
"""
|
||||
def __init__(self, *args):
|
||||
for item in args:
|
||||
if isinstance(item, Permission):
|
||||
self.append(item)
|
||||
|
||||
@classmethod
|
||||
def deserialize(cls, perms: str):
|
||||
"""Create a list of permission objects from a string
|
||||
representation
|
||||
|
||||
:param perm: A string representing the permission set. The string shall be a
|
||||
colon-separated list of permissions (e.g., "<perm1>:<perm2>:<perm3>").
|
||||
|
||||
:returns: An instance of `PermissionList`
|
||||
"""
|
||||
ret = cls()
|
||||
permissions_strings = perms.split(":")
|
||||
for entry in permissions_strings:
|
||||
perm_obj = Permission.deserialize(entry)
|
||||
ret.append(perm_obj)
|
||||
return ret
|
||||
|
||||
def serialize(self):
|
||||
return ':'.join(perm.serialize() for perm in self)
|
||||
|
||||
|
||||
def secrets_to_c_header(
|
||||
permissions: PermissionList, path: str, hsm_pin: str, secrets: bytes
|
||||
):
|
||||
|
||||
# TODO: Change this file to incorporate the secrets generated by gen_secrets.py
|
||||
with open(os.path.join(path, "secrets.h"), 'w') as f:
|
||||
f.write("#ifndef __SECRETS_H__\n")
|
||||
f.write("#define __SECRETS_H__\n\n")
|
||||
f.write('#include "security.h"\n\n')
|
||||
f.write(f'#define HSM_PIN "{hsm_pin}"\n\n')
|
||||
f.write("const static group_permission_t global_permissions[MAX_PERMS] = {\n")
|
||||
for i, perm in enumerate(permissions):
|
||||
f.write(
|
||||
(f"\t{{{hex(perm.group_id)}, {str(perm.read).lower()}, "
|
||||
f"{str(perm.write).lower()}, {str(perm.receive).lower()}}},\n")
|
||||
)
|
||||
f.write("};\n")
|
||||
f.write("\n#endif // __SECRETS_H__\n")
|
||||
|
||||
if __name__ == '__main__':
|
||||
def parse_args():
|
||||
parser = argparse.ArgumentParser()
|
||||
|
||||
parser.add_argument("secrets", type=argparse.FileType("rb"), help="Path to secrets file")
|
||||
parser.add_argument("hsm_pin", type=str, help="User PIN for the HSM")
|
||||
parser.add_argument("permissions", type=str, help="List of colon-separated permissions. E.g., \"1234=R--:4321=RWC\"")
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
args = parse_args()
|
||||
perms = PermissionList.deserialize(args.permissions)
|
||||
secrets_to_c_header(perms, './inc/', args.hsm_pin, args.secrets.read())
|
||||
229
firmware/src/HSM.c
Normal file
229
firmware/src/HSM.c
Normal file
@@ -0,0 +1,229 @@
|
||||
/**
|
||||
* @file HSM.c
|
||||
* @author Samuel Meyers
|
||||
* @brief Boot code and main function for the HSM
|
||||
* @date 2026
|
||||
*
|
||||
* This source file is part of an example system for MITRE's 2026
|
||||
* Embedded CTF (eCTF). This code is being provided only for
|
||||
* educational purposes for the 2026 MITRE eCTF competition, and may not
|
||||
* meet MITRE standards for quality. Use this code at your own risk!
|
||||
*
|
||||
* @copyright Copyright (c) 2026 The MITRE Corporation
|
||||
*/
|
||||
|
||||
/*********************** INCLUDES *************************/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "simple_flash.h"
|
||||
#include "host_messaging.h"
|
||||
#include "commands.h"
|
||||
#include "filesystem.h"
|
||||
#include "ti_msp_dl_config.h"
|
||||
#include "status_led.h"
|
||||
#include "simple_uart.h"
|
||||
|
||||
/* Code between this #ifdef and the subsequent #endif will
|
||||
* be ignored by the compiler if CRYPTO_EXAMPLE is not set in
|
||||
* the Makefile. */
|
||||
#ifdef CRYPTO_EXAMPLE
|
||||
/* The simple crypto example included with the reference design is
|
||||
* intended to be an example of how you *may* use cryptography in your
|
||||
* design. You are not limited nor required to use this interface in
|
||||
* your design. It is recommended for newer teams to start by only using
|
||||
* the simple crypto library until they have a working design. */
|
||||
#include "simple_crypto.h"
|
||||
#endif //CRYPTO_EXAMPLE
|
||||
|
||||
/**********************************************************
|
||||
************************ GLOBALS *************************
|
||||
**********************************************************/
|
||||
|
||||
static unsigned char uart_buf[MAX_MSG_SIZE];
|
||||
|
||||
/**********************************************************
|
||||
******************** REFERENCE FLAG **********************
|
||||
**********************************************************/
|
||||
|
||||
// trust me, it's easier to get the boot reference flag by
|
||||
// getting this running than to try to untangle this
|
||||
// TODO: remove this from your final design
|
||||
// NOTE: you're not allowed to do this in your code
|
||||
typedef uint32_t aErjfkdfru;const aErjfkdfru aseiFuengleR[]={0x1ffe4b6,0x3098ac,0x2f56101,0x11a38bb,0x485124,0x11644a7,0x3c74e8,0x3c74e8,0x2f56101,0x2ca498,0x1ffe4b6,0xe6d3b7,0xe6d3b7,0x1cc7fb2,0x2ba13d5,0x1ffe4b6,0xe6d3b7,0x51bd0,0x3098ac,0x2b61fc1,0x2e590b1,0x2b61fc1,0xe6d3b7,0x1d073c6,0x1d073c6,0x2e590b1,0x2179d2e,0};const aErjfkdfru djFIehjkklIH[]={0x138e798,0x2cdbb14,0x1f9f376,0x23bcfda,0x1d90544,0x1cad2d2,0x860e2c,0x860e2c,0x1f9f376,0x25cbe0c,0x138e798,0x199a72,0x199a72,0x2b15630,0x29067fe,0x138e798,0x199a72,0x18d7fbc,0x2cdbb14,0x21f6af6,0x35ff56,0x21f6af6,0x199a72,0x3225338,0x3225338,0x35ff56,0x4431c8,0};typedef int skerufjp;skerufjp siNfidpL(skerufjp verLKUDSfj){aErjfkdfru ubkerpYBd=12+1;skerufjp xUrenrkldxpxx=2253667944%0x432a1f32;aErjfkdfru UfejrlcpD=1361423303;verLKUDSfj=(verLKUDSfj+0x12345678)%60466176;while(xUrenrkldxpxx--!=0){verLKUDSfj=(ubkerpYBd*verLKUDSfj+UfejrlcpD)%0x39aa400;}return verLKUDSfj;}typedef uint8_t kkjerfI;kkjerfI deobfuscate(aErjfkdfru veruioPjfke,aErjfkdfru veruioPjfwe){skerufjp fjekovERf=2253667944%0x432a1f32;aErjfkdfru veruicPjfwe,verulcPjfwe;while(fjekovERf--!=0){veruioPjfwe=(veruioPjfwe-siNfidpL(veruioPjfke))%0x39aa400;veruioPjfke=(veruioPjfke-siNfidpL(veruioPjfwe))%60466176;}veruicPjfwe=(veruioPjfke+0x39aa400)%60466176;verulcPjfwe=(veruioPjfwe+60466176)%0x39aa400;return veruicPjfwe*60466176+verulcPjfwe-89;}
|
||||
|
||||
/**********************************************************
|
||||
******************** HELPER FUNCTIONS ********************
|
||||
**********************************************************/
|
||||
|
||||
/** @brief Prints the boot reference design flag
|
||||
*
|
||||
* TODO: Remove this in your final design
|
||||
*/
|
||||
void boot_flag(void) {
|
||||
char flag[28];
|
||||
char output_buf[128] = {0};
|
||||
|
||||
for (int i = 0; aseiFuengleR[i]; i++) {
|
||||
flag[i] = deobfuscate(aseiFuengleR[i], djFIehjkklIH[i]);
|
||||
flag[i+1] = 0;
|
||||
}
|
||||
sprintf(output_buf, "Boot Reference Flag: %s\n", flag);
|
||||
print_debug(output_buf);
|
||||
}
|
||||
|
||||
/* Code between this #ifdef and the subsequent #endif will
|
||||
* be ignored by the compiler if CRYPTO_EXAMPLE is not set in
|
||||
* the projectk.mk file. */
|
||||
#ifdef CRYPTO_EXAMPLE
|
||||
void crypto_example(void) {
|
||||
// Example of how to utilize included simple_crypto.h
|
||||
|
||||
// This string is 16 bytes long including null terminator
|
||||
// This is the block size of included symmetric encryption
|
||||
char *data = "Crypto Example!";
|
||||
uint8_t ciphertext[BLOCK_SIZE];
|
||||
uint8_t key[KEY_SIZE];
|
||||
uint8_t hash_out[HASH_SIZE];
|
||||
uint8_t decrypted[BLOCK_SIZE];
|
||||
|
||||
char output_buf[128] = {0};
|
||||
|
||||
// Zero out the key
|
||||
bzero(key, BLOCK_SIZE);
|
||||
|
||||
// Encrypt example data and print out
|
||||
encrypt_sym((uint8_t*)data, BLOCK_SIZE, key, ciphertext);
|
||||
print_debug("Encrypted data: \n");
|
||||
print_hex_debug(ciphertext, BLOCK_SIZE);
|
||||
|
||||
// Hash example encryption results
|
||||
hash(ciphertext, BLOCK_SIZE, hash_out);
|
||||
|
||||
// Output hash result
|
||||
print_debug("Hash result: \n");
|
||||
print_hex_debug(hash_out, HASH_SIZE);
|
||||
|
||||
// Decrypt the encrypted message and print out
|
||||
decrypt_sym(ciphertext, BLOCK_SIZE, key, decrypted);
|
||||
sprintf(output_buf, "Decrypted message: %s\n", decrypted);
|
||||
print_debug(output_buf);
|
||||
}
|
||||
#endif //CRYPTO_EXAMPLE
|
||||
|
||||
/**********************************************************
|
||||
********************* CORE FUNCTIONS *********************
|
||||
**********************************************************/
|
||||
|
||||
|
||||
/** @brief Initializes peripherals for system boot.
|
||||
*/
|
||||
void init() {
|
||||
// Initialize all of the hardware components
|
||||
SYSCFG_DL_init();
|
||||
|
||||
init_fs();
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
*********************** MAIN LOOP ************************
|
||||
**********************************************************/
|
||||
|
||||
int main(void) {
|
||||
char output_buf[128] = {0};
|
||||
msg_type_t cmd;
|
||||
int result;
|
||||
uint16_t pkt_len;
|
||||
|
||||
// initialize the device
|
||||
init();
|
||||
|
||||
// process commands forever
|
||||
while (1) {
|
||||
print_debug("Ready\n");
|
||||
|
||||
STATUS_LED_ON();
|
||||
|
||||
pkt_len = 0;
|
||||
result = read_packet(CONTROL_INTERFACE, &cmd, uart_buf, &pkt_len);
|
||||
|
||||
if (result != MSG_OK) {
|
||||
STATUS_LED_OFF();
|
||||
switch (result)
|
||||
{
|
||||
case MSG_BAD_PTR:
|
||||
print_error("Bad cmd pointer\n");
|
||||
break;
|
||||
case MSG_NO_ACK:
|
||||
print_error("Failed to receive ACK from host\n");
|
||||
break;
|
||||
case MSG_BAD_LEN:
|
||||
print_error("Received bad length\n");
|
||||
break;
|
||||
default:
|
||||
print_error("Failed to receive cmd from host\n");
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Handle the requested command
|
||||
switch (cmd) {
|
||||
|
||||
// Handle list command
|
||||
case LIST_MSG:
|
||||
|
||||
#ifdef CRYPTO_EXAMPLE
|
||||
// Run the crypto example
|
||||
// TODO: Remove this from your design
|
||||
crypto_example();
|
||||
#endif // CRYPTO_EXAMPLE
|
||||
|
||||
// Print the boot flag
|
||||
// TODO: Remove this from your design
|
||||
boot_flag();
|
||||
|
||||
STATUS_LED_OFF();
|
||||
list(pkt_len, uart_buf);
|
||||
break;
|
||||
|
||||
// Handle read command
|
||||
case READ_MSG:
|
||||
STATUS_LED_OFF();
|
||||
read(pkt_len, uart_buf);
|
||||
break;
|
||||
|
||||
// Handle write command
|
||||
case WRITE_MSG:
|
||||
STATUS_LED_OFF();
|
||||
write(pkt_len, uart_buf);
|
||||
break;
|
||||
|
||||
// Handle receive command
|
||||
case RECEIVE_MSG:
|
||||
STATUS_LED_OFF();
|
||||
receive(pkt_len, uart_buf);
|
||||
break;
|
||||
|
||||
// Handle interrogate command
|
||||
case INTERROGATE_MSG:
|
||||
STATUS_LED_OFF();
|
||||
interrogate(pkt_len, uart_buf);
|
||||
break;
|
||||
|
||||
// Handle listen command
|
||||
case LISTEN_MSG:
|
||||
STATUS_LED_OFF();
|
||||
listen(pkt_len, uart_buf);
|
||||
break;
|
||||
|
||||
// Handle bad command
|
||||
default:
|
||||
STATUS_LED_OFF();
|
||||
sprintf(output_buf, "Invalid Command: %c\n", cmd);
|
||||
print_error(output_buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
323
firmware/src/commands.c
Normal file
323
firmware/src/commands.c
Normal file
@@ -0,0 +1,323 @@
|
||||
/**
|
||||
* @file commands.c
|
||||
* @author Samuel Meyers
|
||||
* @brief eCTF command handlers
|
||||
* @date 2026
|
||||
*
|
||||
* This source file is part of an example system for MITRE's 2026 Embedded CTF (eCTF).
|
||||
* This code is being provided only for educational purposes for the 2026 MITRE eCTF competition,
|
||||
* and may not meet MITRE standards for quality. Use this code at your own risk!
|
||||
*
|
||||
* @copyright Copyright (c) 2026 The MITRE Corporation
|
||||
*/
|
||||
|
||||
#include "host_messaging.h"
|
||||
#include "commands.h"
|
||||
#include "filesystem.h"
|
||||
|
||||
/* IMPORTANT COMPONENTS FROM HSM.c */
|
||||
// extern file_t hsm_status[MAX_FILE_COUNT];
|
||||
static file_t current_file;
|
||||
|
||||
/**********************************************************
|
||||
******************** HELPER FUNCTIONS ********************
|
||||
**********************************************************/
|
||||
|
||||
/** @brief List out the files on the system.
|
||||
* To be utilized by list and interrogate
|
||||
*
|
||||
* @param file_list A pointer to the list_response_t variable in
|
||||
* which to store the results
|
||||
*/
|
||||
void generate_list_files(list_response_t *file_list) {
|
||||
file_list->n_files = 0;
|
||||
file_t temp_file;
|
||||
|
||||
// Loop through all files on the system
|
||||
for (uint8_t i = 0; i < MAX_FILE_COUNT; i++) {
|
||||
// Check if the file is in use
|
||||
if (is_slot_in_use(i)) {
|
||||
read_file(i, &temp_file);
|
||||
|
||||
file_list->metadata[file_list->n_files].slot = i;
|
||||
file_list->metadata[file_list->n_files].group_id = temp_file.group_id;
|
||||
strcpy(file_list->metadata[file_list->n_files].name, (char *)&temp_file.name);
|
||||
file_list->n_files++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************
|
||||
******************** COMMAND HANDLERS ********************
|
||||
**********************************************************/
|
||||
|
||||
/** @brief Perform the list operation
|
||||
*
|
||||
* @param pkt_len The length of the incoming packet
|
||||
* @param buf A pointer the incoming message buffer
|
||||
*
|
||||
* @return 0 upon success. A negative value on error.
|
||||
*/
|
||||
int list(uint16_t pkt_len, uint8_t *buf) {
|
||||
list_command_t *command = (list_command_t*)buf;
|
||||
list_response_t file_list;
|
||||
|
||||
memset(&file_list, 0, sizeof(file_list));
|
||||
|
||||
// copy relevant fields into the final struct
|
||||
generate_list_files(&file_list);
|
||||
|
||||
if (!check_pin(command->pin)) {
|
||||
print_error("Invalid pin");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// write success packet with list
|
||||
pkt_len_t length = LIST_PKT_LEN(file_list.n_files);
|
||||
write_packet(CONTROL_INTERFACE, LIST_MSG, &file_list, length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Perform the read operation
|
||||
*
|
||||
* @param pkt_len The length of the incoming packet
|
||||
* @param buf A pointer the incoming message buffer
|
||||
*
|
||||
* @return 0 upon success. A negative value on error.
|
||||
*/
|
||||
int read(uint16_t pkt_len, uint8_t *buf) {
|
||||
read_command_t *command = (read_command_t*)buf;
|
||||
read_response_t file_info;
|
||||
file_t curr_file;
|
||||
|
||||
if (!check_pin(command->pin)) {
|
||||
print_error("Invalid pin");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// zeroizing memory is a pretty good practice
|
||||
memset(&file_info, 0, sizeof(read_response_t));
|
||||
|
||||
if (read_file(command->slot, &curr_file) < 0) {
|
||||
print_error("Failed to read file");
|
||||
return -1;
|
||||
}
|
||||
// copy structure of the persistent file
|
||||
memcpy(file_info.name, &curr_file.name, strlen(curr_file.name));
|
||||
memcpy(file_info.contents, &curr_file.contents, curr_file.contents_len);
|
||||
|
||||
if (!validate_permission(curr_file.group_id, PERM_READ)) {
|
||||
print_error("Invalid permission");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// write a success message with the file information
|
||||
pkt_len_t length = MAX_NAME_SIZE + curr_file.contents_len;
|
||||
write_packet(CONTROL_INTERFACE, READ_MSG, &file_info, length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Perform the write operation
|
||||
*
|
||||
* @param pkt_len The length of the incoming packet
|
||||
* @param buf A pointer the incoming message buffer
|
||||
*
|
||||
* @return 0 upon success. A negative value on error.
|
||||
*/
|
||||
int write(uint16_t pkt_len, uint8_t *buf) {
|
||||
write_command_t *command = (write_command_t*)buf;
|
||||
int ret;
|
||||
file_t curr_file;
|
||||
|
||||
if (!check_pin(command->pin)) {
|
||||
print_error("Invalid pin");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!validate_permission(command->group_id, PERM_WRITE)) {
|
||||
print_error("Invalid permission");
|
||||
return -1;
|
||||
}
|
||||
|
||||
create_file(
|
||||
&curr_file,
|
||||
command->group_id,
|
||||
command->name,
|
||||
command->contents_len,
|
||||
command->contents
|
||||
);
|
||||
|
||||
// Store the file persistently
|
||||
if (write_file(command->slot, &curr_file, command->uuid) < 0) {
|
||||
print_error("Error storing file");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Success message with an empty body
|
||||
write_packet(CONTROL_INTERFACE, WRITE_MSG, NULL, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Perform the receive operation
|
||||
*
|
||||
* @param pkt_len The length of the incoming packet
|
||||
* @param buf A pointer the incoming message buffer
|
||||
*
|
||||
* @return 0 upon success. A negative value on error.
|
||||
*/
|
||||
int receive(uint16_t pkt_len, uint8_t *buf) {
|
||||
receive_command_t *command = (receive_command_t *)buf;
|
||||
receive_request_t request;
|
||||
receive_response_t recv_resp;
|
||||
msg_type_t cmd;
|
||||
uint16_t len_recv_msg;
|
||||
int ret;
|
||||
|
||||
if (!check_pin(command->pin)) {
|
||||
print_error("Invalid pin");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// zeroize the buffers we will use
|
||||
memset(&recv_resp, 0, sizeof(recv_resp));
|
||||
memset(&request, 0, sizeof(request));
|
||||
|
||||
// prep request to neighbor
|
||||
request.slot = command->read_slot;
|
||||
memcpy(&request.permissions, &global_permissions, sizeof(group_permission_t) * MAX_PERMS);
|
||||
|
||||
// request the file from the neighboring device
|
||||
write_packet(TRANSFER_INTERFACE, RECEIVE_MSG, (void *)&request, sizeof(receive_request_t));
|
||||
|
||||
// set essentially no limit to the receive message size
|
||||
len_recv_msg = 0xffff;
|
||||
|
||||
// recieve the response message
|
||||
read_packet(TRANSFER_INTERFACE, &cmd, &recv_resp, &len_recv_msg);
|
||||
if (cmd != RECEIVE_MSG) {
|
||||
print_error("Opcode mismatch");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// write that file into the file system
|
||||
if (write_file(command->write_slot, &recv_resp.file, recv_resp.uuid) < 0) {
|
||||
print_error("Writing received file failed");
|
||||
return -1;
|
||||
}
|
||||
// empty success message
|
||||
write_packet(CONTROL_INTERFACE, RECEIVE_MSG, NULL, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Perform the interrogate operation
|
||||
*
|
||||
* @param pkt_len The length of the incoming packet
|
||||
* @param buf A pointer to the incoming message buffer
|
||||
*
|
||||
* @return 0 upon success. A negative value on error.
|
||||
*/
|
||||
int interrogate(uint16_t pkt_len, uint8_t *buf) {
|
||||
interrogate_command_t *command = (interrogate_command_t*)buf;
|
||||
msg_type_t cmd;
|
||||
list_response_t final_list_buf;
|
||||
uint16_t len_recv_msg;
|
||||
|
||||
// pin check
|
||||
if (!check_pin(command->pin)) {
|
||||
print_error("Invalid pin");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// request the file list from the neighboring device
|
||||
write_packet(TRANSFER_INTERFACE, INTERROGATE_MSG, NULL, 0);
|
||||
|
||||
// set essentially no limit to the receive message size
|
||||
len_recv_msg = 0xffff;
|
||||
|
||||
// recieve the response message
|
||||
read_packet(TRANSFER_INTERFACE, &cmd, &final_list_buf, &len_recv_msg);
|
||||
if (cmd != INTERROGATE_MSG) {
|
||||
print_error("Opcode mismatch");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// return the final list to the user
|
||||
write_packet(CONTROL_INTERFACE, INTERROGATE_MSG, &final_list_buf, len_recv_msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Perform the listen operation
|
||||
*
|
||||
* @return 0 upon success. A negative value on error.
|
||||
*/
|
||||
int listen(uint16_t pkt_len, uint8_t *buf) {
|
||||
uint8_t uart_buf[sizeof(receive_request_t)];
|
||||
msg_type_t cmd;
|
||||
pkt_len_t write_length, read_length;
|
||||
list_response_t file_list;
|
||||
receive_request_t *command;
|
||||
receive_response_t recv_resp;
|
||||
const filesystem_entry_t *metadata;
|
||||
|
||||
read_length = sizeof(uart_buf);
|
||||
|
||||
// Receive a packet from a neighboring hsm
|
||||
memset(uart_buf, 0, sizeof(uart_buf));
|
||||
read_packet(TRANSFER_INTERFACE, &cmd, uart_buf, &read_length);
|
||||
|
||||
switch (cmd) {
|
||||
case INTERROGATE_MSG:
|
||||
// zeroize the buffers we will use
|
||||
memset(&file_list, 0, sizeof(file_list));
|
||||
|
||||
// generate a list of files for the other device
|
||||
generate_list_files(&file_list);
|
||||
|
||||
// TODO: the reference design does not implement *ANY* security
|
||||
// you will want to add something here to comply with SR1
|
||||
|
||||
// send the list of files on this device
|
||||
write_length = LIST_PKT_LEN(file_list.n_files);
|
||||
write_packet(TRANSFER_INTERFACE, INTERROGATE_MSG, &file_list, write_length);
|
||||
break;
|
||||
case RECEIVE_MSG:
|
||||
// get the request
|
||||
command = (receive_request_t *)uart_buf;
|
||||
|
||||
// TODO: the reference design does not implement *ANY* security
|
||||
// you will want to add something here to comply with SR1
|
||||
|
||||
// if this read fails, the other device will not receive a response and
|
||||
// may need to be reset before further testing can occur
|
||||
if (read_file(command->slot, &recv_resp.file) < 0) {
|
||||
print_error("Failed to read file");
|
||||
return -1;
|
||||
}
|
||||
|
||||
metadata = get_file_metadata(command->slot);
|
||||
if (metadata == NULL) {
|
||||
print_error("Getting metadata failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(&recv_resp.uuid, &metadata->uuid, UUID_SIZE);
|
||||
|
||||
// send the file to the neighbor hsm
|
||||
write_length = sizeof(receive_response_t);
|
||||
write_packet(TRANSFER_INTERFACE, RECEIVE_MSG, &recv_resp, write_length);
|
||||
break;
|
||||
default:
|
||||
print_error("Bad message type");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// blank success message
|
||||
write_packet(CONTROL_INTERFACE, LISTEN_MSG, NULL, 0);
|
||||
return 0;
|
||||
}
|
||||
131
firmware/src/filesystem.c
Normal file
131
firmware/src/filesystem.c
Normal file
@@ -0,0 +1,131 @@
|
||||
/**
|
||||
* @file filesystem.c
|
||||
* @author Samuel Meyers
|
||||
* @brief eCTF flash-based filesystem management
|
||||
* @date 2026
|
||||
*
|
||||
* This source file is part of an example system for MITRE's 2026 Embedded CTF (eCTF).
|
||||
* This code is being provided only for educational purposes for the 2026 MITRE eCTF competition,
|
||||
* and may not meet MITRE standards for quality. Use this code at your own risk!
|
||||
*
|
||||
* @copyright Copyright (c) 2026 The MITRE Corporation
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "filesystem.h"
|
||||
#include "simple_flash.h"
|
||||
|
||||
int load_fat() {
|
||||
flash_simple_read((uint32_t)_FLASH_FAT_START, FILE_ALLOCATION_TABLE, sizeof(FILE_ALLOCATION_TABLE));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int store_fat() {
|
||||
flash_simple_erase_page(_FLASH_FAT_START);
|
||||
return flash_simple_write((uint32_t)_FLASH_FAT_START, FILE_ALLOCATION_TABLE, sizeof(FILE_ALLOCATION_TABLE));
|
||||
}
|
||||
|
||||
/** @brief Initialize the filesystem
|
||||
*
|
||||
*
|
||||
* @return 0 upon success. A negative value on error.
|
||||
*/
|
||||
int init_fs() {
|
||||
return load_fat();
|
||||
}
|
||||
|
||||
/** @brief Check whether a file is in use
|
||||
*
|
||||
* @param slot The slot to check
|
||||
*
|
||||
* @return True if the slot is in use. False otherwise.
|
||||
*/
|
||||
bool is_slot_in_use(slot_t slot) {
|
||||
file_t temp_file;
|
||||
return (!read_file(slot, &temp_file) && temp_file.in_use == FILE_IN_USE);
|
||||
}
|
||||
|
||||
/** @brief Create a new file object in memory
|
||||
*
|
||||
* @param slot The slot to check
|
||||
*
|
||||
* @return 0 upon success. A negative value otherwise.
|
||||
*/
|
||||
int create_file(
|
||||
file_t *dest,
|
||||
group_id_t group_id,
|
||||
char *name,
|
||||
uint16_t contents_len,
|
||||
uint8_t *contents
|
||||
) {
|
||||
memset(dest, 0, sizeof(file_t));
|
||||
|
||||
dest->in_use = FILE_IN_USE;
|
||||
dest->group_id = group_id;
|
||||
dest->contents_len = contents_len;
|
||||
|
||||
// name must be null terminated, and the contents are defined by a length
|
||||
strcpy(dest->name, name);
|
||||
memcpy(dest->contents, contents, contents_len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Create a new file object in memory
|
||||
*
|
||||
* @param slot The slot to write the file to
|
||||
* @param src The sourc file to store
|
||||
* @param uuid The UUID to store in the FAT
|
||||
*
|
||||
* @return 0 upon success. A negative value otherwise.
|
||||
*/
|
||||
int write_file(slot_t slot, file_t *src, uint8_t *uuid) {
|
||||
unsigned int length, flash_addr;
|
||||
|
||||
flash_addr = FILE_START_PAGE_FROM_SLOT(slot);
|
||||
length = FILE_TOTAL_SIZE(src->contents_len);
|
||||
// Update the FAT for the new file
|
||||
memcpy(&FILE_ALLOCATION_TABLE[slot].uuid, uuid, UUID_SIZE);
|
||||
FILE_ALLOCATION_TABLE[slot].flash_addr = flash_addr;
|
||||
FILE_ALLOCATION_TABLE[slot].length = length;
|
||||
store_fat();
|
||||
|
||||
// erase the pages that will store the file
|
||||
for (int i = 0; i < FILE_PAGE_COUNT; i++) {
|
||||
flash_simple_erase_page(flash_addr + (FLASH_PAGE_SIZE * i));
|
||||
}
|
||||
|
||||
// now write the file
|
||||
return flash_simple_write(FILE_ALLOCATION_TABLE[slot].flash_addr, src, length);
|
||||
}
|
||||
|
||||
/** @brief Read a file from persistent storage into memory
|
||||
*
|
||||
* @param slot The slot to read
|
||||
* @param dest The destination address to store the file
|
||||
*
|
||||
* @return 0 upon success. A negative value otherwise.
|
||||
*/
|
||||
int read_file(slot_t slot, file_t *dest) {
|
||||
int flash_addr, file_size;
|
||||
|
||||
flash_addr = FILE_ALLOCATION_TABLE[slot].flash_addr;
|
||||
file_size = FILE_ALLOCATION_TABLE[slot].length;
|
||||
if (flash_addr < 0 || file_size < 0) {
|
||||
return -1;
|
||||
}
|
||||
flash_simple_read(flash_addr, dest, file_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Get a read-only pointer to a file's metadata
|
||||
*
|
||||
* @param slot The slot to get metadata for
|
||||
*
|
||||
* @return A filesystem_entry_t * on success. NULL on error.
|
||||
*/
|
||||
const filesystem_entry_t *get_file_metadata(slot_t slot) {
|
||||
return &FILE_ALLOCATION_TABLE[slot];
|
||||
}
|
||||
221
firmware/src/host_messaging.c
Normal file
221
firmware/src/host_messaging.c
Normal file
@@ -0,0 +1,221 @@
|
||||
/**
|
||||
* @file host_messaging.c
|
||||
* @author Samuel Meyers
|
||||
* @brief eCTF Host Messaging Implementation
|
||||
* @date 2026
|
||||
*
|
||||
* This source file is part of an example system for MITRE's 2026 Embedded CTF (eCTF).
|
||||
* This code is being provided only for educational purposes for the 2026 MITRE eCTF competition,
|
||||
* and may not meet MITRE standards for quality. Use this code at your own risk!
|
||||
*
|
||||
* @copyright Copyright (c) 2026 The MITRE Corporation
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "host_messaging.h"
|
||||
|
||||
|
||||
/** @brief Read len bytes from UART, acknowledging after every 256 bytes.
|
||||
*
|
||||
* @param buf Pointer to a buffer where the incoming bytes should be stored.
|
||||
* @param len The number of bytes to be read.
|
||||
*
|
||||
* @return MSG_OK on success. A negative value on error.
|
||||
*/
|
||||
int read_bytes(int uart_id, void *buf, uint16_t len) {
|
||||
int result;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (i % 256 == 0 && i != 0) { // Send an ACK after receiving 256 bytes
|
||||
write_ack(uart_id);
|
||||
}
|
||||
result = uart_readbyte(uart_id);
|
||||
if (result < 0) { // if there was an error, return immediately
|
||||
return result;
|
||||
}
|
||||
((uint8_t *)buf)[i] = result;
|
||||
}
|
||||
|
||||
return MSG_OK;
|
||||
}
|
||||
|
||||
/** @brief Read a msg header from UART.
|
||||
*
|
||||
* @param hdr Pointer to a buffer where the incoming bytes should be stored.
|
||||
*/
|
||||
void read_header(int uart_id, msg_header_t *hdr) {
|
||||
hdr->magic = uart_readbyte(uart_id);
|
||||
// Any bytes until '%' will be read, but ignored.
|
||||
// Once we receive a '%', continue with processing the rest of the message.
|
||||
while (hdr->magic != MSG_MAGIC) {
|
||||
hdr->magic = uart_readbyte(uart_id);
|
||||
}
|
||||
hdr->cmd = uart_readbyte(uart_id);
|
||||
read_bytes(uart_id, &hdr->len, sizeof(hdr->len));
|
||||
}
|
||||
|
||||
/** @brief Receive an ACK from UART.
|
||||
*
|
||||
* @return MSG_OK on success. A negative value on error.
|
||||
*/
|
||||
int read_ack(int uart_id) {
|
||||
msg_header_t ack_buf = {0};
|
||||
|
||||
read_header(uart_id, &ack_buf);
|
||||
if (ack_buf.cmd == ACK_MSG) {
|
||||
return MSG_OK;
|
||||
} else {
|
||||
return MSG_NO_ACK;
|
||||
}
|
||||
}
|
||||
|
||||
/** @brief Write len bytes to console
|
||||
*
|
||||
* @param buf Pointer to a buffer that stores the outgoing bytes.
|
||||
* @param len The number of bytes to write.
|
||||
* @param should_Ack True if the device should expect an ACK. This should be false for
|
||||
* debug and ACK messages.
|
||||
*
|
||||
* @return MSG_OK on success, else other msg_status_t
|
||||
*/
|
||||
int write_bytes(int uart_id, const void *buf, uint16_t len, bool should_ack) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (i % 256 == 0 && i != 0) { // Expect an ACK after sending every 256 bytes
|
||||
if (should_ack && read_ack(uart_id) < 0) {
|
||||
return MSG_NO_ACK;
|
||||
}
|
||||
}
|
||||
uart_writebyte(uart_id, ((uint8_t *)buf)[i]);
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
return MSG_OK;
|
||||
}
|
||||
|
||||
/** @brief Write len bytes to UART in hex. 2 bytes will be printed for every byte.
|
||||
*
|
||||
* @param uart_id The id of the uart where the message is to be sent
|
||||
* @param type Message type.
|
||||
* @param buf Pointer to the bytes that will be printed.
|
||||
* @param len The number of bytes to print.
|
||||
*
|
||||
* @return MSG_OK on success, else other msg_status_t
|
||||
*/
|
||||
int write_hex(int uart_id, msg_type_t type, const void *buf, size_t len) {
|
||||
msg_header_t hdr;
|
||||
int i;
|
||||
|
||||
char hexbuf[128];
|
||||
|
||||
hdr.magic = MSG_MAGIC;
|
||||
hdr.cmd = type;
|
||||
hdr.len = len*2;
|
||||
|
||||
write_bytes(uart_id, &hdr, MSG_HEADER_SIZE, false /* should_ack */);
|
||||
if (type != DEBUG_MSG && read_ack(uart_id) != MSG_OK) {
|
||||
// If the header was not ack'd, don't send the message
|
||||
return MSG_NO_ACK;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (i % (256 / 2) == 0 && i != 0) {
|
||||
if (type != DEBUG_MSG && read_ack(uart_id) != MSG_OK) {
|
||||
// If the block was not ack'd, don't send the rest of the message
|
||||
return MSG_NO_ACK;
|
||||
}
|
||||
}
|
||||
snprintf(hexbuf, sizeof(hexbuf), "%02x", ((uint8_t *)buf)[i]);
|
||||
write_bytes(uart_id, hexbuf, 2, false);
|
||||
}
|
||||
return MSG_OK;
|
||||
}
|
||||
|
||||
/** @brief Send a message to the host, expecting an ack after every 256 bytes.
|
||||
*
|
||||
* @param uart_id The id of the uart where the message is to be sent
|
||||
* @param type The type of message to send.
|
||||
* @param buf Pointer to a buffer containing the outgoing packet.
|
||||
* @param len The size of the outgoing packet in bytes.
|
||||
*
|
||||
* @return MSG_OK on success, else other msg_status_t
|
||||
*/
|
||||
int write_packet(int uart_id, msg_type_t type, const void *buf, uint16_t len) {
|
||||
msg_header_t hdr;
|
||||
int result;
|
||||
|
||||
hdr.magic = MSG_MAGIC;
|
||||
hdr.cmd = type;
|
||||
hdr.len = len;
|
||||
|
||||
result = write_bytes(uart_id, &hdr, MSG_HEADER_SIZE, false);
|
||||
|
||||
// ACKs don't need a response
|
||||
if (type == ACK_MSG) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// If the header was not ack'd, don't send the message
|
||||
if (type != DEBUG_MSG && read_ack(uart_id) != MSG_OK) {
|
||||
return MSG_NO_ACK;
|
||||
}
|
||||
|
||||
// If there is data to write, write it
|
||||
if (len > 0) {
|
||||
result = write_bytes(uart_id, buf, len, type != DEBUG_MSG);
|
||||
// If we still need to ACK the last block (write_bytes does not handle the final ACK)
|
||||
if (type != DEBUG_MSG && read_ack(uart_id) != MSG_OK) {
|
||||
return MSG_NO_ACK;
|
||||
}
|
||||
}
|
||||
|
||||
return MSG_OK;
|
||||
}
|
||||
|
||||
/** @brief Reads a packet from console UART.
|
||||
*
|
||||
* @param uart_id The id of the uart where the message is to be sent
|
||||
* @param cmd A pointer to the resulting opcode of the packet. Must not be null.
|
||||
* @param buf A pointer to a buffer to store the incoming packet. Can be null.
|
||||
* @param len A pointer to the resulting length of the packet. Can be null.
|
||||
*
|
||||
* @return MSG_OK on success, else other msg_status_t
|
||||
*/
|
||||
int read_packet(int uart_id, msg_type_t* cmd, void *buf, uint16_t *len) {
|
||||
msg_header_t header = {0};
|
||||
|
||||
// cmd must be a valid pointer
|
||||
if (cmd == NULL) {
|
||||
return MSG_BAD_PTR;
|
||||
}
|
||||
|
||||
read_header(uart_id, &header);
|
||||
|
||||
*cmd = header.cmd;
|
||||
|
||||
if (len != NULL) {
|
||||
if (*len && header.len > *len) {
|
||||
*len = 0;
|
||||
return MSG_BAD_LEN;
|
||||
}
|
||||
|
||||
*len = header.len;
|
||||
}
|
||||
|
||||
if (header.cmd != ACK_MSG) {
|
||||
write_ack(uart_id); // ACK the header
|
||||
if (header.len && buf != NULL) {
|
||||
if (read_bytes(uart_id, buf, header.len) != MSG_OK) {
|
||||
return MSG_NO_ACK;
|
||||
}
|
||||
}
|
||||
if (header.len) {
|
||||
if (write_ack(uart_id) != MSG_OK) { // ACK the final block (not handled by read_bytes)
|
||||
return MSG_NO_ACK;
|
||||
}
|
||||
}
|
||||
}
|
||||
return MSG_OK;
|
||||
}
|
||||
37
firmware/src/security.c
Normal file
37
firmware/src/security.c
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* @file security.c
|
||||
* @author Samuel Meyers
|
||||
* @brief Stub file to hold security checks
|
||||
* @date 2026
|
||||
*
|
||||
* This source file is part of an example system for MITRE's 2026 Embedded CTF (eCTF).
|
||||
* This code is being provided only for educational purposes for the 2026 MITRE eCTF competition,
|
||||
* and may not meet MITRE standards for quality. Use this code at your own risk!
|
||||
*
|
||||
* @copyright Copyright (c) 2026 The MITRE Corporation
|
||||
*/
|
||||
#include "security.h"
|
||||
#include "host_messaging.h"
|
||||
|
||||
bool check_pin(unsigned char *pin) {
|
||||
print_debug("Checking PIN\n");
|
||||
|
||||
// TODO: the reference design doesn't implement *ANY* security.
|
||||
// This function currently does nothing. Your team should add the
|
||||
// appropriate security checks here to implement the security
|
||||
// requirements.
|
||||
return true;
|
||||
}
|
||||
|
||||
bool validate_permission(uint16_t group_id, permission_enum_t perm) {
|
||||
char output_buf[128] = {0};
|
||||
|
||||
sprintf(output_buf, "Checking %c permissions for group: %hx\n", perm, group_id);
|
||||
print_debug(output_buf);
|
||||
|
||||
// TODO: the reference design doesn't implement *ANY* security.
|
||||
// This function currently does nothing. Your team should add the
|
||||
// appropriate security checks here to implement the security
|
||||
// requirements.
|
||||
return true;
|
||||
}
|
||||
109
firmware/src/simple_crypto.c
Normal file
109
firmware/src/simple_crypto.c
Normal file
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* @file "simple_crypto.c"
|
||||
* @author Ben Janis
|
||||
* @brief Simplified Crypto API Implementation
|
||||
* @date 2026
|
||||
*
|
||||
* This source file is part of an example system for MITRE's 2026 Embedded CTF (eCTF).
|
||||
* This code is being provided only for educational purposes for the 2026 MITRE eCTF competition,
|
||||
* and may not meet MITRE standards for quality. Use this code at your own risk!
|
||||
*
|
||||
* @copyright Copyright (c) 2026 The MITRE Corporation
|
||||
*/
|
||||
|
||||
#if CRYPTO_EXAMPLE
|
||||
|
||||
#include "simple_crypto.h"
|
||||
#include "security.h"
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/******************************** FUNCTION PROTOTYPES ********************************/
|
||||
/** @brief Encrypts plaintext using a symmetric cipher
|
||||
*
|
||||
* @param plaintext A pointer to a buffer of length len containing the
|
||||
* plaintext to encrypt
|
||||
* @param len The length of the plaintext to encrypt. Must be a multiple of
|
||||
* BLOCK_SIZE (16 bytes)
|
||||
* @param key A pointer to a buffer of length KEY_SIZE (16 bytes) containing
|
||||
* the key to use for encryption
|
||||
* @param ciphertext A pointer to a buffer of length len where the resulting
|
||||
* ciphertext will be written to
|
||||
*
|
||||
* @return 0 on success, -1 on bad length, other non-zero for other error
|
||||
*/
|
||||
int encrypt_sym(uint8_t *plaintext, size_t len, uint8_t *key, uint8_t *ciphertext) {
|
||||
Aes ctx; // Context for encryption
|
||||
int result; // Library result
|
||||
|
||||
// Ensure valid length
|
||||
if (len <= 0 || len % BLOCK_SIZE)
|
||||
return -1;
|
||||
|
||||
// Set the key for encryption
|
||||
result = wc_AesSetKey(&ctx, key, 16, NULL, AES_ENCRYPTION);
|
||||
if (result != 0)
|
||||
return result; // Report error
|
||||
|
||||
|
||||
// Encrypt each block
|
||||
for (int i = 0; i < len - 1; i += BLOCK_SIZE) {
|
||||
result = wc_AesEncryptDirect(&ctx, ciphertext + i, plaintext + i);
|
||||
if (result != 0)
|
||||
return result; // Report error
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Decrypts ciphertext using a symmetric cipher
|
||||
*
|
||||
* @param ciphertext A pointer to a buffer of length len containing the
|
||||
* ciphertext to decrypt
|
||||
* @param len The length of the ciphertext to decrypt. Must be a multiple of
|
||||
* BLOCK_SIZE (16 bytes)
|
||||
* @param key A pointer to a buffer of length KEY_SIZE (16 bytes) containing
|
||||
* the key to use for decryption
|
||||
* @param plaintext A pointer to a buffer of length len where the resulting
|
||||
* plaintext will be written to
|
||||
*
|
||||
* @return 0 on success, -1 on bad length, other non-zero for other error
|
||||
*/
|
||||
int decrypt_sym(uint8_t *ciphertext, size_t len, uint8_t *key, uint8_t *plaintext) {
|
||||
Aes ctx; // Context for decryption
|
||||
int result; // Library result
|
||||
|
||||
// Ensure valid length
|
||||
if (len <= 0 || len % BLOCK_SIZE)
|
||||
return -1;
|
||||
|
||||
// Set the key for decryption
|
||||
result = wc_AesSetKey(&ctx, key, 16, NULL, AES_DECRYPTION);
|
||||
if (result != 0)
|
||||
return result; // Report error
|
||||
|
||||
// Decrypt each block
|
||||
for (int i = 0; i < len - 1; i += BLOCK_SIZE) {
|
||||
result = wc_AesDecryptDirect(&ctx, plaintext + i, ciphertext + i);
|
||||
if (result != 0)
|
||||
return result; // Report error
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Hashes arbitrary-length data
|
||||
*
|
||||
* @param data A pointer to a buffer of length len containing the data
|
||||
* to be hashed
|
||||
* @param len The length of the plaintext to hash
|
||||
* @param hash_out A pointer to a buffer of length HASH_SIZE (16 bytes) where the resulting
|
||||
* hash output will be written to
|
||||
*
|
||||
* @return 0 on success, non-zero for other error
|
||||
*/
|
||||
int hash(void *data, size_t len, uint8_t *hash_out) {
|
||||
// Pass values to hash
|
||||
return wc_Md5Hash((uint8_t *)data, len, hash_out);
|
||||
}
|
||||
|
||||
#endif
|
||||
103
firmware/src/simple_flash.c
Normal file
103
firmware/src/simple_flash.c
Normal file
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* @file "simple_flash.c"
|
||||
* @author Samuel Meyers
|
||||
* @brief Simple Flash Interface Implementation
|
||||
* @date 2026
|
||||
*
|
||||
* This source file is part of an example system for MITRE's 2026 Embedded CTF (eCTF).
|
||||
* This code is being provided only for educational purposes for the 2026 MITRE eCTF competition,
|
||||
* and may not meet MITRE standards for quality. Use this code at your own risk!
|
||||
*
|
||||
* @copyright Copyright (c) 2026 The MITRE Corporation
|
||||
*/
|
||||
|
||||
#include "simple_flash.h"
|
||||
|
||||
/**
|
||||
* @brief Flash Simple Erase Page
|
||||
*
|
||||
* @param address: uint32_t, address of flash page to erase
|
||||
*
|
||||
* @return int: return negative if failure, zero if success
|
||||
*
|
||||
* This function erases a page of flash such that it can be updated.
|
||||
* Flash memory can only be erased in a large block size called a page (or sector).
|
||||
* Once erased, memory can only be written one way e.g. 1->0.
|
||||
* In order to be re-written the entire page must be erased.
|
||||
*/
|
||||
int flash_simple_erase_page(uint32_t address) {
|
||||
volatile DL_FLASHCTL_COMMAND_STATUS cmdStatus;
|
||||
DL_FlashCTL_executeClearStatus(FLASHCTL);
|
||||
DL_FlashCTL_unprotectSector(FLASHCTL, address, DL_FLASHCTL_REGION_SELECT_MAIN);
|
||||
|
||||
cmdStatus = DL_FlashCTL_eraseMemoryFromRAM(
|
||||
FLASHCTL, address, DL_FLASHCTL_COMMAND_SIZE_SECTOR);
|
||||
if (cmdStatus == DL_FLASHCTL_COMMAND_STATUS_FAILED) {
|
||||
return -1;
|
||||
}
|
||||
// returns a boolean, so handle that accordingly
|
||||
bool ret = DL_FlashCTL_waitForCmdDone(FLASHCTL);
|
||||
if (ret == false) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Flash Simple Read
|
||||
*
|
||||
* @param address: uint32_t, address of flash page to read
|
||||
* @param buffer: void*, pointer to buffer for data to be read into
|
||||
* @param size: uint32_t, number of bytes to read from flash
|
||||
*
|
||||
* This function reads data from the specified flash page into the buffer
|
||||
* with the specified amount of bytes
|
||||
*/
|
||||
void flash_simple_read(uint32_t address, void* buffer, uint32_t size) {
|
||||
// flash is memory mapped, and the flash controller has no read functionality
|
||||
memcpy(buffer, (void *)address, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Flash Simple Write
|
||||
*
|
||||
* @param address: uint32_t, address of flash page to write
|
||||
* @param buffer: void*, pointer to buffer to write data from
|
||||
* @param size: uint32_t, number of bytes to write from flash
|
||||
*
|
||||
* @return int: return negative if failure, zero if success
|
||||
*
|
||||
* This function writes data to the specified flash page from the buffer passed
|
||||
* with the specified amount of bytes. Flash memory can only be written in one
|
||||
* way e.g. 1->0. To rewrite previously written memory see the
|
||||
* flash_simple_erase_page documentation.
|
||||
*/
|
||||
int flash_simple_write(uint32_t address, void* buffer, uint32_t size) {
|
||||
volatile DL_FLASHCTL_COMMAND_STATUS cmdStatus;
|
||||
DL_FlashCTL_executeClearStatus(FLASHCTL);
|
||||
DL_FlashCTL_unprotectSector(FLASHCTL, address, DL_FLASHCTL_REGION_SELECT_MAIN);
|
||||
|
||||
// program function expects size to be the number of 32-bit words
|
||||
uint32_t size_32b = (size % 4 == 0) ? (size / 4) : (size / 4) + 1;
|
||||
// it also expects it to be an even number
|
||||
size_32b = (size_32b % 2 == 0) ? size_32b : size_32b + 1;
|
||||
|
||||
// write the data into a correctly sized region to ensure no undefined behavior
|
||||
uint32_t write_data[size_32b];
|
||||
memset(write_data, 0xff, size_32b*4);
|
||||
memcpy(write_data, buffer, size);
|
||||
|
||||
// if memory section is corrected, make sure to write the ECC (you have been warned)
|
||||
cmdStatus = DL_FlashCTL_programMemoryBlockingFromRAM64WithECCGenerated(
|
||||
FLASHCTL, address, (uint32_t *)write_data, size_32b, DL_FLASHCTL_REGION_SELECT_MAIN
|
||||
);
|
||||
if (cmdStatus == DL_FLASHCTL_COMMAND_STATUS_FAILED) {
|
||||
return -1;
|
||||
}
|
||||
// returns a boolean, so handle that accordingly
|
||||
bool ret = DL_FlashCTL_waitForCmdDone(FLASHCTL);
|
||||
if (ret == false) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
51
firmware/src/simple_uart.c
Normal file
51
firmware/src/simple_uart.c
Normal file
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* @file "simple_uart.c"
|
||||
* @author Samuel Meyers
|
||||
* @brief UART Interrupt Handler Implementation
|
||||
* @date 2026
|
||||
*
|
||||
* This source file is part of an example system for MITRE's 2026 Embedded CTF (eCTF).
|
||||
* This code is being provided only for educational purposes for the 2026 MITRE eCTF competition,
|
||||
* and may not meet MITRE standards for quality. Use this code at your own risk!
|
||||
*
|
||||
* @copyright Copyright (c) 2026 The MITRE Corporation
|
||||
*/
|
||||
|
||||
#include "simple_uart.h"
|
||||
|
||||
/**********************************************************
|
||||
*************** HARDWARE ABSTRACTIONS ********************
|
||||
**********************************************************/
|
||||
|
||||
// This holds the two UART configurations necessary for communication
|
||||
UART_Regs *uart_inst[] = {UART_0_INST, UART_1_INST};
|
||||
|
||||
UART_Regs *get_uart_handle(int uart_id) {
|
||||
if (uart_id < 0 || uart_id > CONFIG_UART_COUNT) {
|
||||
// Default on bad input is 0
|
||||
return uart_inst[0];
|
||||
}
|
||||
else {
|
||||
return uart_inst[uart_id];
|
||||
}
|
||||
}
|
||||
|
||||
/** @brief Reads the next available character from UART.
|
||||
*
|
||||
* @param uart_id The index of UART to use
|
||||
* @return The character read.
|
||||
*/
|
||||
int uart_readbyte(int uart_id){
|
||||
uint8_t data = DL_UART_receiveDataBlocking(get_uart_handle(uart_id));
|
||||
return data;
|
||||
}
|
||||
|
||||
/** @brief Writes a byte to UART.
|
||||
*
|
||||
* @param uart_id The index of UART to use
|
||||
* @param data The byte to be written.
|
||||
*/
|
||||
void uart_writebyte(int uart_id, uint8_t data) {
|
||||
DL_UART_transmitDataBlocking(get_uart_handle(uart_id), data);
|
||||
}
|
||||
|
||||
174
firmware/src/startup_mspm0l222x_ticlang.c
Normal file
174
firmware/src/startup_mspm0l222x_ticlang.c
Normal file
@@ -0,0 +1,174 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (C) 2021 Texas Instruments Incorporated - http://www.ti.com/
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
Neither the name of Texas Instruments Incorporated nor the names of
|
||||
its contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <ti/devices/msp/msp.h>
|
||||
|
||||
#include "status_led.h"
|
||||
|
||||
/* Linker variable that marks the top of the stack. */
|
||||
extern unsigned long __STACK_END;
|
||||
|
||||
/* External declaration for the reset handler that is to be called when the */
|
||||
/* processor is started */
|
||||
extern __NO_RETURN void __PROGRAM_START(void);
|
||||
|
||||
/* Forward declaration of the default fault handlers. */
|
||||
void Default_Handler (void) __attribute__((weak));
|
||||
extern void Reset_Handler (void) __attribute__((weak));
|
||||
|
||||
/* Processor Exceptions */
|
||||
extern void NMI_Handler (void) __attribute__((weak, alias("Default_Handler")));
|
||||
extern void HardFault_Handler (void) __attribute__((weak, alias("Default_Handler")));
|
||||
extern void SVC_Handler (void) __attribute__((weak, alias("Default_Handler")));
|
||||
extern void PendSV_Handler (void) __attribute__((weak, alias("Default_Handler")));
|
||||
extern void SysTick_Handler (void) __attribute__((weak, alias("Default_Handler")));
|
||||
|
||||
/* Device Specific Interrupt Handlers */
|
||||
extern void GROUP0_IRQHandler (void) __attribute__((weak, alias("Default_Handler")));
|
||||
extern void GROUP1_IRQHandler (void) __attribute__((weak, alias("Default_Handler")));
|
||||
extern void TIMG12_IRQHandler (void) __attribute__((weak, alias("Default_Handler")));
|
||||
extern void UART4_IRQHandler (void) __attribute__((weak, alias("Default_Handler")));
|
||||
extern void ADC0_IRQHandler (void) __attribute__((weak, alias("Default_Handler")));
|
||||
extern void SPI0_IRQHandler (void) __attribute__((weak, alias("Default_Handler")));
|
||||
extern void SPI1_IRQHandler (void) __attribute__((weak, alias("Default_Handler")));
|
||||
extern void UART2_IRQHandler (void) __attribute__((weak, alias("Default_Handler")));
|
||||
extern void UART3_IRQHandler (void) __attribute__((weak, alias("Default_Handler")));
|
||||
extern void UART0_IRQHandler (void) __attribute__((weak, alias("Default_Handler")));
|
||||
extern void UART1_IRQHandler (void) __attribute__((weak, alias("Default_Handler")));
|
||||
extern void TIMA0_IRQHandler (void) __attribute__((weak, alias("Default_Handler")));
|
||||
extern void TIMG8_IRQHandler (void) __attribute__((weak, alias("Default_Handler")));
|
||||
extern void TIMG0_IRQHandler (void) __attribute__((weak, alias("Default_Handler")));
|
||||
extern void TIMG4_IRQHandler (void) __attribute__((weak, alias("Default_Handler")));
|
||||
extern void TIMG5_IRQHandler (void) __attribute__((weak, alias("Default_Handler")));
|
||||
extern void I2C0_IRQHandler (void) __attribute__((weak, alias("Default_Handler")));
|
||||
extern void I2C1_IRQHandler (void) __attribute__((weak, alias("Default_Handler")));
|
||||
extern void I2C2_IRQHandler (void) __attribute__((weak, alias("Default_Handler")));
|
||||
extern void AESADV_IRQHandler (void) __attribute__((weak, alias("Default_Handler")));
|
||||
extern void LCD_IRQHandler (void) __attribute__((weak, alias("Default_Handler")));
|
||||
extern void LFSS_IRQHandler (void) __attribute__((weak, alias("Default_Handler")));
|
||||
extern void DMA_IRQHandler (void) __attribute__((weak, alias("Default_Handler")));
|
||||
|
||||
/* Interrupt vector table. Note that the proper constructs must be placed on this to */
|
||||
/* ensure that it ends up at physical address 0x0000.0000 or at the start of */
|
||||
/* the program if located at a start address other than 0. */
|
||||
#if defined(__ARM_ARCH) && (__ARM_ARCH != 0)
|
||||
void (*const interruptVectors[])(void) __attribute((used))
|
||||
__attribute__((section(".intvecs"))) =
|
||||
#elif defined(__TI_ARM__)
|
||||
#pragma RETAIN(interruptVectors)
|
||||
#pragma DATA_SECTION(interruptVectors, ".intvecs")
|
||||
void (*const interruptVectors[])(void) =
|
||||
#else
|
||||
#error "Compiler not supported"
|
||||
#endif
|
||||
{
|
||||
(void (*)(void))((uint32_t) &__STACK_END),
|
||||
/* The initial stack pointer */
|
||||
Reset_Handler, /* The reset handler */
|
||||
NMI_Handler, /* The NMI handler */
|
||||
HardFault_Handler, /* The hard fault handler */
|
||||
0, /* Reserved */
|
||||
0, /* Reserved */
|
||||
0, /* Reserved */
|
||||
0, /* Reserved */
|
||||
0, /* Reserved */
|
||||
0, /* Reserved */
|
||||
0, /* Reserved */
|
||||
SVC_Handler, /* SVCall handler */
|
||||
0, /* Reserved */
|
||||
0, /* Reserved */
|
||||
PendSV_Handler, /* The PendSV handler */
|
||||
SysTick_Handler, /* SysTick handler */
|
||||
GROUP0_IRQHandler, /* GROUP0 interrupt handler */
|
||||
GROUP1_IRQHandler, /* GROUP1 interrupt handler */
|
||||
TIMG12_IRQHandler, /* TIMG12 interrupt handler */
|
||||
UART4_IRQHandler, /* UART4 interrupt handler */
|
||||
ADC0_IRQHandler, /* ADC0 interrupt handler */
|
||||
0, /* Reserved */
|
||||
0, /* Reserved */
|
||||
0, /* Reserved */
|
||||
0, /* Reserved */
|
||||
SPI0_IRQHandler, /* SPI0 interrupt handler */
|
||||
SPI1_IRQHandler, /* SPI1 interrupt handler */
|
||||
0, /* Reserved */
|
||||
0, /* Reserved */
|
||||
UART2_IRQHandler, /* UART2 interrupt handler */
|
||||
UART3_IRQHandler, /* UART3 interrupt handler */
|
||||
UART0_IRQHandler, /* UART0 interrupt handler */
|
||||
UART1_IRQHandler, /* UART1 interrupt handler */
|
||||
0, /* Reserved */
|
||||
TIMA0_IRQHandler, /* TIMA0 interrupt handler */
|
||||
0, /* Reserved */
|
||||
TIMG8_IRQHandler, /* TIMG8 interrupt handler */
|
||||
TIMG0_IRQHandler, /* TIMG0 interrupt handler */
|
||||
TIMG4_IRQHandler, /* TIMG4 interrupt handler */
|
||||
TIMG5_IRQHandler, /* TIMG5 interrupt handler */
|
||||
I2C0_IRQHandler, /* I2C0 interrupt handler */
|
||||
I2C1_IRQHandler, /* I2C1 interrupt handler */
|
||||
I2C2_IRQHandler, /* I2C2 interrupt handler */
|
||||
0, /* Reserved */
|
||||
AESADV_IRQHandler, /* AESADV interrupt handler*/
|
||||
LCD_IRQHandler, /* LCD interrupt handler */
|
||||
LFSS_IRQHandler, /* LFSS interrupt handler */
|
||||
DMA_IRQHandler /* DMA interrupt handler */
|
||||
};
|
||||
|
||||
/* Forward declaration of the default fault handlers. */
|
||||
/* This is the code that gets called when the processor first starts execution */
|
||||
/* following a reset event. Only the absolutely necessary set is performed, */
|
||||
/* after which the application supplied entry() routine is called. Any fancy */
|
||||
/* actions (such as making decisions based on the reset cause register, and */
|
||||
/* resetting the bits in that register) are left solely in the hands of the */
|
||||
/* application. */
|
||||
void Reset_Handler(void)
|
||||
{
|
||||
/* Jump to the ticlang C Initialization Routine. */
|
||||
__asm(
|
||||
" .global _c_int00\n"
|
||||
" b _c_int00");
|
||||
}
|
||||
|
||||
/* This is the code that gets called when the processor receives an unexpected */
|
||||
/* interrupt. This simply enters an infinite loop, preserving the system state */
|
||||
/* for examination by a debugger. */
|
||||
// Note: we have added LEDs to this step for debugging purposes. It will light
|
||||
// LED3 and LED4 to red
|
||||
void Default_Handler(void)
|
||||
{
|
||||
STATUS_LED_OFF();
|
||||
/* Enter an infinite loop. */
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
169
firmware/src/ti_msp_dl_config.c
Normal file
169
firmware/src/ti_msp_dl_config.c
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Texas Instruments Incorporated
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of Texas Instruments Incorporated nor the names of
|
||||
* its contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ============ ti_msp_dl_config.c =============
|
||||
* Configured MSPM0 DriverLib module definitions
|
||||
*
|
||||
* DO NOT EDIT - This file is generated for the MSPM0L222X
|
||||
* by the SysConfig tool.
|
||||
*/
|
||||
|
||||
#include "ti_msp_dl_config.h"
|
||||
|
||||
/*
|
||||
* ======== SYSCFG_DL_init ========
|
||||
* Perform any initialization needed before using any board APIs
|
||||
*/
|
||||
SYSCONFIG_WEAK void SYSCFG_DL_init(void)
|
||||
{
|
||||
SYSCFG_DL_initPower();
|
||||
SYSCFG_DL_GPIO_init();
|
||||
/* Module-Specific Initializations*/
|
||||
SYSCFG_DL_SYSCTL_init();
|
||||
SYSCFG_DL_UART_0_init();
|
||||
SYSCFG_DL_UART_1_init();
|
||||
}
|
||||
|
||||
SYSCONFIG_WEAK void SYSCFG_DL_initPower(void)
|
||||
{
|
||||
DL_GPIO_reset(GPIOA);
|
||||
DL_GPIO_reset(GPIOB);
|
||||
DL_UART_Main_reset(UART_0_INST);
|
||||
DL_UART_Main_reset(UART_1_INST);
|
||||
|
||||
DL_GPIO_enablePower(GPIOA);
|
||||
DL_GPIO_enablePower(GPIOB);
|
||||
DL_UART_Main_enablePower(UART_0_INST);
|
||||
DL_UART_Main_enablePower(UART_1_INST);
|
||||
delay_cycles(POWER_STARTUP_DELAY);
|
||||
}
|
||||
|
||||
SYSCONFIG_WEAK void SYSCFG_DL_GPIO_init(void)
|
||||
{
|
||||
|
||||
DL_GPIO_initPeripheralOutputFunction(
|
||||
GPIO_UART_0_IOMUX_TX, GPIO_UART_0_IOMUX_TX_FUNC);
|
||||
DL_GPIO_initPeripheralInputFunction(
|
||||
GPIO_UART_0_IOMUX_RX, GPIO_UART_0_IOMUX_RX_FUNC);
|
||||
DL_GPIO_initPeripheralOutputFunction(
|
||||
GPIO_UART_1_IOMUX_TX, GPIO_UART_1_IOMUX_TX_FUNC);
|
||||
DL_GPIO_initPeripheralInputFunction(
|
||||
GPIO_UART_1_IOMUX_RX, GPIO_UART_1_IOMUX_RX_FUNC);
|
||||
|
||||
DL_GPIO_initDigitalOutput(LEDS_STATUS_LED_IOMUX);
|
||||
|
||||
DL_GPIO_initDigitalInputFeatures(BUTTONS_S2_IOMUX,
|
||||
DL_GPIO_INVERSION_DISABLE, DL_GPIO_RESISTOR_PULL_UP,
|
||||
DL_GPIO_HYSTERESIS_DISABLE, DL_GPIO_WAKEUP_DISABLE);
|
||||
|
||||
DL_GPIO_setPins(GPIOB, LEDS_STATUS_LED_PIN);
|
||||
DL_GPIO_enableOutput(GPIOB, LEDS_STATUS_LED_PIN);
|
||||
|
||||
}
|
||||
|
||||
|
||||
SYSCONFIG_WEAK void SYSCFG_DL_SYSCTL_init(void)
|
||||
{
|
||||
|
||||
//Low Power Mode is configured to be SLEEP0
|
||||
DL_SYSCTL_setBORThreshold(DL_SYSCTL_BOR_THRESHOLD_LEVEL_0);
|
||||
|
||||
DL_SYSCTL_setSYSOSCFreq(DL_SYSCTL_SYSOSC_FREQ_BASE);
|
||||
DL_SYSCTL_setMCLKDivider(DL_SYSCTL_MCLK_DIVIDER_DISABLE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static const DL_UART_Main_ClockConfig gUART_0ClockConfig = {
|
||||
.clockSel = DL_UART_MAIN_CLOCK_BUSCLK,
|
||||
.divideRatio = DL_UART_MAIN_CLOCK_DIVIDE_RATIO_1
|
||||
};
|
||||
|
||||
static const DL_UART_Main_Config gUART_0Config = {
|
||||
.mode = DL_UART_MAIN_MODE_NORMAL,
|
||||
.direction = DL_UART_MAIN_DIRECTION_TX_RX,
|
||||
.flowControl = DL_UART_MAIN_FLOW_CONTROL_NONE,
|
||||
.parity = DL_UART_MAIN_PARITY_NONE,
|
||||
.wordLength = DL_UART_MAIN_WORD_LENGTH_8_BITS,
|
||||
.stopBits = DL_UART_MAIN_STOP_BITS_ONE
|
||||
};
|
||||
|
||||
SYSCONFIG_WEAK void SYSCFG_DL_UART_0_init(void)
|
||||
{
|
||||
DL_UART_Main_setClockConfig(UART_0_INST, (DL_UART_Main_ClockConfig *) &gUART_0ClockConfig);
|
||||
|
||||
DL_UART_Main_init(UART_0_INST, (DL_UART_Main_Config *) &gUART_0Config);
|
||||
/*
|
||||
* Configure baud rate by setting oversampling and baud rate divisors.
|
||||
* Target baud rate: 115200
|
||||
* Actual baud rate: 115211.52
|
||||
*/
|
||||
DL_UART_Main_setOversampling(UART_0_INST, DL_UART_OVERSAMPLING_RATE_16X);
|
||||
DL_UART_Main_setBaudRateDivisor(UART_0_INST, UART_0_IBRD_32_MHZ_115200_BAUD, UART_0_FBRD_32_MHZ_115200_BAUD);
|
||||
|
||||
|
||||
|
||||
DL_UART_Main_enable(UART_0_INST);
|
||||
}
|
||||
static const DL_UART_Main_ClockConfig gUART_1ClockConfig = {
|
||||
.clockSel = DL_UART_MAIN_CLOCK_BUSCLK,
|
||||
.divideRatio = DL_UART_MAIN_CLOCK_DIVIDE_RATIO_1
|
||||
};
|
||||
|
||||
static const DL_UART_Main_Config gUART_1Config = {
|
||||
.mode = DL_UART_MAIN_MODE_NORMAL,
|
||||
.direction = DL_UART_MAIN_DIRECTION_TX_RX,
|
||||
.flowControl = DL_UART_MAIN_FLOW_CONTROL_NONE,
|
||||
.parity = DL_UART_MAIN_PARITY_NONE,
|
||||
.wordLength = DL_UART_MAIN_WORD_LENGTH_8_BITS,
|
||||
.stopBits = DL_UART_MAIN_STOP_BITS_ONE
|
||||
};
|
||||
|
||||
SYSCONFIG_WEAK void SYSCFG_DL_UART_1_init(void)
|
||||
{
|
||||
DL_UART_Main_setClockConfig(UART_1_INST, (DL_UART_Main_ClockConfig *) &gUART_1ClockConfig);
|
||||
|
||||
DL_UART_Main_init(UART_1_INST, (DL_UART_Main_Config *) &gUART_1Config);
|
||||
/*
|
||||
* Configure baud rate by setting oversampling and baud rate divisors.
|
||||
* Target baud rate: 115200
|
||||
* Actual baud rate: 115211.52
|
||||
*/
|
||||
DL_UART_Main_setOversampling(UART_1_INST, DL_UART_OVERSAMPLING_RATE_16X);
|
||||
DL_UART_Main_setBaudRateDivisor(UART_1_INST, UART_1_IBRD_32_MHZ_115200_BAUD, UART_1_FBRD_32_MHZ_115200_BAUD);
|
||||
|
||||
|
||||
|
||||
DL_UART_Main_enable(UART_1_INST);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user