Digital signatures for RP2350 boards

Yeah, NIST 800 level random numbers are hard to generate. Not impossible, but hard enough to want to avoid.

In my corporate job, we used a good number of HSMs to manage keys, do signing, randomization, etc. They were nice to use, but I’m glad it wasn’t on my nickel.

An md5 hash of something unique per unit(salted hash, many iterations) for the serial gives you a 16-byte value, 32 hex digits. Not too bad to store in a database; can be encoded as a bit string in an x509 extension. Likelihood of a hash collision is still low enough in this case not to be an issue.

32 hex chars might be a long value, but can be copy/pasted from the terminal. Or, if the cert is on the flash filesystem, it can be pulled to a host machine and the serial extracted with OpenSSL or Python.

1 Like

Agreed. In this case, the stated purpose is to provide unique serial numbers to prevent competitive analysis of production numbers. To distill to specific requirements: (1) unique, and (2) unpredictable.

(1) can be guaranteed by leveraging your choice of database’s UNIQUE qualifier on that column type.

(2) needs to be informed by the use case. For discouraging competitive analysis, grabbing 8 bytes from /dev/urandom may suffice. If not, use your choice of crypto-hard random number generation (HSM, etc.).

1 Like

If you concatenate a monotically increasing number (or timestamp?) + secret key (and perhaps a revision number) and hash that and use that as the serial number, it will be (1) unique, and (2) unpredictable by anyone who does not know the secret key. It would also be (3) authenticated by those that do.

But the board could not authenticate it. If this serial number was also signed by a private key, and a public key was on the board, the board could authenticate itself.

Someone could clone the board, and use their own key pair, of course. But the factory could authenticate the serial number. A database of serial numbers would not be required.

You still need a way to store and protect the secret key for hashing, and the private key used for signing.
And key revocation is an issue.

1 Like

I think I’m missing something.

Could you help me understand why a separate serial number would be beneficial? For example, why better to add all that, vs. just using the RP2350/RP2040 unique ID, which is statistically unique. For validation purposes, just sign the data you want to validate (even if only that unique ID) with your private key, and store that signature in OTP. Public key crypto lets anyone validate it without letting them also sign it?

3 Likes

cert command now has options to display or save the cert and public keys in PEM format.

I didn’t initially conceive of having a unique serial beyond the one in the RPi chip, but up thread we discussed having this secondary ID. I searched for how people “normally” do this, and blowfish was the most common suggestion. It seemed cool to have a number we could reconstitute without a database.

Reading a bit more about the initialization value, it seems unhelpful towards that goal. It is changed each time so that identical ASCII text messages are not identical. That is the opposite of what I’m after, we want each to be guaranteed unique. However, as far as I can tell, it is still secure using the same IV if the data inside is never the same.

That still leaves the issue that there is potentially a security hole by which the actual ID can be found.

I feel my best option is probably creating a random number and inserting it into a UNIQUE database field. I dislike this because when IDs collide it slams the database until it can create a unique one - though this may be exceedingly rare.

We know ahead of time approximately how many certs we need to issue, so I can create random numbers in batches ahead of time. This removes any hypothetical lag doing it in real time while production is in progress. The database is prepopulated with ID, and we can use a locking update to avoid potential simultaneous updates to the same ID.

1 Like

Yeah, the IV should be unique every usage (not necessarily truly random, but unique). Then the IV needs to also be included in the ciphertext, usually appended (sometimes pre-pended; implementation specific). The IV protects starting with the first encrypted block; without an IV, identical “beginning” data encrypted into the first block with the same key becomes a crib to help crack that key. Unique IVs help prevent that.

I thought someone mentioned that they had some chips without the rPI unique ID in them. Having both gives provenance of the device from the DP serial number, and the rPI number ties it to that particular Bus Pirate (assuming there was an rPI serial/ID). This prevents a counterfeiter from simply copying the entire OTP contents for all of their copies.

If all of the chips do indeed have a unique rPI number, then that would be all that’s needed - read it out, add it to the manufacturing database, put it into the birth certificate. Wouldn’t even need to hash it - we’d rely on rPI to make them non-significant and unique.

Yes, adding some value to something getting hashed is called “salting”. I used that word earlier without defining it; apologies for that. The salt doesn’t need to be anything special; the important thing is multiple hashing passes.

My thought was that the hash would be stored in the manufacturing database, not the information used to create it. It would never be necessary to re-hash anything; just look up the hashed value in the manufacturing DB.

Adding the serial to the certificate as an x509 extension is the important part here. The cert is signed with the Dangerous Prototype’s private key; the public key is included in the software to authenticate the cert, which also authenticates everything in that cert.

Yes, key rotation and revocation is always an issue to consider in any PKI.

Side note - this is why threat modeling exists; we’d be able to hash this all out in that process (pun intended) :slight_smile:

2 Likes

There are a handful of rp2350 without unique ID. They were the engineering samples and I have a certification prototype or two with those blank chips :slight_smile:

I don’t think it is supposed to be common though :slight_smile:

1 Like

