Digitally signing ELF binaries.

October 4th, 2004

Ok, I’m still working on getting XMLNode ready and out as a library, but in the mean time, here’s something that’s ready, willing, and waiting.

The Intro:
A while back a project I was working on had a major architecture change. We went to a completely plugin based system. We needed a way to verify that these plugins were from a trusted source (us), unmodified, and uncorrupted. Sounds like a perfect case for digital signatures!

The Problem:
These plugins were all linux shared objects. Linux uses the ELF binary standard for all of it’s executable binary types, including executables, shared objects, and core files. The issue was how to incorporate a digital signature in such a way as to tie it to the shared object. It also needed to be straightforward enough that it didn’t run the risk of corrupting the binary. The last requirement was that it had to be lgpl since I wanted to open-source it, but it would be used for a non-gpl program.

The Solution:
Upon reading the elf spec, I found it would be fairly straight-forward to create a new section in the binary, and just put the signature there. Technically this wasn’t quite the correct and proper solution. The truly proper solution would be to insert the signature into the “notes” section. Anyway, that was a bit harder to do, and not really necessary, so I created a new section (valid and allowed in the ELF spec) to house the signature.

The Implementation:
I grabbed the very useful libcrypt library from openssl, and proceeded to find out how to programatically create RSA keys, store those keys in a format that could be used in source code, sign and verify blocks of data. Once I had that all figured out, I tackled reading and writing ELF sections in a binary. Then to tie it all together, I made a nice little app to sign binaries, and a static library that provided functions to verify signatures in a given binary. I couldn’t use the provided ELF interface because it was gpl, however there were some lower level data structures that I could use. (Thanks lgpl!)

The process for signing a binary is basically this:

  1. Read in the “data” and “text” sections of the binary, these are the compiled code sections.
  2. Sign a buffer of those combined sections with the private RSA key.
  3. Write out the resulting signature in a new section.

To verify:

  1. Read in the “data” and “text” sections of the binary.
  2. Read in the “lsesig” section.
  3. Verify the combined buffer with the signature that was read in using the public RSA key.

This effectively produces a signed binary that can be easily verified, but not easily tampered with. If you remove the signature, then the verification will fail, if you change the compiled code, the signature won’t match.

As long as you don’t distribute the private key, or the singing program, then you can verify that the shared objects you are loading came from you, weren’t tampered with, and weren’t corrupted. (Or at least didn’t have corruption in any of the code sections of the binary)

In theory this could be incorporated in the kernel to allow signed modules. It could also be used to periodically verify objects on a given system. Who knows what else it could be used for, but hey, it does what I need!

To get your hands on this uber-useful library, go to http://sourceforge.net/projects/signelf

-Synwan

Datacentric XML

September 4th, 2004

As I mentioned last post, we like to use the STL to process our XML. This really only works with datacentric XML documents. What I mean by datacentric XML, is XML that tends to hold collections of XML “records” with the same structure. An example would look like this:
<customers>
<customer>
<name>John Doe</name>
<address>
<street-address>123 N. Main</street-address>
<city>Beverly Hills</city>
<state>California</state>
<zip>90210</zip>
</address>
<comment>Rich guy</comment>
</customer>
<customer>
<name>Jane Doe</name>
<address>
<street-address>1235 Hill Ave</street-address>
<city>Beverly Hills</city>
<state>California</state>
<zip>90210</zip>
</address>
<comment/>
</customer>
</customers>

Given that XML tree, we could ask for a collection of customers, and using a std::sort, sort on zipcode. Then we could use std::for_each and a custom function to read each customer tree and populate a mail-merge app for a monthly mailing list.

We could also create a custom function that decorates the address tree with 5+4 digit zip codes. We could then get a collection of the zip code nodes. Using std::transform, and the function, we could iterate over each of these nodes, converting their zip codes, then, reinserting them into the tree, perhaps as a new node called <full-zip>.

Using datacentric XML can provide flexible data storing needs. We’ve found it to be an excellent solution for handling data for several different design patterns. Especially the decorator, and command patterns.

XML and the developer

August 26th, 2004

Ok, here’s a question? Am I the only one that loves the flexibility, self documenting nature, and general coolness factor of XML? And am I the only one that detests working with the DOM? My buddies and I have been coding together for over 3 years now. We’ve been using XML almost exclusively for data storage and communication. We love it, but we all hate working with the DOM. It’s tedious at best. We’ve written a wrapper to sit on top of the DOM. It contains the basic DOM functions for traversal, along with some STL adaptors so we can iterate over XML data trees using STL algorithms. We can iterate over a collection of nodes and extract a given bit of info, using XPath. We can generate new XMLNode trees from a collection of strings, structs, etc. We’re working on getting it out, but in the meantime, I’m curious if anyone else has any solutions that they use? Is everyone just a DOM user? Do you have wrappers? Anyway, I’m curious to hear about anyone else’s experience.

-Synwan

CodeNoise is now transmitting

August 26th, 2004

Welcome to CodeNoise. First, let me introduce myself. Hi, I’m Synwan, I’m a coder. I mainly work in c++, but I venture into other languages regularly. I also enjoy working on complex problems. This is a place where I hope to discuss my latest coding problem, solution, neat trick, or whatever. Every once in a while, there may be ramblings that are non-code related. (Hence codenoise) I hope that this can grow into something useful, but even if not, it’ll be fun.

-Synwan