tree: 9a7e77fc204fb39c95aa5bdc77fb84d73ab9c42b [path history] [tgz]
  1. README.md
  2. __init__.py
  3. dkps.py
  4. dkps_unittest.py
  5. filters/
  6. helpers.py
  7. parsers/
  8. sql/
  9. testdata/
py/dkps/README.md

DRM Keys Provisioning Server (DKPS) User Guide

Introduction

DKPS (DRM Keys Provisioning Server) provides 3 core functions:

  1. allows the uploader to upload DRM keys to the server securely,
  2. stores the DRM keys securely, and
  3. allows the requester to request DRM keys from the server securely. DKPS provides both python RPC call interface or convenient python helper scripts to achieve the goals.

The uploder will typically be an OEM (Original Equipment Manufacturer), and the requester will typically be an ODM (Original Design Manufacturer).

Prerequisite

You'll need python and GnuPG to run the server.

sudo apt-get install python python-gnupg gnupg`
[optional] To make GnuPG key generation faster, you‘ll need rng-tools. This step optional, but if you don’t install rng-tools, your system may take a very long time to initialize the server, because it can not generate random numbers efficiently.
sudo apt-get install rng-tools

Check out DKPS source here.

You‘ll also need the uploader and requester’s GnuPG exported public key files.

Generating GnuPG Keys for Uploader and Requester

If you already have GnuPG keys for uploader and requester, you can skip this section.

Note: for security reason, the uploader should generate the uploader‘s GnuPG key themselves, and the requester should generate the requester’s GnuPG key themselves. The uploader should NOT help the requester generating the requester‘s GnuPG key, and the requester should NOT help the uploader generating the uploader’s GnuPG key, either. Unless the uploader and the requester are the same.

To generate the uploader's GnuPG key:

mkdir gnupg  # create a temporary directory
gpg --homedir gnupg --gen-key
# follow the instruction to generate the key
gpg --homedir gnupg --export -a >uploader.pub
gpg --homedir gnupg --export-secret-keys -a >uploader.key
rm -rf gnupg  # remove temporary directory

Keep uploader.key in a safe place, where only you can access, and send uploader.pub to the person who is going to set up DKPS server.

To generate the requester's GnuPG key, follow the instruction above, change uploader to requester.

DKPS Structure

  • dkps.py the main DKPS server application.
  • requester_helper.py helper module for requesting DRM keys from the server.
  • uploader_helper.py helper module for uploading DRM keys to the server.
  • filters folder that contains filter modules.
  • parsers folder that contains parser modules.
  • sql SQL file for initializing the database.

Initializing the Server

Run the following command:

python dkps.py init

This will create a folder gnupg, a file dkps.db, and the log file dkps.log.

gnupg holds the server's GnuPG key.

dkps.db is the database file, so better back it up from time to time.

dkps.log is the log file. It will grow. If there is no problem with your server, you can truncate this file at any time.

Exporting DKPS Server's GnuPG Public Key

Run the following command: gpg --homedir gnupg --export -a >server.pub

The server‘s GnuPG public key will be saved in server.pub. Send this file to the uploader and requester, they’ll need this file later.

Writing a Parser Module

A parser module parses the raw DRM key list file into python list of DRM keys (also called “de-serialization”).

For example, if the raw DRM key list file is in JSON format:

[{'key': '123'}, {'key': '456'}]

Then the parser module could be:

import json
def Parse(serialized_drm_key_list):
  return json.loads(serialized_drm_key_list)

which just parses the JSON string and converts it to a python list.

Writing a Filter Module

A filter module lets you modify the raw DRM keys before actually saving to the database.

For example, if you want to add abc to every of the DRM keys before saving into the database:

def Filter(drm_key_list):
  return map(lambda k: 'abc' + k, drm_key_list)

If you don't need to modify the DRM keys, you can use sample_filter.py. The filter does nothing but return drm_key_list directly.

Adding a New Project

Now the server has been initialized, time to create a new project:

python dkps.py add -n ${NAME} \
  -u ${UPLOADER_GPG_KEY_FILE} -r ${REQUESTER_GPG_KEY_FILE} \
  -p ${NAME_OF_THE_PARSER_MODULE} -f ${NAME_OF_THE_FILTER_MODULE}

For example, if your project‘s name is superman, and have the uploader’s GnuPG public key as uploader.pub, requester's GnuPG public key as requester.pub, and will use parsers/widevine_parser.py as the parser, filters/sample_filter.py as the filter, then:

python dkps.py add -n superman \
  -u uploader.pub -r requester.pub \
  -p widevine_parser.py -f sample_filter.py

Your project has been set up! You can type:

python dkps.py list

to see if the project has been added correctly.

Starting to Serve DRM Keys

python dkps.py listen

and leave it there.

The default port is 5438, you can change this using the --port argument. For example, to change the listen port to 1234:

python dkps.py listen --port 1234

Uploading DRM Keys

python uploader_helper.py \
  --server_ip ${DKPS_SERVER_IP} \
  --server_port ${DKPS_SERVER_PORT} \
  --server_key_file_path ${DKPS_SERVER_PUBLIC_GPG_KEY_FILE} \
  --uploader_key_file_path ${UPLOADER_GPG_PRIVATE_KEY_FILE} \
  --passphrase_file_path ${PASSPHRASE_FILE_PATH} \
  upload ${DRM_KEYS_FILE_PATH}

By default ${DKPS_SERVER_PORT} is 5438 (if you didn't change the port in the Starting to Serve DRM Keys section.)

${DKPS_SERVER_PUBLIC_GPG_KEY_FILE} is the server's GnuPG public key exported in the Exporting DKPS Server's GnuPG Public Key section.

${UPLOADER_GPG_PRIVATE_KEY_FILE} is the key file (the private one, i.e. uploader.key, not uploader.pub) generated in Generating GnuPG Keys for Uploader and Requester section.

If you have set up a passphrase when generating the uploader's GnuPG key, you need to save the passphrase into a file and give the file path to ${PASSPHRASE_FILE_PATH}.

${DRM_KEYS_FILE_PATH} is the path to raw DRM keys file.

Requesting DRM Keys

python requester_helper.py \
  --server_ip ${DKPS_SERVER_IP} \
  --server_port ${DKPS_SERVER_PORT} \
  --server_key_file_path ${DKPS_SERVER_PUBLIC_GPG_KEY_FILE} \
  --requester_key_file_path ${REQUESTER_GPG_PRIVATE_KEY_FILE} \
  --passphrase_file_path ${PASSPHRASE_FILE_PATH} \
  request ${DUT_SERIAL_NUMBER}

By default ${DKPS_SERVER_PORT} is 5438 (if you didn't change the port in the Starting to Serve DRM Keys section.)

${DKPS_SERVER_PUBLIC_GPG_KEY_FILE} is the server's GnuPG public key exported in the Exporting DKPS Server's GnuPG Public Key section.

${REQUESTER_GPG_PRIVATE_KEY_FILE} is the key file (the private one, i.e. requester.key, not requester.pub) generated in Generating GnuPG Keys for Uploader and Requester section.

If you have set up a passphrase when generating the requester's GnuPG key, you need to save the passphrase into a file and give the file path to ${PASSPHRASE_FILE_PATH}.

${DUT_SERIAL_NUMBER} is a string (DUT‘s serial number). If you give the same serial number, the DKPS server will always return the same DRM key. So it’s fine to ask multiple times.