THE LINUX FOUNDATION PROJECTS

Contributed By:

Shubham Kumar

Shubham Kumar, an LFX Fall 2026 Mentee with a background in applied cryptography and telecom networks, is an active open-source contributor. He serves as an Advisory Committee representative at the OpenSSL Foundation, the NgKore Foundation, and the LF Networking ONAP project. He is passionate about learning new things in open source and contributing back to the ecosystem.

In July 2026, I began my LFX Mentorship as a selected mentee on the project Extending language and library support in CBOMkit, under the guidance of my mentor, Aditya Koranga. My work focused on adding C/C++ support to sonar-cryptography, with the main goal of detecting OpenSSL API usage. Now that the mentorship has come to an end, I want to record my learning experience in this blog post and share how I got started, what I worked on, and how others can contribute in the same way.

What is LFX Mentorship

For those who don’t know about LFX Mentorship, it is a program that pairs new contributors with mentors from open source projects for a fixed period of time. Mentees work on a defined project and contribute directly to the upstream codebase. It helps new contributors get familiar with the open source ecosystem and start their journey towards becoming long-term contributors to these projects.

What is CBOMkit

CBOMkit is a set of tools under the Post-Quantum Cryptography Alliance (PQCA) that creates a Cryptographic Bill of Materials (CBOM) for a piece of software. A CBOM provides an inventory of the cryptographic assets used by a program, including algorithms, keys, key sizes, certificates, and protocols, as well as the relationships and dependencies between them. I have written a separate article on the CBOMkit architecture that explains each part of CBOMkit and how they connect. If you are new to CBOMkit, I would suggest reading it first.

cbomkit-architecture

The part of CBOMkit that reads source code is sonar-cryptography, a SonarQube plugin. I have also written about how it works inside in my article on the Sonar Cryptography Plugin. Before this work, it could scan Java, Python and Go code, but not C/C++. This left out a lot of software, since much of system software, network software and embedded code is written in C/C++ and uses OpenSSL.

Objective

The main goal of the mentorship was to extend CBOMkit to C/C++, with a focus on OpenSSL. This meant adding C/C++ language support to sonar-cryptography, building an OpenSSL detection module with meaningful coverage, and backing it with a test suite that checks the accuracy of the detections. In the end, a C/C++ project scanned with CBOMkit should produce a CBOM that correctly lists the OpenSSL algorithms, keys and protocols it uses.

What Did I Do

My work on C/C++ support actually started in early 2026, a few months before the mentorship began. Before the mentorship, I focused on understanding the project, preparing the C/C++ parser and opening the first PR. During the mentorship, I focused on making the C/C++ support work on real code, extending the OpenSSL coverage, and addressing the review feedback from the maintainers. The sections below go through this work in order.

The First Step

Before writing any code, I spent time understanding the project in three steps.

  1. Understanding CBOMkit: I went through each CBOMkit tool to see what it does, how they depend on each other, and where the language support fits in.
  2. Understanding sonar-cryptography: I picked one detection and followed it from start to end. First, the Sonar language parser reads the source code and builds an Abstract Syntax Tree (AST). Then the detection rules look for crypto API calls in the AST and store what they find in a DetectionStore. After that, a language-specific translator converts the findings into the common INode model, the enricher adds extra details like OIDs, and finally the output module writes everything out as a CycloneDX CBOM. I noticed that only the first two steps depend on the language. Everything after that is shared by all languages.

sonar-cryptography-multi-maven-module

My two articles mentioned above came out of these first two steps.

  1. Reading the contributor guides: These two documents in the repository were my main reference throughout the project:
  1. LANGUAGE_SUPPORT.md explains how to add a new language or library. It covers adding the parser dependency, finding the four generic types the engine needs, implementing the engine interfaces (IDetectionEngine, ILanguageSupport, ILanguageTranslation and others), creating the language module, and writing and translating the first rule.
  2. DETECTION_RULE_STRUCTURE.md explains how a detection rule is written with DetectionRuleBuilder, how its findings are translated into the INode model, and how reorganizer rules restructure the result.

