Transcript
This transcript was autogenerated. To make changes, submit a PR.
Hi. So this talk is about secure building blocks. So secure building
blocks, nothing. But it's a model block which can provide end to end solutions.
In an embryo system or any system, it can be secure boot, secure update,
secure communication, secure process, or secure storage. So it
was our goal to build something can be plugged in,
placed in your code very easily. It can be
get into the existing stack and IoT can be fast
secure, and it can update very fast based on your security
vulnerabilities. Maybe today this cryptographic algorithm is safe. Tomorrow it will
not be same. So how much fast we can update the code. Okay, we need
to have updated in your code.
So we are looking into all these aspects.
We wanted to select a language. Okay, now step was
we selected our secure building block. Obviously, it's an open source software development.
We wanted to go for a language. Which language should we choose? So we had
multiple options in our head. Maybe c, C plus, plus rust.
Go kpython. We have multiple options,
but of course, we have boiled down to two or three options.
C rust, because they were systems level language which can have
high performance because they don't have GC in it. Before you
get into the rust world, right. You have to justify yourself.
Why are you using rust? Because there's so much of stack available CNC.
So justify yourself and everybody, because so legacy
of code is available. You just can't go and change it. So we did
some evaluation from our side. We also saw some papers.
Okay, so why rust? For embedded system development and by extension,
automative software security. So embedded
system is one thing that can come where automotive,
Iot, medical, anything can come there. Okay. Embedded system is a
very vast thing. So rust can go in everywhere. So how
can by extension, give automative security? Automotive is
one of the important aspect area where security
is very important, where any little here
and there could lead to very high disaster. It can be space technology,
it can be anything. So we wanted to see is
it compiler is reliable? Is it certified? This is so many options when
you go for a new language. Getting into the automotive
world where tried and tested software is already running in your field,
we have taken rust. But what is about, what is it about?
It has fast. It is very fast because there's no gc.
There's no gc. Obviously, the performance is very high, then low memory usage.
There's no runtime or vm, and it compiles onto a machine
code. Okay. So obviously,
there's no bytecode available directly. You're going to get a
hex file, which is binary which can edit it run on your which
can edit run on your controller as a bare metal code.
And it also has a memory and concurrency safety.
No use of free dangling pointer, null pointer and data
races and all. So this is one of the very good
thing in automotive when you have a PLS concurrency kind of concept
which is available directly, but the name is a PLS concurrency.
It's very useful in your they can use it. Okay.
And the powerful type system, this is the one thing what rust people
like. The type system is so great that you can have your custom
types and that custom types can be matched from your match
statement or can be handled error. So which will help you to
help you to have a clear flow of data in your code.
Okay. If something is not happening, come on. Pattern matching,
error handling, safe multithreading, all these are powerful
type system, which combination makes it superb.
Along with that we have excellent tooling. We have a ruster, one single tool,
one single compiler. Not like multiple single things.
And documenting is so nice, so good.
The community is built such a way that seeing the drawbacks of
few previous legacy of code data or get documentation should be
must. Because today whatever code you write tomorrow you have to be able to
identify what exactly I wrote. If you're not unable to identify,
then the loss of time to read from the beginning utilised build
system dependency management. All these are reasons
along with it, it gives a modern general purpose language
program language that also has these many features. So then
it has the necessary ingredients to produce a safe, reliable performance systems
code. So you have a safe reliable
performance code. So what does you want still
you're not stopping. Okay, we got from our answers
looking into the rust thing and we will see what is available. What data do
we have? Can existing code base.
So chromium security we went through a couple of projects
and there are so many available online. We tested
ourselves some we read okay, the problem safety,
the memory safety. So around 70% of high severity bugs
are memory save bugs. So memory save bugs are the highest bugs.
So 2021 memory unsafety Apple's operating system
14 had 60.4% of memory vulnerabilities.
13 had 59.4%. Twelve had 66.3%.
Eleven had 60.5%. This is a very huge number.
Android developers blog the queue the hardening
enhancements use after free integer
overflows out of bone reads writes
compares 90% of vulnerabilities with OB being the most
common. These are the things which is not properly managed
in the existing code base. Okay then
also we saw the project zero. The memory corruption issues are the root cause
of 68% understood cvs.
So we know that the memory safety issue has become one of
the important factor in our security software development.
So we have to completely eradicate that. Okay, so we were unable
to completely eradicate memory safety issue from
any existing language. Maybe c or c plus plus or
go python we don't think
could actually completely remove it. So rust is a
language which will make you write a memory safe code. If you know Rust,
Iot means the code. Whatever is going to compile, it's for
sure is memory safe as a guarantee Iot gives you.
Then we saw what exactly it is providing
the safe memory management and powerful type system. These are the two
things, the two combination which is giving you everything in
can automotive security or software development. So what
does it give? It gives three main things. Safety by construction zero cost
abstraction compile time checks okay,
so what does safety by construction means pointers are checked
compile time. So all the pointers, unless you don't put in
unsafe blocks, everything is safe. You can't just go and access some
location and write something into it. Thread or task safety
from types no hidden states zero cost
abstraction efficient zero cost centrix so if you can also define a
marker traits which will not take any memory no GC at
runtime safe and unsafe rust compile
time checks so compile time safety analysis so unless
you don't have a dynamic dispatch, you're going to make every single
code. Compile time check trace based conditional APIs,
control allocation and dispatch. So these things makes
safe performance and fine grain
control of a system. This powerful thing will help you to
have a memory safe code. Can you stop it?
With rust? Safety guarantees plus powerful
type system embedded systems program can write complex
software that's safe. Now you can write a complex software which
is safe from rust. How can rust help in automated systems
or cybersecurity? So we saw that rust can give you a safe
and perform high performance code which can help
you write a complex code. Now we can write a complex embedded system code,
but how does it help in our automotive software security?
Then we have something called as
some more points we have the rust greatly helps
functional safety. So rust guarantees memory
and concurrency. So memory corruption vulnerabilities
are impossible apart from compiler or a hardware malfunction. So there
is no possible that you are going to have memory corruption issues in
rust. If it's happening, it's because of compiler or some hardware
malfunctions. Okay, all shared mutable state
is unsafe, so anything which is mutable state
is unsafe. No race around conditions due to sentencing
traits. So if you just go into the threads part of
rust where you can see how you are trying to
access a variable inside automix where you're going to
lock it, other thread will unable to access it the way it is
designed. Send and sync if a
type implements a send, then you can pass the utility to
it. If it implements a sync then you can share it.
Okay, so everything is completely types and traits here,
which will make the whole code very clean and understandable
and very safe. Exploit by default.
Pub mute clone result propagation casting are beneficial.
And also we have some formal verification tooling called
any risti, miri et cetera which will
help you to test your code like functional
basis, model basis, system basis. We can test
it step by step. Also you don't have to follow the Misla C
standard. What you actually follow in c, right? Because any
code you write is memory safe and IoT is compiler will
make sure that everything is followed. Because you're trying
to write your own memory management in rust,
which is not there in any other language, you're basically managing
the whole memory. You're trying to access the stack memory, you're not trying to access
any heap memory. Here the soundness compiler can verify
the absence of undefined behavior. The compiler can actually verify
the absence of undefined behavior. That's the main thing
which all these factors along with that, we are also
having some compiler releasing October which will make rust
a suitable software for embedded software development and
a security team. We take it as our main building block.
Our first 70% of issue memory safety is solved
by one language. So we take rust as our
main code, main software,
main language for a software development. Now let's
get into SBB. So SBB stands for secure building
blocks. So as I told, there can be multiple
existing code available. It can be can automotive. You just need
to have linking codes or modules
in between those code so that you don't have to change the whole entire
code list. Wherever security is required, go place it
there. That is when our secure boot will come, which will help to
securely boot your firmware or update your firmware. Then you
have something called trusted firmware, where you sign the firmware and you
tell that okay, this is a genuine firmware. What I'm sending it to you and
the verifier will verify it. And you have a trusted
identity, secure authentication. So we're
going to have electric curve cryptography, and our code
is designed such a way that example today this curve
is broken. Tomorrow we're going to have some different curve. So it'll help to
also have post quantum cryptography algorithms also in our system,
such a way it is designed,
then we have secure update. So once the code is
firmware is verified. So if you have any update available
from Phota, when you do phota, so you're going to get the firmware,
it'll be in some location. How do you verify it and how do you update
it is about one aspect. Then you have a cloud available. There is
some data available in Kona. How do you communicate securely from
a device and a middle device? And if
you want to process some data, how do you process it securely within the system,
or you want to store it in somewhere? Securely, how do you store data?
So all these are the small, small blocks,
building blocks of our building blocks,
which will help you to make the whole system secure.
It can be trusted secure authentication rust boot secure
update trusted firmware secure communication secure storage
secure process okay. And everything
is modular. So modeler building blocks to simplify security
development lifecycle, what is it? So what do you benefit
from that? The benefit what you get is faster, go to market and
also you can also keep on updating your code.
Impact reduced operational risk independence
from vendor locking reduced trusted computing base
guaranteed memory data race safety
minimize integral complexity and boot time avoid vendor lock in.
These are some of the benefits. What you get when you have a SBB.
So this project is completely open source. You can find in my GitHub
page Ishwan Singham it's just my full name.
You can also scan my QR code. My first slide
slides will be given, I think I believe. So you can find this project is
completely open source. So now we have built something called as
secure authentication secure bootcup update. These are blocks already available.
The reason why we make open source is because we
need more contributions to it, so that many people can put their own ideas and
build a software collab. And we're going to make a very strong software out of
it. Next Iot security. So if
you see the architecture of your system, right, so you have a hardware layer
here. This is the MCU and this is for a Linux machine.
Basically this is for MPU microprocessor. This is for microcontroller.
So if you have microprocessor then this architecture will follow
controller. We have can architecture. So whatever
is a white thing is basically secure security component security
accelerators are available here on the hardware. Hardware can be anything.
Then you have a trusted execution environment abstraction layer which
will help you to talk to this hardware,
cryptocurrency accelerators, et cetera. And then you have your
firmware upgrade and secure boot, which is in your green layer, what we have developed
as a developer right now. And then we have our crypto
cell library, secure storage, key storage,
certificate management. All this comes in the ABU layer on
that application sets. These are the bare metal things. What we
going to do on MCU, on MPU, the same thing,
trusted execution environment, abstraction layer. Here you're going to have
your kernel and drivers above the hardware. Then you have a
networking stack, secure transport layer, and then application.
Those are typically you're going to have your blocks
designed on your hardware. Then we have our opensource
signature. The key component of secure software
development is distance signatures hashing.
So we follow something called asymmetric as symmetric cryptography,
where you're going to have private key and public key, which is
different. Different. So private key is with the
person who is signing the firmware, maybe a person who is
producing the firmware, a developer has a private key controller
will have, or the device, which is client device is
in the field will have a public key. The private key is used to sign
a digest of firmware image. Okay. Private key is very confidential.
By the way. Public key is used to verify the signed digest
can be shared publicly, Iot can be shared. Anybody has public key can
be shared and whoever has public key can verify it. But private
key is confidential. If you lose it, then it's gone. So data is
something, it can be firmware data. You take a hash of it
and you're going to get digest from it. So what is digest? Digest is something
of fixed value or a fixed data bytes.
Then you're going to encrypt it. Then you're going to use a private key and
you're going to get a signature out of it. Okay,
so data, you're going to hash Iot,
you're going to get a fixed size and you're going to encrypt it
along with the private key and you're going to get a fixed size signature.
So basically it's like a piece of paper. You're signing it on a
piece of paper. If you sign, it becomes a document or it becomes your property,
something like that. The signature is out of your data,
which you are producing uniquely for a particular firm
or data not booting time. How do you verify it?
Okay, the signature, whatever you have signed, will be available
on your firmware or on a piece of paper. Okay,
so how do you verify with the data. So now in a booting time,
the firmware, again, the boot are going to hash
it and you're going to get the digest of it,
and you're going to take the public key and decrypt Iot and
you're going to get the digest of it. So you're going to get these two
digest and to compare it. If it compares
successful, then you're going to get the booting, you're going to verify
it, and you're going to go for next step. Okay, that's how private
key and public key. Private key, I'm going to sign it. Public key, I'm going
to verify it. Hashing is required because to get a fixed length
of data for digest, then we have,
this is a flow typically. So ROM code is something
which serves as a load of all trust. Okay. ROm code is a
code which is immutable, immutable code stored
in some form of onboard non volatile memory. It is flashed during
manufacturing time. ROM code is the first piece of code to execute.
So ROM code is the first piece of code that executes which will do the
signature verification of a bootloader, which is just first stage bootloader.
Our trust of anchor is public key embedded within the ROM code.
So we have public key in our Romcode which is our trust of
anchor. Rom code serves as root of trust.
In practice. It is stored safely in something like a one time
programmable fuse. So it is inside your one
time programmable fuse in what is called OTP.
Integrity of trust of anchor is important,
not confidentiality. Integrity is important. Okay,
so next we're going to have the next public key and then
a verification. The kernel verified, the digest will be verified,
hash verification. Then it goes to boot. This is how the control flows.
Every component is verified using distance signature and public key.
Next is, yeah, next comes our rust boot.
So this talk is mainly focused on how
do you boot a firmware, how do you sign a firmware, how do you verify
it and how do you update the firmware? Okay, these are the things what we're
going to cover in our session and
the remaining secure communication, secure process. Secure storage is a different
topic itself. So boot itself is one topic.
So we're going to take introduction of secure boot
and what are our goals and what are the features we're offering architecture,
what's the flow of booting sequences?
So all is we're going to see, you can actually
scan this QR code and you can get the rust
book. It's open source book we have written. So if
you want to have a bootloader for your MCU, then you can
read this book, follow instructions, and you can have a support for
your controller, basically. Okay, so what is rust?
Boot? Rust boot is a standalone bootloader written entirely
in rust, designed to run anything from microcontroller
to system on chip. It can be used to boot into bare metal or
lux. It's a test definition of rust boot. It's a secure bootloader,
basically, rust boot, just a secure bootloader,
nothing more. Boot order help to boot how it is different
from other boot order. We're going to discuss IoT, we're going to see it.
It's very small, tiny, high performance,
et cetera, et cetera. Okay, so what are our goals when
I'm building a bootloader compiles with key requirements
of IETF suit standard. So whenever you design a
bootloader, right, you don't need to have a whole network stack.
The flashing Uart stacks all the protocols in it,
because you're not building OS, you're just building a first stage of bootloader which
has capability of verifying the next stage.
Okay, so you are going to have the network stage,
network, network layer, everything. This should be in your
application like code or your firmware. Bootloader should
not have all this headache. So if you
increase the size of your bootloader,
you're going to increase the attack surface size means you're going to
adding more and more features to it. If you're going to add
a USB feature or you're going to add some URL feature
or some protocol feature, network feature, attacker gets
hundred ways to go into it. So we're going to minimize it.
Required peripherals, we're going to use it. We will
not even use UART unless it's necessary.
There's IoT going to be any protocol interface from external world
to tamper it. Unless you go into memory using a JTAG or something like
that, there's no way possible you're going to get access to it. Reliable updates.
Also, your bootload should be updatable.
See, today you have an electrical free two to six
mist, two to six. Tomorrow IoT can break. How do you
make sure that your bootloader is updated? Hardware can stay for
hundreds of years, but your software has to be updated every single time.
How do you make it so? Our goal is to also have a reliable
updates. Predictability or performance?
Performance is fine. Okay, this is very fast every single day of performance,
but how much predictable it is today, it is behaving like this tomorrow. Also,
are you making sure it is behaving like this every single day? So how
do you make sure it. That's called predictability.
Zero dynamic memory allocation. So how do you
make sure that your bootloader is having no
heap in it? Okay, we don't want any dynamic memory allocation
in your bootloader. That's the fourth point. Fifth point is
the most important point, which is memory safety and type state programming.
This is completely offered from our rust itself.
Okay. So there are some features like predictability or performance,
zero dynamic memory location and rust safety and
type state programming. All these are features are directly available
from rust. The top two features are available
from maybe first feature is available the way you design the
software. Second is how much model you're going to make to get a lab updates.
Then we go into our features. Okay, this is what goals
we have. So whatever features, whatever we have offered.
So currently our Rust bootler offers support for ARM,
Cortex M and Cortex a MCUs or Meg architectures.
So we support different family controllers like STM microchip,
NRF. Many people have added support for us
as opensource project support for multi slot partitioning
of flash memory. This allows to implement boot update approach for bare metal
firmware. So you're going to have a flash, you're going to make IoT partition
the flash, which I'm going to go in detail in the coming things
where you're going to have boot partition update partition and SAP partition
support for Arc 64 Linux supporting.
So we have also support for Arc 64. Right now it's the only architecture what
we have. Cortex support elliptic cryptography
for integrity and authenticity verification. Crypto credits. We are
going to also add postponed crypto to it. Tiny hardware
abstraction layer for non volatile memory flash access. So I told you
we're going to have very tiny ha layer, flash layer so that we're going to
make our bootloader very less memory. That going
to have high performance anti roll up protection over version
numbering. So if there is any,
while booting the firmware, if there is any power gone,
we're going to roll back to the previous firmware or authentication failed.
We're going to roll back. So we're going to have a rollback facility also in
our firmware fully memory safe bootloader.
Core bootloader implemented with safe passes and firmware update logic.
So it's all about how we've designed. So we have a lot of,
it's not only rust which is giving offering the safety, of course,
it offers 70%. The rest 30% you have to offer it. So how are
you making sure so you're going to use passes and firmware update logic.
The power interruptible firmware updates along with the
assurance of fallback ability. So power interruptible
rollback is available. Switch to rust based signing
tool. The key features firmware signing improve
scalability and security. So we have written our own firmware signing tool which
will help you to produce trusted firmware. And we are also using
trusted authentication also there. So everything is written from
scratch. Support for external flash devices.
Apart from this we also support something called as trusted execution.
We have also given support for Arm trust zone thing
and which the pr is on the way. So we
support various families of controllers like as I told NXP,
STM,
NRF, RPI and
ESP, things like that. Also we are adding support and we
also have the Cortex architectures like M Zero, M four, M seven,
et cetera, like that. So every single architecture we're
trying to cover it. If you want, feel free. If you have
to add support for your controller board, also you can go from
our rust board book and you can follow the steps and you can add to
it. Then we have architecture. So in our architecture
we have two main stages. One is called pre handover stage, other is called
as post handover stage. The design is based on a simple idea.
A bootloader handles only a bare essentials and offloads
the rest of the system that is better suited for a job.
So any bare essential requirements only
will be in our bootloader rest. All things will be given to your
controller. Okay, there are two main things here. One is the
pre handover stage, other is a post handover stage. In the pre handover
stage we're going to have the bootrom. So basically boot ROM is a
guy which is a bootloader available on your rom
which will give the handle to the bootloader. Some other intermediate
stage bootloader executes and hands over to our rust boot.
This is a stage where rust boot has full execution
control. So pre handover stage is where the boot ROM
give control to your rust bootloader and then you have your post
handover stage where firmware has begun execution and has counted
execution control. The firmware uses a couple of rust boot dependencies to
trigger and confirm updates. So pre handover stage is when the
boot ROM will give control to your rust boot. And rust boot has a complete
control. And a post handover stage is where the bootloader
will give control to your firmware. So this is how the flow works.
Let's get into her pre handover stage. So pre handover stage,
we have a couple of things here. So we have a rust boot core
bootloader. It has an embedded public key. So embedded
in software or in hardware, it depends on the architecture. So if you have a
crypto accelerator similar, we can keep there. If you don't have any cryptographic
hardware, then you can keep embedded in your software itself. There are two
ways available. Yeah, so this is your
hardware MCU or MPU. On that you have your
ha layer, which is your hardware abstraction layer. So we're going to have only bare
minimum things.
We're going to extract it, maybe Uart, GPIo, flash and crypto
peripherals. Okay. Only these things. We're going to make it
available. We're going to make the code as small as possible. The next
is rust crypto. So basically optional software
based crypto library. So if you want, if you have a hardware available,
go for it. If you don't have, you can use the rust crypto
layer, which is a third party layer which is proven and
we're going to take IoT we're going to take and we're going to use it
which will help to your verification of your firmware.
This is your, basically a pre handover stage where rust
boot will have a complete control. Okay. Then we
have our post handover stage where your
application will have a control over it. So secure
element hardware is here. Linux or bare metal. So bare metal
firmware is here. You have your networking stack available here
and there are some respite APIs. So now the
control is gone to your firmware. But there are some APIs using which
you can talk to your bootloader. Rust boot provides a tiny
API to trigger and confirm updates. So if you have any
update available, how do you confirm it? It's available in your Rust boot
API. Then you can download your download and install your
app and trigger update. This is basically in your pre
handover stage you're going to have the rust boot complete control.
In post handover stage you're going to have the firmware complete control.
So basically signing means what exactly signing means.
So you're going to have the firmware here and you're going to put two to
six header over it. So how do you do it? So you have your image.
So this is your two to six bed header. What you want
to attach it to your firmware. So you have your firmware. You're going to attach
a two to six byte header which will make a signed firmware. So how do
you make a signed firmware? This is a technique, so you have your firmware.
So magic and eos are basically header and footer. What are you
going to add? Iot can be anything. So we are adding rust and boot here
just like that. Then you have image size. How big is your image? Then you
have a type length value. So for next piece of thing,
what is the type, what is the length and what is the value? And we're
going to have some padding, and we're going to have type length value again,
which is type length value for a next field, which is a timestamp. The timestamp
is nothing but of at what time you are compiling
your code. Then you have something called type length value for image type.
So what is the image type you are having? It is a boot image update
image. So that information will be given here. Then again you have padding.
Then again you have type length value. Okay, so now till
here we have information of our firmware. So we're going to take all this
information and we're going to produce a digest of it.
You're going to hash it and you're going to get a digest of it,
which is two to six bytes. And this we're
going to have fixed shard digest,
which is, which we're going to store here. Then we're going to have a TLB
and whatever public key is embedded in your bootloader. We're going
to take the digest of that also here. So we're going to do everything verification.
And now we have can Elv. We're going to take
everything and we're going to make a signature out of it. We're going to take
can elliptic curve, and you're going to do
some manual operation. You're going to get a unique number which is called a signature,
and that will be stored here. And all this thing is called
a header, which is responsible for a name of a signed firmware.
We take this and attach to a firmware. We call it a signed firmware.
Okay, so this is your signed firmware. This will be sitting
in your boot partition. So we're going to take the signed firmware and
we're going to put in our boot partition. Rush boot is a bootloader which
will go and check every single byte of every single byte
of your header. If it is verifies, then only
the control will be passed here. Else the bootloader will be here. So rushboard
will go and check every single thing. So this firmware will be sitting in your
boot partition. This will go and check every single thing. If everything
is verified. Okay then go ahead. The controller is going to boot firmware.
And next if you have an update available. So now boot partition,
boot firmware has a capacity to download
a firmware. So we are offloading all the network stack in our boot partition.
So now this boot partition will update the example.
You have an update available. So it's going to download and keep the update
here. Now the trigger again, the control is given back to
bootloader. So bootloader will now go and verify
the update partitions firmware. If it is verified and valid,
then it's going to swap the firmware. The boot going to come here, the update
going to come here and boot going to go here and start the boot form
execution. This is how the cycle goes on. If you have update, swap it and
get it. So bootloader's job is to verify
the boot firmware. If any update is available, then boot firmware will
give control again to bootloader and again so the cycle
goes on. So boot firmware, update firmware. Then again, next update firmware,
next update firmware. The swap foundation is used to just swapping your firmware.
This is your flow basically. So let's
go into flowchart. So whenever the bootloader
start, right, it's going to open the partitions, okay.
If it is initially it will be false,
right? So Iot means it's only the boot partition.
Then go and check for any update. If it
is not there false, then go boot in new state. Then again
check it, then verify the integrity. Or if it is
false then panic it. Or if it is true then Abraham available.
Then jump to rust boot open all partitions. Okay.
Then verify authenticity integrity. Then if it is false,
panic again. So this is basically a flow where actually the rust
bootloader will follow some steps which is there here.
So at the end if it is booting is there.
So if there is any rollback available trigger
here, there's a complete flow of your rust bootloader which will be followed
in your complete process. So if you have an update available,
go for update and come back. So we have some of a couple of
flags here called as ff called new state and 70 called
updating state and 10 called testing state and zero called SS
state. So there is a flag what we'll be monitoring. So based on that flag,
the bootloader will be verifying it. Okay, so if
you have a boot, boot it. If you update, update it. If you have some
other thing, just go and discard it. This is what the flow is about.
So today's talk is mainly focused on rust boot
and how do you sign the firmware and from where do you
sign it and how the execution goes. So this is all about
today's talk. So maybe next we can go ahead next
talk, we can go ahead with the secure execution,
secure process, and secure communication. Yeah.
So thank you. So thank you for your time. So you can always reach
out to me via my LinkedIn. You can scan this QR code and
you can always reach out to me for anything. So this
SBB is can open source project. As I told, it's available in
my GitHub page. You can find my GitHub page in my LinkedIn
or yeah, my GitHub name is just Yashwanth
Singh M with no spaces. If you type this, you're going to get my GitHub
page. So I work on multiple projects.
I work on multiple projects. I work on a simple level language.
I work on RTL coding, rust C.
I mainly work on some low level coding stuff,
but I also have experience in high
level coding, but I have restricted myself for low level coding. So there
are a couple of projects which I work in freedom.
Everything is available as open source, may have different sensors. So rust
is what we're exploring from past two years. I have a lot of projects available
in C, so please do go and check it. This is my page
and you can find my GitHub from that. Thank you.