One thought on this: “what prevents the counterfeiter from making their own cert with serial numbers and downloading the code from git and replacing the public key with their own?”

That cert would validate and it would look legit.

The only defense is: download the latest from the official git repo and do the internal validation; it will fail.

Also: every PR needs to be reviewed before merge to be sure that functionality and/or keys are not changed.

1 Like

If the counterfeiter has a RP2350 without OTP page 0 (unique ID, etc.), and a real BP6 device, what prevents them from cloning anything you put into it?

I suppose you could also pull the flash chip’s unique ID, and include that in the certificate. That would raise the bar to requiring not only an unpersonalized RP2350, but also a flash chip allowing customer defined serial number.

So, if your threat model includes blocking the use of unpersonalized RP2350 exist, what is preventing the full clone of an existing BP6 device?

Yes! Agreement 100%. Private / Public key crypto is exactly for this purpose! :slight_smile: The data within that signed certificate is implicitly protected from modification (without detection).

I submit that this is outside the threat model. A counterfeiter could load firmware that just skips the check altogether and prints whatever result it wants to console / LCD. Nothing should rely on this certificate. It’s entirely up to the user if they want to validate it.

If you really wanted to prevent counterfeits, you’re looking at code signing and code integrity enforced by the chip. I refer folks to the multi-stage bootloader used in the Xbox One (and later) for a good method.

Given the busPirate is a device targeting hackers (and custom firmware), preventing folks from loading their own certificates / custom firmware seems out-of-scope.

2 Likes

I didn’t mean that the cert affects any operation, just that it would be a step in, for example, a warranty claim. “Download latest from git, run the cert command, and copy/paste ID info into an email/form”. That’s assuming it powers up, of course.

100%! I always build the firmware and load it because I’ve been hacking on it.

As far as a user’s own cert, that’s fine, too. This is just about knowing if you have an “authentic BP”.

1 Like

Does it sound like we can avoid the bus pirate specific serial and go with the unique chip ID?

I’ll make a new cert proposal tomorrow. I’d like to get it as short as possible. I believe the crashing we’re seeing is due to all the big variables involved, and it’s going to get worse when we have to load the cert into ram from OTP. Currently it’s in flash.

One thing that would reduce ram is if I wrote our own DER to PEM base64 encoder so we can save/display in a loop instead of into a huge buffer. I looked at the mbedtls code that’s doing it. Not too complicated but not high on my list to deal with.

Another option is to only print/save DER format only, but that feels like a cop out.

1 Like

I don’t see a problem with DER-only handling. It’s pretty trivial to convert to PEM if a user wanted to.

As long as we’re confident in the rPI ID being available, unique, and non-significant then I’m good with it.

1 Like

Well,we aren’t and we discovered the vulnerability ourselves :smiley: I fully intend to demo that attack vector :slight_smile:

But it would be very rare and also really funny if someone made the effort. I’d never shut up about it :slight_smile:

1 Like

Oh no! I don’t have a genuine Bus Pirate!! :rofl:

I got my shipment of a few Pico2 boards and wanted to play with the OTP and other stuff. Of course, the first thing I did was checkout the cert branch and give it a try!

(Yes, I expected to have an error on serial number; just having some fun)

1 Like

Looks like the info shows the opposite word order compared to the cert command.

Really glad it runs on a pico2. I tried recently to run on a pico1 and I think we do something horrible to one of the onboard SMPS pins.

1 Like

I took a chance. I figured if it did work, it would save me a lot of time just making a project to do what’s happening in the BP code.

I did notice that…

This is making me giggle!

1 Like

True, although they are engineering samples, and not generally available in this form. Also of note, from the datasheet 13.5.4:

Page 0, known as the chip info page, is not a special page. Raspberry Pi sets page 0 to read-only during factory test, after writing chip identification and calibration values

Items in OTP Page0

  • 64-bit ChipID
  • 64-bit Per-device Random ID
  • Ring oscillator frequency (@ 1.1V, room temp, reset state, etc.)
  • Low-Power oscillator frequency (@ 1.1V…)
  • CRIT0 boot flags (permanent disabling of ARM and/or RISC cores)

Thus, although the unique IDs might be zero, it’s also highly likely that the calibration values for the two main oscillators are also unprogrammed. It’s unclear how the chips would operate (especially at boundary conditions) without proper values written there. Maybe there’s a way to write the proper values there manually, after testing to detect the right values? But … I wouldn’t trust anything timing sensitive, which is pretty much everything the BusPirate was built for. Or maybe that’s just me? :slight_smile:

2 Likes

Ah, I missed that they were engineering samples; that makes a lot more sense. Fine for some basic testing, but definitely not for prime time.

2 Likes

The BusPirate is Open Source, right? So this is allowed and/or encouraged.

I thought the issue is determining it it’s an official BP vs. a clone.
Why this is important is another point to consider.

If nothing else, it makes support of the BP easier. If it’s a clone, then inferior/wrong parts may have been used.

2 Likes

It helps prevent dangerous prototype from doing warranty work/replacements on units they didn’t produce.

One last thing - to protect DP’s excellent reputation for good products and service.

2 Likes