Digital Rights Management (DRM) with CBFS Storage

CBFS Storage, having convenient file management features and built-in encryption, is often used for Digital Rights Management (DRM). In other words, developers use CBFS Storage to secure information and to prevent unauthorized access to this information. Unauthorized can mean access by third-parties, but also by the user himself. It's a common task when the user may access the data only via the application interface, but may not export this information to external media, both electronic and physical (paper etc.).

The problem with such use is that the reliable DRM is a hardly achievable goal. You can implement it, but to implement it right you need to employ more than just a library (for example CBFS Storage).

To get access to the protected entity, one would need to have the key and the keyhole. In other words, knowing the key won't help if you don't know where and how to use it. And brute force attack on the encrypted data (when you have it) can be very time consuming. With CBFS Storage, the keyhole is available by default. The key (password) will protect your data from the average John Doe, but not from an experienced hacker.


Protecting information from copying

The first level of security is the obfuscation of the file format. When the experienced hacker sees the storage, he can easily find out that it's CBFS Storage. The hacker can take CBFS Storage Explorer and attempt to open the storage. He will find out that this is CBFS Storage. To avoid this, you can apply some permutations on the storage pages. When CBFS Storage is used in callback mode, it calls the functions provided by your application to read and write the pages from / to the storage. You can write and read the pages as is, but you can also change them. Changes can be as simple as XOR'ing the bytes with some constant, or you can even employ some encryption algorithm. Callback mode is described in the corresponding article.

The next step to follow is protecting the key. To use built-in encryption features of CBFS Storage, it means that you provide a password (pass phrase) which CBFS Storage uses to encrypt the files (when you encrypt the files one by one) or the whole storage (when whole-storage encryption is used). And this is a good vector for attack which is carried by an experienced hacker. No matter how you or CBFS Storage secure the password, there's a place where this password is in clear text - it's where the password is transferred from your code to CBFS Storage code. Can we pass the password in a unclear text? Of course, but again, there will be some place where it will appear in clear text - either in your application or in the library. There are two approaches to secure the key. Both of them require custom encryption, which is possible using encryption and hashing callbacks of CBFS Storage. The first approach relies on the code obfuscation. The second approach provides almost 100% protection but requires hardware support. The differences between the approaches will be described below.

To get custom encryption you need to take several steps:

  1. Set encryption mode for the storage or the files that you want to encrypt to Custom.
  2. Implement handlers for OnDataEncrypt, OnDataDecrypt callbacks. They will be used for the data encryption.
  3. Implement handlers for OnHashValidate and OnHashCalculate callbacks. They will be used for hash calculation.

Now it's time for encryption and password. With the first approach, the idea is that you construct the obfuscated encryption key and perform an encryption and decryption in your code, and this code is obfuscated to hide the key and data permutations. The obfuscation of the executable code is done using special tools which are not mentioned here intentionally. The goal of obfuscating the code, is to make it hard, if not impossible, for the hackers to find out the password and the permuted algorithm used.

The second approach requires that you use cryptographic hardware (USB crypto tokens or smart cards). The symmetric key, used for the encryption / decryption of the disk data, is stored in the hardware. Cryptographic hardware supports both, the storage of the secret keys and the cryptographic operations (encryption / decryption) using this key. The secret key doesn't (and can't) leave the token, so the hacker won't be able to get the pass phrase. You can re-encrypt the data using other key if needed: most hardwares let you generate a symmetric key and store it in the device.

This approach has several disadvantages:

  1. The cryptographic hardware is quite slow when performing the encryption / decryption operations. This will slow down significantly the disk operations.
  2. Hardwares cost money (a minimum of 50 USD for a USB crypto token at the moment of writing) and it needs physical shipping to your clients.

The advantages are also significant:

  1. You get very high level of protection for your data.
  2. You get an additional tool of license control for your data or software. It's not possible to install and use unauthorized copies of your software or export the data to use it on other systems.

Controlling the user access

User rights control is possible when your data can't be easily extracted and copied to the external media for unprotected access. The measures to prevent this were discussed above. Here we will discuss several possible ways to control access to information by several users.

When you ship some data, you might want to make this information available to certain list of users / devices while preventing others from using your application and accessing the data. This can be done using PKI.

PKI stands for "Public Key Infrastructure", the set of standards and protocols that let you use asymmetric cryptography (also called public key cryptography) to sign and encrypt the data in order to prove its authenticity and to secure the data from unauthorized access.

In our scenario, we will encrypt the encrypted key used to encrypt the key used to access CBFS Storage. Is this too complicated?
Well, this is just the beginning ;-). CBFS Storage data is encrypted with a key, which we will call CBFS Storage Key. As discussed above, we can either keep it in cryptographic hardware or keep it hidden in our code or data. Now, we need to prevent access to this key.

First case is when we don't have a hardware in our scheme. In this case, you need to encrypt CBFS Storage Key using some random key (we'll name it RKey). You encrypt the RKey using the public keys that belong to the authorized users and give the encrypted RKey to the users as blocks of data (in a file). This block of data will be decrypted by your application by applying the users private key. The decrypted RKey will be used to decrypt CBFS Storage Key in your application. No need to say, that RKey decryption and CBFSStorageKey decryption procedures must be obfuscated.

If we have the hardware, the scheme is slightly different. The crypto card or USB token can be stolen. They are usually protected using a PIN (password), but as it happens with any password known to the user, they can be obtained relatively easily. So, we will need to remove the human from the equation. You need to assign a unique cryptographically strong PIN to each token or smart card that you distribute (and which contain CBFS Storage Key). You encrypt the PIN using the public keys that belong to the authorized users and give the encrypted PIN to the users as blocks of data (in a file). This block of data will be decrypted by your application by applying users private key. The decrypted PIN will be used to access the hardware using PKCS#11 interface which lets you provide the PIN programmatically (Windows CryptoAPI doesn't let you pass the PIN in code). No need to say that the PIN decryption procedure must be obfuscated. Now, the attacker would need to steal the hardware and the private key in order to just get access to any of your data stored in CBFS Storage. Since the user doesn't have a PIN for the hardware, he can't use this hardware to store his private key, and the risk of stealing both pieces of the secret is reduced this way. Only the legitimate users of your application will be able to use it.

Both of the above schemes have one more benefit besides protecting the access key. The encrypted RKey or PIN are not the only information that you can store in encrypted data block. You can add any access control information that you need there. For example, you can specify that the owner of the private key may read the text documents but may not alter them. Of course, these permissions will be checked in your application and the permission checking code must be protected in some way.


Conclusions

The ideas discussed above are not the only possible ways to secure your information. You are welcome to improve the offered schemes and create your own schemes if needed. It's very hard to secure information from the curious minds that have access to this information (even in encrypted form), but the most creative you are, the stronger the protection is. Just note, that cryptography itself must be implemented by professionals.

To implement the whole scheme correctly you need certain cryptographic library. Consider SecureBlackbox® , the product that will let you use both symmetric and PKI security with CBFS Storage.

Ready to get started?

Learn more about Callback Technologies or download a free trial.

Download Now