Looking back, this step saved me a lot of time later. Once I knew which parts were language-specific and which were shared, it was clear what I had to build for C/C++ and what I could reuse.

Symbol Support in sonar-cxx

sonar-cryptography does not read source code by itself. For each language, it uses an existing Sonar parser plugin, like sonar-java for Java and sonar-python for Python. For C/C++, I used sonar-cxx, a community plugin that reads C/C++ files and builds the AST.

According to LANGUAGE_SUPPORT.md, the detection engine works with four generic types that every Sonar language parser has to provide:

Type What it does Class in sonar-cxx
Rule (R) The base for a check that looks at the code. SquidCheck
Tree (T) A single node in the AST. AstNode
Symbol (S) What a name in the code refers to. missing
Publisher (P) The context used to report what was found. SquidAstVisitorContext

To see if sonar-cxx had everything needed, I made a list of all the methods and classes from sonar-java and sonar-python that sonar-cryptography actually uses in its Java and Python support. Then I compared this list with what sonar-cxx already had. This is how I found that sonar-cxx had the rule, tree, and publisher types, but no Symbol class or symbol table.

A symbol connects a name in the code to the place where it was declared. For example, if the code has int bits = 2048; and later calls EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bits), the AST alone only sees an identifier called bits in two places. With symbols, sonar-cryptography can find where bits was declared and read its value, 2048. This is what lets it find variable values and connect a key to the calls that use it later.

So I added symbol support and a few helper methods to sonar-cxx, following the same design as sonar-java and sonar-python (sonar-cxx#3013, sonar-cxx#3032).

Building the cpp Module

Once the parser had what I needed, I created a new cpp module in sonar-cryptography. I used the existing java and python modules as a reference. I went through their files side by side, created a similar structure for cpp, and connected it to the shared modules (engine, mapper, enricher, and output) in the same way.

Most of the logic was similar to the other languages, so figuring out the solution was not the hard part. The harder part was the parser. sonar-java and sonar-python are both maintained by SonarSource, so they are built in a similar way. sonar-cxx is maintained by the community (SonarSource’s own C/C++ analyzer is a paid product), so it is built quite differently. I spent a good amount of time understanding these differences and making sonar-cxx fit into the same flow as the other languages.

With this ready, I opened sonar-cryptography#377 with the new cpp module and a first set of detection rules for OpenSSL 3.6. While working on it, I ran into two main problems:

  1. Getting sonar-cxx into the build: sonar-cxx is not published on Maven Central like the other Sonar parsers, so there was no simple way to add it as a dependency. One of the CBOMkit maintainers suggested JitPack, which builds a package directly from a GitHub repository. That is how the plugin gets sonar-cxx now.
  2. OpenSSL macros: Many OpenSSL functions are actually macros. For example, SSL_CTX_set_min_proto_version(ctx, v) becomes SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MIN_PROTO_VERSION, v, NULL) (see ssl.h.in). sonar-cxx expands macros during preprocessing, before building the AST, so if the OpenSSL headers are available, the rules only see the expanded call. After discussing this with another CBOMkit maintainer, I first wrote the rules for the expanded calls. Later, I noticed that this needs the OpenSSL headers to be shipped with the plugin, and more headers would have to be added for every new library. So I checked how the other languages handle this. They do not ship any library headers or classpaths, and their rules match the API names exactly as they are written in the user’s code. I followed the same approach: I removed the OpenSSL headers from the build, so that sonar-cxx leaves these calls unexpanded. The rules can now match the macro names, like SSL_CTX_set_min_proto_version, directly and report the correct detection locations.

Following Values Through C Code

