Bermet Talantbekova's Notebook - cps-vip/cps-cosimulation-env GitHub Wiki

Spring 2026

Week 15

Final presentation demo and preparation for the report

Week 13

An additional set of 20 trials was completed on both the 1724 and 5223 STM32 boards, further expanding the dataset and improving the overall reliability of the measurements. Increasing the number of trials helps reduce the impact of randomness and provides a clearer picture of the stability and repeatability of the PUF responses across multiple evaluations.

Alongside data collection, the existing Python scripts used for PUF analysis were significantly enhanced. The updated scripts now compute more detailed metrics, including the average bit instability for each board and the intra-chip Hamming distance represented as a percentage. These additions make it easier to quantify how much variation exists within a single device over time, which is crucial for understanding noise characteristics and determining how much error correction will be required in later stages.

Following a discussion with Hayden, it was confirmed that BCH codes are a well-suited choice for the error-correcting component of the system due to their effectiveness in handling random bit errors commonly observed in PUF outputs. With this direction established, the next phase will focus on selecting appropriate BCH parameters, such as block size and error correction capability, based on the instability metrics gathered from the experiments. This will enable a more informed and optimized implementation of the fuzzy extractor moving forward.

Week 12

Began setting up a Rust-based framework for a fuzzy extractor. Progress is somewhat blocked until an appropriate error-correcting code (ECC) is selected.

Week 11

Spring break

Week 10

All scripts and CVS can be found on https://github.com/btalantbekova3/pufs/tree/bermet/puf_memory_analyzer under Bermet branch.

Main goal is to write program to count how many times a bit is a 0 vs a 1 for each bit then compare across runs on the same board and runs across different boards. For each board folder (1724_SRAM4_data and 5223_SRAM4_data), it reads all .bits files, counts zeros and ones per bit position, and writes a CSV file with columns:

  • bit_position (index of the bit, starting at 0)
  • zeros_count (how many trials had a 0 at this bit in 20 trials)
  • ones_count (how many trials had a 1)
  • majority ('0', '1', or 'equal' on 20 trials)
  • stability (fraction of trials where the majority value occurs)
image image image
  • match = yes → both boards have the same majority (both 0 or both 1).
  • match = no → the majority values differ (one board has 0, the other has 1).

Week 9

Main goal is to write python script to parse out all of the logger info in the text files and leave just the memory in bits instead of bytes

image

Files are located in https://github.com/cps-vip/pufs

image

Successfully converted

image

Week 8- Week 14

image

We have done

  • Dump SRAM contents (specifically bottom half of 4th SRAM on STM32)
  • Run it ~20 times per board
  • Collect logs (memory dumps in files)
  • Separate data by board (using 4-digit labels)

Week 7

Experiment 1 - SRAM Startup Pattern Stability Measure SRAM bits at power-up and check stability across multiple boots.

Experiment 2 - Environmental Stress Effects Test SRAM under different temperatures (cold, normal, hot) and voltages; see if bits flip.

Experiment 3 - Randomness Test Use SRAM dumps to check if bits form a good random number source

*Task 1 - Learn Rust and Embedded RustStatus: In progress. Team members are individually learning Rust using Rustlings *Task 2 - Run Experiments on the STM32 SRAM: --> Run a series of experiments to validate the randomness and quality of the STM32 SRAM in preparation to building a PUF.

  • Task 3 - Develop a PUF-Based Key Generation System: --> Implement SRAM-PUF–derived key generation on a Raspberry Pi STM32 and use the keys to protect stored data.

Week 6

Main language is gonna be RUST language Possible tutorials :

Planing on meeting up for the midterm presentations

We have 2 of STM32 delivered

Week 5

Next steps

VIP Steps once we recieve SMPT32 Write code SMPT32, make sure to have good memory allocation both for the program,

  • Randomness !!

  • Create a program that creates the randomness

  • Get content of the more out of laptop —> Via debugging cable to print all bits—> use Python script to read the statistical analysis

  • How random is it?

  • Make sure to have pace for the linker file

  • Draw heat map manifacutirng defects in certain parts of the the chips, fussier —> not as good, this bit are either all 1 or 0 all across the part, draw a box -- cluster bias in certain direction

  • Working on research and early discoveries on papers related to the PUFS

  • Intrinsic ID's SRAM PUF white paper

  • A Proof of Concept SRAM-based Physically Unclonable Function (PUF) Key Generation Mechanism for IoT Devices

  • Since ROS/HELICS team has decided tow work on SRAM on a STM32 micro controller.

