Update entitlement unit tests

This patch updates the entitlement keys in the sample code and in the
unit tests to use AES 256.
This commit is contained in:
Fred Gylys-Colwell
2018-02-02 15:37:05 -08:00
parent 7b71a449d0
commit 44e206898d
14 changed files with 812 additions and 137 deletions

4
README
View File

@@ -5,8 +5,8 @@ as well as unit tests and reference code.
Several versions of OEMCrypto are available on different branches. This is the
only file on the master branch. Please use the git checkout command to work
with the correct version of OEMCrypto, for example, to see version 13, use the
command "git checkout origin/v13".
with the correct version of OEMCrypto, for example, to see version 14, use the
command "git checkout origin/v14".
Use "git branch -a" to see a list of all branches.

View File

@@ -421,7 +421,7 @@ typedef enum OEMCrypto_ProvisioningMethod {
#define OEMCrypto_IsSRMUpdateSupported _oecc53
#define OEMCrypto_GetCurrentSRMVersion _oecc54
#define OEMCrypto_LoadSRM _oecc55
#define OEMCrypto_LoadKeys_v13 _oecc56
#define OEMCrypto_LoadKeys_V13 _oecc56
#define OEMCrypto_RemoveSRM _oecc57
#define OEMCrypto_CreateUsageTableHeader _oecc61
#define OEMCrypto_LoadUsageTableHeader _oecc62

View File

@@ -14,6 +14,7 @@
#include "level3_file_system.h"
#include "OEMCryptoCENC.h"
#include "oemcrypto_adapter.h"
namespace wvoec3 {
@@ -68,7 +69,7 @@ namespace wvoec3 {
#define Level3_IsSRMUpdateSupported _lcc53
#define Level3_GetCurrentSRMVersion _lcc54
#define Level3_LoadSRM _lcc55
#define Level3_LoadKeys _lcc56
#define Level3_LoadKeys_V13 _lcc56
#define Level3_RemoveSRM _lcc57
#define Level3_CreateUsageTableHeader _lcc61
#define Level3_LoadUsageTableHeader _lcc62
@@ -128,7 +129,7 @@ namespace wvoec3 {
#define Level3_IsSRMUpdateSupported _oecc53
#define Level3_GetCurrentSRMVersion _oecc54
#define Level3_LoadSRM _oecc55
#define Level3_LoadKeys _oecc56
#define Level3_LoadKeys_V13 _oecc56
#define Level3_RemoveSRM _oecc57
#define Level3_CreateUsageTableHeader _oecc61
#define Level3_LoadUsageTableHeader _oecc62
@@ -163,12 +164,14 @@ OEMCryptoResult Level3_GenerateSignature(OEMCrypto_SESSION session,
size_t message_length,
uint8_t* signature,
size_t* signature_length);
OEMCryptoResult Level3_LoadKeys(
// TODO(srujzs): Change this to LoadKeys once V14 has been implemented for
// Level 3.
OEMCryptoResult Level3_LoadKeys_V13(
OEMCrypto_SESSION session, const uint8_t* message, size_t message_length,
const uint8_t* signature, size_t signature_length,
const uint8_t* enc_mac_keys_iv, const uint8_t* enc_mac_keys,
size_t num_keys, const OEMCrypto_KeyObject* key_array, const uint8_t* pst,
size_t pst_length, const uint8_t* srm_requirement);
size_t num_keys, const OEMCrypto_KeyObject_V13* key_array,
const uint8_t* pst, size_t pst_length, const uint8_t* srm_requirement);
OEMCryptoResult Level3_RefreshKeys(OEMCrypto_SESSION session,
const uint8_t* message,
size_t message_length,

View File

@@ -1,41 +0,0 @@
# Copyright 2013 Google Inc. All Rights Reserved.
{
'target_defaults': {
# It seems that if one target uses -fPIC, then all targets will need that
# flag or else there will be linking errors. For generating a shared
# library, we need position independent code.
'cflags': [
'-g',
'-fPIC',
'-std=gnu++98',
],
'ldflags': [
'-fPIC',
],
},
'targets': [
{
'target_name': 'oec_mock',
'type': 'static_library',
'sources': [
'src/oemcrypto_keybox_testkey.cpp',
'src/oemcrypto_engine_device_properties.cpp',
],
'variables': {
'oec_mock_dir': '.',
},
'includes': [
'oec_mock_kernel.gypi',
],
},
{
'target_name': 'oec_mock_shared',
'type': 'shared_library',
'dependencies': [
'oec_mock'
# TODO(joeyparrish or fredgc): circular dependencies. 'wvcdm_sysdep'
],
},
],
}

View File

@@ -1,37 +0,0 @@
# Copyright 2013 Google Inc. All Rights Reserved.
# Define oec_mock_dir and include into your oec target.
{
'include_dirs': [
'<(oec_mock_dir)/../../core/include', # for lock.h and wvcdm_types.h
'<(oec_mock_dir)/../include',
'<(oec_mock_dir)/src',
],
'direct_dependent_settings': {
'include_dirs': [
'<(oec_mock_dir)/../../core/include',
'<(oec_mock_dir)/../include',
'<(oec_mock_dir)/src',
],
},
'sources': [
'<(oec_mock_dir)/src/keys.cpp',
'<(oec_mock_dir)/src/oemcrypto_auth_mock.cpp',
'<(oec_mock_dir)/src/oemcrypto_engine_mock.cpp',
'<(oec_mock_dir)/src/oemcrypto_key_mock.cpp',
'<(oec_mock_dir)/src/oemcrypto_keybox_mock.cpp',
'<(oec_mock_dir)/src/oemcrypto_mock.cpp',
'<(oec_mock_dir)/src/oemcrypto_nonce_table.cpp',
'<(oec_mock_dir)/src/oemcrypto_old_usage_table_mock.cpp',
'<(oec_mock_dir)/src/oemcrypto_rsa_key_shared.cpp',
'<(oec_mock_dir)/src/oemcrypto_session.cpp',
'<(oec_mock_dir)/src/oemcrypto_session_key_table.cpp',
'<(oec_mock_dir)/src/oemcrypto_usage_table_mock.cpp',
'<(oec_mock_dir)/src/wvcrc.cpp',
'<(oec_mock_dir)/src/oemcrypto_logging.cpp',
],
'dependencies': [
'<(oec_mock_dir)/../../third_party/boringssl/boringssl.gyp:crypto',
],
}

View File

@@ -95,8 +95,8 @@ class EntitlementKey : public Key {
const std::vector<uint8_t>& content_key() { return content_key_; }
const std::vector<uint8_t>& content_key_id() { return content_key_id_; }
const std::vector<uint8_t>& entitlement_key() { return Key::value(); }
bool SetContentKey(const std::vector<uint8_t>& content_key,
const std::vector<uint8_t>& content_key_id) {
bool SetContentKey(const std::vector<uint8_t>& content_key_id,
const std::vector<uint8_t>& content_key) {
content_key_.assign(content_key.begin(), content_key.end());
content_key_id_.assign(content_key_id.begin(), content_key_id.end());
return true;

View File

@@ -73,9 +73,8 @@ class ContentKeysContext : public SessionContextKeys {
virtual bool SetContentKey(const KeyId& entitlement_id,
const KeyId& content_key_id,
const std::vector<uint8_t>& content_key);
virtual bool GetEntitlementKey(
const KeyId& entitlement_id,
const std::vector<uint8_t>** entitlement_key);
virtual bool GetEntitlementKey(const KeyId& entitlement_id,
const std::vector<uint8_t>** entitlement_key);
private:
SessionKeyTable session_keys_;
@@ -105,8 +104,8 @@ bool ContentKeysContext::SetContentKey(
return false;
}
bool ContentKeysContext::GetEntitlementKey(
const KeyId& entitlement_id, const std::vector<uint8_t>** key) {
bool ContentKeysContext::GetEntitlementKey(const KeyId& entitlement_id,
const std::vector<uint8_t>** key) {
// Unsupported action for this type.
return false;
};
@@ -314,7 +313,7 @@ bool SessionContext::GenerateSignature(const uint8_t* message,
return false;
}
const uint8_t *mac_key = NULL;
const uint8_t* mac_key = NULL;
bool using_usage_mac_key_client = false;
if (mac_key_client_.size() == wvcdm::MAC_KEY_SIZE) {
// If we have a mac key, use it.
@@ -333,7 +332,7 @@ bool SessionContext::GenerateSignature(const uint8_t* message,
}
if (using_usage_mac_key_client &&
LogCategoryEnabled(kLoggingDumpDerivedKeys)) {
LogCategoryEnabled(kLoggingDumpDerivedKeys)) {
std::vector<uint8_t> usage_entry_mac_key_client(
usage_entry_->mac_key_client(),
usage_entry_->mac_key_client() + wvcdm::MAC_KEY_SIZE * sizeof(uint8_t));
@@ -620,9 +619,9 @@ OEMCryptoResult SessionContext::LoadKeys(
key_control_iv.assign(key_array[i].key_control_iv,
key_array[i].key_control_iv + wvcdm::KEY_IV_SIZE);
OEMCryptoResult result = InstallKey(
key_id, enc_key_data, key_data_iv, key_control, key_control_iv,
second_license);
OEMCryptoResult result =
InstallKey(key_id, enc_key_data, key_data_iv, key_control,
key_control_iv, second_license);
if (result != OEMCrypto_SUCCESS) {
status = result;
break;
@@ -683,8 +682,7 @@ OEMCryptoResult SessionContext::LoadKeys(
}
OEMCryptoResult SessionContext::LoadEntitledContentKeys(
size_t num_keys,
const OEMCrypto_EntitledContentKeyObject* key_array) {
size_t num_keys, const OEMCrypto_EntitledContentKeyObject* key_array) {
if (!key_array) {
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
@@ -694,9 +692,9 @@ OEMCryptoResult SessionContext::LoadEntitledContentKeys(
for (size_t i = 0; i < num_keys; ++i) {
const OEMCrypto_EntitledContentKeyObject* key_data = &key_array[i];
std::vector<uint8_t> entitlement_key_id;
entitlement_key_id.assign(key_data->entitlement_key_id,
key_data->entitlement_key_id +
key_data->entitlement_key_id_length);
entitlement_key_id.assign(
key_data->entitlement_key_id,
key_data->entitlement_key_id + key_data->entitlement_key_id_length);
const std::vector<uint8_t>* entitlement_key = NULL;
if (!session_keys_->GetEntitlementKey(entitlement_key_id,
@@ -716,12 +714,12 @@ OEMCryptoResult SessionContext::LoadEntitledContentKeys(
content_key_id.assign(
key_data->content_key_id,
key_data->content_key_id + key_data->content_key_id_length);
if (!DecryptEntitlement(*entitlement_key, iv,
encrypted_content_key, &content_key)) {
if (!DecryptMessage(*entitlement_key, iv, encrypted_content_key,
&content_key)) {
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (!session_keys_->SetContentKey(
entitlement_key_id, content_key_id, content_key)) {
if (!session_keys_->SetContentKey(entitlement_key_id, content_key_id,
content_key)) {
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
}
@@ -732,8 +730,7 @@ OEMCryptoResult SessionContext::InstallKey(
const KeyId& key_id, const std::vector<uint8_t>& key_data,
const std::vector<uint8_t>& key_data_iv,
const std::vector<uint8_t>& key_control,
const std::vector<uint8_t>& key_control_iv,
bool second_license) {
const std::vector<uint8_t>& key_control_iv, bool second_license) {
// Decrypt encrypted key_data using derived encryption key and offered iv
std::vector<uint8_t> content_key;
std::vector<uint8_t> key_control_str;
@@ -1339,26 +1336,7 @@ bool SessionContext::DecryptMessage(const std::vector<uint8_t>& key,
uint8_t iv_buffer[16];
memcpy(iv_buffer, &iv[0], 16);
AES_KEY aes_key;
AES_set_decrypt_key(&key[0], 128, &aes_key);
AES_cbc_encrypt(&message[0], &(decrypted->front()), message.size(), &aes_key,
iv_buffer, AES_DECRYPT);
return true;
}
bool SessionContext::DecryptEntitlement(
const std::vector<uint8_t>& key,
const std::vector<uint8_t>& iv,
const std::vector<uint8_t>& message,
std::vector<uint8_t>* decrypted) {
if (key.empty() || iv.empty() || message.empty() || !decrypted) {
LOGE("[DecryptMessage(): OEMCrypto_ERROR_INVALID_CONTEXT]");
return false;
}
decrypted->resize(message.size());
uint8_t iv_buffer[16];
memcpy(iv_buffer, &iv[0], 16);
AES_KEY aes_key;
AES_set_decrypt_key(&key[0], 256, &aes_key);
AES_set_decrypt_key(&key[0], key.size() * 8, &aes_key);
AES_cbc_encrypt(&message[0], &(decrypted->front()), message.size(), &aes_key,
iv_buffer, AES_DECRYPT);
return true;

View File

@@ -190,10 +190,6 @@ class SessionContext {
const std::vector<uint8_t>& iv,
const std::vector<uint8_t>& message,
std::vector<uint8_t>* decrypted);
bool DecryptEntitlement(const std::vector<uint8_t>& key,
const std::vector<uint8_t>& iv,
const std::vector<uint8_t>& message,
std::vector<uint8_t>* decrypted);
// Either verify the nonce or usage entry, as required by the key control
// block.
OEMCryptoResult CheckNonceOrEntry(const KeyControlBlock& key_control_block);

View File

@@ -0,0 +1,52 @@
OEM certificate generation tool
===================================================
## Supports
- Generating CSR (certificate signing request)
- Generating OEM intermediate certificate (for testing)
- Generating OEM leaf certificate chain
- Erasing file securely
- Getting CSR/certificate/certificate chain information
## Prerequirements
- Install pip: https://pip.pypa.io/en/stable/installing/
- Install python cryptography: https://cryptography.io/en/latest/installation/
## Usage
Run `python oem_certificate.py --help` to see available commands.
The arguments can be partially or fully loaded from a configuration file, for
example, if file "location.cfg" is,
```
-C=US
-ST=CA
-L=Kirkland
-O=Some Company
-OU=Some Unit
```
A command of
```bash
python oem_certificate.py generate_csr @location.cfg -CN TestDevice1 \
--output_csr_file=csr.pem --output_private_key_file=key.der
```
is equivalent to
```bash
python oem_certificate.py generate_csr -CN TestDevice1 -C=US -ST=CA \
-L=Kirkland -O='Some Company' -OU='Some Unit' --output_csr_file=csr.pem \
--output_private_key_file=key.der.
```
Note that
- The arguments in the config file must be one per line;
- The arguments should not be quoted in the config file.
The script uses a default configuration file 'oem_certificate.cfg', which will
be loaded automatically if exists.

View File

@@ -0,0 +1,492 @@
# Copyright 2017 Google Inc. All Rights Reserved.
"""OEM certificate generation tool.
Supports:
- Generating CSR (certificate signing request)
- Generating OEM intermediate certificate (for testing)
- Generating OEM leaf certificate chain
- Erasing file securely
- Getting CSR/certificate/certificate chain information
Prerequirements:
- Install pip: https://pip.pypa.io/en/stable/installing/
- Install python cryptography: https://cryptography.io/en/latest/installation/
Run 'python oem_certificate.py --help' to see available commands.
The arguments can be partially or fully loaded from a configuration file, for
example, if file "location.cfg" is,
-C=US
-ST=CA
-L=Kirkland
-O=Some Company
-OU=Some Unit
A command of
"python oem_certificate.py generate_csr @location.cfg -CN TestDevice1 "
"--output_csr_file=csr.pem --output_private_key_file=key.der",
is equivalent to
"python oem_certificate.py generate_csr -CN TestDevice1 -C=US -ST=CA "
"-L=Kirkland -O='Some Company' -OU='Some Unit' --output_csr_file=csr.pem "
"--output_private_key_file=key.der".
Note that (1) the arguments in the config file must be one per line; (2) the
arguments should not be quoted in the config file.
The script uses a default configuration file 'oem_certificate.cfg', which will
be loaded automatically if exists.
"""
import argparse
import datetime
import os
import sys
from cryptography import utils
from cryptography import x509
from cryptography.hazmat import backends
from cryptography.hazmat.backends import openssl
from cryptography.hazmat.backends.openssl import backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.x509 import oid
from pyasn1.codec.der import decoder
from pyasn1.codec.der import encoder
from pyasn1.type import univ
import six
class WidevineSystemId(x509.UnrecognizedExtension):
"""Implement WidevineSystemId x509 extension."""
# oid of Widevine system id.
oid = oid.ObjectIdentifier('1.3.6.1.4.1.11129.4.1.1')
def __init__(self, value):
"""Inits from raw bytes."""
super(WidevineSystemId, self).__init__(WidevineSystemId.oid, value)
@classmethod
def from_int_value(cls, int_value):
"""Construct from integer system id value."""
return cls(encoder.encode(univ.Integer(int_value)))
def int_value(self):
"""Return the integer value of the system id."""
return int(decoder.decode(self.value)[0])
class X509CertificateChain(object):
"""Implement x509 certificate chain object.
cryptography does not support certificate chain (pkcs7 container) right
now, so we have to implement it using low level functions directly.
"""
# Disable pylint on protected-access in class X509CertificateChain.
# pylint: disable=protected-access
def __init__(self, certificates):
"""Inits from certificate list."""
self._certificates = certificates
def __iter__(self):
"""Iterates through certificates."""
return self._certificates.__iter__()
@classmethod
def load_der(cls, certificate_chain_data):
"""Load from DER formatted data."""
bio = backend._bytes_to_bio(certificate_chain_data)
pkcs7 = backend._lib.d2i_PKCS7_bio(bio.bio, backend._ffi.NULL)
if pkcs7 == backend._ffi.NULL:
raise ValueError('Unable to load certificate chain')
pkcs7 = backend._ffi.gc(pkcs7, backend._lib.PKCS7_free)
if not backend._lib.PKCS7_type_is_signed(pkcs7):
raise ValueError('Invalid certificate chain')
x509_stack = pkcs7.d.sign.cert
certificates = []
for i in xrange(backend._lib.sk_X509_num(x509_stack)):
x509_value = backend._ffi.gc(
backend._lib.X509_dup(backend._lib.sk_X509_value(x509_stack, i)),
backend._lib.X509_free)
certificates.append(openssl.x509._Certificate(backend, x509_value))
return cls(certificates)
def der_bytes(self):
"""Return DER formatted bytes."""
x509_stack = backend._ffi.gc(backend._lib.sk_X509_new_null(),
backend._lib.sk_X509_free)
for certificate in self._certificates:
backend._lib.sk_X509_push(x509_stack, certificate._x509)
pkcs7_partial = 0x4000
p7 = backend._lib.PKCS7_sign(backend._ffi.NULL, backend._ffi.NULL,
x509_stack, backend._ffi.NULL, pkcs7_partial)
p7 = backend._ffi.gc(p7, backend._lib.PKCS7_free)
bio = backend._create_mem_bio_gc()
backend.openssl_assert(backend._lib.i2d_PKCS7_bio(bio, p7) == 1)
return backend._read_mem_bio(bio)
def _multiple_of_1024(key_size_str):
"""argparse custom type function for key size."""
key_size = int(key_size_str)
if key_size % 1024:
msg = '%r is not multiple of 1024' % key_size_str
raise argparse.ArgumentTypeError(msg)
return key_size
def _valid_date(date_str):
"""argparse custom type function dates."""
return datetime.datetime.strptime(date_str, '%Y-%m-%d')
def _get_encryption_algorithm(passphrase):
"""Convenient function to get the encryption algorithm."""
if passphrase:
return serialization.BestAvailableEncryption(passphrase)
else:
return serialization.NoEncryption()
def generate_csr(args):
"""Subparser handler for generating certificate signing request."""
key = rsa.generate_private_key(
public_exponent=65537,
key_size=args.key_size,
backend=backends.default_backend())
args.output_private_key_file.write(
key.private_bytes(
encoding=serialization.Encoding.DER,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=_get_encryption_algorithm(args.passphrase)))
x509_name = [
# Provide various details about who we are.
x509.NameAttribute(oid.NameOID.COUNTRY_NAME,
six.text_type(args.country_name)),
x509.NameAttribute(oid.NameOID.STATE_OR_PROVINCE_NAME,
six.text_type(args.state_or_province_name)),
x509.NameAttribute(oid.NameOID.LOCALITY_NAME,
six.text_type(args.locality_name)),
x509.NameAttribute(oid.NameOID.ORGANIZATION_NAME,
six.text_type(args.organization_name)),
x509.NameAttribute(oid.NameOID.ORGANIZATIONAL_UNIT_NAME,
six.text_type(args.organizational_unit_name)),
]
if args.common_name:
x509_name.append(x509.NameAttribute(oid.NameOID.COMMON_NAME,
six.text_type(args.common_name)))
csr = x509.CertificateSigningRequestBuilder().subject_name(
x509.Name(x509_name)).sign(key, hashes.SHA256(),
backends.default_backend())
args.output_csr_file.write(csr.public_bytes(serialization.Encoding.PEM))
def _random_serial_number():
"""Utility function to generate random serial number."""
return utils.int_from_bytes(os.urandom(16), byteorder='big')
def build_certificate(subject_name, issuer_name, system_id, not_valid_before,
valid_duration, public_key, signing_key, ca):
"""Utility function to build certificate."""
builder = x509.CertificateBuilder()
builder = builder.subject_name(subject_name).issuer_name(issuer_name)
if ca:
builder = builder.add_extension(
x509.SubjectKeyIdentifier.from_public_key(public_key), critical=False)
builder = builder.add_extension(
x509.AuthorityKeyIdentifier.from_issuer_public_key(
signing_key.public_key()),
critical=False)
builder = builder.add_extension(
x509.BasicConstraints(True, 0), critical=True)
if system_id:
builder = builder.add_extension(
WidevineSystemId.from_int_value(system_id), critical=False)
builder = builder.not_valid_before(not_valid_before).not_valid_after(
not_valid_before + datetime.timedelta(valid_duration)).serial_number(
_random_serial_number()).public_key(public_key)
return builder.sign(
private_key=signing_key,
algorithm=hashes.SHA256(),
backend=backends.default_backend())
def generate_intermediate_certificate(args):
"""Subparser handler for generating intermediate certificate."""
root_cert = x509.load_der_x509_certificate(args.root_certificate_file.read(),
backends.default_backend())
root_private_key = serialization.load_der_private_key(
args.root_private_key_file.read(),
password=args.root_private_key_passphrase,
backend=backends.default_backend())
if (root_private_key.public_key().public_numbers() !=
root_cert.public_key().public_numbers()):
raise ValueError('Root certificate does not match with root private key')
csr = x509.load_pem_x509_csr(args.csr_file.read(), backends.default_backend())
certificate = build_certificate(csr.subject, root_cert.subject,
args.system_id, args.not_valid_before,
args.valid_duration,
csr.public_key(), root_private_key, True)
args.output_certificate_file.write(
certificate.public_bytes(serialization.Encoding.DER))
def generate_leaf_certificate(args):
"""Subparser handler for generating leaf certificate."""
intermediate_cert_bytes = args.intermediate_certificate_file.read()
intermediate_cert = x509.load_der_x509_certificate(intermediate_cert_bytes,
backends.default_backend())
intermediate_private_key = serialization.load_der_private_key(
args.intermediate_private_key_file.read(),
password=args.intermediate_private_key_passphrase,
backend=backends.default_backend())
if (intermediate_private_key.public_key().public_numbers() !=
intermediate_cert.public_key().public_numbers()):
raise ValueError(
'Intermediate certificate does not match with intermediate private key')
system_id_raw_bytes = intermediate_cert.extensions.get_extension_for_oid(
WidevineSystemId.oid).value.value
system_id = WidevineSystemId(system_id_raw_bytes).int_value()
name_attributes = [
x509.NameAttribute(oid.NameOID.COMMON_NAME, u'{0}-leaf'.format(system_id))
]
name_attributes.extend([
attribute for attribute in intermediate_cert.subject
if attribute.oid != oid.NameOID.COMMON_NAME
])
subject_name = x509.Name(name_attributes)
leaf_private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=args.key_size,
backend=backends.default_backend())
args.output_private_key_file.write(
leaf_private_key.private_bytes(
encoding=serialization.Encoding.DER,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=_get_encryption_algorithm(args.passphrase)))
certificate = build_certificate(subject_name, intermediate_cert.subject,
system_id, args.not_valid_before,
args.valid_duration,
leaf_private_key.public_key(),
intermediate_private_key, False)
args.output_certificate_file.write(
X509CertificateChain([certificate, intermediate_cert]).der_bytes())
def secure_erase(args):
"""Subparser handler for secure erasing of a file."""
length = args.file.tell()
for _ in xrange(args.passes):
args.file.seek(0)
for _ in xrange(length):
args.file.write(os.urandom(1))
args.file.close()
os.remove(args.file.name)
def _certificate_as_string(cert):
"""Utility function to format certificate as string."""
lines = ['Certificate Subject Name:']
lines.extend([' {0}'.format(attribute) for attribute in cert.subject])
lines.append('Issuer Name:')
lines.extend([' {0}'.format(attribute) for attribute in cert.issuer])
lines.append('Key Size: {0.key_size}'.format(cert.public_key()))
try:
system_id_raw_bytes = cert.extensions.get_extension_for_oid(
WidevineSystemId.oid).value.value
lines.append('Widevine System Id: {0}'.format(
WidevineSystemId(system_id_raw_bytes).int_value()))
except x509.ExtensionNotFound:
pass
lines.append('Not valid before: {0.not_valid_before}'.format(cert))
lines.append('Not valid after: {0.not_valid_after}'.format(cert))
return '\n'.join(lines)
def _csr_as_string(csr):
"""Utility function to format csr as string."""
lines = ['CSR Subject Name:']
lines.extend([' {0}'.format(attribute) for attribute in csr.subject])
lines.append('Key Size: {0.key_size}'.format(csr.public_key()))
return '\n'.join(lines)
def _handle_csr(data):
"""Utility function for get_info to parse csr."""
return _csr_as_string(
x509.load_pem_x509_csr(data, backends.default_backend()))
def _handle_certificate(data):
"""Utility function for get_info to parse certificate."""
return _certificate_as_string(
x509.load_der_x509_certificate(data, backends.default_backend()))
def _handle_certificate_chain(data):
"""Utility function for get_info to parse certificate chain."""
return '\n\n'.join([
_certificate_as_string(certificate)
for certificate in X509CertificateChain.load_der(data)
])
def get_info(args, out=sys.stdout):
"""Subparser handler to get csr or certificate information."""
# The input is either a CSR or a certificate, or a certificate chain.
# Loop through the corresponding handlers one by one.
data = args.file.read()
for handler in [_handle_csr, _handle_certificate, _handle_certificate_chain]:
try:
out.write(handler(data))
return
except ValueError:
pass
print('Error occurred. The input file is not a valid CSR, nor certificate, '
'nor certificate chain.')
def create_parser():
"""Command line parsing."""
parser = argparse.ArgumentParser(fromfile_prefix_chars='@')
subparsers = parser.add_subparsers()
# Subparser for certificate signing request generation.
parser_csr = subparsers.add_parser(
'generate_csr', help='generate certificate signing request')
parser_csr.add_argument(
'--key_size',
type=_multiple_of_1024,
default=2048,
help='specify RSA key size.')
parser_csr.add_argument('-C', '--country_name', required=True)
parser_csr.add_argument('-ST', '--state_or_province_name', required=True)
parser_csr.add_argument('-L', '--locality_name', required=True)
parser_csr.add_argument('-O', '--organization_name', required=True)
parser_csr.add_argument('-OU', '--organizational_unit_name', required=True)
parser_csr.add_argument('-CN', '--common_name', required=False)
parser_csr.add_argument(
'--output_csr_file', type=argparse.FileType('wb'), required=True)
parser_csr.add_argument(
'--output_private_key_file', type=argparse.FileType('wb'), required=True)
parser_csr.add_argument(
'--passphrase',
help=('specify an optional passphrase to encrypt the private key. The '
'private key is not encrypted if omitted.'))
parser_csr.set_defaults(func=generate_csr)
# Subparser for intermediate certificate generation.
parser_intermediate_cert = subparsers.add_parser(
'generate_intermediate_certificate',
help=('generate intermediate certificate from csr. This should only be '
'used for testing.'))
parser_intermediate_cert.add_argument(
'--not_valid_before',
type=_valid_date,
default=datetime.datetime.today(),
help='certificate validity start date - format YYYY-MM-DD')
parser_intermediate_cert.add_argument(
'--valid_duration',
type=int,
default=3650,
help='the certificate will expire after the specified number of days.')
parser_intermediate_cert.add_argument('--system_id', type=int, required=True)
parser_intermediate_cert.add_argument(
'--csr_file', type=argparse.FileType('rb'), required=True)
parser_intermediate_cert.add_argument(
'--root_certificate_file', type=argparse.FileType('rb'), required=True)
parser_intermediate_cert.add_argument(
'--root_private_key_file', type=argparse.FileType('rb'), required=True)
parser_intermediate_cert.add_argument('--root_private_key_passphrase')
parser_intermediate_cert.add_argument(
'--output_certificate_file', type=argparse.FileType('wb'), required=True)
parser_intermediate_cert.set_defaults(func=generate_intermediate_certificate)
# Subparser for leaf certificate generation.
parser_leaf_cert = subparsers.add_parser(
'generate_leaf_certificate', help='generate leaf certificate')
parser_leaf_cert.add_argument(
'--key_size',
type=_multiple_of_1024,
default=2048,
help='specify RSA key size.')
parser_leaf_cert.add_argument(
'--not_valid_before',
type=_valid_date,
default=datetime.datetime.today(),
help='certificate validity start date - format YYYY-MM-DD')
parser_leaf_cert.add_argument(
'--valid_duration',
type=int,
default=3650,
help='the certificate will expire after the specified number of days.')
parser_leaf_cert.add_argument(
'--intermediate_certificate_file',
type=argparse.FileType('rb'),
required=True)
parser_leaf_cert.add_argument(
'--intermediate_private_key_file',
type=argparse.FileType('rb'),
required=True)
parser_leaf_cert.add_argument('--intermediate_private_key_passphrase')
parser_leaf_cert.add_argument(
'--output_certificate_file', type=argparse.FileType('wb'), required=True)
parser_leaf_cert.add_argument(
'--output_private_key_file', type=argparse.FileType('wb'), required=True)
parser_leaf_cert.add_argument(
'--passphrase',
help=('specify an optional passphrase to encrypt the private key. The '
'private key is not encrypted if omitted.'))
parser_leaf_cert.set_defaults(func=generate_leaf_certificate)
# Subparser for secure file erase.
parser_erase = subparsers.add_parser('erase', help='erase a file securely')
parser_erase.add_argument(
'-F', '--file', type=argparse.FileType('a'), required=True)
parser_erase.add_argument(
'--passes',
type=int,
default=3,
help=('the file will be overwritten with random patterns for the '
'specified number of passes'))
parser_erase.set_defaults(func=secure_erase)
# Subparser to get CSR or certificate or certificate chain metadata.
parser_info = subparsers.add_parser(
'info', help='get CSR or certificate metadata')
parser_info.add_argument(
'-F', '--file', type=argparse.FileType('rb'), required=True)
parser_info.set_defaults(func=get_info)
return parser
def main():
args = sys.argv[1:]
config_file_name = 'oem_certificate.cfg'
if os.path.isfile(config_file_name):
print 'Load from args default configuration file: ', config_file_name
args.append('@' + config_file_name)
parser_args = create_parser().parse_args(args)
parser_args.func(parser_args)
if __name__ == '__main__':
main()

View File

@@ -171,7 +171,6 @@ void DeviceFeatures::PickDerivedKey() {
}
if (uses_keybox) {
// If device uses a keybox, try to load the test keybox.
// TODO(jfore): Update to pass in parameters.
if (OEMCrypto_ERROR_NOT_IMPLEMENTED != OEMCrypto_LoadTestKeybox(NULL, 0)) {
derive_key_method = LOAD_TEST_KEYBOX;
} else if (IsTestKeyboxInstalled()) {

View File

@@ -566,7 +566,7 @@ void Session::FillRefreshMessage(size_t key_count, uint32_t control_bits,
encrypted_license().keys[i].key_id_length);
if (global_features.api_version == 14) {
// For version 14, we require OEMCrypto to handle kc14 for all licenses.
memcpy(license_.keys[i].control.verification, "kc14", 4);
memcpy(encrypted_license().keys[i].control.verification, "kc14", 4);
} else if (global_features.api_version == 13) {
// For version 13, we require OEMCrypto to handle kc13 for all licenses.
memcpy(encrypted_license().keys[i].control.verification, "kc13", 4);
@@ -596,7 +596,8 @@ void Session::EncryptAndSign() {
for (unsigned int i = 0; i < num_keys_; i++) {
memcpy(iv_buffer, &license_.keys[i].control_iv[0], wvcdm::KEY_IV_SIZE);
AES_set_encrypt_key(&license_.keys[i].key_data[0], 128, &aes_key);
AES_set_encrypt_key(&license_.keys[i].key_data[0],
license_.keys[i].key_data_length * 8, &aes_key);
AES_cbc_encrypt(
reinterpret_cast<const uint8_t*>(&license_.keys[i].control),
reinterpret_cast<uint8_t*>(&encrypted_license().keys[i].control),

View File

@@ -460,6 +460,220 @@ static const uint8_t kTestRSAPKCS8PrivateKeyInfo3_3072[] = {
0x7f, 0xad, 0x7d, 0xcd, 0x22, 0x06
};
// This is an RSA key where e*d != 1 mod phi. Instead, it uses the carmicahel
// totient. That means e*d = 1 mod lambda, where lambda = lcm(p-1, q-1).
static const uint8_t kTestKeyRSACarmichael_2048[] = {
0x30, 0x82, 0x04, 0xbc, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a,
0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
0x04, 0xa6, 0x30, 0x82, 0x04, 0xa2, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01,
0x01, 0x00, 0xa7, 0x00, 0x36, 0x60, 0x65, 0xdc, 0xbd, 0x54, 0x5a, 0x2a,
0x40, 0xb4, 0xe1, 0x15, 0x94, 0x58, 0x11, 0x4f, 0x94, 0x58, 0xdd, 0xde,
0xa7, 0x1f, 0x3c, 0x2c, 0xe0, 0x88, 0x09, 0x29, 0x61, 0x57, 0x67, 0x5e,
0x56, 0x7e, 0xee, 0x27, 0x8f, 0x59, 0x34, 0x9a, 0x2a, 0xaa, 0x9d, 0xb4,
0x4e, 0xfa, 0xa7, 0x6a, 0xd4, 0xc9, 0x7a, 0x53, 0xc1, 0x4e, 0x9f, 0xe3,
0x34, 0xf7, 0x3d, 0xb7, 0xc9, 0x10, 0x47, 0x4f, 0x28, 0xda, 0x3f, 0xce,
0x31, 0x7b, 0xfd, 0x06, 0x10, 0xeb, 0xf7, 0xbe, 0x92, 0xf9, 0xaf, 0xfb,
0x3e, 0x68, 0xda, 0xee, 0x1a, 0x64, 0x4c, 0xf3, 0x29, 0xf2, 0x73, 0x9e,
0x39, 0xd8, 0xf6, 0x6f, 0xd8, 0xb2, 0x80, 0x82, 0x71, 0x8e, 0xb5, 0xa4,
0xf2, 0xc2, 0x3e, 0xcd, 0x0a, 0xca, 0xb6, 0x04, 0xcd, 0x9a, 0x13, 0x8b,
0x54, 0x73, 0x54, 0x25, 0x54, 0x8c, 0xbe, 0x98, 0x7a, 0x67, 0xad, 0xda,
0xb3, 0x4e, 0xb3, 0xfa, 0x82, 0xa8, 0x4a, 0x67, 0x98, 0x56, 0x57, 0x54,
0x71, 0xcd, 0x12, 0x7f, 0xed, 0xa3, 0x01, 0xc0, 0x6a, 0x8b, 0x24, 0x03,
0x96, 0x88, 0xbe, 0x97, 0x66, 0x2a, 0xbc, 0x53, 0xc9, 0x83, 0x06, 0x51,
0x5a, 0x88, 0x65, 0x13, 0x18, 0xe4, 0x3a, 0xed, 0x6b, 0xf1, 0x61, 0x5b,
0x4c, 0xc8, 0x1e, 0xf4, 0xc2, 0xae, 0x08, 0x5e, 0x2d, 0x5f, 0xf8, 0x12,
0x7f, 0xa2, 0xfc, 0xbb, 0x21, 0x18, 0x30, 0xda, 0xfe, 0x40, 0xfb, 0x01,
0xca, 0x2e, 0x37, 0x0e, 0xce, 0xdd, 0x76, 0x87, 0x82, 0x46, 0x0b, 0x3a,
0x77, 0x8f, 0xc0, 0x72, 0x07, 0x2c, 0x7f, 0x9d, 0x1e, 0x86, 0x5b, 0xed,
0x27, 0x29, 0xdf, 0x03, 0x97, 0x62, 0xef, 0x44, 0xd3, 0x5b, 0x3d, 0xdb,
0x9c, 0x5e, 0x1b, 0x7b, 0x39, 0xb4, 0x0b, 0x6d, 0x04, 0x6b, 0xbb, 0xbb,
0x2c, 0x5f, 0xcf, 0xb3, 0x7a, 0x05, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02,
0x82, 0x01, 0x00, 0x0a, 0xf9, 0x4a, 0x19, 0x72, 0x88, 0x1b, 0x4e, 0xd8,
0x2f, 0xef, 0x99, 0x93, 0x32, 0xda, 0x51, 0x21, 0x2e, 0x14, 0x06, 0xf4,
0xe9, 0x65, 0x1c, 0xf9, 0xd4, 0xcf, 0x1a, 0x51, 0x53, 0xcd, 0x48, 0x33,
0x8c, 0x30, 0xed, 0xdd, 0x53, 0x6f, 0x29, 0x82, 0xf9, 0xe0, 0x74, 0xde,
0xb1, 0x13, 0x01, 0x88, 0x8f, 0xce, 0x14, 0xc1, 0x3b, 0x90, 0xb7, 0xcc,
0x6c, 0xdf, 0x35, 0xa1, 0xf2, 0x1a, 0x3d, 0xbe, 0x19, 0xd7, 0x0a, 0xe4,
0x67, 0x75, 0xbb, 0xfa, 0x87, 0xf4, 0x03, 0xb5, 0x7f, 0x69, 0xe4, 0x0b,
0x6a, 0xdc, 0x92, 0x82, 0x54, 0x64, 0x1a, 0x94, 0x2d, 0xe4, 0x63, 0x40,
0xb2, 0xb4, 0x85, 0x6b, 0xc8, 0x34, 0xba, 0xa2, 0x14, 0x30, 0x47, 0x1a,
0xeb, 0x90, 0x62, 0x30, 0x43, 0x44, 0x02, 0xc7, 0x0c, 0x30, 0xc0, 0x7f,
0xa9, 0x47, 0xae, 0xde, 0x68, 0x27, 0x92, 0xaa, 0x11, 0x95, 0xf5, 0x6f,
0xfc, 0x19, 0x8b, 0x49, 0xa0, 0x77, 0x9d, 0xc6, 0x13, 0x5d, 0x73, 0xff,
0x45, 0xa2, 0x4c, 0x3b, 0xf3, 0xe1, 0x2d, 0xd7, 0xc4, 0x70, 0xe2, 0x6c,
0x37, 0x99, 0x4c, 0x7a, 0xa9, 0x27, 0xf8, 0x3a, 0xd6, 0xfd, 0xc5, 0xd8,
0xfa, 0x2d, 0x0e, 0x71, 0x4b, 0x85, 0x7e, 0xce, 0xcb, 0x1c, 0x79, 0x71,
0xbd, 0xff, 0x63, 0x03, 0x6b, 0x58, 0x68, 0xe0, 0x14, 0xca, 0x5e, 0x85,
0xfd, 0xd0, 0xb7, 0xe0, 0x68, 0x14, 0xff, 0x2c, 0x82, 0x22, 0x26, 0x8a,
0x3f, 0xbf, 0xb0, 0x2a, 0x90, 0xff, 0xc7, 0x72, 0xfc, 0x66, 0x51, 0x3e,
0x51, 0x9f, 0x82, 0x68, 0x0e, 0xf3, 0x65, 0x74, 0x88, 0xab, 0xb7, 0xe5,
0x97, 0x5f, 0x0f, 0x3e, 0xe5, 0x3a, 0xbc, 0xa4, 0xa1, 0x50, 0xdd, 0x5c,
0x94, 0x4b, 0x0c, 0x70, 0x71, 0x48, 0x4e, 0xd0, 0xec, 0x46, 0x8f, 0xdf,
0xa2, 0x9a, 0xfe, 0xd8, 0x35, 0x1a, 0x2f, 0x02, 0x81, 0x81, 0x00, 0xcf,
0x73, 0x8c, 0xbe, 0x6d, 0x45, 0x2d, 0x0c, 0x0b, 0x5d, 0x5c, 0x6c, 0x75,
0x78, 0xcc, 0x35, 0x48, 0xb6, 0x98, 0xf1, 0xb9, 0x64, 0x60, 0x8c, 0x43,
0xeb, 0x85, 0xab, 0x04, 0xb6, 0x7d, 0x1b, 0x71, 0x75, 0x06, 0xe2, 0xda,
0x84, 0x68, 0x2e, 0x7f, 0x4c, 0xe3, 0x73, 0xb4, 0xde, 0x51, 0x4b, 0xb6,
0x51, 0x86, 0x7b, 0xd0, 0xe6, 0x4d, 0xf3, 0xd1, 0xcf, 0x1a, 0xfe, 0x7f,
0x3a, 0x83, 0xba, 0xb3, 0xe1, 0xff, 0x54, 0x13, 0x93, 0xd7, 0x9c, 0x27,
0x80, 0xb7, 0x1e, 0x64, 0x9e, 0xf7, 0x32, 0x2b, 0x46, 0x29, 0xf7, 0xf8,
0x18, 0x6c, 0xf7, 0x4a, 0xbe, 0x4b, 0xee, 0x96, 0x90, 0x8f, 0xa2, 0x16,
0x22, 0x6a, 0xcc, 0x48, 0x06, 0x74, 0x63, 0x43, 0x7f, 0x27, 0x22, 0x44,
0x3c, 0x2d, 0x3b, 0x62, 0xf1, 0x1c, 0xb4, 0x27, 0x33, 0x85, 0x26, 0x60,
0x48, 0x16, 0xcb, 0xef, 0xf8, 0xcd, 0x37, 0x02, 0x81, 0x81, 0x00, 0xce,
0x15, 0x43, 0x6e, 0x4b, 0x0f, 0xf9, 0x3f, 0x87, 0xc3, 0x41, 0x45, 0x97,
0xb1, 0x49, 0xc2, 0x19, 0x23, 0x87, 0xe4, 0x24, 0x1c, 0x64, 0xe5, 0x28,
0xcb, 0x43, 0x10, 0x14, 0x14, 0x0e, 0x19, 0xcb, 0xbb, 0xdb, 0xfd, 0x11,
0x9d, 0x17, 0x68, 0x78, 0x6d, 0x61, 0x70, 0x63, 0x3a, 0xa1, 0xb3, 0xf3,
0xa7, 0x5b, 0x0e, 0xff, 0xb7, 0x61, 0x11, 0x54, 0x91, 0x99, 0xe5, 0x91,
0x32, 0x2d, 0xeb, 0x3f, 0xd8, 0x3e, 0xf7, 0xd4, 0xcb, 0xd2, 0xa3, 0x41,
0xc1, 0xee, 0xc6, 0x92, 0x13, 0xeb, 0x7f, 0x42, 0x58, 0xf4, 0xd0, 0xb2,
0x74, 0x1d, 0x8e, 0x87, 0x46, 0xcd, 0x14, 0xb8, 0x16, 0xad, 0xb5, 0xbd,
0x0d, 0x6c, 0x95, 0x5a, 0x16, 0xbf, 0xe9, 0x53, 0xda, 0xfb, 0xed, 0x83,
0x51, 0x67, 0xa9, 0x55, 0xab, 0x54, 0x02, 0x95, 0x20, 0xa6, 0x68, 0x17,
0x53, 0xa8, 0xea, 0x43, 0xe5, 0xb0, 0xa3, 0x02, 0x81, 0x80, 0x67, 0x9c,
0x32, 0x83, 0x39, 0x57, 0xff, 0x73, 0xb0, 0x89, 0x64, 0x8b, 0xd6, 0xf0,
0x0a, 0x2d, 0xe2, 0xaf, 0x30, 0x1c, 0x2a, 0x97, 0xf3, 0x90, 0x9a, 0xab,
0x9b, 0x0b, 0x1b, 0x43, 0x79, 0xa0, 0xa7, 0x3d, 0xe7, 0xbe, 0x8d, 0x9c,
0xeb, 0xdb, 0xad, 0x40, 0xdd, 0xa9, 0x00, 0x80, 0xb8, 0xe1, 0xb3, 0xa1,
0x6c, 0x25, 0x92, 0xe4, 0x33, 0xb2, 0xbe, 0xeb, 0x4d, 0x74, 0x26, 0x5f,
0x37, 0x43, 0x9c, 0x6c, 0x17, 0x76, 0x0a, 0x81, 0x20, 0x82, 0xa1, 0x48,
0x2c, 0x2d, 0x45, 0xdc, 0x0f, 0x62, 0x43, 0x32, 0xbb, 0xeb, 0x59, 0x41,
0xf9, 0xca, 0x58, 0xce, 0x4a, 0x66, 0x53, 0x54, 0xc8, 0x28, 0x10, 0x1e,
0x08, 0x71, 0x16, 0xd8, 0x02, 0x71, 0x41, 0x58, 0xd4, 0x56, 0xcc, 0xf5,
0xb1, 0x31, 0xa3, 0xed, 0x00, 0x85, 0x09, 0xbf, 0x35, 0x95, 0x41, 0x29,
0x40, 0x19, 0x83, 0x35, 0x24, 0x69, 0x02, 0x81, 0x80, 0x55, 0x10, 0x0b,
0xcc, 0x3b, 0xa9, 0x75, 0x3d, 0x16, 0xe1, 0xae, 0x50, 0x76, 0x63, 0x94,
0x49, 0x4c, 0xad, 0x10, 0xcb, 0x47, 0x68, 0x7c, 0xf0, 0xe5, 0xdc, 0xb8,
0x6a, 0xab, 0x8e, 0xf7, 0x9f, 0x08, 0x2c, 0x1b, 0x8a, 0xa2, 0xb9, 0x8f,
0xce, 0xec, 0x5e, 0x61, 0xa8, 0xcd, 0x1c, 0x87, 0x60, 0x4a, 0xc3, 0x1a,
0x5f, 0xdf, 0x87, 0x26, 0xc6, 0xcb, 0x7c, 0x69, 0xe4, 0x8b, 0x01, 0x06,
0x59, 0x22, 0xfa, 0x34, 0x4b, 0x81, 0x87, 0x3c, 0x03, 0x6d, 0x02, 0x0a,
0x77, 0xe6, 0x15, 0xd8, 0xcf, 0xa7, 0x68, 0x26, 0x6c, 0xfa, 0x2b, 0xd9,
0x83, 0x5a, 0x2d, 0x0c, 0x3b, 0x70, 0x1c, 0xd4, 0x48, 0xbe, 0xa7, 0x0a,
0xd9, 0xbe, 0xdc, 0xc3, 0x0c, 0x21, 0x33, 0xb3, 0x66, 0xff, 0x1c, 0x1b,
0xc8, 0x96, 0x76, 0xe8, 0x6f, 0x44, 0x74, 0xbc, 0x9b, 0x1c, 0x7d, 0xc8,
0xac, 0x21, 0xa8, 0x6e, 0x37, 0x02, 0x81, 0x80, 0x2c, 0x7c, 0xad, 0x1e,
0x75, 0xf6, 0x69, 0x1d, 0xe7, 0xa6, 0xca, 0x74, 0x7d, 0x67, 0xc8, 0x65,
0x28, 0x66, 0xc4, 0x43, 0xa6, 0xbd, 0x40, 0x57, 0xae, 0xb7, 0x65, 0x2c,
0x52, 0xf9, 0xe4, 0xc7, 0x81, 0x7b, 0x56, 0xa3, 0xd2, 0x0d, 0xe8, 0x33,
0x70, 0xcf, 0x06, 0x84, 0xb3, 0x4e, 0x44, 0x50, 0x75, 0x61, 0x96, 0x86,
0x4b, 0xb6, 0x2b, 0xad, 0xf0, 0xad, 0x57, 0xd0, 0x37, 0x0d, 0x1d, 0x35,
0x50, 0xcb, 0x69, 0x22, 0x39, 0x29, 0xb9, 0x3a, 0xd3, 0x29, 0x23, 0x02,
0x60, 0xf7, 0xab, 0x30, 0x40, 0xda, 0x8e, 0x4d, 0x45, 0x70, 0x26, 0xf4,
0xa2, 0x0d, 0xd0, 0x64, 0x5d, 0x47, 0x3c, 0x18, 0xf4, 0xd4, 0x52, 0x95,
0x00, 0xae, 0x84, 0x6b, 0x47, 0xb2, 0x3c, 0x82, 0xd3, 0x72, 0x53, 0xde,
0x72, 0x2c, 0xf7, 0xc1, 0x22, 0x36, 0xd9, 0x18, 0x56, 0xfe, 0x39, 0x28,
0x33, 0xe0, 0xdb, 0x03,
};
// This is the same key as above, except the private key was chosen using the
// Euler totient.
static const uint8_t kTestKeyRSAEuler_2048[] = {
0x30, 0x82, 0x04, 0xbc, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a,
0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
0x04, 0xa6, 0x30, 0x82, 0x04, 0xa2, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01,
0x01, 0x00, 0xa7, 0x00, 0x36, 0x60, 0x65, 0xdc, 0xbd, 0x54, 0x5a, 0x2a,
0x40, 0xb4, 0xe1, 0x15, 0x94, 0x58, 0x11, 0x4f, 0x94, 0x58, 0xdd, 0xde,
0xa7, 0x1f, 0x3c, 0x2c, 0xe0, 0x88, 0x09, 0x29, 0x61, 0x57, 0x67, 0x5e,
0x56, 0x7e, 0xee, 0x27, 0x8f, 0x59, 0x34, 0x9a, 0x2a, 0xaa, 0x9d, 0xb4,
0x4e, 0xfa, 0xa7, 0x6a, 0xd4, 0xc9, 0x7a, 0x53, 0xc1, 0x4e, 0x9f, 0xe3,
0x34, 0xf7, 0x3d, 0xb7, 0xc9, 0x10, 0x47, 0x4f, 0x28, 0xda, 0x3f, 0xce,
0x31, 0x7b, 0xfd, 0x06, 0x10, 0xeb, 0xf7, 0xbe, 0x92, 0xf9, 0xaf, 0xfb,
0x3e, 0x68, 0xda, 0xee, 0x1a, 0x64, 0x4c, 0xf3, 0x29, 0xf2, 0x73, 0x9e,
0x39, 0xd8, 0xf6, 0x6f, 0xd8, 0xb2, 0x80, 0x82, 0x71, 0x8e, 0xb5, 0xa4,
0xf2, 0xc2, 0x3e, 0xcd, 0x0a, 0xca, 0xb6, 0x04, 0xcd, 0x9a, 0x13, 0x8b,
0x54, 0x73, 0x54, 0x25, 0x54, 0x8c, 0xbe, 0x98, 0x7a, 0x67, 0xad, 0xda,
0xb3, 0x4e, 0xb3, 0xfa, 0x82, 0xa8, 0x4a, 0x67, 0x98, 0x56, 0x57, 0x54,
0x71, 0xcd, 0x12, 0x7f, 0xed, 0xa3, 0x01, 0xc0, 0x6a, 0x8b, 0x24, 0x03,
0x96, 0x88, 0xbe, 0x97, 0x66, 0x2a, 0xbc, 0x53, 0xc9, 0x83, 0x06, 0x51,
0x5a, 0x88, 0x65, 0x13, 0x18, 0xe4, 0x3a, 0xed, 0x6b, 0xf1, 0x61, 0x5b,
0x4c, 0xc8, 0x1e, 0xf4, 0xc2, 0xae, 0x08, 0x5e, 0x2d, 0x5f, 0xf8, 0x12,
0x7f, 0xa2, 0xfc, 0xbb, 0x21, 0x18, 0x30, 0xda, 0xfe, 0x40, 0xfb, 0x01,
0xca, 0x2e, 0x37, 0x0e, 0xce, 0xdd, 0x76, 0x87, 0x82, 0x46, 0x0b, 0x3a,
0x77, 0x8f, 0xc0, 0x72, 0x07, 0x2c, 0x7f, 0x9d, 0x1e, 0x86, 0x5b, 0xed,
0x27, 0x29, 0xdf, 0x03, 0x97, 0x62, 0xef, 0x44, 0xd3, 0x5b, 0x3d, 0xdb,
0x9c, 0x5e, 0x1b, 0x7b, 0x39, 0xb4, 0x0b, 0x6d, 0x04, 0x6b, 0xbb, 0xbb,
0x2c, 0x5f, 0xcf, 0xb3, 0x7a, 0x05, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02,
0x82, 0x01, 0x00, 0x5e, 0x79, 0x65, 0x49, 0xa5, 0x76, 0x79, 0xf9, 0x05,
0x45, 0x0f, 0xf4, 0x03, 0xbd, 0xa4, 0x7d, 0x29, 0xd5, 0xde, 0x33, 0x63,
0xd8, 0xb8, 0xac, 0x97, 0xeb, 0x3f, 0x5e, 0x55, 0xe8, 0x7d, 0xf3, 0xe7,
0x3b, 0x5c, 0x2d, 0x54, 0x67, 0x36, 0xd6, 0x1d, 0x46, 0xf5, 0xca, 0x2d,
0x8b, 0x3a, 0x7e, 0xdc, 0x45, 0x38, 0x79, 0x7e, 0x65, 0x71, 0x5f, 0x1c,
0x5e, 0x79, 0xb1, 0x40, 0xcd, 0xfe, 0xc5, 0xe1, 0xc1, 0x6b, 0x78, 0x04,
0x4e, 0x8e, 0x79, 0xf9, 0x0a, 0xfc, 0x79, 0xb1, 0x5e, 0xb3, 0x60, 0xe3,
0x68, 0x7b, 0xc6, 0xef, 0xcb, 0x71, 0x4c, 0xba, 0xa7, 0x79, 0x5c, 0x7a,
0x81, 0xd1, 0x71, 0xe7, 0x00, 0x21, 0x13, 0xe2, 0x55, 0x69, 0x0e, 0x75,
0xbe, 0x09, 0xc3, 0x4f, 0xa9, 0xc9, 0x68, 0x22, 0x0e, 0x97, 0x8d, 0x89,
0x6e, 0xf1, 0xe8, 0x88, 0x7a, 0xd1, 0xd9, 0x09, 0x5d, 0xd3, 0x28, 0x78,
0x25, 0x0b, 0x1c, 0x47, 0x73, 0x25, 0xcc, 0x21, 0xb6, 0xda, 0xc6, 0x24,
0x5a, 0xd0, 0x37, 0x14, 0x46, 0xc7, 0x94, 0x69, 0xe4, 0x43, 0x6f, 0x47,
0xde, 0x00, 0x33, 0x4d, 0x8f, 0x95, 0x72, 0xfa, 0x68, 0x71, 0x17, 0x66,
0x12, 0x1a, 0x87, 0x27, 0xf7, 0xef, 0x7e, 0xe0, 0x35, 0x58, 0xf2, 0x4d,
0x6f, 0x35, 0x01, 0xaa, 0x96, 0xe2, 0x3d, 0x51, 0x13, 0x86, 0x9c, 0x79,
0xd0, 0xb7, 0xb6, 0x64, 0xe8, 0x86, 0x65, 0x50, 0xbf, 0xcc, 0x27, 0x53,
0x1f, 0x51, 0xd4, 0xca, 0xbe, 0xf5, 0xdd, 0x77, 0x70, 0x98, 0x0f, 0xee,
0xa8, 0x96, 0x07, 0x5f, 0x45, 0x6a, 0x7a, 0x0d, 0x03, 0x9c, 0x4f, 0x29,
0xf6, 0x06, 0xf3, 0x5d, 0x58, 0x6c, 0x47, 0xd0, 0x96, 0xa9, 0x03, 0x17,
0xbb, 0x4e, 0xc9, 0x21, 0xe0, 0xac, 0xcd, 0x78, 0x78, 0xb2, 0xfe, 0x81,
0xb2, 0x51, 0x53, 0xa6, 0x1f, 0x98, 0x45, 0x02, 0x81, 0x81, 0x00, 0xcf,
0x73, 0x8c, 0xbe, 0x6d, 0x45, 0x2d, 0x0c, 0x0b, 0x5d, 0x5c, 0x6c, 0x75,
0x78, 0xcc, 0x35, 0x48, 0xb6, 0x98, 0xf1, 0xb9, 0x64, 0x60, 0x8c, 0x43,
0xeb, 0x85, 0xab, 0x04, 0xb6, 0x7d, 0x1b, 0x71, 0x75, 0x06, 0xe2, 0xda,
0x84, 0x68, 0x2e, 0x7f, 0x4c, 0xe3, 0x73, 0xb4, 0xde, 0x51, 0x4b, 0xb6,
0x51, 0x86, 0x7b, 0xd0, 0xe6, 0x4d, 0xf3, 0xd1, 0xcf, 0x1a, 0xfe, 0x7f,
0x3a, 0x83, 0xba, 0xb3, 0xe1, 0xff, 0x54, 0x13, 0x93, 0xd7, 0x9c, 0x27,
0x80, 0xb7, 0x1e, 0x64, 0x9e, 0xf7, 0x32, 0x2b, 0x46, 0x29, 0xf7, 0xf8,
0x18, 0x6c, 0xf7, 0x4a, 0xbe, 0x4b, 0xee, 0x96, 0x90, 0x8f, 0xa2, 0x16,
0x22, 0x6a, 0xcc, 0x48, 0x06, 0x74, 0x63, 0x43, 0x7f, 0x27, 0x22, 0x44,
0x3c, 0x2d, 0x3b, 0x62, 0xf1, 0x1c, 0xb4, 0x27, 0x33, 0x85, 0x26, 0x60,
0x48, 0x16, 0xcb, 0xef, 0xf8, 0xcd, 0x37, 0x02, 0x81, 0x81, 0x00, 0xce,
0x15, 0x43, 0x6e, 0x4b, 0x0f, 0xf9, 0x3f, 0x87, 0xc3, 0x41, 0x45, 0x97,
0xb1, 0x49, 0xc2, 0x19, 0x23, 0x87, 0xe4, 0x24, 0x1c, 0x64, 0xe5, 0x28,
0xcb, 0x43, 0x10, 0x14, 0x14, 0x0e, 0x19, 0xcb, 0xbb, 0xdb, 0xfd, 0x11,
0x9d, 0x17, 0x68, 0x78, 0x6d, 0x61, 0x70, 0x63, 0x3a, 0xa1, 0xb3, 0xf3,
0xa7, 0x5b, 0x0e, 0xff, 0xb7, 0x61, 0x11, 0x54, 0x91, 0x99, 0xe5, 0x91,
0x32, 0x2d, 0xeb, 0x3f, 0xd8, 0x3e, 0xf7, 0xd4, 0xcb, 0xd2, 0xa3, 0x41,
0xc1, 0xee, 0xc6, 0x92, 0x13, 0xeb, 0x7f, 0x42, 0x58, 0xf4, 0xd0, 0xb2,
0x74, 0x1d, 0x8e, 0x87, 0x46, 0xcd, 0x14, 0xb8, 0x16, 0xad, 0xb5, 0xbd,
0x0d, 0x6c, 0x95, 0x5a, 0x16, 0xbf, 0xe9, 0x53, 0xda, 0xfb, 0xed, 0x83,
0x51, 0x67, 0xa9, 0x55, 0xab, 0x54, 0x02, 0x95, 0x20, 0xa6, 0x68, 0x17,
0x53, 0xa8, 0xea, 0x43, 0xe5, 0xb0, 0xa3, 0x02, 0x81, 0x80, 0x67, 0x9c,
0x32, 0x83, 0x39, 0x57, 0xff, 0x73, 0xb0, 0x89, 0x64, 0x8b, 0xd6, 0xf0,
0x0a, 0x2d, 0xe2, 0xaf, 0x30, 0x1c, 0x2a, 0x97, 0xf3, 0x90, 0x9a, 0xab,
0x9b, 0x0b, 0x1b, 0x43, 0x79, 0xa0, 0xa7, 0x3d, 0xe7, 0xbe, 0x8d, 0x9c,
0xeb, 0xdb, 0xad, 0x40, 0xdd, 0xa9, 0x00, 0x80, 0xb8, 0xe1, 0xb3, 0xa1,
0x6c, 0x25, 0x92, 0xe4, 0x33, 0xb2, 0xbe, 0xeb, 0x4d, 0x74, 0x26, 0x5f,
0x37, 0x43, 0x9c, 0x6c, 0x17, 0x76, 0x0a, 0x81, 0x20, 0x82, 0xa1, 0x48,
0x2c, 0x2d, 0x45, 0xdc, 0x0f, 0x62, 0x43, 0x32, 0xbb, 0xeb, 0x59, 0x41,
0xf9, 0xca, 0x58, 0xce, 0x4a, 0x66, 0x53, 0x54, 0xc8, 0x28, 0x10, 0x1e,
0x08, 0x71, 0x16, 0xd8, 0x02, 0x71, 0x41, 0x58, 0xd4, 0x56, 0xcc, 0xf5,
0xb1, 0x31, 0xa3, 0xed, 0x00, 0x85, 0x09, 0xbf, 0x35, 0x95, 0x41, 0x29,
0x40, 0x19, 0x83, 0x35, 0x24, 0x69, 0x02, 0x81, 0x80, 0x55, 0x10, 0x0b,
0xcc, 0x3b, 0xa9, 0x75, 0x3d, 0x16, 0xe1, 0xae, 0x50, 0x76, 0x63, 0x94,
0x49, 0x4c, 0xad, 0x10, 0xcb, 0x47, 0x68, 0x7c, 0xf0, 0xe5, 0xdc, 0xb8,
0x6a, 0xab, 0x8e, 0xf7, 0x9f, 0x08, 0x2c, 0x1b, 0x8a, 0xa2, 0xb9, 0x8f,
0xce, 0xec, 0x5e, 0x61, 0xa8, 0xcd, 0x1c, 0x87, 0x60, 0x4a, 0xc3, 0x1a,
0x5f, 0xdf, 0x87, 0x26, 0xc6, 0xcb, 0x7c, 0x69, 0xe4, 0x8b, 0x01, 0x06,
0x59, 0x22, 0xfa, 0x34, 0x4b, 0x81, 0x87, 0x3c, 0x03, 0x6d, 0x02, 0x0a,
0x77, 0xe6, 0x15, 0xd8, 0xcf, 0xa7, 0x68, 0x26, 0x6c, 0xfa, 0x2b, 0xd9,
0x83, 0x5a, 0x2d, 0x0c, 0x3b, 0x70, 0x1c, 0xd4, 0x48, 0xbe, 0xa7, 0x0a,
0xd9, 0xbe, 0xdc, 0xc3, 0x0c, 0x21, 0x33, 0xb3, 0x66, 0xff, 0x1c, 0x1b,
0xc8, 0x96, 0x76, 0xe8, 0x6f, 0x44, 0x74, 0xbc, 0x9b, 0x1c, 0x7d, 0xc8,
0xac, 0x21, 0xa8, 0x6e, 0x37, 0x02, 0x81, 0x80, 0x2c, 0x7c, 0xad, 0x1e,
0x75, 0xf6, 0x69, 0x1d, 0xe7, 0xa6, 0xca, 0x74, 0x7d, 0x67, 0xc8, 0x65,
0x28, 0x66, 0xc4, 0x43, 0xa6, 0xbd, 0x40, 0x57, 0xae, 0xb7, 0x65, 0x2c,
0x52, 0xf9, 0xe4, 0xc7, 0x81, 0x7b, 0x56, 0xa3, 0xd2, 0x0d, 0xe8, 0x33,
0x70, 0xcf, 0x06, 0x84, 0xb3, 0x4e, 0x44, 0x50, 0x75, 0x61, 0x96, 0x86,
0x4b, 0xb6, 0x2b, 0xad, 0xf0, 0xad, 0x57, 0xd0, 0x37, 0x0d, 0x1d, 0x35,
0x50, 0xcb, 0x69, 0x22, 0x39, 0x29, 0xb9, 0x3a, 0xd3, 0x29, 0x23, 0x02,
0x60, 0xf7, 0xab, 0x30, 0x40, 0xda, 0x8e, 0x4d, 0x45, 0x70, 0x26, 0xf4,
0xa2, 0x0d, 0xd0, 0x64, 0x5d, 0x47, 0x3c, 0x18, 0xf4, 0xd4, 0x52, 0x95,
0x00, 0xae, 0x84, 0x6b, 0x47, 0xb2, 0x3c, 0x82, 0xd3, 0x72, 0x53, 0xde,
0x72, 0x2c, 0xf7, 0xc1, 0x22, 0x36, 0xd9, 0x18, 0x56, 0xfe, 0x39, 0x28,
0x33, 0xe0, 0xdb, 0x03,
};
} // namespace wvoec
#endif // CDM_OEC_TEST_DATA_H_

View File

@@ -2445,6 +2445,24 @@ TEST_F(OEMCryptoLoadsCertificate, TestLargeRSAKey3072) {
ASSERT_NO_FATAL_FAILURE(s.TestDecryptCTR());
}
// Test an RSA key certificate which has a private key generated using the
// Carmichael totient.
TEST_F(OEMCryptoLoadsCertificate, TestCarmichaelRSAKey) {
encoded_rsa_key_.assign(
kTestKeyRSACarmichael_2048,
kTestKeyRSACarmichael_2048 + sizeof(kTestKeyRSACarmichael_2048));
CreateWrappedRSAKey(kSign_RSASSA_PSS, true);
Session s;
ASSERT_NO_FATAL_FAILURE(s.open());
ASSERT_NO_FATAL_FAILURE(s.PreparePublicKey(&encoded_rsa_key_[0],
encoded_rsa_key_.size()));
ASSERT_NO_FATAL_FAILURE(s.InstallRSASessionTestKey(wrapped_rsa_key_));
ASSERT_NO_FATAL_FAILURE(s.FillSimpleMessage(kDuration, 0, 0));
ASSERT_NO_FATAL_FAILURE(s.EncryptAndSign());
ASSERT_NO_FATAL_FAILURE(s.LoadTestKeys());
ASSERT_NO_FATAL_FAILURE(s.TestDecryptCTR());
}
// Devices that load certificates, should at least support RSA 2048 keys.
TEST_F(OEMCryptoLoadsCertificate, SupportsCertificatesAPI13) {
ASSERT_NE(0u,
@@ -5265,7 +5283,7 @@ TEST_F(UsageTableDefragTest, ReloadUsageEntryBadData) {
ASSERT_NO_FATAL_FAILURE(s.open());
ASSERT_NO_FATAL_FAILURE(InstallTestSessionKeys(&s));
vector<uint8_t> data = s.encrypted_usage_entry();
ASSERT_LT(0, data.size());
ASSERT_LT(0UL, data.size());
data[0] ^= 42;
// Error could be signature or verification error.
ASSERT_NE(OEMCrypto_SUCCESS,