When the mentorship started in July, the first thing I did was run the plugin on a few open source projects that use OpenSSL. One of the first things I noticed was that TLS versions were not being detected correctly. After that, I kept testing on real projects along with the unit tests, because small test files don’t always show the problems that real code does.

Testing on real code also made one difference between Java and C very clear. In Java, Cipher.getInstance(“AES/GCM/NoPadding”) gives the full algorithm in one call. OpenSSL code works differently. You usually create a context in one call, choose the algorithm in another, and set the key or other options in more calls, sometimes in different functions or files.

To handle this, sonar-cxx also needed to fill in the symbol information while scanning, which I added in sonar-cxx#3102 and improved in sonar-cxx#3143. In sonar-cryptography, I then extended the C/C++ detection engine so it can follow a value or an object as it moves through variables, function calls, return values, C++ constructors, and pointers. Now the plugin can connect, for example, an RSA key created with 2048 bits to the signing call that uses it later.

Extending the OpenSSL Coverage

With the detection engine able to follow values, I moved on to covering more of the OpenSSL API. The OpenSSL rules now cover:

  1. EVP API: ciphers, digests, MACs, KDFs, key agreement, key encapsulation, key generation and signatures, including OSSL_PARAM based configuration.
  2. Legacy (pre-EVP) API: direct calls like AES_*, RSA_* and HMAC_*.
  3. SSL/TLS: protocol versions from *_method() calls and min/max version settings, plus groups, signature algorithms, and cipher suites.
  4. Other areas: X.509 certificate signatures, CMS/PKCS#7/OCSP, password-based encryption and random number generation.
  5. Post-quantum algorithms: ML-KEM, ML-DSA and SLH-DSA, available from OpenSSL 3.5.

I also added OpenSSL name mappers in the mapper module, so that OpenSSL algorithm names, NIDs, named curves and cipher suite names map to the correct INode model classes in the CBOM.

Reviews and Accuracy of the CBOM

Throughout the PR, the maintainers pointed out issues and gaps, like algorithms being mapped incorrectly, cases that were missed, and high memory use on larger projects. I worked through them one by one, with the goal of making sure the CBOM the plugin produces is accurate.

Towards the end, I cleaned up the cpp module so it follows the same conventions as the java and python modules, like loading rules through the shared RuleSets registry. I also bundled sonar-cxx inside the plugin JAR, the same way sonar-java, sonar-python, and sonar-go are bundled, so users don’t need to install it separately.

How to Get Familiar with the Project

If you want to add a new language or library to CBOMkit, these are the steps that worked for me:

  1. Read about the CBOMkit architecture to see how all the tools fit together.
  2. Pick an existing language module and follow one detection from the AST to the CBOM.
  3. Go through LANGUAGE_SUPPORT.md and DETECTION_RULE_STRUCTURE.md step by step.
  4. List the files you will need to add, using an existing language module as a reference.
  5. Check that the parser for your language has all four generic types (R, T, S, P) and the methods sonar-cryptography uses. If something is missing, you may need to add it to the parser first, like I did with sonar-cxx.
  6. Start with one rule and one test file, and get that working before adding more.

Conclusion

Over these three months, the C/C++ support went from something that worked on small examples to something that can follow values across real code and cover most of OpenSSL. I learned a lot about OpenSSL, about how Sonar parsers build and resolve ASTs, and about adding a new module to an existing project.

I plan to keep contributing to CBOMkit after the mentorship, keep learning in this area, and stay involved with the project for the long term. One of my next steps is to switch the plugin from my fork of sonar-cxx to an official sonar-cxx release once my changes are merged.

I would like to thank my mentor, Aditya Koranga, and the CBOMkit maintainers, Nicklas Körtge and Andreas Schade, for their guidance and support throughout the mentorship. Their reviews and feedback helped a lot in shaping this work. I also want to thank my co-mentee, Siddhartha Bhattarai, who worked on JavaScript/TypeScript support in sonar-cryptography during the same time and worked alongside me.