The downside is that learning embedded Rust and the STM32 framework is IMO a much higher learning curve than using SPI on a Raspberry PI.

Week 3

As team we work = presentations and did presentation on Thursday,

Week 2

Team decided to meet virtually on Sunday

I worked on how False Injection can be used in Power grids

Using links :https://csrc.nist.rip/CSRC/media/Presentations/False-Data-Injection-Attacks-in-Smart-Grid-Challe/images-media/presentation-10_yu.pdf

FDI are carried out by compromising grid sensor to inject malicious data (data is mathematically consistent) or follow the physics) into the power system state estimation . Attacker needs to know grid topology, all sensors and meters (RTUs and PMUs) Since power grids have a lot of noise when receiving signals, standard detection only looks for the difference in “residual” which is equal to a= HC, where H→ network topology, c → desired change state

image
  • z → data coming from sensors(PMUs) about flow and voltage
  • H → grids structure, map that explain how one change on part of the grade affects other part
  • x → actual reality of the grid(voltage) that operator is figuring out
  • e → error, natural noise, small mistakes from sensors

An attacker uses a= HC

  • c → targeted lie (10 % higher the voltage)
  • a→ injectio vector ( by multiplying the lie with map H, attacker has fake data package)

Week 1

Planning with team members to work on meeting times with teams, and refining what task we could work this semester

  • PUF (Physical Unclonable Functions)
  • Fault Injection
  • Side-channel Attacks
  • disk encryption

Fall 2025

Week 12

We will be working off the branch "callback is not working " on repo https://github.com/cps-vip/dnp3-example/blob/callback_not_working/c_api_example/dnp3-module/devices/master.py

  • Binary Input (partially done)
  • Double-bit Binary Input
  • Binary Output Status
  • Counter
  • Frozen Counter
  • Analog Input
  • Analog Output Status
  • Octet Strings
  • String Attributes

For each data type, we need to:

  1. Extract the data from the DNP3 iterator
  2. Convert to Python objects
  3. Call the appropriate Python callback

Week 11

Installation Steps

Clone this repo: git clone https://github.com/cps-vip/cps-cosimulation-env.git Go into the repo: cd cps-cosimulation-env Switch to the Networking_team branch: git switch Networking_team Update the Git submodules: git submodule update --init --recursive Build the Docker image: docker build --platform=linux/amd64 -t cps-cosimulation-env:latest . Run the Docker container: docker run -it --rm --name cps-vip --platform linux/amd64 -v .:/home/vip/cps-cosimulation-env cps-cosimulation-env:latest /bin/bash Run the one-time setup script: ./setup.sh. Warning - this will take a long time.

image

Running into the issue after running the command docker run -it --rm --name cps-vip --platform linux/amd64 -v .:/home/vip/cps-cosimulation-env cps-cosimulation-env:latest /bin/bash

Week 9

image Working on installing ROS-HELICS Docker container with both the cps-cosimulation-env repo and dnp3-example repo.

Week 8 Midterm Paper

Following the DNP3 implementation guide, this means configuring our outstation servers with a specific TlsServerConfig. This isn't just an abstract concept; it involves concrete setup steps:

  • Certificate-Based Authentication: Each outstation will be configured with its own unique X.509 certificate and private key, typically loaded from PEM files on the server's filesystem.

-- Example: An outstation for a "Circuit Breaker 1A" would load its identity from breaker_1a_cert.pem and breaker_1a_key.pem.

  • Enforcing Mutual Authentication: The real security boost comes from configuring mutual TLS. The outstation's TLS configuration will have the peer_cert_path parameter set, pointing to a file containing the Certificate Authority (CA) that issued the master station's certificate.

-- Example: The outstation is configured with peer_cert_path = "trusted_master_ca.pem". When a master connects, the outstation will verify that the master's certificate is signed by this trusted CA. This two-way check ensures only authorized masters can connect, effectively locking out impersonators.

  • Control Over Protocols and Encryption: We can enforce modern security standards by configuring the TLS server to use specific protocols like TLS 1.2 and strong cipher suites that support Forward Secrecy. This ensures that each session uses a unique key, so a compromised long-term key cannot decrypt past communications.

