Password protecting embedded firmware download - c++

I need to protect against the users of our product from downloading firmware that is incompatible with the revision of the hardware that they're trying to download to. I'll describe what exists right now and what I'm looking for.
We have an alpha-numeric hardware part number and revision stored in EEPROM that is only factory programmable. When a customer attempts to download a firmware file he will have to enter a password that is distributed with the firmware release. The existing firmware needs to be able to use this password to verify that the new firmware is compatible with the current hardware revision. Keep in mind that more than one hardware revisions may be compatible with a single released version of firmware.
Is there some form of public key cryptography that can be used to validate multiple hardware revision numbers to a key that is generated during the firmware build process? The hardware revision number(s) would act as the private key while the password entered by the customer to unlock the download mechanism would be the public key.
The embedded firmware is written in C and it would be great if the encryption algorithm were the same. It can be C++ as long as it has an interface that lends itself to being called from C functions.
There are a couple of hardware revisions out in the wild, but we can ignore those exist for now. Let's say a brand new product is going to be released that includes this feature, so it will be revision 0.
The password will be transferred from the client's computer to the embedded hardware without any modifications. So the decryption and password matching needs to happen in the embedded firmware, which will then report success / failure back to the client. The reason for this is that it may not always be a laptop being used to download the firmware. It'll more likely be a handheld download tool so options for executing custom software are limited.

Forget the passwords.
The simplest way to do this is to include in the firmware file, at a known location, a list of compatible hardware IDs. This could be stored as a length-prefixed array. When a new firmware is to be loaded into a device, the device looks for its own hardware ID in the list, and rejects the firmware if it is not present.
Such a system is robust, easy to understand and easy to debug. If space is a concern then you can store the list as a bitset, with each hardware revision allocated a bit.
If you wish to prevent active tampering, you can further sign the entire firmware file, including the list of compatible hardware IDs, with a normal public key signature algorithm like DSA or RSA.