Week 7

https://www.overleaf.com/9167837843pcxktnzrqdsg#c007bd

This link how to configure a DNP3 outstation to act as a TLS server, enabling secure encrypted communications between masters and outstations.

Core Requirements:

  • Must create a TlsServerConfig object
  • Need X.509 certificate and private key files (PEM format)
  • Can enable mutual authentication (client certificate verification)
  • Server Configuration:

text TlsServerConfig {
certificate_path: "server_cert.pem",
private_key_path: "server_key.pem",
peer_cert_path: "client_ca.pem" // for mutual auth. }. Security Features:

  • Supports TLS 1.2 and TLS 1.3
  • Configurable cipher suites
  • Optional mutual certificate authentication
  • Certificate chain verification

Implementation Flow:

  1. Load server certificate and private key
  2. Optionally configure client CA for mutual auth
  3. Create TLS server configuration
  4. Apply to outstation connection
  5. Outstation now accepts only TLS-secured connections. Key Benefit: Provides transport-layer encryption that secures the entire DNP3 session, not just application data.

Week 6

Today I worked with the c_api_example/dnp3-module to understand how the fault handling works. I tried to set up the fault dump, but the module did not behave as expected. The current problem seems to be with how the fault is being triggered or logged, and I need to trace the flow to see where it breaks. The next step will be to check the module configuration and review the debug logs to pinpoint the root cause of the fault.

Week 5

Kaden and I worked on duplicating the set fault problem with Python Threading on virtual env image image

Week 4

Me and Alex with help of Kaden are worked on figuring out the segfaulting issue with the extension module. https://github.com/cps-vip/dnp3-example/tree/callback_not_working

We followed the steps for the README in the c_api_example/dnp3-module directory in a Linux VM.

Week 3

Worked on goals for the networking team to work on this semester. With new cybersecurity team we decided to work on what our "Threat Objectives" are The reason we do this is because we do not have luxury to protect substation with every portable threats Out LONG-TERM goals for this semester:

  1. Accurately model all communication within a substation

  2. Model inter-substation and inter-protocol communication

  3. Research substation network security

  4. Develop novel security approaches

Out SHORT-TERM goals for this semester:

  1. Design and implement DNP3 outstation API in cosimulation repository

  2. Architect network structure within substation

  3. Integrate communication with HELICS

  4. Work with device modeling team to accurately model behavior of Master

Week 2

We went through overall introduction to the power grid system

  • Transmission --> done via PyPower
  • Substation --> done via
  • Distribution --> done via Grid lab D
  • Broker --> responsible for managing all three above.
  • Communication --> Helicks

Spring 2025

Week 1

  • 1st meeting on Thursday, 1/9

Introduction to team; joined the Discord Server and completed the welcome quiz Learned basics about power grid and maintenance

  • Individual time

Read through syllabus; added important dates to calendar

Week 2

  • 2nd meeting on Thursday, 1/16

Joined the Device Modeling sub-team, chose extra meeting date (Firdays, 4pm)

  • Introduction to kick-off presentation requirements

Learned more about specific tasks within Overall team ROS (robot operating system simulator) HELICS (program that coordinates and interfaces other simulation programs) Gridlab D (physics simulator) Gazebo (physical visualization simulator) Individual time

Week 3

  • Task 1 - DNP3 Documantation

Kaden provided a reading for DNP3, to gain better understanding of DNP3 protocol, library, and usage.

DNP3 Documantation

  • Goal - Model how networking works in a substation (and potentially between multiple substations). The long term goal is to do security research on substation networking, but that will come after we've established an accurate simulation.

Quick run down on OSI layers

image

DNP3

DNP3 is a specialized networking protocol made for communication within a substation. We use DNP3 over the TCP/IP stack, but DNP3 can also run independently of TCP/IP, using its own link layer and transport layer. DNP3 packets still contain this link and transport layer information as a historic relic.

  • Important Links

Networking branch - https://github.com/cps-vip/cps-cosimulation-env/tree/Networking_team

image

Master file - https://github.com/cps-vip/cps-cosimulation-env/blob/Networking_team/device_modeling/src/station_level/master.py

image

Outstation - https://github.com/cps-vip/cps-cosimulation-env/blob/Networking_team/device_modeling/src/dnp3/dnp3_outstation.py

image

There are two ways to call the Rust library from Python:

  1. Use a third-party library like PyO3 and Maturin to directly call Rust from Python, or
  2. Utilize one of the existing foreign function interfaces (FFI)

Kaden used the 2nd option

The Rust library exposes functions that you can call from C, which we then call from Python. Kaden created an example repo to demonstrate this working.

image

Where to Start

  • While not necessary for what we are doing, get the simple_gridlabd_example working (see the instructions on the main README for this repo) - WORKING
  • Read up on the OSI model and TCP/IP basics if you aren’t already familiar - DONE
  • Learn the basics of DNP3 Take a look at the Rust library's documentation - WORKING
  • Understand what's happening in the DNP3 example repo -

Potential Areas of Work

Understanding DNP3 better - Most of the stuff we’ve worked on so far hasn’t required knowing how you use DNP3 in practice since the Rust library handles all of that for us. Having someone proficient in DNP3 would be extremely useful, even if it’s just to explain details to the people who will be implementing it.

Python API and Implementation - We need to determine how a substation device will interface with the Rust library. This involves creating more methods in the Outstation class that individual devices can call.

C work - Since we call the Rust library through the C FFI, we need to do some work in C. This mostly involves wrapping the existing C functions in a way that’s easier to call from Python.

HELICS integration - Somehow, the substation needs to communicate with the rest of the cosimulation through HELICS. We need to determine how to do this. For example, does every substation device publish to HELICS, or does everything go through the Master station? Another problem here is timing - we want DNP3 timestamps to be consistent with the rest of the cosimulation.

Human-Machine Interface - Real substations have GUIs to interact with the devices in the substation. Currently, we have no progress or even a starting point for this, but it will need to be done at some point.

Inter-substation and inter-protocol communication - So far, we are building code around one substation and one communication protocol. In the future, we may want to be able to model multiple substations and other protocols. The current design accommodates inter-substation communication by having the Master inherit from the Substation class, and inter-protocol communication can be done through a data concentrator device. This is long-term and so lower priority.

DNP3- Research

DNP3 (Distributed Network Protocol) is a communication protocol for SCADA systems in utilities (electric, water).

  • Efficient: Handles large data with low latency.
  • Reliable: Ensures error-checked, validated data.
  • Interoperable: Connects devices from different manufacturers.
  • Secure: Modern versions support encryption/authentication.

DNP3 (Distributed Network Protocol) is like the “language” that devices in a utility network (power, water, etc.) use to talk to each other. It’s commonly used in SCADA systems (those big control systems that keep critical infrastructure running).

  1. Using DNP3 in Python: Substation devices are programmed in Python. To use DNP3 with Python, they needed a library. Two libraries existed before: dnp3-python and pydnp3. Both relied on a tool called opendnp3, but that tool was discontinued in 2022.

  2. Switch to Rust: The maintainers of opendnp3 (Step Function I/O) created a new library written in Rust, called simply DNP3. Since there wasn’t a direct way to use this new Rust-based library in Python, the team decided to build a Python wrapper for it.

  3. How did they connect Rust to Python? They used an FFI (Foreign Function Interface) approach. This means they treated the Rust library as if it were a C library (because Rust can expose C-compatible functions). Then, Python can call those C functions, indirectly using Rust.

DEVICES ??????? What Devices, or devices that Chungman and Maria are working on?

  • sensors
  • breakers
  • other control devices used in utilities like electricity and water systems.

Master: This is the central controller or device that sends requests for data and controls the outstations. Outstation: These are the field devices (sensors, relays, remote terminal units) that respond to requests from the master. They collect and report data such as temperatures, voltages, etc.

Data Points

  1. binaryValue (c_bool): (1 for ON, 0 for OFF).
  2. doubleBitBinaryValue (c_uint32): An enumerated value (usually 0-3)
  3. binaryOutputStatusValue (c_bool): Similar to binaryValue but (ON or OFF).
  4. counterValue (c_uint32): A 32-bit unsigned integer, representing a counter
  5. frozenCounterValue (c_uint32): Similar to counterValue, but the counter is "frozen" (i.e., a snapshot of the counter's value taken at a certain time).
  6. analogValue (c_double): A double-precision floating-point value representing analog measurements, such as temperature, voltage, etc.
  7. analogOutputStatusValue (c_double): Similar to analogValue, but for analog outputs. It can represent things like the current output status of a control.

MASTER DNP3

  • The client_state_on_change callback handles client state changes, which prints the new state whenever it changes.
  • The port_state_on_change callback is structured well for printing port state changes STEP 1
image

Week 4

Working on Example

  • downloaded Cmake
image - Countered issues being not compatible MAC architecture image

Runing grid-lab

  • nix flake issue with M3 chip, even if I have permissions set image

image

Bash & zsh Terminals

Basic Navigation & File Management

  • pwd Print the current directory.
  • ls List files in the directory.
  • ls -la List all files, including hidden, with details.
  • cd Change directory.
  • cd - Go back to the last directory.
  • mkdir Create a new directory.
  • touch Create an empty file.
  • rm Remove a file.
  • rm -rf Force delete a directory and its contents.
  • cp Copy files or directories.
  • mv Move or rename files.

Process Management

  • top or htop. Display active processes (htop is more user-friendly).
  • kill . Terminate a process by PID.
  • kill -9 Force kill a process.
  • jobs List background jobs.
  • fg <job_id> Bring a background job to the foreground.
  • bg <job_id>. Resume a job in the background.
  • nohup & Run a command immune to logouts.

Netwokring commands

  • curl -O Download a file from a URL.
  • wget Another way to download files.
  • ping Test connectivity to a host.
  • traceroute Show the route packets take to a host.
  • netstat -tulnp Show open ports.

Basic Network Information

ifconfig # Show network interfaces (deprecated, use ip instead) ip a # Display IP addresses and interfaces ip r # Show routing table hostname -I # Show local IP address whois # Get WHOIS information of a domain dig # Get DNS records of a domain nslookup # Query a domain’s IP address arp -a # Show ARP table (IP-MAC mappings) iwconfig # Show wireless interface details (for Wi-Fi)

Network Scanning & Analysis

  • nmap -sP 192.168.1.0/24 # Scan active devices in a subnet
  • nmap -sV # Scan open ports and detect service versions
  • nmap -A # Run aggressive scan (detect OS, services)
  • tcpdump -i eth0 # Capture packets on interface eth0
  • tcpdump -nn port 80 # Capture HTTP traffic
  • wireshark # Open Wireshark (GUI packet analyzer)
  • netstat -tulnp # Show all listening ports and associated processes
  • ss -tulnp # Faster alternative to netstat
  • lsof -i :80 # List processes using port 80

Network Troubleshooting

  • ping # Check if a host is reachable
  • traceroute # Show the path packets take
  • mtr # Real-time traceroute with stats
  • curl -I # Get HTTP headers of a URL
  • wget --spider # Check if a website is accessible
  • telnet # Test if a port is open
  • nc -zv # Another way to check if a port is open
  • ethtool eth0 # Get information about Ethernet interfaces
  • ip link set eth0 down # Disable an interface
  • ip link set eth0 up # Enable an interface

Week 5

The files are hosted on my personal GT OneDrive since nowhere else has >2GB for free. Download the files there.

Steps (Linux or Mac)

  • Make scripts executable: chmod +x run.sh connect.sh

  • Make a directory for sharing files between the host and VM: mkdir share

  • In the first terminal, type ./run.sh share/

  • In the second terminal, type ./connect.sh

  • You should now be logged into the VM. Type ls -la and you should see some files already there named setup_linux.sh, setup_mac.sh, and setup_windows.sh.

  • If on Linux, run ./setup_linux.sh. If on Mac, run ./setup_mac.sh.

  • It will prompt for your password. Enter networking.

  • If nothing happens, then you are good. That setup script should've activated the share directory, so test it out by doing touch share/test.

  • Now, on your host machine, navigate to the same directory you've been working out of (the one with the directory named share that we created in step 4). Look inside that share directory, and you should see a file named test. This is the same one we created in step 12, which means that the shared directory between the host and VM is working. Everything is good to go. Keep the first terminal open (the one that says "Welcome to Grub!") in the background. This is running your VM in the background, while the second terminal is ssh'd into it.

dnp-example

Install basic tools we need to run the example sudo apt update sudo apt install git gcc g++ cmake -y

Clone the repo and change directory into it git clone https://github.com/cps-vip/dnp3-example.git cd dnp3-example/default_example

Create a build directory for CMake to place its files mkdir build cd build

Build the project make .. make

From here, you will need to open another terminal through ssh. This means repeating steps 2, 6, 7, and 8 to get another terminal open. In that newly connected terminal, run these commands: cd dnp3-example/default_example/build ./outstation_example TCP

Now in the other terminal, run this: ./master_example TCP

If you see a bunch of text on both terminals, then the example is working. Press Ctrl+c on both terminals to stop the example.

cps-costimulation-env

Week 6 - Guest Lecture

  • Aerospace and defense Research team within GTRI
  • Hardware Security in Power Grid(both physical and digital locks)
  • Hardware - vulnerable due to being remote
  • Digital is secured using cryptography
  • Every code runs on hardware. side effect: timing, electromagnetic radiation, power consumption

Week 7

Worked on research paper this week. OWkred on section 4, pard 5 implementing DNP3 architecture image image

Week 8

Day of presentation

Week 9

Details about Task 3. There are actually a lot of subtasks for this one, but these are the main two: Read handlers - whenever the master receives values from an outstation, the DNP3 library calls a function that you specify through a function pointer. These functions are called "callbacks." There are different functions for the different types of values the master receives (e.g., a binary value vs a string). More info: https://docs.stepfunc.io/dnp3/1.6.0/guide/docs/api/master/read_handler

The functions listed in the docs there still exist in all the examples (dnp3-example/c_api_example/dnp3-module/src/dnp3/master.c, dnp3-example/ctypes_example/src/master/master.c, and dnp3-example/default_example/master_example.c).

Our goal is to be able to write the callback functions in Python, since we don't want to specify how the master actually behaves in C (since Python is easier for that). For example, we might write a function in Python that says "when I receive a new analog value representing the voltage, print it, and if it is >50 kV, tell the other outstations to shut off."

Controls - For that above example, how would we actually tell the other outstations to shut off? We need control functions. We want to be able to call the DNP3 library functions for sending commands/controls to outstations from Python. This should be pretty simple and mirrors Piper's task, which is simply exposing some methods to the Python code using the extension module API. More info: https://docs.stepfunc.io/dnp3/1.6.0/guide/docs/api/master/association/controls

#Week 10 Still working on Task3 and completing DNP documentation

Week 12 Guest Lecture

Lecute guest - Trevor M.Lewis Cyber Network Operations Observed problems in Critical Infrastructure: Why do attacks on Critical Infrsatructure exits?

  • Vulnerabilities --> sush as knows CVs, patched, zero days
  • Architecture> Engineer Failires --> Inhelful Congiguration - Miscondfiguration _ Defense Failures --> Technolgy Indeqaucies , technology Bypasses --> Secuirty Operations Failures

Week 12 -13

For task 3 I want to make it possible to write Python functions that act as callbacks when the device receives new data. Basically, I'm building the ability for the system to react in Python when something comes in from the field.

When a DNP3 device (like an outstation or master) receives a new value or command, it needs to know what to do. Right now, the code just logs it. But in the real world, it should actually act on that information.

In C, this is done using function pointers passed to the DNP3

image

I’m handling the Master, I’m working with the read handler instead of the control handler.

My goal: Let Python functions handle these events instead of C functions.

To do that, I need to:

Create C extension methods that allow Python to set callback functions. These must be set before creating the Outstation or Master object (because the C struct is created during that process). That means I’ll need to write a Python class that holds these handlers and pass it as a parameter to the Outstation/Master constructor. So, I’ll be building this out for the Master side, using dnp3_read_handler_t.

Example functions that I’ll expose to Python:

handle_binary_input handle_octet_string handle_string_attr

Week 15

Creating a Screen Recording of Launching QEMU to Access CPS-Cosimulation: A Demonstration for macOS Users

This screen recording serves as a visual demonstration of how to successfully launch QEMU on a macOS system in order to access the CPS-co-simulation environment. The goal is to verify and showcase that the simulation setup is fully operational on a Mac device, offering a practical reference for users who may be setting this up for the first time or encountering system-specific issues.

image

Week 16

Working with MAria and Changmin for mo portion of my Final Paper

⚠️ **GitHub.com Fallback** ⚠️