So we assume this is a fresh design:
I am not really how much security you want/need and how processing power your device has...
I would make the firmware package consist of two parts - a header and the "real thing".
Both should be encrypted differently and then signed independently plus together (this is the public key cryptography part).
first check the outer signature
then check the signature of header (which must be calculated based on the header, header length plus the password)
The header is encrypted with the password you distribute and contains a list of hashes of the compatible hardware revisions (these hashes are calculated from the hardware revision + password).
The device decrypts the header, hashes its own revision from the EEPROM accordingly (again revision + password) and tries to find a match in the list.
IF it finds a match then it takes the hash of the list in the header.
with the hash of the list it check the signature of the the "real thing" (calculated on the encrypted content plus length plus password plus hash of the list)
if the signature is valid it proceeds decrypting the "real thing" (key would be password + hash of list)
For the signature part you create a cert, sign that cert with your root cert... the derived cert would be embedded into the devices... so you create the signatures with the private key of that cert and check them in the device with the public key.
The above is NOT 100% secure but provides several aspects:
tampering with package would be always detectable (as long as you don't loose your private key that is)
it won't be installable on any incompatible hardware revision
figuring out the scheme wouldn't allow for installation on incompatble hardware revisions (except if your customer somehow modifies your hardware)
IF that is two much calculations etc. you could always simplify the scheme... at the bare minimum I would keep the outer signature and the password...
EDIT - after some discussion (see comments):
The base algorithms to create the "password" I suggest consists of 2 parts - a hashing algorithm and an encryption algorithm:
hashing algorithm
The respective firmware should be hashed ("good" algorithms are SHA-512, SHA-384, SHA-256, MD5 - "VERY WEAK" algorithm would be CRC32)
encryption algorithm
The password would be encrypted using either an asymetric algorithm (like RSA, EC etc.) or a symetric algorithm ("strong" ones are AES, Blowfisch etc. - "weak" ones are for example DES - "VERY WEAK" is for example XOR)
The scheme consists of the following steps:
hash the firmware with any of the above hashing algorithms
build a string consisting of part number/ revision number + firmware hash
encrypt the string with any of the above mentioned encryption algorithms (asymetric means you use the private key, symetric means you use the same key for encryption/decryption)
The device need to contain a secret key (which is either the public key if asymetric encryption is used or the key in case of symetric encryption) and the part number/revision number.
Checking the firmware against the password means decrypting the password, hashing the firmware and comparing the part number/revision number and firmware hash...
Security aspects versus processing requirements:
asymetric encryption means handling big number (1024 bit or bigger)
IF the device is not capable of handling that you should perhaps take a symetric encryption.
symetric encryption means that IF your customer reads out the key from your hardware he would be able to create "valid passwords" himself while in the asymetric case this won't be possible
you could stick with hashing only (hash the firmware plus part numerb/revision number) and provide the result as a password but this leaves you open to a customer figuring the algorithm used out and then they can create themselves "valid passwords"
Some relevant links:
http://www.cryptosys.net/
http://www.openssl.org/
http://www.cryptopp.com/
http://en.wikipedia.org/wiki/Public-key_cryptography
http://en.wikipedia.org/wiki/Symmetric-key_algorithm

Related

Asymmetric authenticated encryption

I want to protect my data from being changed or read by unauthorized people. Searching around I found that Authenticated Encryption(AE) is a solution.
I know I can do AE in Crypto++ using any of CCM, GCM, or EAX. But I noticed they're using the same key to encrypt and decrypt data. I don't want that, I'd rather use asymmetric keys to encrypt and decrypt my data.
If I sign data using an asymmetric algorithm and then encrypt it using a symmetric algorithm, I will achieve what I want (Which should be safe since it's AtE method, right?).
But before I do that, are there any crypto libraries that do what I want already?
I know I can do Authenticated Encryption ... using ... CCM, GCM, or EAX. But I noticed they're using the same key to encrypt and decrypt data. I don't want that, I'd rather use asymmetric keys to encrypt and decrypt my data.
All the schemes I am aware will use a symmetric cipher for the bulk data encryption. The symmetric cipher can be a block cipher or a stream cipher.
I've also seen a few incorrect applications of RSA, where RSA is operated in ECB mode. That is, the data is "chunked" or "blocked", and then RSA is applied to each block. The Handbook of Applied Cryptography specifically warns against this.
The best you are probably going to do is Elliptic Curve Integrated Encryption Scheme (ECIES) or Discrete Log Integrated Encryption System (DLIES). Both are available in Crypto++. Both use public key (asymmetric) cryptography.
ECIES and DLIES combine a Key Encapsulation Mechanism (KEM) with a Data Encapsulation Mechanism (DEM). The system independently derives a symmetric cipher key and a MAC key from a common secret. Data is first encrypted under a symmetric cipher, and then the cipher text is MAC'd under an authentication scheme. Finally, the common secret is encrypted under the public part of a public/private key pair. The output of the encryption function is the tuple {K,C,T}, where K is the encrypted common secret, C is the ciphertext, and T is the authentication tag.
There is some hand waiving around the "common secret" since its actually the result of applying a Key Agreement function and later digested with a KDF. It uses the static public key and an ephemeral key pair. The person performing the decrypt uses their public key to perform the other half of the key exchange to arrive at the "common secret".
The KEM and the DEM avoid padding, so padding oracles are not a concern. That's why a KDF is used to digest the large "common secret" under the KEM. Omitting padding vastly simplifies the security proofs of the system. Because of the security proofs, ECIES and DLIES are IND-CCA2, which is one of the strongest you can achieve.
If I sign data using an asymmetric algorithm and then encrypt it using a symmetric algorithm...
Here's some related reading... First is Hugo Krawczyk's The Order of Encryption and Authentication for Protecting Communications. Second is Don Davis' Defective Sign & Encrypt in S/MIME, PKCS#7, MOSS, PEM, PGP, and XML.
The relevance here is: Krawczyk's paper deals with symmetric key cryptography and the Encrypt-then-Authenticate style of authenticated encryption (and how to perform authenticated encryption). Davis' paper deals with asymmetric cryptography and the disconnect between signing and encryption (and how to repair it).
But before I do that, are there any crypto libraries that do what I want already?
Yes (but it depends on what you want to do). Crypto++ is the only one I am aware that provides ECIES, DLIES, and a collection of PSSRs.
Bouncy Castle is a close second because it provides ECIES, but not DLIES. I'm not sure how many PSSRs it provides.
Crypto++, Bouncy Castle, OpenSSL (and others) provide the PSSR. You should not have any trouble finding a lib with PSSR.
You could possibly consider an OpenPGP-based solution. This would provide you with the functionality you desire and would scale to support arbitrary data sizes, unlike a solution based purely on asymmetric encryption (with no transport key).
There are a few open source implementations out there. BouncyCastle offer one, but I'm not sure they have a C++ implementation.
GPGME (GnuPG Made Easy). It's a high level encryption library in C and is LGPL licensed.

What method/algorithm/library can securely encrypt then decrypt

The following project is done in C++ with WinAPI, for encryption/encoding I am using CryptoC++ but I am open to better libraries. I need to encrypt/encode email data, transmit it, then decrypt it at the other end so privileged users can read the email.
My original idea was just to encrypt the email text using SHA256 using my key(eg "MYKEY"). But I think I don't fully understand what hashing is. I understand that a string encrypted with SHA256 or MD5 or AES is impossible to decrypt, BUT I thought that if I encrypt the string with my special key("MYKEY") that I could then decrypt it aslong as I know the special key. Is that correct?
If not can you suggest a library, algorithm or method I can use to achieve my task of encrypting/encoding email text & ONLY being able to decrypt it if I have a key or some shared secret that will allow me to decrypt the data?
As said by Captain Giraffe, a hash algorithm is not an encryption algorithm (though they are both counted in the area of symmetric cryptography). A good hash function has no way to recover a message which fits to the produced hash (other than trying all possible messages to see if they give the same hash). (And also, a hash function has fixed size output, but has a variable size input, which means that there are many messages giving the same hash. It still should be difficult finding even one pair of messages giving the same hash, or a message for a given hash.)
You need an encryption algorithm. Most probably asymmetric encryption (using public keys to encrypt, private keys to decrypt) is a good idea.
Don't invent new cryptographic data formats or protocols. You will make mistakes, which make your product insecure.
For email encryption, use either OpenPGP (RFC 4880) or S/MIME (RFC 3851), or some subsets of one of these.
You can then use any library which supports the necessary algorithms, or some library which supports specifically these file formats.
SHA256 and MD5 are One way functions. i.e. There is no decryption. See Hashing http://en.wikipedia.org/wiki/Cryptographic_hash_function.
But you really need to read up on encryption procedures before attempting to create a secure communication.
That being said wikipedia has an article dedicated to implementations http://en.wikipedia.org/wiki/AES_implementations

md5sum a file that contain the sum itself?

I have written a small app in C++ consisting of a single EXE file.
I want to put in its "about" dialog the md5sum of the executable itself. It should be embedded statically into the executable (so that can be seen from hex editor), rather than computed on the fly.
As both #Shi & #matthewdaniel have already said, this can't be done directly.
However a couple of workarounds are possible:
Calculating MD5 of your application, and packaging your executable inside a container app that will simply extract it and check it's MD5
Compiling your code and hashing only the code segments or other segments (except the Data), and than adding the MD5 check code. This will work as the MD5 string will be stored in the Data segment keeping the validity of the precalculated hash of any other memory segment valid.
This is not possible.
If you enter the md5 hash into the binary, the binary will change, so the md5 hash changes as well. If you create a new one, and try to add it to the binary, the binary will change again.
So best is to put the hash into a file, and read that file and display its content.
Another way could be to create the md5 hash of the binary, and then append it to the executable. In order to fetch the value, you read the last 32 byte of the binary and display it as md5. Of course, if you create a hash of the complete executable, it won't match the hash - you have to create the hash of the executable excluding the last 32 byte.
If you store the 128 bit md5 hash in a raw format (base 256 instead of base 16), you only need 16 byte.
As soon as you add the md5 to the file the file will have a different md5. There is no way to get the md5 in the file itself.
The typical method is a signature. A signature is a hash that is further signed by a public/private key. The application can use the public key to verify the hash contained within.
However, this needs to be separate from the executable. As the other answers state, it is impossible to do this with one file. You can merge the signature and the binary and provide instructions to use tools to separate them to compute the verification.
However, this does not stop in-memory attacks against the application. Ie, you have a buffer overflow and an attacker can re-write code in memory.
You might not need the hash of the public key. You need to encrypt the hash of the binary so it can not be altered. You might use the hash of the public key to verify instructions to user, etc. The distribution of the public key and verification instruction can not be bundled. Otherwise an attacker can just re-create with an alternate key pair. Including the hash of the public key can prevent some other attack against instruction. Ie, the signature has some verification that the advertised public key is matching what the binary was signed with.
Using established methods is probably better as users can have alternate tools to verify the integrity. Also, this only makes the public key needed to distribute through some other channel.
Reference: Digital signature with OpenSSL
The above fixes another attack. Given that what you said was possible, what would stop someone else from doing the same thing, but with a trojan horse binary. Distribution of the public key is an authentication of the source (legitimate developer). None of the other answers addressed this.

Advice about the Encryption Method I should Use

Ok, so I need some advice on which encryption method I should use for my current project. All the questions about this subject on here are to do with networking and passing encrypted data from one machine to another.
A brief summary of how the system works is:
I have some data that is held in tables that are in text format. I then use a tool to parse this data and serialize it to a dat file. This works fine but I need to encrypt this data as it will be stored with the application in a public place. The data wont be sent anywhere it is simply read by the application. I just need it to be encrypted so that if it were to fall into the wrong hands, it would not be possible to read the data.
I am using the crypto++ library for my encryption and I have read that it can perform most types of encryption algorithms. I have noticed however that most algorithms use a public and private key to encrypt/decrypt the data. This would mean I would have to store the private key with the data which seems counter intuitive to me. Are there any ways that I can perform the encryption without storing a private key with the data?
I see no reason to use asymmetric crypto in your case. I see two decent solutions depending on the availability of internet access:
Store the key on a server. Only if the user of the program logs in to the server he gets back the key to his local storage.
Use a Key-Derivation-Function such as PBKDF2 to derive the key from a password.
Of course all of this fails if the attacker is patient and installs a keylogger and waits until you access the files the next time. There is no way to secure your data once your machine has been compromised.
Short answer: don't bother.
Long answer: If you store your .DAT file with the application, you'll have to store the key somewhere too. Most probably in the same place (maybe hidden in the code). So if a malicious user wants to break your encryption all he has to do is to look for that key, and that's it. It doesn't really matter which method or algorithm you use. Even if you don't store the decryption key with the application, it will get there eventually, and the malicious user can catch it with the debugger at run time (unless you're using a dedicated secured memory chip and running on a device that has the necessary protections)
That said, many times the mere fact that the data is encrypted is enough protection because the data is just not worth the trouble. If this is your case - then you can just embed the key in the code and use any symmetric algorithm available (AES would be the best pick).
Common way to solve your issue is:
use symetric key algorithm to cipher your data, common algorithm are AES, twofish. most probably, you want to use CBC chaining.
use a digest (sha-256) and sign it with an asymetric algorithm (RSA), using your private key : this way you embed a signature and a public key to check it, making sure that if your scrambling key is compromised, other persons won't be able to forge your personal data. Of course, if you need to update these data, then you can't use this private key mechanism.
In any case, you should check
symetric cipher vs asymetric ones
signature vs ciphering
mode of operation, meaning how you chain one block to the next one for block ciphers, like AES, 3DES (CBC vs ECB)
As previously said, if your data is read andwritten by same application, in any way, it will be very hard to prevent malicious users to steal these data. There are ways to hide keys in the code (you can search for Whitebox cryptography), but it will be definitely fairly complex (and obviously not relying on a simple external crypto library which can be easily templated to steal the key).
If your application can read the data and people have access to that application, someone with enough motivation and time will eventually figure out (by disassembling your application) how to read the data.
In other words, all the information that is needed to decipher the encrypted data is already in the hand of the attacker. You have the consumer=attacker problem in all DRM-related designs and this is why people can easily decrypt DVDs, BluRays, M4As, encrypted eBooks, etc etc etc...
That is called an asymmetric encryption when you use public/private key pairs.
You could use a symmetric encryption algorithm, that way you would only require one key.
That key will still need to be stored somewhere (it could be in the executable). But if the user has access to the .dat, he probably also has access to the exe. Meaning he could still extract that information. But if he has access to the pc (and the needed rights) he could read all the information from memory anyways.
You could ask the user for a passphrase (aka password) and use that to encrypt symmetrically. This way you don't need to store the passphrase anywhere.

Is RIJNDAEL encryption safe to use with small amounts of text given to users?

I am thinking about making the switch to storing session data in encrypted cookies rather than somewhere on my server. While this will result in more bandwidth used for each request - it will save extra database server load and storage space.
Anyway, I plan on encrypting the cookie contents using RIJNDAEL 256.
function encrypt($text, $key)
{
return mcrypt_encrypt(MCRYPT_RIJNDAEL_256,$key,$text,MCRYPT_MODE_ECB,mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256,MCRYPT_MODE_ECB),MCRYPT_RAND));
}
Which in use would produce something like this (base64 encoded for display)
print base64_encode(encrypt('text', 'key'));
7s6RyMaYd4yAibXZJ3C8EuBtB4F0qfJ31xu1tXm8Xvw=
I'm not worried about a single users cookie being compromised as much as I am worried that an attacker would discover the key and be able to construct any session for any user since they know what I use to sign the data.
Is there a way I can verify estimated cracking times in relation to the parameters used? Or is there a standard measure of time in relation to the size of the text or key used?
I heard someone say that the keys needed to exceed 256bits themselves to be safe enough to be used with RIJNDAEL. I'm also wondering if the length of the text encrypted needs to be a certain length so as not to give away the key.
The data will generally be about 200 characters
a:3{s:7:"user_id";i:345;s:5:"token";s:32:"0c4a14547ad221a5d877c2509b887ee6";s:4:"lang";s:2:"en";}
So is this safe?
Yes Rijndael(AES) is safe, however your implementation is far from safe. There are 2 outstanding issues with your implementation. The use of ECB mode and your IV is a static variable that will be used for all messages. An IV must always be a Cryptographic Nonce. Your code is in clear violation of CWE-329.
ECB mode should never be used, CBC mode must be used and this why:
Original:
Encrypted with ECB Mode:
Encrypted using CBC mode:
Avoid using ECB. It can reveal information about what's encrypted. Any two blocks with the same plaintext will have the same ciphertext. CBC would avoid this, but requires an IV to be generated or saved.
Avoid simply saving a key and IV. Generate a 256 bit master key using a cryptographically strong random number generator and save that into you application somewhere safe. Use that to generate session keys for use in encryption. The IV can be derived from the session key. When generating the session key include any and all available data that can be used to narrow the scope of the session key. (e.g. include the scope the cookie, the remote host address, a random nounce stored with the encrypted data, and/or a user ID if it isn't within the encrypted data)
Depending on how the data is to be used you may have to include a MAC. ECB and CBC are not designed to detect any changes to the ciphertext, and such changes will result in garbage in plaintext. You might want to include an HMAC with the encrypted data to allow you to authenticate it before taking it as canon. A session HMAC key must be derived from the session encryption key. Alternatively, you could use PCBC mode. PCBC was made to detect changes in the ciphertext, but its ability to do so is limited by the size of the padding, witch is dependent on the data that is encrypted, and not all crypto APIs will have it as an option.
Once you have gone so far as to include a MAC, then you should consider taking steps against replay attacks. Any time someone can resend old data within the scope of a session is a chance for a replay attack. Making a session key usage as narrow as possible without causing issues for the user is one way to thwart replay attacks. Another thing you could do is include a date and time into the encrypted data to create a window for while the data is to be considered valid.
In summery, protecting the key is just the tip of the iceburg.
If you use a long key, I'd say the key was pretty safe. Some things to concern yourself with:
You are offloading data storage to the client. NEVER TRUST THE CLIENT. This doesn't mean you can't do this, just that you either have to treat the data in the cookie as untrusted (don't make any decisions more serious than what 'theme' to show the user based on it) or provide for a way to validate the data.
Some examples of how to validate the data would be to:
include a salt (so that people with the same session data don't get the same cookie) and
a checksum (so that someone who changes even one bit of the cookie makes it useless).
Rijndael was renamed AES. Yes, it is safe to use.
That said, you should consider carefully what you put in the cookie. It depends on what you have available in the way of storage on your system, but you could simply choose a random number (say a 64-bit number), and store that in the cookie. In your server-side system, you'd keep a record of who that number was associated with, and the other details. This avoids encryption altogether. You use the other details to validate (to the extent anything can be validated) whether the cookie was sent back from the browser you originally sent it to.
Alternatively, you can use a different encryption key for each session, keeping a track of which key was used with which session.
Even if you go with straight encryption with a fixed key, consider including a random number in with the data to be encrypted - this makes it harder to crack using a known plaintext attack because, by definition, the random number can't be known.
AES-128 should be more than sufficient, with no needs to use longer keys - if the key is chosen randomly.
However there are other issues. The first is that you should not use ECB. With ECB a given 128-bit block of plaintext always maps into the same 128-bit ciphertext if the key is the same. This means that adversaries can surgically modify the ciphertext injecting different blocks for which they know the corresponding ciphertext. For example they could mix the data of two different users. With other modes, CBC for example is fine, the ciphertext also depends on the IV (initialization vector), which should be different at every execution of the algorithm. This way, the same plaintext is ciphered differently each time and the adversary cannot gain any advantage. You also need to save the IV somewhere with the ciphertext, no need to protect it. Whenever the chance of reusing the same IV becomes non-negligible you should also change the key.
The second issue is that you should also append a message authentication code. Otherwise you would not be able to distinguish the forged cookies from the good ones.