Refactor oemcrypto mock into stand alone reference code
Merge from Widevine repo of http://go/wvgerrit/46204 Refactor utility code - split the mock, step 1 Merge from Widevine repo of http://go/wvgerrit/46205 Move some OEMCrypto types to common header - split the mock, step 2 Merge from Widevine repo of http://go/wvgerrit/46206 Split mock into two -- step 3 Merge from Widevine repo of http://go/wvgerrit/47460 Split the mock into two -- step 3.5 The CL moves several files used by oemcrypto and cdm into a common subdirectory, so that it may more easily be shared with partners. The CORE_DISALLOW_COPY_AND_ASSIGN macro was moved to its own header in the util/include directory. This CL removes some references to the mock from other code, and puts some constants and types, such as the definition of the keybox, into a header in oemcrypto. Test: tested as part of http://go/ag/4674759 bug: 76393338 Change-Id: I75b4bde7062ed8ee572c97ebc2f4da018f4be0c9
This commit is contained in:
10
libwvdrmengine/oemcrypto/ref/src/keys.cpp
Normal file
10
libwvdrmengine/oemcrypto/ref/src/keys.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
// If you are using a baked-in certificate instead of supporting keyboxes,
|
||||
// you should have received a keys.cpp from Widevine that replaces this file.
|
||||
//
|
||||
// If you are not using a baked-in certificate, then you may ignore this file,
|
||||
// as it intentionally defines an empty key.
|
||||
|
||||
#include "keys.h"
|
||||
|
||||
const uint8_t kPrivateKey[] = { 0, };
|
||||
const size_t kPrivateKeySize = 0;
|
||||
11
libwvdrmengine/oemcrypto/ref/src/keys.h
Normal file
11
libwvdrmengine/oemcrypto/ref/src/keys.h
Normal file
@@ -0,0 +1,11 @@
|
||||
// This header is used to access the baked-in certificate if one is in use.
|
||||
#ifndef KEYS_H_
|
||||
#define KEYS_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
extern const uint8_t kPrivateKey[];
|
||||
extern const size_t kPrivateKeySize;
|
||||
|
||||
#endif // KEYS_H_
|
||||
392
libwvdrmengine/oemcrypto/ref/src/oem_cert.cpp
Normal file
392
libwvdrmengine/oemcrypto/ref/src/oem_cert.cpp
Normal file
@@ -0,0 +1,392 @@
|
||||
// This file contains the test OEM cert.
|
||||
|
||||
#include "oem_cert.h"
|
||||
|
||||
namespace wvoec_ref {
|
||||
|
||||
extern const uint32_t kOEMSystemId_Prod = 7346;
|
||||
|
||||
extern const uint8_t kOEMPrivateKey_Prod[] = {
|
||||
0x30, 0x82, 0x06, 0xfe, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a,
|
||||
0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
|
||||
0x06, 0xe8, 0x30, 0x82, 0x06, 0xe4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01,
|
||||
0x81, 0x00, 0xf5, 0x09, 0x64, 0x4a, 0x26, 0xfe, 0xc0, 0x98, 0x55, 0x6a,
|
||||
0x1d, 0x5d, 0x1c, 0xc7, 0x38, 0xaf, 0xfd, 0x49, 0x9e, 0x85, 0x3f, 0xd6,
|
||||
0x45, 0x0e, 0x99, 0x09, 0x85, 0x69, 0x84, 0x3c, 0xfe, 0x72, 0xa5, 0x56,
|
||||
0xfa, 0x11, 0x4f, 0x6b, 0x7d, 0x32, 0x2b, 0x0c, 0xbf, 0x8f, 0xac, 0x47,
|
||||
0x96, 0x22, 0x82, 0x3d, 0xf5, 0x64, 0x74, 0x7e, 0x62, 0x68, 0x74, 0xcd,
|
||||
0x0a, 0xec, 0x84, 0xc5, 0x15, 0x06, 0x0e, 0x5a, 0x2f, 0x20, 0xe3, 0xc9,
|
||||
0x67, 0xcd, 0xdd, 0x01, 0xb8, 0xb3, 0x18, 0x87, 0x8c, 0xa9, 0x58, 0x86,
|
||||
0x0f, 0xb6, 0xc3, 0x42, 0x7e, 0x87, 0x48, 0x5e, 0x10, 0x49, 0xc7, 0xd7,
|
||||
0xb7, 0xb8, 0xa6, 0x34, 0x08, 0x0c, 0x94, 0xf4, 0xbb, 0x2a, 0x06, 0xa4,
|
||||
0x4f, 0xec, 0xbc, 0xc4, 0x37, 0xbe, 0x99, 0x10, 0x23, 0x37, 0x24, 0xb1,
|
||||
0xdf, 0xcb, 0xe6, 0x3f, 0xc1, 0xf0, 0x0f, 0x04, 0x03, 0xc8, 0xb0, 0x1e,
|
||||
0xd6, 0xb8, 0xae, 0x77, 0xe1, 0x4d, 0x6d, 0x97, 0x69, 0x6d, 0x8a, 0x73,
|
||||
0x66, 0x32, 0x57, 0x6f, 0xcf, 0xea, 0x1e, 0x7b, 0x87, 0x03, 0x75, 0xb1,
|
||||
0xef, 0x83, 0x64, 0x26, 0xf1, 0x3f, 0xbf, 0xe6, 0x28, 0x03, 0x72, 0x57,
|
||||
0xbf, 0x47, 0x29, 0x99, 0x8f, 0x74, 0x1d, 0x01, 0x16, 0xad, 0xb2, 0xdf,
|
||||
0x80, 0xa4, 0xd3, 0x8b, 0xeb, 0x61, 0xd1, 0x40, 0x68, 0xb9, 0xa2, 0xa5,
|
||||
0xef, 0x2b, 0xe5, 0x78, 0xe8, 0x28, 0x88, 0x87, 0xb7, 0x53, 0x49, 0xbb,
|
||||
0xe4, 0xea, 0x0d, 0x5e, 0x96, 0xa5, 0xdd, 0x1f, 0x0b, 0x25, 0x8b, 0xb5,
|
||||
0x95, 0x46, 0xe7, 0xba, 0xb8, 0xc4, 0x0a, 0x36, 0xb1, 0x89, 0xeb, 0x27,
|
||||
0x5d, 0xd9, 0x97, 0x24, 0x59, 0xa3, 0x9b, 0xb0, 0x23, 0x0b, 0xd2, 0xec,
|
||||
0x65, 0x91, 0xf9, 0xf0, 0xa0, 0x74, 0x5f, 0xb4, 0xce, 0x22, 0x27, 0x18,
|
||||
0x37, 0xe2, 0x4b, 0xfc, 0x91, 0xf9, 0x09, 0x15, 0xe6, 0xdb, 0x06, 0x9b,
|
||||
0x4d, 0x82, 0xdc, 0x36, 0x14, 0x48, 0xc6, 0xd5, 0x87, 0xca, 0xec, 0x5a,
|
||||
0xa2, 0x29, 0x33, 0xef, 0x22, 0x0c, 0x4b, 0xbf, 0xe7, 0x2f, 0x95, 0xe1,
|
||||
0xd3, 0xa5, 0xd8, 0xaa, 0x44, 0x77, 0x29, 0xa3, 0x20, 0x33, 0xd2, 0x51,
|
||||
0xa2, 0xf9, 0x4a, 0x6f, 0xf7, 0x3e, 0xf7, 0x0b, 0x8a, 0xec, 0xc1, 0x99,
|
||||
0x1d, 0x47, 0xf3, 0x74, 0x02, 0x04, 0xab, 0x8e, 0x62, 0x4c, 0x9e, 0x00,
|
||||
0xc2, 0x84, 0xd7, 0xd0, 0xf8, 0xe4, 0x1c, 0x9d, 0x98, 0x15, 0xa8, 0x8f,
|
||||
0x08, 0x98, 0x4e, 0x5a, 0xfa, 0xd6, 0x60, 0x87, 0x12, 0xdc, 0x8e, 0xfd,
|
||||
0xcb, 0xb3, 0x13, 0x97, 0x7a, 0xa8, 0x8c, 0x56, 0x2e, 0x49, 0x26, 0x60,
|
||||
0xe9, 0x4a, 0xdc, 0xec, 0x3f, 0xf0, 0x94, 0xcd, 0x90, 0x8e, 0x7c, 0x21,
|
||||
0x3f, 0x80, 0x14, 0x33, 0xdd, 0xb0, 0x00, 0xe2, 0x09, 0x37, 0x06, 0xdd,
|
||||
0x17, 0x69, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x81, 0x00,
|
||||
0xa1, 0xc9, 0x44, 0xad, 0x6d, 0x17, 0xd1, 0x04, 0x03, 0x89, 0x5f, 0xbf,
|
||||
0xe5, 0xcb, 0x68, 0x13, 0x52, 0xf2, 0x33, 0xb7, 0x19, 0x12, 0x19, 0x60,
|
||||
0x6d, 0x0d, 0x0b, 0x48, 0x42, 0xe6, 0x9e, 0xbe, 0x05, 0x8a, 0xea, 0xeb,
|
||||
0x58, 0xfb, 0xc8, 0x9a, 0xc2, 0x2f, 0xd5, 0x9f, 0x40, 0x09, 0xb8, 0x08,
|
||||
0x2a, 0xe4, 0x4b, 0xcc, 0xba, 0xd9, 0xe3, 0x91, 0xc2, 0x64, 0xcb, 0x6c,
|
||||
0xa4, 0xb1, 0x17, 0x93, 0x7b, 0x10, 0x72, 0x83, 0x8d, 0xc2, 0xa2, 0x46,
|
||||
0x1b, 0x41, 0x12, 0xb9, 0x35, 0x5d, 0xf2, 0x32, 0xb1, 0xdf, 0x3a, 0x2a,
|
||||
0xda, 0xbb, 0x61, 0x9d, 0x62, 0xdb, 0xb0, 0x77, 0x76, 0x7a, 0x68, 0xb4,
|
||||
0x83, 0x10, 0x61, 0xac, 0x25, 0x01, 0x7d, 0x3e, 0x5f, 0x4a, 0x47, 0xf7,
|
||||
0x30, 0x1f, 0x82, 0x0a, 0xd7, 0x36, 0xff, 0x79, 0x5e, 0x42, 0x0f, 0x58,
|
||||
0xaa, 0x3a, 0xb8, 0x8b, 0x0e, 0xef, 0x00, 0xac, 0x96, 0x14, 0x96, 0x83,
|
||||
0x33, 0xb6, 0xb5, 0x4c, 0x91, 0x2a, 0x62, 0x92, 0xcf, 0xd2, 0x27, 0xcc,
|
||||
0xdf, 0x4c, 0x55, 0x03, 0xe8, 0x82, 0x78, 0xff, 0x80, 0xcb, 0x2e, 0x30,
|
||||
0x1b, 0x85, 0x56, 0xce, 0x57, 0x9e, 0xd8, 0x16, 0x86, 0x7d, 0x87, 0x2e,
|
||||
0xae, 0x39, 0xd4, 0xac, 0xbe, 0xa5, 0xc4, 0x5a, 0x85, 0x7a, 0xea, 0x8e,
|
||||
0x69, 0x9a, 0xbd, 0x9c, 0x45, 0x33, 0xf8, 0xb1, 0x70, 0xc1, 0x8c, 0xaa,
|
||||
0xad, 0x3d, 0x76, 0x08, 0x5b, 0x7d, 0x12, 0x93, 0x03, 0x70, 0xe6, 0x5f,
|
||||
0xb2, 0xac, 0x78, 0xae, 0xbe, 0xc5, 0x31, 0xc8, 0x6d, 0x2c, 0x1c, 0x2f,
|
||||
0x41, 0x37, 0xf6, 0x88, 0xd3, 0x80, 0x93, 0xed, 0x55, 0xb1, 0xaa, 0x49,
|
||||
0xe8, 0x42, 0xd0, 0x19, 0x20, 0x58, 0xe7, 0x2d, 0x10, 0xf2, 0x69, 0x49,
|
||||
0xe9, 0x47, 0x95, 0xbb, 0xce, 0xa7, 0xe9, 0x86, 0x46, 0x1c, 0xd1, 0x1f,
|
||||
0xd4, 0xa9, 0xeb, 0x28, 0x57, 0x78, 0x6c, 0xc6, 0x6f, 0x84, 0x3b, 0xb4,
|
||||
0x8c, 0xe5, 0xd3, 0x23, 0x8b, 0xbe, 0x83, 0x75, 0x5e, 0xea, 0xcd, 0x93,
|
||||
0xd2, 0x42, 0x86, 0xfd, 0x2b, 0x67, 0x72, 0xe0, 0x46, 0x9c, 0xf7, 0xc1,
|
||||
0xe9, 0x5d, 0xad, 0xac, 0xcb, 0x57, 0xb4, 0xe7, 0x87, 0x25, 0x7d, 0x5a,
|
||||
0x43, 0x90, 0xa3, 0x2e, 0xbf, 0x36, 0xbd, 0x4c, 0xba, 0xec, 0x0f, 0x21,
|
||||
0x51, 0xda, 0x66, 0xb8, 0x1e, 0xac, 0x33, 0xeb, 0xa1, 0x3e, 0x72, 0x15,
|
||||
0x10, 0x45, 0xc0, 0xe4, 0xdb, 0x04, 0x6d, 0xaf, 0x66, 0xc2, 0xfc, 0x35,
|
||||
0x04, 0x60, 0x7d, 0x2f, 0x5e, 0x9e, 0x83, 0xf6, 0x72, 0x92, 0x6a, 0x9f,
|
||||
0xba, 0x94, 0x97, 0x33, 0xe1, 0x1d, 0x42, 0xda, 0xad, 0xa5, 0x8b, 0xad,
|
||||
0x2f, 0x2f, 0x32, 0x16, 0x88, 0x54, 0x88, 0xb2, 0x85, 0xe2, 0x33, 0x08,
|
||||
0x43, 0xc8, 0x68, 0x69, 0xaa, 0xea, 0x9a, 0xbf, 0x41, 0x12, 0xe6, 0xf1,
|
||||
0x02, 0x81, 0xc1, 0x00, 0xfe, 0x96, 0xe7, 0xc8, 0x89, 0x61, 0x2b, 0x58,
|
||||
0xaa, 0xcd, 0x37, 0x46, 0x13, 0xa1, 0x2a, 0xc8, 0x1b, 0x76, 0xde, 0x4c,
|
||||
0xb3, 0x00, 0x4f, 0x6b, 0x02, 0xc0, 0x10, 0xef, 0x87, 0xe2, 0x6d, 0x7f,
|
||||
0x10, 0x57, 0xec, 0xde, 0x70, 0x60, 0xb5, 0x8f, 0x6d, 0x17, 0x35, 0xbd,
|
||||
0xfd, 0x6a, 0x2c, 0xbb, 0xf0, 0x48, 0x5b, 0x32, 0x41, 0xf6, 0xc0, 0x62,
|
||||
0x3a, 0x88, 0xc5, 0x41, 0x83, 0x85, 0x56, 0xa7, 0x11, 0xf4, 0xd2, 0xa9,
|
||||
0xb3, 0xa3, 0xcb, 0xae, 0xca, 0xee, 0x1c, 0x52, 0x7f, 0x04, 0x34, 0x61,
|
||||
0xb9, 0x8d, 0xa3, 0x26, 0x88, 0xce, 0x3d, 0xdb, 0x9c, 0xbf, 0xcc, 0xc4,
|
||||
0x38, 0x8b, 0xf2, 0xe4, 0x7e, 0xcc, 0x46, 0x86, 0x7a, 0x3c, 0xb7, 0x95,
|
||||
0x3f, 0xbd, 0x81, 0x45, 0xc3, 0x1d, 0xbb, 0xf8, 0x56, 0x6e, 0xa5, 0x88,
|
||||
0x2d, 0xff, 0x78, 0xc0, 0xc2, 0x4a, 0x4f, 0xea, 0xb8, 0x81, 0xf3, 0x96,
|
||||
0x5e, 0xd8, 0xcb, 0x96, 0x42, 0xa3, 0x21, 0x03, 0xc8, 0x00, 0xbf, 0x95,
|
||||
0xc7, 0x83, 0x80, 0xc6, 0xc2, 0x38, 0xe4, 0xaf, 0xb2, 0x0e, 0x80, 0x92,
|
||||
0x97, 0x21, 0x16, 0xce, 0x39, 0xd3, 0x95, 0xb7, 0xc3, 0x78, 0xe1, 0x1c,
|
||||
0xc0, 0x5a, 0xbc, 0x9b, 0x68, 0x3f, 0xd6, 0x42, 0xcd, 0xca, 0x0b, 0x6d,
|
||||
0x9f, 0xde, 0x6b, 0x98, 0x3b, 0x47, 0x57, 0xb9, 0x2d, 0x92, 0x52, 0x29,
|
||||
0xc5, 0xed, 0xb5, 0x0d, 0x02, 0x81, 0xc1, 0x00, 0xf6, 0x64, 0xef, 0xef,
|
||||
0x57, 0xdb, 0x06, 0xae, 0x36, 0x86, 0x11, 0xaf, 0x96, 0xb9, 0xb1, 0x29,
|
||||
0x53, 0xce, 0x24, 0x60, 0x96, 0x8f, 0xd0, 0xb7, 0x4b, 0x60, 0x1e, 0xb3,
|
||||
0x1f, 0xae, 0x15, 0x41, 0xf1, 0x56, 0xd6, 0xf3, 0x07, 0xf8, 0xd7, 0xdd,
|
||||
0x1c, 0x82, 0xe8, 0xe0, 0xff, 0xb3, 0x41, 0x0d, 0x41, 0x96, 0x0d, 0xf2,
|
||||
0x03, 0xb0, 0x68, 0xed, 0xda, 0x8b, 0x83, 0x18, 0x4d, 0xae, 0xaf, 0x72,
|
||||
0xa1, 0x82, 0xe5, 0x5a, 0xdc, 0x2a, 0x5f, 0x93, 0x29, 0xc7, 0x24, 0xa0,
|
||||
0x8e, 0x32, 0x4c, 0x0e, 0xca, 0x6d, 0x14, 0x69, 0x5b, 0x61, 0xc5, 0xdc,
|
||||
0x0e, 0x50, 0x0c, 0x14, 0x84, 0x8b, 0xee, 0x9e, 0x1e, 0x8c, 0x3d, 0xdb,
|
||||
0x24, 0xe7, 0x99, 0x6d, 0x3c, 0xaf, 0xe6, 0x3b, 0xaa, 0xb4, 0xe4, 0x42,
|
||||
0x13, 0x53, 0x3e, 0x02, 0x47, 0x0d, 0x3a, 0x2b, 0x97, 0x71, 0x9f, 0x1b,
|
||||
0x76, 0x2d, 0xe5, 0x9c, 0x5e, 0x46, 0x5f, 0x36, 0xbf, 0x18, 0xb1, 0x1d,
|
||||
0x9a, 0xeb, 0x4d, 0x5e, 0x83, 0xd5, 0x3e, 0x5f, 0xf2, 0x6a, 0x56, 0x79,
|
||||
0x0f, 0x54, 0xec, 0x41, 0xc0, 0xdc, 0x29, 0x42, 0x45, 0xae, 0x47, 0x1c,
|
||||
0x7a, 0xd5, 0xb7, 0x92, 0x1e, 0x66, 0xb8, 0x1a, 0x2f, 0x53, 0xd2, 0x6d,
|
||||
0x42, 0x3c, 0x6c, 0x02, 0x01, 0x03, 0x9e, 0x9a, 0x95, 0x35, 0x81, 0x21,
|
||||
0x53, 0x53, 0x16, 0xda, 0x8a, 0x80, 0x8c, 0xcd, 0x02, 0x81, 0xc1, 0x00,
|
||||
0xd5, 0xba, 0x05, 0xf7, 0x7a, 0x2d, 0x52, 0xe0, 0x6a, 0xf3, 0x40, 0xd5,
|
||||
0xd9, 0xa0, 0xd1, 0x73, 0x90, 0x6a, 0xe8, 0x10, 0x67, 0xad, 0x78, 0xfe,
|
||||
0x93, 0x1e, 0x7e, 0x99, 0x37, 0xf0, 0x44, 0x90, 0x09, 0x3e, 0x67, 0x22,
|
||||
0x0e, 0x21, 0x82, 0x0a, 0x58, 0x40, 0xc5, 0xe3, 0x2b, 0x9d, 0x38, 0xd4,
|
||||
0xc5, 0xd1, 0x58, 0x8e, 0x06, 0x86, 0x89, 0xd7, 0x6c, 0xe0, 0x69, 0x08,
|
||||
0xa8, 0xcb, 0x05, 0x85, 0xd8, 0x33, 0x39, 0xaf, 0x31, 0x99, 0xee, 0x62,
|
||||
0x5d, 0x06, 0x2c, 0x4c, 0xad, 0x48, 0xf0, 0x58, 0xa2, 0x17, 0x5f, 0xc1,
|
||||
0xf7, 0xd3, 0x7c, 0x66, 0xa3, 0x5e, 0xf9, 0x1e, 0x39, 0x82, 0x73, 0x74,
|
||||
0x93, 0x66, 0x16, 0x46, 0xca, 0xd3, 0xb2, 0x22, 0xdf, 0x91, 0xcd, 0xb6,
|
||||
0xad, 0x28, 0x87, 0x26, 0xe2, 0x18, 0x9d, 0x6a, 0x87, 0x83, 0x12, 0xf2,
|
||||
0x6f, 0xa9, 0x47, 0x11, 0xfb, 0xb7, 0x4c, 0xb1, 0x0e, 0x0a, 0xde, 0x4e,
|
||||
0xd4, 0xbe, 0x71, 0xf6, 0xe4, 0xae, 0x8c, 0x27, 0xc7, 0x88, 0x84, 0x51,
|
||||
0x57, 0xb7, 0xbf, 0x74, 0x27, 0xfc, 0xb8, 0xbf, 0x57, 0x94, 0x75, 0xba,
|
||||
0xc7, 0x1c, 0xf3, 0x71, 0x83, 0xee, 0x34, 0xbd, 0x98, 0x56, 0x14, 0x44,
|
||||
0x3a, 0xee, 0x6c, 0x87, 0x44, 0x8f, 0xbb, 0xac, 0x5a, 0x2b, 0xb5, 0x13,
|
||||
0xe5, 0x9f, 0xec, 0xeb, 0x0e, 0x70, 0xe9, 0xfd, 0x1b, 0xa6, 0x84, 0xf9,
|
||||
0x02, 0x81, 0xc0, 0x4e, 0x82, 0x26, 0xf9, 0x6a, 0x52, 0xfd, 0xb3, 0xf0,
|
||||
0xe7, 0x93, 0x27, 0x11, 0xad, 0xa5, 0x47, 0x77, 0xce, 0x8d, 0x44, 0xc1,
|
||||
0x74, 0x9d, 0x9a, 0x69, 0xc7, 0xfc, 0xc0, 0x32, 0x6d, 0xf3, 0x94, 0x09,
|
||||
0x64, 0x14, 0x25, 0x67, 0xfa, 0xe0, 0x3d, 0x31, 0xe2, 0x7c, 0x75, 0x84,
|
||||
0xc4, 0x07, 0x0c, 0x44, 0x43, 0x9d, 0xb9, 0xe9, 0x77, 0x02, 0x58, 0x17,
|
||||
0x74, 0xb0, 0x96, 0xc3, 0xd9, 0xcf, 0x49, 0x85, 0x31, 0x02, 0x07, 0x8b,
|
||||
0x73, 0x6c, 0xf4, 0xa5, 0x31, 0x30, 0xf8, 0x7f, 0x96, 0x83, 0x29, 0x8b,
|
||||
0x52, 0x6a, 0x58, 0x8f, 0xa7, 0x7d, 0xb5, 0xfa, 0x51, 0x83, 0x27, 0xde,
|
||||
0x7b, 0xff, 0xd2, 0x1e, 0x05, 0xad, 0x87, 0xf0, 0x20, 0x63, 0x80, 0xac,
|
||||
0xff, 0x97, 0x2a, 0x97, 0xdf, 0xff, 0x83, 0x16, 0x49, 0x45, 0xce, 0xcf,
|
||||
0xf8, 0xe4, 0xfa, 0x12, 0xcd, 0x3f, 0x57, 0x2e, 0xb6, 0xbd, 0x1c, 0xaf,
|
||||
0xe5, 0x58, 0x5d, 0x47, 0x52, 0x84, 0xcc, 0xdc, 0x19, 0xf1, 0x93, 0x16,
|
||||
0x0a, 0x92, 0x4f, 0x5c, 0x1c, 0x89, 0xe5, 0x14, 0xff, 0x88, 0x30, 0x03,
|
||||
0x55, 0xa3, 0x47, 0xdc, 0x90, 0x05, 0x54, 0x8b, 0xc7, 0x21, 0x30, 0xcb,
|
||||
0xc3, 0x0b, 0x12, 0x3c, 0xd6, 0x46, 0x8c, 0x4d, 0xb8, 0x96, 0xe9, 0xa4,
|
||||
0x8d, 0x14, 0xb2, 0x48, 0xac, 0xbd, 0xb2, 0x72, 0xac, 0x5c, 0xf1, 0xd1,
|
||||
0x83, 0xd8, 0x59, 0x02, 0x81, 0xc0, 0x2d, 0x65, 0xc1, 0xc7, 0x0f, 0xca,
|
||||
0xbc, 0x5d, 0xa1, 0x30, 0x28, 0x27, 0x51, 0xcc, 0xc9, 0x6c, 0x7b, 0x76,
|
||||
0x43, 0xa9, 0x77, 0xd8, 0x29, 0xa3, 0x80, 0x57, 0x3b, 0xe9, 0x72, 0x1c,
|
||||
0x51, 0x37, 0xc2, 0x0b, 0x74, 0xb7, 0xaa, 0x63, 0xd5, 0xe2, 0x9b, 0x3a,
|
||||
0x3c, 0x78, 0x50, 0xcb, 0x88, 0x1a, 0xd6, 0x59, 0xdc, 0xb3, 0x05, 0xbf,
|
||||
0xe5, 0xc5, 0xb5, 0xe3, 0x9b, 0xba, 0xe7, 0xbb, 0x4d, 0x45, 0xb3, 0x4c,
|
||||
0xf2, 0x48, 0x65, 0xe7, 0x6b, 0xee, 0x12, 0xc8, 0xd5, 0xea, 0xf0, 0x89,
|
||||
0xf9, 0x03, 0xa3, 0xd9, 0x5f, 0x62, 0x2d, 0x1a, 0x55, 0x51, 0x5d, 0xf6,
|
||||
0xca, 0x6e, 0x5f, 0xf0, 0x66, 0x02, 0xf4, 0x20, 0xe6, 0xe9, 0xc4, 0xd7,
|
||||
0x36, 0x8d, 0x00, 0xce, 0x23, 0xfd, 0x90, 0xd4, 0x19, 0x5c, 0xe9, 0xcb,
|
||||
0x23, 0xe2, 0x2c, 0xf5, 0xe1, 0x6f, 0x9d, 0xb5, 0xdf, 0xea, 0x51, 0xdd,
|
||||
0x02, 0xd8, 0x40, 0xd6, 0x7f, 0x4b, 0xdb, 0x0e, 0xe2, 0x27, 0x4d, 0x0d,
|
||||
0x9b, 0x2e, 0xf7, 0xc8, 0x22, 0xca, 0x63, 0x3c, 0x2c, 0xe5, 0xa8, 0x42,
|
||||
0x26, 0xd9, 0xfc, 0xdc, 0x42, 0xc8, 0x07, 0x64, 0xa2, 0x98, 0xae, 0xb4,
|
||||
0x57, 0x02, 0x02, 0xb2, 0x2d, 0xc8, 0x59, 0x73, 0x9b, 0xee, 0xc0, 0x9a,
|
||||
0x42, 0x9a, 0xef, 0xc2, 0x27, 0x24, 0x2b, 0x20, 0x92, 0xad, 0x50, 0xfe,
|
||||
0x2c, 0x2d, 0xb6, 0xb6, 0xb5, 0xba
|
||||
};
|
||||
extern const size_t kOEMPrivateKeySize_Prod = 1794;
|
||||
|
||||
extern const uint8_t kOEMPublicCert_Prod[] = {
|
||||
0x30, 0x82, 0x09, 0xf7, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
|
||||
0x01, 0x07, 0x02, 0xa0, 0x82, 0x09, 0xe8, 0x30, 0x82, 0x09, 0xe4, 0x02,
|
||||
0x01, 0x01, 0x31, 0x00, 0x30, 0x0f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
|
||||
0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x02, 0x04, 0x00, 0xa0, 0x82, 0x09,
|
||||
0xc8, 0x30, 0x82, 0x04, 0x1a, 0x30, 0x82, 0x03, 0x02, 0xa0, 0x03, 0x02,
|
||||
0x01, 0x02, 0x02, 0x11, 0x00, 0xf2, 0xa1, 0x08, 0xdf, 0x12, 0x84, 0xb9,
|
||||
0x73, 0x6c, 0x23, 0x73, 0xe1, 0x1f, 0xf3, 0xac, 0x7a, 0x30, 0x0d, 0x06,
|
||||
0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00,
|
||||
0x30, 0x81, 0x8b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
|
||||
0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
|
||||
0x08, 0x0c, 0x0a, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x74, 0x6f,
|
||||
0x6e, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x08,
|
||||
0x4b, 0x69, 0x72, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x31, 0x0f, 0x30, 0x0d,
|
||||
0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x47, 0x6f, 0x6f, 0x67, 0x6c,
|
||||
0x65, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08,
|
||||
0x57, 0x69, 0x64, 0x65, 0x76, 0x69, 0x6e, 0x65, 0x31, 0x30, 0x30, 0x2e,
|
||||
0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x27, 0x47, 0x6f, 0x6f, 0x67, 0x6c,
|
||||
0x65, 0x20, 0x4f, 0x45, 0x4d, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x44,
|
||||
0x65, 0x76, 0x69, 0x63, 0x65, 0x3b, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65,
|
||||
0x6d, 0x20, 0x69, 0x64, 0x3a, 0x20, 0x37, 0x33, 0x34, 0x36, 0x30, 0x1e,
|
||||
0x17, 0x0d, 0x31, 0x37, 0x30, 0x33, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30,
|
||||
0x30, 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x39, 0x31, 0x32, 0x30, 0x38, 0x30,
|
||||
0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x6d, 0x31, 0x12, 0x30, 0x10,
|
||||
0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x09, 0x37, 0x33, 0x34, 0x36, 0x2d,
|
||||
0x6c, 0x65, 0x61, 0x66, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
|
||||
0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
|
||||
0x04, 0x08, 0x0c, 0x0a, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x74,
|
||||
0x6f, 0x6e, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c,
|
||||
0x08, 0x4b, 0x69, 0x72, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x31, 0x0f, 0x30,
|
||||
0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x47, 0x6f, 0x6f, 0x67,
|
||||
0x6c, 0x65, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c,
|
||||
0x08, 0x57, 0x69, 0x64, 0x65, 0x76, 0x69, 0x6e, 0x65, 0x30, 0x82, 0x01,
|
||||
0xa2, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
|
||||
0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x8f, 0x00, 0x30, 0x82, 0x01,
|
||||
0x8a, 0x02, 0x82, 0x01, 0x81, 0x00, 0xf5, 0x09, 0x64, 0x4a, 0x26, 0xfe,
|
||||
0xc0, 0x98, 0x55, 0x6a, 0x1d, 0x5d, 0x1c, 0xc7, 0x38, 0xaf, 0xfd, 0x49,
|
||||
0x9e, 0x85, 0x3f, 0xd6, 0x45, 0x0e, 0x99, 0x09, 0x85, 0x69, 0x84, 0x3c,
|
||||
0xfe, 0x72, 0xa5, 0x56, 0xfa, 0x11, 0x4f, 0x6b, 0x7d, 0x32, 0x2b, 0x0c,
|
||||
0xbf, 0x8f, 0xac, 0x47, 0x96, 0x22, 0x82, 0x3d, 0xf5, 0x64, 0x74, 0x7e,
|
||||
0x62, 0x68, 0x74, 0xcd, 0x0a, 0xec, 0x84, 0xc5, 0x15, 0x06, 0x0e, 0x5a,
|
||||
0x2f, 0x20, 0xe3, 0xc9, 0x67, 0xcd, 0xdd, 0x01, 0xb8, 0xb3, 0x18, 0x87,
|
||||
0x8c, 0xa9, 0x58, 0x86, 0x0f, 0xb6, 0xc3, 0x42, 0x7e, 0x87, 0x48, 0x5e,
|
||||
0x10, 0x49, 0xc7, 0xd7, 0xb7, 0xb8, 0xa6, 0x34, 0x08, 0x0c, 0x94, 0xf4,
|
||||
0xbb, 0x2a, 0x06, 0xa4, 0x4f, 0xec, 0xbc, 0xc4, 0x37, 0xbe, 0x99, 0x10,
|
||||
0x23, 0x37, 0x24, 0xb1, 0xdf, 0xcb, 0xe6, 0x3f, 0xc1, 0xf0, 0x0f, 0x04,
|
||||
0x03, 0xc8, 0xb0, 0x1e, 0xd6, 0xb8, 0xae, 0x77, 0xe1, 0x4d, 0x6d, 0x97,
|
||||
0x69, 0x6d, 0x8a, 0x73, 0x66, 0x32, 0x57, 0x6f, 0xcf, 0xea, 0x1e, 0x7b,
|
||||
0x87, 0x03, 0x75, 0xb1, 0xef, 0x83, 0x64, 0x26, 0xf1, 0x3f, 0xbf, 0xe6,
|
||||
0x28, 0x03, 0x72, 0x57, 0xbf, 0x47, 0x29, 0x99, 0x8f, 0x74, 0x1d, 0x01,
|
||||
0x16, 0xad, 0xb2, 0xdf, 0x80, 0xa4, 0xd3, 0x8b, 0xeb, 0x61, 0xd1, 0x40,
|
||||
0x68, 0xb9, 0xa2, 0xa5, 0xef, 0x2b, 0xe5, 0x78, 0xe8, 0x28, 0x88, 0x87,
|
||||
0xb7, 0x53, 0x49, 0xbb, 0xe4, 0xea, 0x0d, 0x5e, 0x96, 0xa5, 0xdd, 0x1f,
|
||||
0x0b, 0x25, 0x8b, 0xb5, 0x95, 0x46, 0xe7, 0xba, 0xb8, 0xc4, 0x0a, 0x36,
|
||||
0xb1, 0x89, 0xeb, 0x27, 0x5d, 0xd9, 0x97, 0x24, 0x59, 0xa3, 0x9b, 0xb0,
|
||||
0x23, 0x0b, 0xd2, 0xec, 0x65, 0x91, 0xf9, 0xf0, 0xa0, 0x74, 0x5f, 0xb4,
|
||||
0xce, 0x22, 0x27, 0x18, 0x37, 0xe2, 0x4b, 0xfc, 0x91, 0xf9, 0x09, 0x15,
|
||||
0xe6, 0xdb, 0x06, 0x9b, 0x4d, 0x82, 0xdc, 0x36, 0x14, 0x48, 0xc6, 0xd5,
|
||||
0x87, 0xca, 0xec, 0x5a, 0xa2, 0x29, 0x33, 0xef, 0x22, 0x0c, 0x4b, 0xbf,
|
||||
0xe7, 0x2f, 0x95, 0xe1, 0xd3, 0xa5, 0xd8, 0xaa, 0x44, 0x77, 0x29, 0xa3,
|
||||
0x20, 0x33, 0xd2, 0x51, 0xa2, 0xf9, 0x4a, 0x6f, 0xf7, 0x3e, 0xf7, 0x0b,
|
||||
0x8a, 0xec, 0xc1, 0x99, 0x1d, 0x47, 0xf3, 0x74, 0x02, 0x04, 0xab, 0x8e,
|
||||
0x62, 0x4c, 0x9e, 0x00, 0xc2, 0x84, 0xd7, 0xd0, 0xf8, 0xe4, 0x1c, 0x9d,
|
||||
0x98, 0x15, 0xa8, 0x8f, 0x08, 0x98, 0x4e, 0x5a, 0xfa, 0xd6, 0x60, 0x87,
|
||||
0x12, 0xdc, 0x8e, 0xfd, 0xcb, 0xb3, 0x13, 0x97, 0x7a, 0xa8, 0x8c, 0x56,
|
||||
0x2e, 0x49, 0x26, 0x60, 0xe9, 0x4a, 0xdc, 0xec, 0x3f, 0xf0, 0x94, 0xcd,
|
||||
0x90, 0x8e, 0x7c, 0x21, 0x3f, 0x80, 0x14, 0x33, 0xdd, 0xb0, 0x00, 0xe2,
|
||||
0x09, 0x37, 0x06, 0xdd, 0x17, 0x69, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3,
|
||||
0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01,
|
||||
0xd6, 0x79, 0x04, 0x01, 0x01, 0x04, 0x04, 0x02, 0x02, 0x1c, 0xb2, 0x30,
|
||||
0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b,
|
||||
0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x8e, 0x2d, 0x13, 0x1e, 0x60,
|
||||
0xaa, 0xda, 0x52, 0x53, 0x55, 0x64, 0x3a, 0xdc, 0xb6, 0x7a, 0xc0, 0xba,
|
||||
0xfa, 0xeb, 0x20, 0xab, 0xb6, 0x63, 0xcf, 0xcd, 0x9b, 0xdb, 0x71, 0xf3,
|
||||
0xa0, 0xd6, 0x91, 0xbf, 0x0c, 0xc1, 0xae, 0x8f, 0x02, 0x18, 0x00, 0x54,
|
||||
0xfb, 0x49, 0x03, 0x34, 0x8d, 0x92, 0x9d, 0x5d, 0x8d, 0xa8, 0x1c, 0x20,
|
||||
0x0f, 0x85, 0x60, 0xf9, 0xf6, 0x8b, 0xbb, 0x2b, 0x82, 0xce, 0xb3, 0xe2,
|
||||
0x91, 0xe7, 0xbd, 0x91, 0x61, 0x52, 0x36, 0x40, 0x9f, 0x2f, 0x5e, 0xa6,
|
||||
0x5d, 0x2f, 0xb3, 0x81, 0xe7, 0xf1, 0x87, 0xbe, 0xc5, 0x9d, 0x67, 0x5a,
|
||||
0xf7, 0x41, 0x1e, 0x73, 0xb0, 0x1e, 0xdc, 0x4f, 0x8d, 0x53, 0x21, 0x38,
|
||||
0x1b, 0xfd, 0x92, 0x43, 0x68, 0x83, 0x03, 0xd0, 0x9a, 0xca, 0x92, 0x14,
|
||||
0x73, 0x04, 0x94, 0x2a, 0x93, 0x22, 0x60, 0x5e, 0xee, 0xb6, 0xec, 0x0f,
|
||||
0xb0, 0xc8, 0x92, 0x97, 0xfb, 0x5d, 0xed, 0x1f, 0xa0, 0x5f, 0xe4, 0x98,
|
||||
0x2f, 0xf6, 0x13, 0x78, 0x99, 0xec, 0xb3, 0xf1, 0x0d, 0x27, 0xaa, 0x19,
|
||||
0x95, 0x39, 0xdb, 0xb0, 0x7b, 0x96, 0x74, 0x03, 0x5e, 0x51, 0xf5, 0x15,
|
||||
0x27, 0xce, 0xca, 0x0b, 0x2a, 0x0d, 0x43, 0xb3, 0x68, 0x17, 0x1e, 0x11,
|
||||
0x60, 0xd9, 0x84, 0x9b, 0xc3, 0x53, 0xce, 0xbd, 0xf4, 0x61, 0x51, 0x4b,
|
||||
0x41, 0x00, 0x7e, 0xe1, 0x5f, 0x69, 0xb3, 0x4a, 0x89, 0x7e, 0x47, 0x67,
|
||||
0xfd, 0x76, 0xf8, 0x94, 0x2f, 0x72, 0xb6, 0x14, 0x08, 0x2c, 0x16, 0x4e,
|
||||
0x9d, 0x37, 0x62, 0xbf, 0x11, 0x67, 0xc0, 0x70, 0x71, 0xec, 0x55, 0x51,
|
||||
0x4e, 0x46, 0x76, 0xb4, 0xc3, 0xeb, 0x52, 0x06, 0x17, 0x06, 0xce, 0x61,
|
||||
0x43, 0xce, 0x26, 0x80, 0x68, 0xb6, 0x2d, 0x57, 0xba, 0x8c, 0x7d, 0xb7,
|
||||
0xc5, 0x05, 0x2c, 0xf8, 0xa3, 0x69, 0xf8, 0x96, 0xad, 0xac, 0xd1, 0x30,
|
||||
0x82, 0x05, 0xa6, 0x30, 0x82, 0x03, 0x8e, 0xa0, 0x03, 0x02, 0x01, 0x02,
|
||||
0x02, 0x10, 0x73, 0xd1, 0xe1, 0x1d, 0xa9, 0x75, 0xfd, 0x0c, 0xda, 0x7f,
|
||||
0xfa, 0x43, 0x3c, 0x26, 0xbd, 0x3d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
|
||||
0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x7e, 0x31,
|
||||
0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53,
|
||||
0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x57,
|
||||
0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x31, 0x11, 0x30,
|
||||
0x0f, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x08, 0x4b, 0x69, 0x72, 0x6b,
|
||||
0x6c, 0x61, 0x6e, 0x64, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04,
|
||||
0x0a, 0x0c, 0x06, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x31, 0x11, 0x30,
|
||||
0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x08, 0x57, 0x69, 0x64, 0x65,
|
||||
0x76, 0x69, 0x6e, 0x65, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04,
|
||||
0x03, 0x0c, 0x1a, 0x77, 0x69, 0x64, 0x65, 0x76, 0x69, 0x6e, 0x65, 0x2e,
|
||||
0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x65, 0x6d, 0x2d, 0x72, 0x6f, 0x6f, 0x74,
|
||||
0x2d, 0x70, 0x72, 0x6f, 0x64, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x37, 0x30,
|
||||
0x33, 0x31, 0x34, 0x30, 0x33, 0x30, 0x32, 0x34, 0x31, 0x5a, 0x17, 0x0d,
|
||||
0x32, 0x37, 0x30, 0x33, 0x31, 0x34, 0x30, 0x33, 0x30, 0x32, 0x34, 0x31,
|
||||
0x5a, 0x30, 0x81, 0x8b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
|
||||
0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
|
||||
0x04, 0x08, 0x0c, 0x0a, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x74,
|
||||
0x6f, 0x6e, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c,
|
||||
0x08, 0x4b, 0x69, 0x72, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x31, 0x0f, 0x30,
|
||||
0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x47, 0x6f, 0x6f, 0x67,
|
||||
0x6c, 0x65, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c,
|
||||
0x08, 0x57, 0x69, 0x64, 0x65, 0x76, 0x69, 0x6e, 0x65, 0x31, 0x30, 0x30,
|
||||
0x2e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x27, 0x47, 0x6f, 0x6f, 0x67,
|
||||
0x6c, 0x65, 0x20, 0x4f, 0x45, 0x4d, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20,
|
||||
0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x3b, 0x20, 0x73, 0x79, 0x73, 0x74,
|
||||
0x65, 0x6d, 0x20, 0x69, 0x64, 0x3a, 0x20, 0x37, 0x33, 0x34, 0x36, 0x30,
|
||||
0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
|
||||
0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30,
|
||||
0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xa5, 0x45, 0x13, 0xf2,
|
||||
0xb2, 0xcb, 0x4b, 0x0f, 0xb4, 0x44, 0x25, 0x9c, 0x8a, 0x68, 0x54, 0xd5,
|
||||
0x45, 0x1e, 0x15, 0x89, 0x5b, 0xb8, 0xce, 0xda, 0x5a, 0x42, 0xe6, 0x9a,
|
||||
0x8c, 0xc1, 0xcb, 0xe8, 0xc5, 0xf5, 0x8f, 0x49, 0x0e, 0x02, 0xef, 0x5e,
|
||||
0x97, 0x1a, 0x91, 0xa4, 0x94, 0xc3, 0x50, 0x13, 0xe5, 0x13, 0xb7, 0x7f,
|
||||
0x26, 0x53, 0x19, 0xb0, 0x37, 0xa5, 0xef, 0xe6, 0x2a, 0x39, 0xdc, 0x93,
|
||||
0x37, 0xe2, 0x3d, 0x7f, 0xcb, 0x4b, 0x93, 0xa2, 0xc3, 0x69, 0x78, 0xc9,
|
||||
0x01, 0xfa, 0x68, 0x3b, 0xe0, 0xe2, 0x22, 0x6c, 0xeb, 0xe4, 0x8a, 0xa8,
|
||||
0x3e, 0xf5, 0x20, 0x82, 0xa8, 0x62, 0x68, 0x59, 0x78, 0x24, 0xde, 0xef,
|
||||
0x47, 0x43, 0xb1, 0x6c, 0x38, 0x29, 0xd3, 0x69, 0x3f, 0xae, 0x35, 0x57,
|
||||
0x75, 0x80, 0xc9, 0x21, 0xe7, 0x01, 0xb9, 0x54, 0x8b, 0x6e, 0x4e, 0x2e,
|
||||
0x5a, 0x5b, 0x77, 0xa4, 0x22, 0xc2, 0x7b, 0x95, 0xb9, 0x39, 0x2c, 0xbd,
|
||||
0xc2, 0x1e, 0x02, 0xa6, 0xb2, 0xbc, 0x0f, 0x7a, 0xcb, 0xdc, 0xbc, 0xbc,
|
||||
0x90, 0x66, 0xe3, 0xca, 0x46, 0x53, 0x3e, 0x98, 0xff, 0x2e, 0x78, 0x9f,
|
||||
0xd3, 0xa1, 0x12, 0x93, 0x66, 0x7d, 0xcc, 0x94, 0x6b, 0xec, 0x19, 0x0e,
|
||||
0x20, 0x45, 0x22, 0x57, 0x6d, 0x9e, 0xd0, 0x89, 0xf2, 0xa9, 0x34, 0xdc,
|
||||
0xab, 0xa5, 0x73, 0x47, 0x38, 0xe3, 0x7f, 0x98, 0x3a, 0x61, 0xae, 0x6c,
|
||||
0x4d, 0xf2, 0x31, 0x90, 0xcb, 0x83, 0xc1, 0xee, 0xb4, 0xf2, 0x9a, 0x28,
|
||||
0x5f, 0xbb, 0x7d, 0x89, 0xdf, 0xa2, 0x31, 0xb6, 0x1d, 0x39, 0x2b, 0x70,
|
||||
0xbf, 0x1e, 0xad, 0xe1, 0x74, 0x94, 0x1d, 0xf8, 0xc5, 0x1a, 0x8d, 0x13,
|
||||
0x45, 0xf0, 0x6a, 0x80, 0x0c, 0x5d, 0xbb, 0x46, 0x8a, 0x43, 0xd0, 0xff,
|
||||
0x21, 0x39, 0x57, 0x53, 0x5b, 0x51, 0xf8, 0xa2, 0x8f, 0x7f, 0x27, 0xc7,
|
||||
0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0x10, 0x30, 0x82, 0x01,
|
||||
0x0c, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04,
|
||||
0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x00, 0x30, 0x0e, 0x06,
|
||||
0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x02,
|
||||
0x04, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14,
|
||||
0xe8, 0xe9, 0xac, 0x16, 0x5c, 0x5e, 0xb2, 0xe8, 0xeb, 0xff, 0x57, 0x27,
|
||||
0x20, 0x08, 0x72, 0x63, 0x9b, 0xe5, 0xb5, 0x16, 0x30, 0x81, 0xb2, 0x06,
|
||||
0x03, 0x55, 0x1d, 0x23, 0x04, 0x81, 0xaa, 0x30, 0x81, 0xa7, 0x80, 0x14,
|
||||
0x04, 0x94, 0x66, 0xaa, 0xf9, 0x61, 0x89, 0xb6, 0xdb, 0xb5, 0xf7, 0x13,
|
||||
0x38, 0x3d, 0x62, 0x84, 0xb8, 0x18, 0x0a, 0x8f, 0xa1, 0x81, 0x83, 0xa4,
|
||||
0x81, 0x80, 0x30, 0x7e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
|
||||
0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
|
||||
0x04, 0x08, 0x0c, 0x0a, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x74,
|
||||
0x6f, 0x6e, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c,
|
||||
0x08, 0x4b, 0x69, 0x72, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x31, 0x0f, 0x30,
|
||||
0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x47, 0x6f, 0x6f, 0x67,
|
||||
0x6c, 0x65, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c,
|
||||
0x08, 0x57, 0x69, 0x64, 0x65, 0x76, 0x69, 0x6e, 0x65, 0x31, 0x23, 0x30,
|
||||
0x21, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1a, 0x77, 0x69, 0x64, 0x65,
|
||||
0x76, 0x69, 0x6e, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x65, 0x6d,
|
||||
0x2d, 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x70, 0x72, 0x6f, 0x64, 0x82, 0x09,
|
||||
0x00, 0xdf, 0x86, 0x05, 0x31, 0x01, 0xbe, 0x9a, 0x9a, 0x30, 0x12, 0x06,
|
||||
0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, 0x79, 0x04, 0x01, 0x01, 0x04,
|
||||
0x04, 0x02, 0x02, 0x1c, 0xb2, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
|
||||
0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01,
|
||||
0x00, 0x25, 0xce, 0xd2, 0x02, 0x48, 0xbb, 0xbe, 0xfc, 0xb6, 0xa4, 0x87,
|
||||
0x87, 0xe0, 0x21, 0x7d, 0xfa, 0x23, 0xc3, 0x0d, 0x73, 0x8f, 0x46, 0xe7,
|
||||
0x09, 0x59, 0xda, 0x2e, 0x55, 0x59, 0xff, 0x3c, 0x1b, 0xf6, 0xf8, 0x9a,
|
||||
0xc4, 0x1c, 0xf7, 0xac, 0xca, 0xe7, 0x63, 0xf2, 0xc7, 0xd6, 0x0c, 0x2d,
|
||||
0xa6, 0xad, 0x55, 0xf4, 0x10, 0x0e, 0xa8, 0x82, 0x0f, 0x88, 0xb5, 0x44,
|
||||
0xe8, 0x8e, 0x84, 0x08, 0xf7, 0xdd, 0xe7, 0x10, 0xce, 0x71, 0x56, 0x57,
|
||||
0x3f, 0xed, 0x48, 0xee, 0xe2, 0x5d, 0x08, 0x0a, 0x58, 0xe4, 0xfe, 0xbc,
|
||||
0x8c, 0x27, 0x1a, 0x46, 0x3f, 0xd5, 0x2d, 0xdb, 0x0b, 0x71, 0x73, 0xd1,
|
||||
0x49, 0xf3, 0x5c, 0x86, 0x4d, 0x0a, 0xe1, 0xeb, 0x53, 0x21, 0x38, 0x4f,
|
||||
0xec, 0x1e, 0xc2, 0x68, 0x1f, 0x7d, 0xa6, 0x33, 0xe9, 0xa5, 0x37, 0x2a,
|
||||
0xef, 0xcd, 0x78, 0x56, 0xb3, 0x39, 0x60, 0xf4, 0xa5, 0xf9, 0x2b, 0x85,
|
||||
0xcf, 0xe6, 0x1c, 0x7c, 0x8a, 0x5d, 0xe8, 0x26, 0x02, 0xcf, 0x7a, 0x56,
|
||||
0x1f, 0xae, 0x0d, 0x71, 0x20, 0xee, 0xec, 0x3b, 0xae, 0x95, 0x25, 0x15,
|
||||
0xc8, 0xf6, 0x92, 0x5d, 0xb8, 0x9b, 0xc2, 0xb4, 0x95, 0x33, 0x13, 0x76,
|
||||
0x45, 0xbe, 0x21, 0xe2, 0x3a, 0x69, 0x66, 0xd7, 0xff, 0x22, 0x00, 0x89,
|
||||
0xc9, 0x44, 0xb6, 0x54, 0x38, 0x1f, 0x33, 0xe4, 0xda, 0x7b, 0x87, 0xf3,
|
||||
0x23, 0xed, 0xf5, 0x16, 0x08, 0xbe, 0x4b, 0xea, 0x91, 0x8f, 0x91, 0x8b,
|
||||
0x4e, 0xd1, 0x02, 0x06, 0xa2, 0x77, 0x15, 0x03, 0x46, 0x11, 0x7d, 0x5b,
|
||||
0xea, 0x7a, 0xf6, 0x86, 0x7d, 0x96, 0xb7, 0x73, 0x9b, 0x5b, 0x32, 0xc3,
|
||||
0xf8, 0x92, 0x36, 0xe3, 0xe3, 0x2f, 0xe8, 0xf1, 0x72, 0xec, 0x0d, 0x50,
|
||||
0xd4, 0x86, 0xc5, 0x62, 0x83, 0xf1, 0x2a, 0x4c, 0xd1, 0xbf, 0x76, 0x62,
|
||||
0xd4, 0x21, 0x11, 0x68, 0xb2, 0xd6, 0x8d, 0xc4, 0xf8, 0xe4, 0x70, 0x85,
|
||||
0x19, 0xa7, 0x82, 0x27, 0x2c, 0x24, 0x21, 0x7a, 0x3b, 0xad, 0x8a, 0xd3,
|
||||
0xae, 0xda, 0x78, 0x3c, 0x6c, 0xab, 0xa2, 0xaa, 0x36, 0xf0, 0x1c, 0x58,
|
||||
0xd4, 0x72, 0x5e, 0xe8, 0x8b, 0x41, 0x08, 0xf5, 0x85, 0xdd, 0xee, 0x99,
|
||||
0x12, 0xf4, 0xd6, 0x41, 0x83, 0x69, 0xe7, 0x79, 0x19, 0xa3, 0x74, 0xc4,
|
||||
0x34, 0x2a, 0x8a, 0x7e, 0x4d, 0xbb, 0x2c, 0x49, 0x19, 0xf7, 0x98, 0x98,
|
||||
0xfc, 0x81, 0xf7, 0x9b, 0x7f, 0xff, 0xd9, 0x66, 0xf4, 0x51, 0x14, 0x29,
|
||||
0x2a, 0x14, 0x1d, 0x4f, 0xbd, 0x91, 0xba, 0x6f, 0x32, 0x34, 0x3c, 0x40,
|
||||
0x28, 0x6c, 0x97, 0xf8, 0x6d, 0x38, 0xcd, 0xa3, 0x7b, 0x18, 0xc8, 0x77,
|
||||
0x58, 0x4d, 0x53, 0x30, 0x7f, 0x4d, 0x89, 0xca, 0x95, 0x6e, 0xb5, 0xb8,
|
||||
0x8e, 0xc8, 0x2d, 0x18, 0x2f, 0x52, 0x2a, 0xde, 0xac, 0x56, 0x8d, 0x8c,
|
||||
0x67, 0x14, 0xf6, 0xb9, 0xf1, 0x65, 0xd3, 0x22, 0x43, 0xa3, 0x98, 0x42,
|
||||
0x20, 0x43, 0x4c, 0xdf, 0xf2, 0xeb, 0x31, 0x8c, 0x0e, 0x53, 0x5b, 0x99,
|
||||
0x82, 0xc3, 0x48, 0x04, 0x53, 0xad, 0x96, 0xb6, 0x9f, 0x52, 0xcc, 0x01,
|
||||
0xc8, 0xb3, 0x87, 0x6b, 0x9e, 0xea, 0xa9, 0xeb, 0xda, 0xac, 0xf9, 0x6f,
|
||||
0xde, 0xa1, 0x44, 0x32, 0x52, 0x49, 0x47, 0xff, 0x65, 0x79, 0x1e, 0xc5,
|
||||
0x73, 0x17, 0xb3, 0x36, 0xfc, 0x45, 0xca, 0x90, 0x37, 0x59, 0x1e, 0x16,
|
||||
0xab, 0x09, 0x69, 0xcf, 0xda, 0x56, 0x51, 0xfd, 0xeb, 0xcf, 0xcb, 0x8f,
|
||||
0xb1, 0xc3, 0x45, 0x2b, 0x7c, 0x0a, 0xa5, 0x9c, 0x0d, 0x2c, 0xad, 0x1c,
|
||||
0xd3, 0x33, 0xdd, 0xfe, 0x93, 0x69, 0xa2, 0x4b, 0x4b, 0xcf, 0x1d, 0x20,
|
||||
0x98, 0x4a, 0x4f, 0x5b, 0xe9, 0x24, 0xca, 0xfa, 0x18, 0x11, 0x81, 0x8b,
|
||||
0x7a, 0xb4, 0x5a, 0xc8, 0xdf, 0x6f, 0x5f, 0x21, 0x07, 0x31, 0x00
|
||||
};
|
||||
extern const size_t kOEMPublicCertSize_Prod = 2555;
|
||||
|
||||
// Refer to the following in main modules.
|
||||
// This level of indirection is present so new OEM Certificates can be
|
||||
// added and then selected for use at compile time or run time.
|
||||
|
||||
const uint32_t kOEMSystemId = kOEMSystemId_Prod;
|
||||
|
||||
const uint8_t* kOEMPrivateKey = kOEMPrivateKey_Prod;
|
||||
const uint8_t* kOEMPublicCert = kOEMPublicCert_Prod;
|
||||
|
||||
const size_t kOEMPrivateKeySize = kOEMPrivateKeySize_Prod;
|
||||
const size_t kOEMPublicCertSize = kOEMPublicCertSize_Prod;
|
||||
|
||||
} // namespace wvoec_ref
|
||||
21
libwvdrmengine/oemcrypto/ref/src/oem_cert.h
Normal file
21
libwvdrmengine/oemcrypto/ref/src/oem_cert.h
Normal file
@@ -0,0 +1,21 @@
|
||||
// This header is used to access the OEM certificate if one is in use.
|
||||
#ifndef OEM_CERT_H_
|
||||
#define OEM_CERT_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace wvoec_ref {
|
||||
|
||||
// Refer to the following in main modules
|
||||
extern const uint32_t kOEMSystemId;
|
||||
|
||||
extern const uint8_t* kOEMPrivateKey;
|
||||
extern const uint8_t* kOEMPublicCert;
|
||||
|
||||
extern const size_t kOEMPrivateKeySize;
|
||||
extern const size_t kOEMPublicCertSize;
|
||||
|
||||
} // namespace wvoec_ref
|
||||
|
||||
#endif // OEM_CERT_H_
|
||||
205
libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.cpp
Normal file
205
libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.cpp
Normal file
@@ -0,0 +1,205 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// Ref implementation of OEMCrypto APIs
|
||||
//
|
||||
#include "oemcrypto_auth_ref.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "keys.h"
|
||||
#include "log.h"
|
||||
#include "oemcrypto_key_ref.h"
|
||||
#include "oemcrypto_logging.h"
|
||||
#include "oemcrypto_rsa_key_shared.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// A 2048 bit RSA key in PKCS#8 PrivateKeyInfo format
|
||||
// This is the RSA Test Key. This key is not derived
|
||||
// from any Widevine authentication root.
|
||||
static const uint8_t kTestRSAPKCS8PrivateKeyInfo2_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
|
||||
|
||||
namespace wvoec_ref {
|
||||
|
||||
AuthenticationRoot::AuthenticationRoot(OEMCrypto_ProvisioningMethod method) :
|
||||
provisioning_method_(method),
|
||||
use_test_keybox_(false) {
|
||||
if ((provisioning_method_ == OEMCrypto_DrmCertificate) &&
|
||||
!rsa_key_.LoadPkcs8RsaKey(kPrivateKey, kPrivateKeySize)) {
|
||||
// This error message is OK in unit tests which use test certificate.
|
||||
LOGE("FATAL ERROR: Platform uses a baked-in certificate instead of a "
|
||||
"keybox, but the certificate could not be loaded.");
|
||||
}
|
||||
}
|
||||
|
||||
KeyboxError AuthenticationRoot::ValidateKeybox() {
|
||||
return keybox().Validate();
|
||||
}
|
||||
|
||||
bool AuthenticationRoot::LoadTestRsaKey() {
|
||||
return rsa_key_.LoadPkcs8RsaKey(kTestRSAPKCS8PrivateKeyInfo2_2048,
|
||||
sizeof(kTestRSAPKCS8PrivateKeyInfo2_2048));
|
||||
}
|
||||
|
||||
bool AuthenticationRoot::Validate() {
|
||||
return NO_ERROR == ValidateKeybox();
|
||||
}
|
||||
|
||||
} // namespace wvoec_ref
|
||||
80
libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.h
Normal file
80
libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.h
Normal file
@@ -0,0 +1,80 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// Ref implementation of OEMCrypto APIs
|
||||
//
|
||||
#ifndef OEMCRYPTO_AUTH_REF_H_
|
||||
#define OEMCRYPTO_AUTH_REF_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
#include "OEMCryptoCENC.h" // Needed for enums only.
|
||||
#include "disallow_copy_and_assign.h"
|
||||
#include "oemcrypto_key_ref.h"
|
||||
#include "oemcrypto_keybox_ref.h"
|
||||
#include "oemcrypto_rsa_key_shared.h"
|
||||
#include "oemcrypto_scoped_ptr.h"
|
||||
#include "oemcrypto_types.h"
|
||||
|
||||
namespace wvoec_ref {
|
||||
|
||||
class AuthenticationRoot {
|
||||
public:
|
||||
explicit AuthenticationRoot(OEMCrypto_ProvisioningMethod method);
|
||||
~AuthenticationRoot() {}
|
||||
|
||||
bool Validate();
|
||||
|
||||
KeyboxError ValidateKeybox();
|
||||
|
||||
bool InstallKeybox(const uint8_t* keybox_data, size_t keybox_length) {
|
||||
return keybox().InstallKeybox(keybox_data, keybox_length);
|
||||
}
|
||||
|
||||
const std::vector<uint8_t>& DeviceKey(bool use_real_keybox = false) {
|
||||
return use_real_keybox ? real_keybox().device_key() :
|
||||
keybox().device_key();
|
||||
}
|
||||
|
||||
const std::vector<uint8_t>& DeviceId() {
|
||||
return keybox().device_id();
|
||||
}
|
||||
|
||||
size_t DeviceTokenLength() {
|
||||
return keybox().key_data_length();
|
||||
}
|
||||
|
||||
const uint8_t* DeviceToken() {
|
||||
return keybox().key_data();
|
||||
}
|
||||
|
||||
WvKeybox& keybox() { return use_test_keybox_ ? test_keybox_ : keybox_; }
|
||||
bool UseTestKeybox(const uint8_t* keybox_data, size_t keybox_length) {
|
||||
use_test_keybox_ = true;
|
||||
return test_keybox_.InstallKeybox(keybox_data, keybox_length);
|
||||
}
|
||||
|
||||
RSA_shared_ptr& SharedRsaKey() { return rsa_key_; }
|
||||
RSA* rsa_key() { return rsa_key_.get(); }
|
||||
bool LoadTestRsaKey();
|
||||
|
||||
private:
|
||||
OEMCrypto_ProvisioningMethod provisioning_method_;
|
||||
WvKeybox& real_keybox() { return keybox_; }
|
||||
|
||||
WvKeybox keybox_;
|
||||
WvTestKeybox test_keybox_;
|
||||
bool use_test_keybox_;
|
||||
|
||||
RSA_shared_ptr rsa_key_; // If no keybox, this is baked in certificate.
|
||||
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(AuthenticationRoot);
|
||||
};
|
||||
|
||||
} // namespace wvoec_ref
|
||||
|
||||
#endif // OEMCRYPTO_AUTH_REF_H_
|
||||
@@ -0,0 +1,17 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// Ref implementation of OEMCrypto APIs
|
||||
//
|
||||
|
||||
#include "oemcrypto_engine_ref.h"
|
||||
|
||||
namespace wvoec_ref {
|
||||
|
||||
CryptoEngine* CryptoEngine::MakeCryptoEngine(
|
||||
scoped_ptr<wvcdm::FileSystem> file_system) {
|
||||
return new CryptoEngine(file_system);
|
||||
}
|
||||
|
||||
} // namespace wvoec_ref
|
||||
@@ -0,0 +1,38 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// Ref implementation of OEMCrypto APIs
|
||||
//
|
||||
// This file contains oemcrypto engine properties that would be for a
|
||||
// level 1 device.
|
||||
#include "oemcrypto_engine_ref.h"
|
||||
|
||||
namespace wvoec_ref {
|
||||
|
||||
class L1CryptoEngine : public CryptoEngine {
|
||||
public:
|
||||
explicit L1CryptoEngine(scoped_ptr<wvcdm::FileSystem> file_system)
|
||||
: CryptoEngine(file_system) {}
|
||||
|
||||
bool config_local_display_only() { return true; }
|
||||
|
||||
OEMCrypto_HDCP_Capability config_maximum_hdcp_capability() {
|
||||
return HDCP_V2;
|
||||
}
|
||||
|
||||
bool config_is_anti_rollback_hw_present() { return true; }
|
||||
|
||||
const char* config_security_level() { return "L1"; }
|
||||
|
||||
// This should start at 0, and be incremented only when a security patch has
|
||||
// been applied to the device that fixes a security bug.
|
||||
uint8_t config_security_patch_level() { return 3; }
|
||||
};
|
||||
|
||||
CryptoEngine* CryptoEngine::MakeCryptoEngine(
|
||||
scoped_ptr<wvcdm::FileSystem> file_system) {
|
||||
return new L1CryptoEngine(file_system);
|
||||
}
|
||||
|
||||
} // namespace wvoec_ref
|
||||
@@ -0,0 +1,37 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// Ref implementation of OEMCrypto APIs
|
||||
//
|
||||
// This file contains oemcrypto engine properties that would be for a device
|
||||
// that does not have persistant storage or a keybox.
|
||||
//
|
||||
// Note: We also define it to be L2 for illustration only. Production devices
|
||||
// are rarely level 2.
|
||||
#include "oemcrypto_engine_ref.h"
|
||||
|
||||
namespace wvoec_ref {
|
||||
|
||||
class CertOnlyCryptoEngine : public CryptoEngine {
|
||||
public:
|
||||
explicit CertOnlyCryptoEngine(scoped_ptr<wvcdm::FileSystem> file_system)
|
||||
: CryptoEngine(file_system) {}
|
||||
|
||||
bool config_local_display_only() { return true; }
|
||||
|
||||
bool config_supports_usage_table() { return false; }
|
||||
|
||||
OEMCrypto_ProvisioningMethod config_provisioning_method() {
|
||||
return OEMCrypto_DrmCertificate;
|
||||
}
|
||||
|
||||
const char* config_security_level() { return "L2"; }
|
||||
};
|
||||
|
||||
CryptoEngine* CryptoEngine::MakeCryptoEngine(
|
||||
scoped_ptr<wvcdm::FileSystem> file_system) {
|
||||
return new CertOnlyCryptoEngine(file_system);
|
||||
}
|
||||
|
||||
} // namespace wvoec_ref
|
||||
@@ -0,0 +1,84 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// Ref implementation of OEMCrypto APIs
|
||||
//
|
||||
// This file contains oemcrypto engine properties that would be for a
|
||||
// level 2 device that does not have persistant storage or a keybox.
|
||||
// Note: this is for illustration only. Production devices are rarely level 2.
|
||||
|
||||
#include "oemcrypto_engine_ref.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "oem_cert.h"
|
||||
|
||||
namespace wvoec_ref {
|
||||
|
||||
class Prov30CryptoEngine : public CryptoEngine {
|
||||
public:
|
||||
explicit Prov30CryptoEngine(scoped_ptr<wvcdm::FileSystem> file_system)
|
||||
: CryptoEngine(file_system) {}
|
||||
|
||||
bool config_local_display_only() { return true; }
|
||||
|
||||
// Returns the max HDCP version supported.
|
||||
OEMCrypto_HDCP_Capability config_maximum_hdcp_capability() {
|
||||
return HDCP_NO_DIGITAL_OUTPUT;
|
||||
}
|
||||
|
||||
// Returns true if the client supports persistent storage of
|
||||
// offline usage table information.
|
||||
bool config_supports_usage_table() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns true if the client uses a keybox as the root of trust.
|
||||
bool config_supports_keybox() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// This version uses an OEM Certificate.
|
||||
OEMCrypto_ProvisioningMethod config_provisioning_method() {
|
||||
return OEMCrypto_OEMCertificate;
|
||||
}
|
||||
|
||||
OEMCryptoResult get_oem_certificate(SessionContext* session,
|
||||
uint8_t* public_cert,
|
||||
size_t* public_cert_length) {
|
||||
if (kOEMPublicCertSize == 0) {
|
||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
if (public_cert_length == NULL) {
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
if (*public_cert_length < kOEMPublicCertSize) {
|
||||
*public_cert_length = kOEMPublicCertSize;
|
||||
return OEMCrypto_ERROR_SHORT_BUFFER;
|
||||
}
|
||||
*public_cert_length = kOEMPublicCertSize;
|
||||
if (public_cert == NULL) {
|
||||
return OEMCrypto_ERROR_SHORT_BUFFER;
|
||||
}
|
||||
memcpy(public_cert, kOEMPublicCert, kOEMPublicCertSize);
|
||||
if (!session->LoadRSAKey(kOEMPrivateKey, kOEMPrivateKeySize)) {
|
||||
LOGE("Private RSA Key did not load correctly.");
|
||||
return OEMCrypto_ERROR_INVALID_RSA_KEY;
|
||||
}
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
// Returns "L3" for a software only library. L1 is for hardware protected
|
||||
// keys and data paths. L2 is for hardware protected keys but no data path
|
||||
// protection.
|
||||
const char* config_security_level() { return "L2"; }
|
||||
};
|
||||
|
||||
CryptoEngine* CryptoEngine::MakeCryptoEngine(
|
||||
scoped_ptr<wvcdm::FileSystem> file_system) {
|
||||
return new Prov30CryptoEngine(file_system);
|
||||
}
|
||||
|
||||
} // namespace wvoec_ref
|
||||
124
libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.cpp
Normal file
124
libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// Ref implementation of OEMCrypto APIs
|
||||
//
|
||||
#include "oemcrypto_engine_ref.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "keys.h"
|
||||
#include "log.h"
|
||||
#include "oemcrypto_key_ref.h"
|
||||
#include "oemcrypto_rsa_key_shared.h"
|
||||
|
||||
namespace wvoec_ref {
|
||||
|
||||
// Note: The class CryptoEngine is configured at compile time by compiling in
|
||||
// different device property files. The methods in this file are generic to
|
||||
// all configurations. See the files oemcrypto_engine_device_properties*.cpp
|
||||
// for methods that are configured for specific configurations.
|
||||
|
||||
CryptoEngine::CryptoEngine(scoped_ptr<wvcdm::FileSystem> file_system)
|
||||
: root_of_trust_(config_provisioning_method()),
|
||||
file_system_(file_system),
|
||||
usage_table_(this) {
|
||||
ERR_load_crypto_strings();
|
||||
}
|
||||
|
||||
CryptoEngine::~CryptoEngine() {
|
||||
wvcdm::AutoLock lock(session_table_lock_);
|
||||
ActiveSessions::iterator it;
|
||||
for (it = sessions_.begin(); it != sessions_.end(); ++it) {
|
||||
delete it->second;
|
||||
}
|
||||
sessions_.clear();
|
||||
ERR_free_strings();
|
||||
}
|
||||
|
||||
SessionId CryptoEngine::CreateSession() {
|
||||
wvcdm::AutoLock lock(session_table_lock_);
|
||||
static int unique_id = 1;
|
||||
SessionId sid = (SessionId)++unique_id;
|
||||
SessionContext* sctx =
|
||||
new SessionContext(this, sid, root_of_trust_.SharedRsaKey());
|
||||
sessions_[sid] = sctx;
|
||||
return sid;
|
||||
}
|
||||
|
||||
bool CryptoEngine::DestroySession(SessionId sid) {
|
||||
SessionContext* sctx = FindSession(sid);
|
||||
wvcdm::AutoLock lock(session_table_lock_);
|
||||
if (sctx) {
|
||||
sessions_.erase(sid);
|
||||
delete sctx;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
SessionContext* CryptoEngine::FindSession(SessionId sid) {
|
||||
wvcdm::AutoLock lock(session_table_lock_);
|
||||
ActiveSessions::iterator it = sessions_.find(sid);
|
||||
if (it != sessions_.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OEMCrypto_HDCP_Capability CryptoEngine::config_current_hdcp_capability() {
|
||||
return config_local_display_only() ? HDCP_NO_DIGITAL_OUTPUT : HDCP_V1;
|
||||
}
|
||||
|
||||
OEMCrypto_HDCP_Capability CryptoEngine::config_maximum_hdcp_capability() {
|
||||
return HDCP_NO_DIGITAL_OUTPUT;
|
||||
}
|
||||
|
||||
OEMCryptoResult CryptoEngine::SetDestination(
|
||||
OEMCrypto_DestBufferDesc* out_description, size_t data_length,
|
||||
uint8_t subsample_flags) {
|
||||
size_t max_length = 0;
|
||||
switch (out_description->type) {
|
||||
case OEMCrypto_BufferType_Clear:
|
||||
destination_ = out_description->buffer.clear.address;
|
||||
max_length = out_description->buffer.clear.max_length;
|
||||
break;
|
||||
case OEMCrypto_BufferType_Secure:
|
||||
destination_ =
|
||||
reinterpret_cast<uint8_t*>(out_description->buffer.secure.handle) +
|
||||
out_description->buffer.secure.offset;
|
||||
max_length = out_description->buffer.secure.max_length -
|
||||
out_description->buffer.secure.offset;
|
||||
break;
|
||||
case OEMCrypto_BufferType_Direct:
|
||||
// Direct buffer type is only used on some specialized devices where
|
||||
// oemcrypto has a direct connection to the screen buffer. It is not,
|
||||
// for example, supported on Android.
|
||||
destination_ = NULL;
|
||||
break;
|
||||
default:
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
if (out_description->type != OEMCrypto_BufferType_Direct &&
|
||||
max_length < data_length) {
|
||||
LOGE("[SetDestination(): OEMCrypto_ERROR_SHORT_BUFFER]");
|
||||
return OEMCrypto_ERROR_SHORT_BUFFER;
|
||||
}
|
||||
adjust_destination(out_description, data_length, subsample_flags);
|
||||
if ((out_description->type != OEMCrypto_BufferType_Direct) &&
|
||||
(destination_ == NULL)) {
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace wvoec_ref
|
||||
189
libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.h
Normal file
189
libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.h
Normal file
@@ -0,0 +1,189 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// Ref implementation of OEMCrypto APIs
|
||||
//
|
||||
#ifndef REF_OEMCRYPTO_ENGINE_REF_H_
|
||||
#define REF_OEMCRYPTO_ENGINE_REF_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
#include "OEMCryptoCENC.h" // Needed for enums only.
|
||||
#include "file_store.h"
|
||||
#include "lock.h"
|
||||
#include "oemcrypto_auth_ref.h"
|
||||
#include "oemcrypto_key_ref.h"
|
||||
#include "oemcrypto_rsa_key_shared.h"
|
||||
#include "oemcrypto_scoped_ptr.h"
|
||||
#include "oemcrypto_session.h"
|
||||
#include "oemcrypto_usage_table_ref.h"
|
||||
#include "oemcrypto_types.h"
|
||||
|
||||
namespace wvoec_ref {
|
||||
|
||||
typedef std::map<SessionId, SessionContext*> ActiveSessions;
|
||||
|
||||
class CryptoEngine {
|
||||
public:
|
||||
// This is like a factory method, except we choose which version to use at
|
||||
// compile time. It is defined in several source files. The build system
|
||||
// should choose which one to use by only linking in the correct one.
|
||||
// NOTE: The caller must instantiate a FileSystem object - ownership
|
||||
// will be transferred to the new CryptoEngine object.
|
||||
static CryptoEngine* MakeCryptoEngine(
|
||||
scoped_ptr<wvcdm::FileSystem> file_system);
|
||||
|
||||
virtual ~CryptoEngine();
|
||||
|
||||
virtual bool Initialize() { return true; }
|
||||
|
||||
bool ValidRootOfTrust() { return root_of_trust_.Validate(); }
|
||||
|
||||
bool InstallKeybox(const uint8_t* keybox, size_t keybox_length) {
|
||||
return root_of_trust_.InstallKeybox(keybox, keybox_length);
|
||||
}
|
||||
|
||||
bool UseTestKeybox(const uint8_t* keybox_data, size_t keybox_length) {
|
||||
return root_of_trust_.UseTestKeybox(keybox_data, keybox_length);
|
||||
}
|
||||
|
||||
bool LoadTestRsaKey() { return root_of_trust_.LoadTestRsaKey(); }
|
||||
|
||||
KeyboxError ValidateKeybox() { return root_of_trust_.ValidateKeybox(); }
|
||||
|
||||
const std::vector<uint8_t>& DeviceRootKey(bool override_to_real = false) {
|
||||
return root_of_trust_.DeviceKey(override_to_real);
|
||||
}
|
||||
|
||||
const std::vector<uint8_t>& DeviceRootId() {
|
||||
return root_of_trust_.DeviceId();
|
||||
}
|
||||
|
||||
size_t DeviceRootTokenLength() { return root_of_trust_.DeviceTokenLength(); }
|
||||
|
||||
const uint8_t* DeviceRootToken() {
|
||||
return root_of_trust_.DeviceToken();
|
||||
}
|
||||
|
||||
virtual void Terminate() {}
|
||||
|
||||
SessionId CreateSession();
|
||||
|
||||
bool DestroySession(SessionId sid);
|
||||
|
||||
SessionContext* FindSession(SessionId sid);
|
||||
|
||||
size_t GetNumberOfOpenSessions() { return sessions_.size(); }
|
||||
|
||||
size_t GetMaxNumberOfSessions() {
|
||||
// An arbitrary limit for ref implementation.
|
||||
static const size_t kMaxSupportedOEMCryptoSessions = 64;
|
||||
return kMaxSupportedOEMCryptoSessions;
|
||||
}
|
||||
|
||||
// Returns the HDCP version currently in use.
|
||||
virtual OEMCrypto_HDCP_Capability config_current_hdcp_capability();
|
||||
|
||||
// Returns the max HDCP version supported.
|
||||
virtual OEMCrypto_HDCP_Capability config_maximum_hdcp_capability();
|
||||
|
||||
UsageTable& usage_table() { return usage_table_; }
|
||||
wvcdm::FileSystem* file_system() { return file_system_.get(); }
|
||||
|
||||
// If config_local_display_only() returns true, we pretend we are using a
|
||||
// built-in display, instead of HDMI or WiFi output.
|
||||
virtual bool config_local_display_only() { return false; }
|
||||
|
||||
// A closed platform is permitted to use clear buffers.
|
||||
virtual bool config_closed_platform() { return false; }
|
||||
|
||||
// Returns true if the client supports persistent storage of
|
||||
// offline usage table information.
|
||||
virtual bool config_supports_usage_table() { return true; }
|
||||
|
||||
virtual OEMCrypto_ProvisioningMethod config_provisioning_method() {
|
||||
return OEMCrypto_Keybox;
|
||||
}
|
||||
|
||||
virtual OEMCryptoResult get_oem_certificate(SessionContext* session,
|
||||
uint8_t* public_cert,
|
||||
size_t* public_cert_length) {
|
||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
// Used for OEMCrypto_IsAntiRollbackHwPresent.
|
||||
virtual bool config_is_anti_rollback_hw_present() { return false; }
|
||||
|
||||
// Returns "L3" for a software only library. L1 is for hardware protected
|
||||
// data paths.
|
||||
virtual const char* config_security_level() { return "L3"; }
|
||||
|
||||
// This should start at 0, and be incremented only when a security patch has
|
||||
// been applied to the device that fixes a security bug.
|
||||
virtual uint8_t config_security_patch_level() { return 0; }
|
||||
|
||||
// If 0 no restriction, otherwise it's the max buffer for DecryptCENC.
|
||||
virtual size_t max_buffer_size() { return 1024 * 100; } // 100 KiB.
|
||||
|
||||
virtual bool srm_update_supported() { return false; }
|
||||
|
||||
virtual OEMCryptoResult current_srm_version(uint16_t* version) {
|
||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
virtual OEMCryptoResult load_srm(const uint8_t* buffer,
|
||||
size_t buffer_length) {
|
||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
virtual OEMCryptoResult remove_srm() {
|
||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
virtual bool srm_blacklisted_device_attached() { return false; }
|
||||
|
||||
// Rate limit for nonce generation. Default to 20 nonce/second.
|
||||
virtual int nonce_flood_count() { return 20; }
|
||||
|
||||
// Set destination pointer based on the output destination description.
|
||||
OEMCryptoResult SetDestination(OEMCrypto_DestBufferDesc* out_description,
|
||||
size_t data_length, uint8_t subsample_flags);
|
||||
|
||||
// The current destination.
|
||||
uint8_t* destination() { return destination_; }
|
||||
|
||||
// Subclasses can adjust the destination -- for use in testing.
|
||||
virtual void adjust_destination(OEMCrypto_DestBufferDesc* out_description,
|
||||
size_t data_length, uint8_t subsample_flags) {
|
||||
}
|
||||
|
||||
// Push destination buffer to output -- used by subclasses for testing.
|
||||
virtual OEMCryptoResult PushDestination(
|
||||
OEMCrypto_DestBufferDesc* out_description, uint8_t subsample_flags) {
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
protected:
|
||||
explicit CryptoEngine(scoped_ptr<wvcdm::FileSystem> file_system);
|
||||
uint8_t* destination_;
|
||||
|
||||
private:
|
||||
ActiveSessions sessions_;
|
||||
AuthenticationRoot root_of_trust_;
|
||||
wvcdm::Lock session_table_lock_;
|
||||
scoped_ptr<wvcdm::FileSystem> file_system_;
|
||||
UsageTable usage_table_;
|
||||
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(CryptoEngine);
|
||||
};
|
||||
|
||||
} // namespace wvoec_ref
|
||||
|
||||
#endif // REF_OEMCRYPTO_ENGINE_REF_H_
|
||||
125
libwvdrmengine/oemcrypto/ref/src/oemcrypto_key_ref.cpp
Normal file
125
libwvdrmengine/oemcrypto/ref/src/oemcrypto_key_ref.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// Ref implementation of OEMCrypto APIs
|
||||
//
|
||||
#include "oemcrypto_key_ref.h"
|
||||
#include "oemcrypto_types.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
|
||||
#include "log.h"
|
||||
#include "oemcrypto_logging.h"
|
||||
|
||||
namespace wvoec_ref {
|
||||
|
||||
bool KeyControlBlock::Validate() {
|
||||
if (memcmp(verification_, "kctl", 4) && // original verification
|
||||
memcmp(verification_, "kc09", 4) && // add in version 9 api
|
||||
memcmp(verification_, "kc10", 4) && // add in version 10 api
|
||||
memcmp(verification_, "kc11", 4) && // add in version 11 api
|
||||
memcmp(verification_, "kc12", 4) && // add in version 12 api
|
||||
memcmp(verification_, "kc13", 4) && // add in version 13 api
|
||||
memcmp(verification_, "kc14", 4)) { // add in version 14 api
|
||||
LOGE("KCB: BAD verification string: %4.4s", verification_);
|
||||
valid_ = false;
|
||||
} else {
|
||||
valid_ = true;
|
||||
}
|
||||
return valid_;
|
||||
}
|
||||
|
||||
// This extracts 4 bytes in network byte order to a 32 bit integer in
|
||||
// host byte order.
|
||||
uint32_t KeyControlBlock::ExtractField(const std::vector<uint8_t>& str,
|
||||
int idx) {
|
||||
int bidx = idx * 4;
|
||||
uint32_t t = static_cast<unsigned char>(str[bidx]) << 24;
|
||||
t |= static_cast<unsigned char>(str[bidx + 1]) << 16;
|
||||
t |= static_cast<unsigned char>(str[bidx + 2]) << 8;
|
||||
t |= static_cast<unsigned char>(str[bidx + 3]);
|
||||
return t;
|
||||
}
|
||||
|
||||
KeyControlBlock::KeyControlBlock(
|
||||
const std::vector<uint8_t>& key_control_string) {
|
||||
if (key_control_string.size() < wvoec::KEY_CONTROL_SIZE) {
|
||||
LOGE("KCB: BAD Size: %d (not %d)", key_control_string.size(),
|
||||
wvoec::KEY_CONTROL_SIZE);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(verification_, &key_control_string[0], 4);
|
||||
duration_ = ExtractField(key_control_string, 1);
|
||||
nonce_ = ExtractField(key_control_string, 2);
|
||||
control_bits_ = ExtractField(key_control_string, 3);
|
||||
if (LogCategoryEnabled(kLoggingDumpKeyControlBlocks)) {
|
||||
LOGD("KCB:");
|
||||
LOGD(" valid: %d", valid());
|
||||
LOGD(" duration: %d", duration());
|
||||
LOGD(" nonce: %08X", nonce());
|
||||
LOGD(" magic: %08X", verification());
|
||||
LOGD(" bits: %08X", control_bits());
|
||||
LOGD(" bit kSharedLicense %s.",
|
||||
(control_bits() & wvoec::kSharedLicense) ? "set" : "unset");
|
||||
LOGD(" bit kControlSRMVersionRequired %s.",
|
||||
(control_bits() & wvoec::kControlSRMVersionRequired) ? "set" : "unset");
|
||||
LOGD(" bit kControlDisableAnalogOutput %s.",
|
||||
(control_bits() & wvoec::kControlDisableAnalogOutput) ? "set"
|
||||
: "unset");
|
||||
LOGD(" bits kControlSecurityPatchLevel 0x%02x.",
|
||||
(control_bits() & wvoec::kControlSecurityPatchLevelMask) >>
|
||||
wvoec::kControlSecurityPatchLevelShift);
|
||||
switch (control_bits() & wvoec::kControlReplayMask) {
|
||||
case wvoec::kControlNonceRequired:
|
||||
LOGD(" bits kControlReplay kControlNonceRequired.");
|
||||
break;
|
||||
case wvoec::kControlNonceOrEntry:
|
||||
LOGD(" bits kControlReplay kControlNonceOrEntry.");
|
||||
break;
|
||||
default:
|
||||
LOGD(" bits kControlReplay unset.");
|
||||
break;
|
||||
}
|
||||
LOGD(" bits kControlHDCPVersion 0x%02x.",
|
||||
(control_bits() & wvoec::kControlHDCPVersionMask) >>
|
||||
wvoec::kControlHDCPVersionShift);
|
||||
LOGD(" bit kControlAllowEncrypt %s.",
|
||||
(control_bits() & wvoec::kControlAllowEncrypt) ? "set" : "unset");
|
||||
LOGD(" bit kControlAllowDecrypt %s.",
|
||||
(control_bits() & wvoec::kControlAllowDecrypt) ? "set" : "unset");
|
||||
LOGD(" bit kControlAllowSign %s.",
|
||||
(control_bits() & wvoec::kControlAllowSign) ? "set" : "unset");
|
||||
LOGD(" bit kControlAllowVerify %s.",
|
||||
(control_bits() & wvoec::kControlAllowVerify) ? "set" : "unset");
|
||||
LOGD(" bit kControlObserveDataPath %s.",
|
||||
(control_bits() & wvoec::kControlObserveDataPath) ? "set" : "unset");
|
||||
LOGD(" bit kControlObserveHDCP %s.",
|
||||
(control_bits() & wvoec::kControlObserveHDCP) ? "set" : "unset");
|
||||
LOGD(" bit kControlObserveCGMS %s.",
|
||||
(control_bits() & wvoec::kControlObserveCGMS) ? "set" : "unset");
|
||||
LOGD(" bit kControlDataPathSecure %s.",
|
||||
(control_bits() & wvoec::kControlDataPathSecure) ? "set" : "unset");
|
||||
LOGD(" bit kControlNonceEnabled %s.",
|
||||
(control_bits() & wvoec::kControlNonceEnabled) ? "set" : "unset");
|
||||
LOGD(" bit kControlHDCPRequired %s.",
|
||||
(control_bits() & wvoec::kControlHDCPRequired) ? "set" : "unset");
|
||||
uint32_t cgms_bits = control_bits() & 0x3;
|
||||
const char* cgms_values[4] = {"free", "BAD", "once", "never"};
|
||||
LOGD(" CGMS = %s", cgms_values[cgms_bits]);
|
||||
}
|
||||
Validate();
|
||||
}
|
||||
|
||||
void Key::UpdateDuration(const KeyControlBlock& control) {
|
||||
control_.set_duration(control.duration());
|
||||
}
|
||||
|
||||
void KeyControlBlock::RequireLocalDisplay() {
|
||||
// Set all bits to require HDCP Local Display Only.
|
||||
control_bits_ |= wvoec::kControlHDCPVersionMask;
|
||||
}
|
||||
|
||||
} // namespace wvoec_ref
|
||||
87
libwvdrmengine/oemcrypto/ref/src/oemcrypto_key_ref.h
Normal file
87
libwvdrmengine/oemcrypto/ref/src/oemcrypto_key_ref.h
Normal file
@@ -0,0 +1,87 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// Ref implementation of OEMCrypto APIs
|
||||
//
|
||||
#ifndef OEMCRYPTO_KEY_REF_H_
|
||||
#define OEMCRYPTO_KEY_REF_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace wvoec_ref {
|
||||
|
||||
class KeyControlBlock {
|
||||
public:
|
||||
KeyControlBlock(const std::vector<uint8_t>& key_control_string);
|
||||
~KeyControlBlock() {}
|
||||
|
||||
bool Validate();
|
||||
void Invalidate() { valid_ = false; }
|
||||
|
||||
bool valid() const { return valid_; }
|
||||
uint32_t duration() const { return duration_; }
|
||||
void set_duration(uint32_t duration) { duration_ = duration; }
|
||||
uint32_t nonce() const { return nonce_; }
|
||||
const char* verification() const { return verification_; }
|
||||
uint32_t control_bits() const { return control_bits_; }
|
||||
void RequireLocalDisplay();
|
||||
|
||||
private:
|
||||
uint32_t ExtractField(const std::vector<uint8_t>& str, int idx);
|
||||
|
||||
bool valid_;
|
||||
char verification_[4];
|
||||
uint32_t duration_;
|
||||
uint32_t nonce_;
|
||||
uint32_t control_bits_;
|
||||
};
|
||||
|
||||
// AES-128 crypto key, or HMAC signing key.
|
||||
class Key {
|
||||
public:
|
||||
Key(const Key& key)
|
||||
: value_(key.value_), control_(key.control_), ctr_mode_(key.ctr_mode_) {}
|
||||
Key(const std::vector<uint8_t>& key_string, const KeyControlBlock& control)
|
||||
: value_(key_string), control_(control), ctr_mode_(true){};
|
||||
|
||||
virtual ~Key(){};
|
||||
void UpdateDuration(const KeyControlBlock& control);
|
||||
virtual const std::vector<uint8_t>& value() const { return value_; }
|
||||
const KeyControlBlock& control() const { return control_; }
|
||||
bool ctr_mode() const { return ctr_mode_; }
|
||||
void set_ctr_mode(bool ctr_mode) { ctr_mode_ = ctr_mode; }
|
||||
|
||||
private:
|
||||
std::vector<uint8_t> value_;
|
||||
KeyControlBlock control_;
|
||||
bool ctr_mode_;
|
||||
};
|
||||
|
||||
// AES-256 entitlement key. |Key| holds the entitlement key. |EntitlementKey|
|
||||
// holds the content key.
|
||||
class EntitlementKey : public Key {
|
||||
public:
|
||||
EntitlementKey(const Key& key) : Key(key) {}
|
||||
virtual ~EntitlementKey() {}
|
||||
virtual const std::vector<uint8_t>& value() const { return content_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_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;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<uint8_t> content_key_;
|
||||
std::vector<uint8_t> content_key_id_;
|
||||
};
|
||||
|
||||
} // namespace wvoec_ref
|
||||
|
||||
#endif // OEMCRYPTO_KEY_REF_H_
|
||||
115
libwvdrmengine/oemcrypto/ref/src/oemcrypto_keybox_ref.cpp
Normal file
115
libwvdrmengine/oemcrypto/ref/src/oemcrypto_keybox_ref.cpp
Normal file
@@ -0,0 +1,115 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// Ref implementation of OEMCrypto APIs
|
||||
//
|
||||
#include "oemcrypto_keybox_ref.h"
|
||||
|
||||
#include <arpa/inet.h> // needed for ntoh()
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <string>
|
||||
|
||||
#include "log.h"
|
||||
#include "oemcrypto_types.h"
|
||||
#include "wvcrc32.h"
|
||||
|
||||
namespace wvoec_ref {
|
||||
|
||||
namespace {
|
||||
|
||||
const wvoec::WidevineKeybox kTestKeybox = {
|
||||
// Sample keybox used for test vectors
|
||||
{
|
||||
// deviceID
|
||||
0x54, 0x65, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x30, // TestKey01
|
||||
0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
|
||||
}, {
|
||||
// key
|
||||
0xfb, 0xda, 0x04, 0x89, 0xa1, 0x58, 0x16, 0x0e,
|
||||
0xa4, 0x02, 0xe9, 0x29, 0xe3, 0xb6, 0x8f, 0x04,
|
||||
}, {
|
||||
// data
|
||||
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x19,
|
||||
0x07, 0xd9, 0xff, 0xde, 0x13, 0xaa, 0x95, 0xc1,
|
||||
0x22, 0x67, 0x80, 0x53, 0x36, 0x21, 0x36, 0xbd,
|
||||
0xf8, 0x40, 0x8f, 0x82, 0x76, 0xe4, 0xc2, 0xd8,
|
||||
0x7e, 0xc5, 0x2b, 0x61, 0xaa, 0x1b, 0x9f, 0x64,
|
||||
0x6e, 0x58, 0x73, 0x49, 0x30, 0xac, 0xeb, 0xe8,
|
||||
0x99, 0xb3, 0xe4, 0x64, 0x18, 0x9a, 0x14, 0xa8,
|
||||
0x72, 0x02, 0xfb, 0x02, 0x57, 0x4e, 0x70, 0x64,
|
||||
0x0b, 0xd2, 0x2e, 0xf4, 0x4b, 0x2d, 0x7e, 0x39,
|
||||
}, {
|
||||
// magic
|
||||
0x6b, 0x62, 0x6f, 0x78,
|
||||
}, {
|
||||
// Crc
|
||||
0x0a, 0x7a, 0x2c, 0x35,
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
WvKeybox::WvKeybox() {
|
||||
valid_ = Prepare();
|
||||
}
|
||||
|
||||
KeyboxError WvKeybox::Validate() {
|
||||
if (!valid_) {
|
||||
LOGE("[KEYBOX NOT LOADED]");
|
||||
return OTHER_ERROR;
|
||||
}
|
||||
if (strncmp(reinterpret_cast<char*>(magic_), "kbox", 4) != 0) {
|
||||
LOGE("[KEYBOX HAS BAD MAGIC]");
|
||||
return BAD_MAGIC;
|
||||
}
|
||||
uint32_t crc_computed;
|
||||
uint32_t crc_stored;
|
||||
uint8_t* crc_stored_bytes = (uint8_t*) &crc_stored;
|
||||
memcpy(crc_stored_bytes, crc_, sizeof(crc_));
|
||||
wvoec::WidevineKeybox keybox;
|
||||
memset(&keybox, 0, sizeof(keybox));
|
||||
memcpy(keybox.device_id_, &device_id_[0], device_id_.size());
|
||||
memcpy(keybox.device_key_, &device_key_[0], sizeof(keybox.device_key_));
|
||||
memcpy(keybox.data_, key_data_, sizeof(keybox.data_));
|
||||
memcpy(keybox.magic_, magic_, sizeof(keybox.magic_));
|
||||
|
||||
crc_computed = ntohl(wvcrc32(reinterpret_cast<uint8_t*>(&keybox),
|
||||
sizeof(keybox) - 4)); // Drop last 4 bytes.
|
||||
if (crc_computed != crc_stored) {
|
||||
LOGE("[KEYBOX CRC problem: computed = %08x, stored = %08x]\n",
|
||||
crc_computed, crc_stored);
|
||||
return BAD_CRC;
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
bool WvKeybox::InstallKeybox(const uint8_t* buffer, size_t keyBoxLength) {
|
||||
if (keyBoxLength != 128) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const wvoec::WidevineKeybox* keybox
|
||||
= reinterpret_cast<const wvoec::WidevineKeybox*>(buffer);
|
||||
size_t device_id_length
|
||||
= strnlen(reinterpret_cast<const char*>(keybox->device_id_), 32);
|
||||
device_id_.assign(keybox->device_id_,
|
||||
keybox->device_id_ + device_id_length);
|
||||
device_key_.assign(keybox->device_key_,
|
||||
keybox->device_key_ + sizeof(keybox->device_key_));
|
||||
memcpy(key_data_, keybox->data_, sizeof(keybox->data_));
|
||||
memcpy(magic_, keybox->magic_, sizeof(keybox->magic_));
|
||||
memcpy(crc_, keybox->crc_, sizeof(keybox->crc_));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
WvTestKeybox::WvTestKeybox() {
|
||||
InstallKeybox(reinterpret_cast<const uint8_t*>(&kTestKeybox),
|
||||
sizeof(kTestKeybox));
|
||||
}
|
||||
|
||||
} // namespace wvoec_ref
|
||||
53
libwvdrmengine/oemcrypto/ref/src/oemcrypto_keybox_ref.h
Normal file
53
libwvdrmengine/oemcrypto/ref/src/oemcrypto_keybox_ref.h
Normal file
@@ -0,0 +1,53 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// Ref implementation of OEMCrypto APIs
|
||||
//
|
||||
#ifndef OEMCRYPTO_KEYBOX_REF_H_
|
||||
#define OEMCRYPTO_KEYBOX_REF_H_
|
||||
|
||||
#include "oemcrypto_key_ref.h"
|
||||
|
||||
namespace wvoec_ref {
|
||||
|
||||
const int DEVICE_KEY_LENGTH = 16;
|
||||
typedef uint8_t WvKeyboxKey[DEVICE_KEY_LENGTH];
|
||||
|
||||
const int KEY_DATA_LENGTH = 72;
|
||||
typedef uint8_t WvKeyboxKeyData[KEY_DATA_LENGTH];
|
||||
|
||||
enum KeyboxError { NO_ERROR, BAD_CRC, BAD_MAGIC, OTHER_ERROR };
|
||||
|
||||
// Widevine keybox
|
||||
class WvKeybox {
|
||||
public:
|
||||
WvKeybox();
|
||||
~WvKeybox() {}
|
||||
|
||||
KeyboxError Validate();
|
||||
const std::vector<uint8_t>& device_id() { return device_id_; }
|
||||
std::vector<uint8_t>& device_key() { return device_key_; }
|
||||
const WvKeyboxKeyData& key_data() { return key_data_; }
|
||||
size_t key_data_length() { return KEY_DATA_LENGTH; }
|
||||
bool InstallKeybox(const uint8_t* keybox, size_t keyBoxLength);
|
||||
|
||||
private:
|
||||
bool Prepare();
|
||||
|
||||
bool valid_;
|
||||
std::vector<uint8_t> device_id_;
|
||||
std::vector<uint8_t> device_key_;
|
||||
WvKeyboxKeyData key_data_;
|
||||
uint8_t magic_[4];
|
||||
uint8_t crc_[4];
|
||||
};
|
||||
|
||||
class WvTestKeybox : public WvKeybox {
|
||||
public:
|
||||
WvTestKeybox();
|
||||
};
|
||||
|
||||
} // namespace wvoec_ref
|
||||
|
||||
#endif // OEMCRYPTO_KEYBOX_REF_H_
|
||||
@@ -0,0 +1,56 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// Test keybox.
|
||||
|
||||
#include "oemcrypto_keybox_ref.h"
|
||||
#include "oemcrypto_types.h"
|
||||
|
||||
namespace wvoec_ref {
|
||||
|
||||
namespace {
|
||||
|
||||
// Note: this is a valid keybox, but it is not accepted by production servers.
|
||||
// However, it is different from the one used for most of the unit tests.
|
||||
const wvoec::WidevineKeybox kKeybox = {
|
||||
// Sample keybox used for test vectors
|
||||
{
|
||||
// deviceID
|
||||
0x54, 0x65, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x30, // TestKey02
|
||||
0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
|
||||
}, {
|
||||
// key
|
||||
0x76, 0x5d, 0xce, 0x01, 0x04, 0x89, 0xb3, 0xd0,
|
||||
0xdf, 0xce, 0x54, 0x8a, 0x49, 0xda, 0xdc, 0xb6,
|
||||
}, {
|
||||
// data
|
||||
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x19,
|
||||
0x92, 0x27, 0x0b, 0x1f, 0x1a, 0xd5, 0xc6, 0x93,
|
||||
0x19, 0x3f, 0xaa, 0x74, 0x1f, 0xdd, 0x5f, 0xb4,
|
||||
0xe9, 0x40, 0x2f, 0x34, 0xa4, 0x92, 0xf4, 0xae,
|
||||
0x9a, 0x52, 0x39, 0xbc, 0xb7, 0x24, 0x38, 0x13,
|
||||
0xab, 0xf4, 0x92, 0x96, 0xc4, 0x81, 0x60, 0x33,
|
||||
0xd8, 0xb8, 0x09, 0xc7, 0x55, 0x0e, 0x12, 0xfa,
|
||||
0xa8, 0x98, 0x62, 0x8a, 0xec, 0xea, 0x74, 0x8a,
|
||||
0x4b, 0xfa, 0x5a, 0x9e, 0xb6, 0x49, 0x0d, 0x80,
|
||||
}, {
|
||||
// magic
|
||||
0x6b, 0x62, 0x6f, 0x78,
|
||||
}, {
|
||||
// Crc
|
||||
0x2a, 0x3b, 0x3e, 0xe4,
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
bool WvKeybox::Prepare() {
|
||||
InstallKeybox(reinterpret_cast<const uint8_t*>(&kKeybox),
|
||||
sizeof(kKeybox));
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace wvoec_ref
|
||||
106
libwvdrmengine/oemcrypto/ref/src/oemcrypto_logging.cpp
Normal file
106
libwvdrmengine/oemcrypto/ref/src/oemcrypto_logging.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
|
||||
#include "oemcrypto_logging.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace wvoec_ref {
|
||||
|
||||
int logging_category_setting = 0x00;
|
||||
|
||||
void SetLoggingSettings(int level, int categories) {
|
||||
SetLoggingLevel(level);
|
||||
TurnOffLoggingForAllCategories();
|
||||
AddLoggingForCategories(categories);
|
||||
}
|
||||
|
||||
void TurnOffLoggingForAllCategories() { logging_category_setting = 0; }
|
||||
|
||||
void SetLoggingLevel(int level) {
|
||||
wvcdm::g_cutoff = static_cast<wvcdm::LogPriority>(level);
|
||||
}
|
||||
|
||||
void SetLoggingLevel(wvcdm::LogPriority level) { wvcdm::g_cutoff = level; }
|
||||
|
||||
void AddLoggingForCategories(int categories) {
|
||||
logging_category_setting |= categories;
|
||||
}
|
||||
|
||||
void RemoveLoggingForCategories(int categories) {
|
||||
logging_category_setting &= ~categories;
|
||||
}
|
||||
|
||||
bool LogCategoryEnabled(int categories) {
|
||||
return ((logging_category_setting & categories) != 0);
|
||||
}
|
||||
|
||||
void dump_hex_helper(std::string& buffer, std::string name,
|
||||
const uint8_t* vector, size_t length) {
|
||||
buffer += name + " = ";
|
||||
if (vector == NULL) {
|
||||
buffer += "NULL;\n";
|
||||
LOGE(buffer.c_str());
|
||||
return;
|
||||
}
|
||||
int a, b;
|
||||
char int_to_hexcar[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
|
||||
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
if (i == 0) {
|
||||
buffer += "\n a2b_hex(\"";
|
||||
} else if (i % 32 == 0) {
|
||||
buffer += "\"\n \"";
|
||||
}
|
||||
a = vector[i] % 16;
|
||||
b = (vector[i] - a) / 16;
|
||||
buffer += int_to_hexcar[b];
|
||||
buffer += int_to_hexcar[a];
|
||||
}
|
||||
buffer += "\");\n";
|
||||
}
|
||||
|
||||
void dump_hex(std::string name, const uint8_t* vector, size_t length) {
|
||||
std::string buffer = "";
|
||||
dump_hex_helper(buffer, name, vector, length);
|
||||
LOGV(buffer.c_str());
|
||||
}
|
||||
|
||||
void dump_array_part_helper(std::string& buffer, std::string array,
|
||||
size_t index, std::string name,
|
||||
const uint8_t* vector, size_t length) {
|
||||
char index_str[256];
|
||||
|
||||
snprintf(index_str, sizeof index_str, "%zu", index);
|
||||
|
||||
if (vector == NULL) {
|
||||
buffer += array.c_str();
|
||||
buffer += "[";
|
||||
buffer += index_str;
|
||||
buffer += "].";
|
||||
buffer += name.c_str();
|
||||
buffer += " = NULL;\n";
|
||||
LOGW(buffer.c_str());
|
||||
return;
|
||||
}
|
||||
buffer += "std::string s";
|
||||
buffer += index_str;
|
||||
buffer += "_";
|
||||
dump_hex_helper(buffer, name, vector, length);
|
||||
buffer += array.c_str();
|
||||
buffer += "[";
|
||||
buffer += index_str;
|
||||
buffer += "]." + name + " = message_ptr + message.find(s";
|
||||
buffer += index_str;
|
||||
buffer += "_" + name + ".data());\n";
|
||||
}
|
||||
|
||||
void dump_array_part(std::string array, size_t index, std::string name,
|
||||
const uint8_t* vector, size_t length) {
|
||||
std::string buffer = "";
|
||||
dump_array_part_helper(buffer, array, index, name, vector, length);
|
||||
LOGV(buffer.c_str());
|
||||
}
|
||||
|
||||
} // namespace wvoec_ref
|
||||
67
libwvdrmengine/oemcrypto/ref/src/oemcrypto_logging.h
Normal file
67
libwvdrmengine/oemcrypto/ref/src/oemcrypto_logging.h
Normal file
@@ -0,0 +1,67 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
|
||||
#ifndef WVOEC_OEMCRYPTO_LOGGING_H_
|
||||
#define WVOEC_OEMCRYPTO_LOGGING_H_
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "OEMCryptoCENC.h"
|
||||
#include "log.h"
|
||||
|
||||
namespace wvoec_ref {
|
||||
|
||||
// The constants below represent integers with a single "on" bit that
|
||||
// represents categories of logging This allows users to specify with
|
||||
// more precision what they want to log. LogCategoryEnabled(category)
|
||||
// is used to see if the category passed in the parameters is to
|
||||
// be logged based on the current settings. Categories can be combines
|
||||
// using the | (or) bitwise operator. For example
|
||||
// LogCategoryEnabled(category1 | category2) will return true if
|
||||
// category1 and/or category2 are set to logging.
|
||||
|
||||
const int kLoggingTraceOEMCryptoCalls = 0x01; // All except decrypt calls.
|
||||
const int kLoggingDumpContentKeys = 0x02;
|
||||
const int kLoggingDumpKeyControlBlocks = 0x04;
|
||||
const int kLoggingDumpDerivedKeys = 0x08;
|
||||
const int kLoggingTraceNonce = 0x10;
|
||||
const int kLoggingTraceDecryption = 0x20;
|
||||
const int kLoggingTraceUsageTable = 0x40;
|
||||
const int kLoggingTraceDecryptCalls = 0x80;
|
||||
const int kLoggingDumpTraceAll = 0xFF;
|
||||
|
||||
void SetLoggingSettings(int level, int categories);
|
||||
|
||||
// set level of logging
|
||||
void SetLoggingLevel(int level);
|
||||
|
||||
void TurnOffLoggingForAllCategories();
|
||||
|
||||
// Returns true if the category passed is set to logging.
|
||||
// Returns false otherwise. The category constant declared
|
||||
// above are passed.
|
||||
bool LogCategoryEnabled(int category);
|
||||
|
||||
// Turn on logging for the categories passed.
|
||||
void AddLoggingForCategories(int categories);
|
||||
|
||||
// Turn off logging for the categories passed.
|
||||
void RemoveLoggingForCategories(int categories);
|
||||
|
||||
void dump_hex_helper(std::string& buffer, std::string name,
|
||||
const uint8_t* vector, size_t length);
|
||||
|
||||
void dump_hex(std::string name, const uint8_t* vector, size_t length);
|
||||
|
||||
void dump_array_part_helper(std::string& buffer, std::string array,
|
||||
size_t index, std::string name,
|
||||
const uint8_t* vector, size_t length);
|
||||
|
||||
void dump_array_part(std::string array, size_t index, std::string name,
|
||||
const uint8_t* vector, size_t length);
|
||||
|
||||
} // namespace wvoec_ref
|
||||
|
||||
#endif // WVOEC_OEMCRYPTO_LOGGING_H_
|
||||
69
libwvdrmengine/oemcrypto/ref/src/oemcrypto_nonce_table.cpp
Normal file
69
libwvdrmengine/oemcrypto/ref/src/oemcrypto_nonce_table.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// Ref implementation of OEMCrypto APIs
|
||||
//
|
||||
#include "oemcrypto_nonce_table.h"
|
||||
|
||||
namespace wvoec_ref {
|
||||
|
||||
void NonceTable::AddNonce(uint32_t nonce) {
|
||||
int new_slot = -1;
|
||||
int oldest_slot = -1;
|
||||
|
||||
// Flush any nonces that have been checked but not flushed.
|
||||
// After flush, nonces will be either valid or invalid.
|
||||
Flush();
|
||||
|
||||
for (int i = 0; i < kTableSize; ++i) {
|
||||
// Increase age of all valid nonces.
|
||||
if (kNTStateValid == state_[i]) {
|
||||
++age_[i];
|
||||
if (-1 == oldest_slot) {
|
||||
oldest_slot = i;
|
||||
} else {
|
||||
if (age_[i] > age_[oldest_slot]) {
|
||||
oldest_slot = i;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (-1 == new_slot) {
|
||||
age_[i] = 0;
|
||||
nonces_[i] = nonce;
|
||||
state_[i] = kNTStateValid;
|
||||
new_slot = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (-1 == new_slot) {
|
||||
// reuse oldest
|
||||
// assert (oldest_slot != -1)
|
||||
int i = oldest_slot;
|
||||
age_[i] = 0;
|
||||
nonces_[i] = nonce;
|
||||
state_[i] = kNTStateValid;
|
||||
}
|
||||
}
|
||||
|
||||
bool NonceTable::CheckNonce(uint32_t nonce) {
|
||||
for (int i = 0; i < kTableSize; ++i) {
|
||||
if (kNTStateInvalid != state_[i]) {
|
||||
if (nonce == nonces_[i]) {
|
||||
state_[i] = kNTStateFlushPending;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void NonceTable::Flush() {
|
||||
for (int i = 0; i < kTableSize; ++i) {
|
||||
if (kNTStateFlushPending == state_[i]) {
|
||||
state_[i] = kNTStateInvalid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace wvoec_ref
|
||||
40
libwvdrmengine/oemcrypto/ref/src/oemcrypto_nonce_table.h
Normal file
40
libwvdrmengine/oemcrypto/ref/src/oemcrypto_nonce_table.h
Normal file
@@ -0,0 +1,40 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// Ref implementation of OEMCrypto APIs
|
||||
//
|
||||
#ifndef REF_OEMCRYPTO_NONCE_TABLE_H_
|
||||
#define REF_OEMCRYPTO_NONCE_TABLE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace wvoec_ref {
|
||||
|
||||
class NonceTable {
|
||||
public:
|
||||
static const int kTableSize = 16;
|
||||
NonceTable() {
|
||||
for (int i = 0; i < kTableSize; ++i) {
|
||||
state_[i] = kNTStateInvalid;
|
||||
}
|
||||
}
|
||||
~NonceTable() {}
|
||||
void AddNonce(uint32_t nonce);
|
||||
bool CheckNonce(uint32_t nonce);
|
||||
void Flush();
|
||||
|
||||
private:
|
||||
enum NonceTableState {
|
||||
kNTStateInvalid,
|
||||
kNTStateValid,
|
||||
kNTStateFlushPending
|
||||
};
|
||||
NonceTableState state_[kTableSize];
|
||||
uint32_t age_[kTableSize];
|
||||
uint32_t nonces_[kTableSize];
|
||||
};
|
||||
|
||||
} // namespace wvoec_ref
|
||||
|
||||
#endif // REF_OEMCRYPTO_NONCE_TABLE_H_
|
||||
@@ -0,0 +1,247 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// Ref implementation of OEMCrypto APIs
|
||||
//
|
||||
// This is from the v12 version of oemcrypto usage tables. It is used for
|
||||
// devices that upgrade from v12 to v13 in the field, and need to convert from
|
||||
// the old type of usage table to the new.
|
||||
#include "oemcrypto_old_usage_table_ref.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#include "file_store.h"
|
||||
#include "log.h"
|
||||
#include "oemcrypto_engine_ref.h"
|
||||
#include "oemcrypto_logging.h"
|
||||
// TODO(fredgc): Setting the device files base bath is currently broken as
|
||||
// wvcdm::Properties is no longer used by the reference code.
|
||||
//#include "properties.h"
|
||||
#include "pst_report.h"
|
||||
#include "string_conversions.h"
|
||||
|
||||
namespace wvoec_ref {
|
||||
|
||||
OldUsageTableEntry::OldUsageTableEntry(const std::vector<uint8_t> &pst_hash)
|
||||
: pst_hash_(pst_hash),
|
||||
time_of_license_received_(time(NULL)),
|
||||
time_of_first_decrypt_(0),
|
||||
time_of_last_decrypt_(0),
|
||||
status_(kUnused) {}
|
||||
|
||||
OldUsageTableEntry::~OldUsageTableEntry() {}
|
||||
|
||||
OldUsageTableEntry::OldUsageTableEntry(const OldStoredUsageEntry *buffer) {
|
||||
pst_hash_.assign(buffer->pst_hash, buffer->pst_hash + SHA256_DIGEST_LENGTH);
|
||||
time_of_license_received_ = buffer->time_of_license_received;
|
||||
time_of_first_decrypt_ = buffer->time_of_first_decrypt;
|
||||
time_of_last_decrypt_ = buffer->time_of_last_decrypt;
|
||||
status_ = buffer->status;
|
||||
mac_key_server_.assign(buffer->mac_key_server,
|
||||
buffer->mac_key_server + wvoec::MAC_KEY_SIZE);
|
||||
mac_key_client_.assign(buffer->mac_key_client,
|
||||
buffer->mac_key_client + wvoec::MAC_KEY_SIZE);
|
||||
}
|
||||
|
||||
OldUsageTable::OldUsageTable(CryptoEngine *ce) {
|
||||
ce_ = ce;
|
||||
generation_ = 0;
|
||||
table_.clear();
|
||||
|
||||
// Load saved table.
|
||||
wvcdm::FileSystem *file_system = ce->file_system();
|
||||
wvcdm::File *file;
|
||||
std::string path;
|
||||
// Note: this path is OK for a real implementation, but using security level 1
|
||||
// would be better.
|
||||
// TODO(fredgc, jfore): Address how this property is presented to the ref.
|
||||
// For now, the path is empty.
|
||||
/*if (!Properties::GetDeviceFilesBasePath(kSecurityLevelL3, &path)) {
|
||||
LOGE("OldUsageTable: Unable to get base path");
|
||||
return;
|
||||
}*/
|
||||
std::string filename = path + "UsageTable.dat";
|
||||
if (!file_system->Exists(filename)) {
|
||||
if (LogCategoryEnabled(kLoggingTraceUsageTable)) {
|
||||
LOGI("OldUsageTable: No saved usage table. Creating new table.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
size_t file_size = file_system->FileSize(filename);
|
||||
std::vector<uint8_t> encrypted_buffer(file_size);
|
||||
std::vector<uint8_t> buffer(file_size);
|
||||
OldStoredUsageTable *stored_table =
|
||||
reinterpret_cast<OldStoredUsageTable *>(&buffer[0]);
|
||||
OldStoredUsageTable *encrypted_table =
|
||||
reinterpret_cast<OldStoredUsageTable *>(&encrypted_buffer[0]);
|
||||
|
||||
file = file_system->Open(filename, wvcdm::FileSystem::kReadOnly);
|
||||
if (!file) {
|
||||
LOGE("OldUsageTable: File open failed: %s", path.c_str());
|
||||
return;
|
||||
}
|
||||
file->Read(reinterpret_cast<char *>(&encrypted_buffer[0]), file_size);
|
||||
file->Close();
|
||||
|
||||
// Verify the signature of the usage table file.
|
||||
|
||||
// This should be encrypted and signed with a device specific key.
|
||||
// For the reference implementation, I'm just going to use the keybox key.
|
||||
const bool override_to_real = true;
|
||||
const std::vector<uint8_t> &key = ce_->DeviceRootKey(override_to_real);
|
||||
|
||||
uint8_t computed_signature[SHA256_DIGEST_LENGTH];
|
||||
unsigned int sig_length = sizeof(computed_signature);
|
||||
if (!HMAC(EVP_sha256(), &key[0], key.size(),
|
||||
&encrypted_buffer[SHA256_DIGEST_LENGTH],
|
||||
file_size - SHA256_DIGEST_LENGTH, computed_signature,
|
||||
&sig_length)) {
|
||||
LOGE("OldUsageTable: Could not recreate signature.");
|
||||
table_.clear();
|
||||
return;
|
||||
}
|
||||
if (memcmp(encrypted_table->signature, computed_signature, sig_length)) {
|
||||
LOGE("OldUsageTable: Invalid signature given: %s",
|
||||
wvcdm::HexEncode(&encrypted_buffer[0], sig_length).c_str());
|
||||
LOGE("OldUsageTable: Invalid signature computed: %s",
|
||||
wvcdm::HexEncode(computed_signature, sig_length).c_str());
|
||||
table_.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// Next, decrypt the table.
|
||||
uint8_t iv_buffer[wvoec::KEY_IV_SIZE];
|
||||
memcpy(iv_buffer, encrypted_table->iv, wvoec::KEY_IV_SIZE);
|
||||
AES_KEY aes_key;
|
||||
AES_set_decrypt_key(&key[0], 128, &aes_key);
|
||||
AES_cbc_encrypt(&encrypted_buffer[SHA256_DIGEST_LENGTH + wvoec::KEY_IV_SIZE],
|
||||
&buffer[SHA256_DIGEST_LENGTH + wvoec::KEY_IV_SIZE],
|
||||
file_size - SHA256_DIGEST_LENGTH - wvoec::KEY_IV_SIZE, &aes_key,
|
||||
iv_buffer, AES_DECRYPT);
|
||||
|
||||
// Next, read the generation number from a different location.
|
||||
// On a real implementation, you should NOT put the generation number in
|
||||
// a file in user space. It should be stored in secure memory. For the
|
||||
// reference implementation, we'll just pretend this is secure.
|
||||
std::string filename2 = path + "GenerationNumber.dat";
|
||||
file = file_system->Open(filename2, wvcdm::FileSystem::kReadOnly);
|
||||
if (!file) {
|
||||
LOGE("OldUsageTable: File open failed: %s (clearing table)", path.c_str());
|
||||
generation_ = 0;
|
||||
table_.clear();
|
||||
return;
|
||||
}
|
||||
file->Read(reinterpret_cast<char *>(&generation_), sizeof(int64_t));
|
||||
file->Close();
|
||||
if (stored_table->generation == generation_ + 1) {
|
||||
if (LogCategoryEnabled(kLoggingTraceUsageTable)) {
|
||||
LOGW("OldUsageTable: File is one generation old. Acceptable rollback.");
|
||||
}
|
||||
} else if (stored_table->generation == generation_ - 1) {
|
||||
if (LogCategoryEnabled(kLoggingTraceUsageTable)) {
|
||||
LOGW("OldUsageTable: File is one generation new. Acceptable rollback.");
|
||||
}
|
||||
// This might happen if the generation number was rolled back?
|
||||
} else if (stored_table->generation != generation_) {
|
||||
LOGE("OldUsageTable: Rollback detected. Clearing Usage Table. %lx -> %lx",
|
||||
generation_, stored_table->generation);
|
||||
table_.clear();
|
||||
generation_ = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// At this point, the stored table looks valid. We can load in all the
|
||||
// entries.
|
||||
for (uint64_t i = 0; i < stored_table->count; i++) {
|
||||
OldUsageTableEntry *entry =
|
||||
new OldUsageTableEntry(&stored_table->entries[i].entry);
|
||||
table_[entry->pst_hash()] = entry;
|
||||
}
|
||||
if (LogCategoryEnabled(kLoggingTraceUsageTable)) {
|
||||
LOGI("OldUsageTable: loaded %d entries.", stored_table->count);
|
||||
}
|
||||
}
|
||||
|
||||
OldUsageTableEntry *OldUsageTable::FindEntry(const std::vector<uint8_t> &pst) {
|
||||
wvcdm::AutoLock lock(lock_);
|
||||
return FindEntryLocked(pst);
|
||||
}
|
||||
|
||||
OldUsageTableEntry *OldUsageTable::FindEntryLocked(
|
||||
const std::vector<uint8_t> &pst) {
|
||||
std::vector<uint8_t> pst_hash;
|
||||
if (!ComputeHash(pst, pst_hash)) {
|
||||
LOGE("OldUsageTable: Could not compute hash of pst.");
|
||||
return NULL;
|
||||
}
|
||||
EntryMap::iterator it = table_.find(pst_hash);
|
||||
if (it == table_.end()) {
|
||||
return NULL;
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
OldUsageTableEntry *OldUsageTable::CreateEntry(
|
||||
const std::vector<uint8_t> &pst) {
|
||||
std::vector<uint8_t> pst_hash;
|
||||
if (!ComputeHash(pst, pst_hash)) {
|
||||
LOGE("OldUsageTable: Could not compute hash of pst.");
|
||||
return NULL;
|
||||
}
|
||||
OldUsageTableEntry *entry = new OldUsageTableEntry(pst_hash);
|
||||
wvcdm::AutoLock lock(lock_);
|
||||
table_[pst_hash] = entry;
|
||||
return entry;
|
||||
}
|
||||
|
||||
void OldUsageTable::Clear() {
|
||||
wvcdm::AutoLock lock(lock_);
|
||||
for (EntryMap::iterator i = table_.begin(); i != table_.end(); ++i) {
|
||||
if (i->second) delete i->second;
|
||||
}
|
||||
table_.clear();
|
||||
}
|
||||
|
||||
void OldUsageTable::DeleteFile(CryptoEngine *ce) {
|
||||
wvcdm::FileSystem *file_system = ce->file_system();
|
||||
std::string path;
|
||||
// Note: this path is OK for a real implementation, but using security level 1
|
||||
// would be better.
|
||||
// TODO(jfore): Address how this property is presented to the ref. For now,
|
||||
// the path is empty.
|
||||
/*if (!Properties::GetDeviceFilesBasePath(kSecurityLevelL3, &path)) {
|
||||
LOGE("OldUsageTable: Unable to get base path");
|
||||
return;
|
||||
}*/
|
||||
std::string filename = path + "UsageTable.dat";
|
||||
if (file_system->Exists(filename)) {
|
||||
if (!file_system->Remove(filename)) {
|
||||
LOGE("DeleteOldUsageTable: error removing file.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool OldUsageTable::ComputeHash(const std::vector<uint8_t> &pst,
|
||||
std::vector<uint8_t> &pst_hash) {
|
||||
// The PST is not fixed size, and we have no promises that it is reasonbly
|
||||
// sized, so we compute a hash of it, and store that instead.
|
||||
pst_hash.resize(SHA256_DIGEST_LENGTH);
|
||||
SHA256_CTX context;
|
||||
if (!SHA256_Init(&context)) return false;
|
||||
if (!SHA256_Update(&context, &pst[0], pst.size())) return false;
|
||||
if (!SHA256_Final(&pst_hash[0], &context)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace wvoec_ref
|
||||
@@ -0,0 +1,95 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// Ref implementation of OEMCrypto APIs
|
||||
//
|
||||
// This is from the v12 version of oemcrypto usage tables. It is used for
|
||||
// devices that upgrade from v12 to v13 in the field, and need to convert from
|
||||
// the old type of usage table to the new.
|
||||
#ifndef OEMCRYPTO_OLD_USAGE_TABLE_REF_H_
|
||||
#define OEMCRYPTO_OLD_USAGE_TABLE_REF_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "OEMCryptoCENC.h"
|
||||
#include "lock.h"
|
||||
#include "oemcrypto_types.h"
|
||||
#include "openssl/sha.h"
|
||||
|
||||
namespace wvoec_ref {
|
||||
|
||||
class CryptoEngine;
|
||||
class UsagetTableEntry;
|
||||
|
||||
struct OldStoredUsageEntry {
|
||||
// To save disk space, we only store a hash of the pst.
|
||||
uint8_t pst_hash[SHA256_DIGEST_LENGTH];
|
||||
int64_t time_of_license_received;
|
||||
int64_t time_of_first_decrypt;
|
||||
int64_t time_of_last_decrypt;
|
||||
enum OEMCrypto_Usage_Entry_Status status;
|
||||
uint8_t mac_key_server[wvoec::MAC_KEY_SIZE];
|
||||
uint8_t mac_key_client[wvoec::MAC_KEY_SIZE];
|
||||
};
|
||||
|
||||
typedef union {
|
||||
struct OldStoredUsageEntry entry;
|
||||
uint8_t padding[128]; // multiple of block size and bigger than entry size.
|
||||
} AlignedOldStoredUsageEntry;
|
||||
|
||||
struct OldStoredUsageTable {
|
||||
uint8_t signature[SHA256_DIGEST_LENGTH];
|
||||
uint8_t iv[wvoec::KEY_IV_SIZE];
|
||||
int64_t generation;
|
||||
uint64_t count;
|
||||
AlignedOldStoredUsageEntry entries[];
|
||||
};
|
||||
|
||||
class OldUsageTableEntry {
|
||||
public:
|
||||
OldUsageTableEntry(const std::vector<uint8_t> &pst_hash);
|
||||
OldUsageTableEntry(const OldStoredUsageEntry *buffer);
|
||||
~OldUsageTableEntry();
|
||||
const std::vector<uint8_t> &pst_hash() const { return pst_hash_; }
|
||||
|
||||
private:
|
||||
std::vector<uint8_t> pst_hash_;
|
||||
int64_t time_of_license_received_;
|
||||
int64_t time_of_first_decrypt_;
|
||||
int64_t time_of_last_decrypt_;
|
||||
enum OEMCrypto_Usage_Entry_Status status_;
|
||||
std::vector<uint8_t> mac_key_server_;
|
||||
std::vector<uint8_t> mac_key_client_;
|
||||
|
||||
friend class UsageTableEntry;
|
||||
friend class UsageTable;
|
||||
};
|
||||
|
||||
class OldUsageTable {
|
||||
public:
|
||||
OldUsageTable(CryptoEngine *ce);
|
||||
~OldUsageTable() { Clear(); }
|
||||
OldUsageTableEntry *FindEntry(const std::vector<uint8_t> &pst);
|
||||
OldUsageTableEntry *CreateEntry(const std::vector<uint8_t> &pst);
|
||||
void Clear();
|
||||
static void DeleteFile(CryptoEngine *ce);
|
||||
|
||||
private:
|
||||
OldUsageTableEntry *FindEntryLocked(const std::vector<uint8_t> &pst);
|
||||
bool ComputeHash(const std::vector<uint8_t> &pst,
|
||||
std::vector<uint8_t> &pst_hash);
|
||||
|
||||
typedef std::map<std::vector<uint8_t>, OldUsageTableEntry *> EntryMap;
|
||||
EntryMap table_;
|
||||
wvcdm::Lock lock_;
|
||||
int64_t generation_;
|
||||
CryptoEngine *ce_;
|
||||
};
|
||||
|
||||
} // namespace wvoec_ref
|
||||
|
||||
#endif // OEMCRYPTO_OLD_USAGE_TABLE_REF_H_
|
||||
1974
libwvdrmengine/oemcrypto/ref/src/oemcrypto_ref.cpp
Normal file
1974
libwvdrmengine/oemcrypto/ref/src/oemcrypto_ref.cpp
Normal file
File diff suppressed because it is too large
Load Diff
101
libwvdrmengine/oemcrypto/ref/src/oemcrypto_rsa_key_shared.cpp
Normal file
101
libwvdrmengine/oemcrypto/ref/src/oemcrypto_rsa_key_shared.cpp
Normal file
@@ -0,0 +1,101 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// Ref implementation of OEMCrypto APIs
|
||||
//
|
||||
#include "oemcrypto_rsa_key_shared.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/x509.h>
|
||||
|
||||
#include "oemcrypto_logging.h"
|
||||
|
||||
namespace wvoec_ref {
|
||||
|
||||
void dump_boringssl_error() {
|
||||
int count = 0;
|
||||
while (unsigned long err = ERR_get_error()) {
|
||||
count++;
|
||||
char buffer[120];
|
||||
ERR_error_string_n(err, buffer, sizeof(buffer));
|
||||
LOGE("BoringSSL Error %d -- %lu -- %s", count, err, buffer);
|
||||
}
|
||||
LOGE("Reported %d BoringSSL Errors", count);
|
||||
}
|
||||
|
||||
void RSA_shared_ptr::reset() {
|
||||
if (rsa_key_ && key_owned_) {
|
||||
RSA_free(rsa_key_);
|
||||
}
|
||||
key_owned_ = false;
|
||||
rsa_key_ = NULL;
|
||||
}
|
||||
|
||||
bool RSA_shared_ptr::LoadPkcs8RsaKey(const uint8_t* buffer, size_t length) {
|
||||
assert(buffer != NULL);
|
||||
reset();
|
||||
uint8_t* pkcs8_rsa_key = const_cast<uint8_t*>(buffer);
|
||||
BIO* bio = BIO_new_mem_buf(pkcs8_rsa_key, length);
|
||||
if (bio == NULL) {
|
||||
LOGE("[LoadPkcs8RsaKey(): Could not allocate bio buffer]");
|
||||
return false;
|
||||
}
|
||||
bool success = true;
|
||||
PKCS8_PRIV_KEY_INFO* pkcs8_pki = d2i_PKCS8_PRIV_KEY_INFO_bio(bio, NULL);
|
||||
if (pkcs8_pki == NULL) {
|
||||
BIO_reset(bio);
|
||||
pkcs8_pki = d2i_PKCS8_PRIV_KEY_INFO_bio(bio, NULL);
|
||||
if (pkcs8_pki == NULL) {
|
||||
LOGE("[LoadPkcs8RsaKey(): d2i_PKCS8_PRIV_KEY_INFO_bio returned NULL]");
|
||||
dump_boringssl_error();
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
EVP_PKEY* evp = NULL;
|
||||
if (success) {
|
||||
evp = EVP_PKCS82PKEY(pkcs8_pki);
|
||||
if (evp == NULL) {
|
||||
LOGE("[LoadPkcs8RsaKey(): EVP_PKCS82PKEY returned NULL]");
|
||||
dump_boringssl_error();
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
if (success) {
|
||||
rsa_key_ = EVP_PKEY_get1_RSA(evp);
|
||||
if (rsa_key_ == NULL) {
|
||||
LOGE("[LoadPkcs8RsaKey(): PrivateKeyInfo did not contain an RSA key]");
|
||||
success = false;
|
||||
}
|
||||
key_owned_ = true;
|
||||
}
|
||||
if (evp != NULL) {
|
||||
EVP_PKEY_free(evp);
|
||||
}
|
||||
if (pkcs8_pki != NULL) {
|
||||
PKCS8_PRIV_KEY_INFO_free(pkcs8_pki);
|
||||
}
|
||||
BIO_free(bio);
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
switch (RSA_check_key(rsa_key_)) {
|
||||
case 1: // valid.
|
||||
return true;
|
||||
case 0: // not valid.
|
||||
LOGE("[LoadPkcs8RsaKey(): rsa key not valid]");
|
||||
dump_boringssl_error();
|
||||
return false;
|
||||
default: // -1 == check failed.
|
||||
LOGE("[LoadPkcs8RsaKey(): error checking rsa key]");
|
||||
dump_boringssl_error();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace wvoec_ref
|
||||
42
libwvdrmengine/oemcrypto/ref/src/oemcrypto_rsa_key_shared.h
Normal file
42
libwvdrmengine/oemcrypto/ref/src/oemcrypto_rsa_key_shared.h
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// Ref implementation of OEMCrypto APIs
|
||||
//
|
||||
#ifndef OEMCRYPTO_RSA_KEY_SHARED_H_
|
||||
#define OEMCRYPTO_RSA_KEY_SHARED_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
namespace wvoec_ref {
|
||||
|
||||
// Shared pointer with specialized destructor. This pointer is only shared
|
||||
// from a CryptoEngine to a Session -- so we don't have to use full reference
|
||||
// counting.
|
||||
class RSA_shared_ptr {
|
||||
public:
|
||||
RSA_shared_ptr() : rsa_key_(NULL), key_owned_(false) {}
|
||||
~RSA_shared_ptr() { reset(); };
|
||||
// Explicitly allow copy as share.
|
||||
explicit RSA_shared_ptr(const RSA_shared_ptr& other) :
|
||||
rsa_key_(other.rsa_key_), key_owned_(false) {}
|
||||
RSA* get() { return rsa_key_; }
|
||||
void reset();
|
||||
bool LoadPkcs8RsaKey(const uint8_t* buffer, size_t length);
|
||||
|
||||
private:
|
||||
void operator=(const RSA_shared_ptr); // disallow assign.
|
||||
|
||||
RSA* rsa_key_;
|
||||
bool key_owned_;
|
||||
};
|
||||
|
||||
// Log errors from BoringSSL.
|
||||
void dump_boringssl_error();
|
||||
|
||||
} // namespace wvoec_ref
|
||||
|
||||
#endif // OEMCRYPTO_RSA_KEY_SHARED_H_
|
||||
44
libwvdrmengine/oemcrypto/ref/src/oemcrypto_scoped_ptr.h
Normal file
44
libwvdrmengine/oemcrypto/ref/src/oemcrypto_scoped_ptr.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#ifndef OEMCRYPTO_SCOPED_PTR_H_
|
||||
#define OEMCRYPTO_SCOPED_PTR_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <memory>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
namespace wvoec_ref {
|
||||
|
||||
// TODO(fredgc, jfore): scoped_ptr may not be the best name for this smart
|
||||
// pointer type. It basically works like auto_ptr which is deprecated.
|
||||
#if __cplusplus < 201103L
|
||||
|
||||
template <typename T>
|
||||
class scoped_ptr {
|
||||
public:
|
||||
explicit scoped_ptr(T* p = NULL) : ptr_(p) {}
|
||||
T* get() const { return ptr_.get(); }
|
||||
|
||||
private:
|
||||
std::auto_ptr<T> ptr_;
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
template <typename T>
|
||||
class scoped_ptr {
|
||||
public:
|
||||
explicit scoped_ptr(T* p = nullptr) : ptr_(p) {}
|
||||
scoped_ptr(scoped_ptr& r) { ptr_ = std::move(r.ptr_); }
|
||||
T& operator*() const { return *ptr_; }
|
||||
T* operator->() const { return ptr_.get(); }
|
||||
T* get() const { return ptr_.get(); }
|
||||
void reset(T* p = NULL) { ptr_.reset(); }
|
||||
|
||||
private:
|
||||
std::unique_ptr<T> ptr_;
|
||||
};
|
||||
#endif
|
||||
|
||||
} // namespace wvoec_ref
|
||||
|
||||
#endif // OEMCRYPTO_SCOPED_PTR_H_
|
||||
1572
libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.cpp
Normal file
1572
libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.cpp
Normal file
File diff suppressed because it is too large
Load Diff
248
libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.h
Normal file
248
libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.h
Normal file
@@ -0,0 +1,248 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// Ref implementation of OEMCrypto APIs
|
||||
//
|
||||
#ifndef REF_OEMCRYPTO_SESSION_H_
|
||||
#define REF_OEMCRYPTO_SESSION_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
#include "OEMCryptoCENC.h" // Needed for enums only.
|
||||
#include "oemcrypto_auth_ref.h"
|
||||
#include "oemcrypto_key_ref.h"
|
||||
#include "oemcrypto_nonce_table.h"
|
||||
#include "oemcrypto_rsa_key_shared.h"
|
||||
#include "oemcrypto_session_key_table.h"
|
||||
#include "oemcrypto_usage_table_ref.h"
|
||||
#include "oemcrypto_types.h"
|
||||
|
||||
namespace wvoec_ref {
|
||||
|
||||
class CryptoEngine;
|
||||
typedef uint32_t SessionId;
|
||||
|
||||
enum SRMVersionStatus { NoSRMVersion, ValidSRMVersion, InvalidSRMVersion };
|
||||
|
||||
// TODO(jfore): Is there a better name?
|
||||
class SessionContextKeys {
|
||||
public:
|
||||
virtual OEMCrypto_LicenseType type() = 0;
|
||||
virtual size_t size() = 0;
|
||||
virtual bool Insert(const KeyId& key_id, const Key& key_data) = 0;
|
||||
virtual Key* Find(const KeyId& key_id) = 0;
|
||||
virtual void Remove(const KeyId& key_id) = 0;
|
||||
virtual void UpdateDuration(const KeyControlBlock& control) = 0;
|
||||
|
||||
// Methods supported exclusively for entitlement keys. Returns false if
|
||||
// entitlement keys are not found or not supported by the current key table.
|
||||
// It is the caller's responsibility to check the context.
|
||||
virtual bool SetContentKey(const KeyId& entitlement_id,
|
||||
const KeyId& content_key_id,
|
||||
const std::vector<uint8_t>& content_key) = 0;
|
||||
virtual bool GetEntitlementKey(const KeyId& entitlement_id,
|
||||
const std::vector<uint8_t>** key) = 0;
|
||||
|
||||
virtual ~SessionContextKeys() {}
|
||||
|
||||
protected:
|
||||
SessionContextKeys() {}
|
||||
|
||||
private:
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(SessionContextKeys);
|
||||
};
|
||||
|
||||
class SessionContext {
|
||||
private:
|
||||
SessionContext() {}
|
||||
|
||||
public:
|
||||
SessionContext(CryptoEngine* ce, SessionId sid, const RSA_shared_ptr& rsa_key)
|
||||
: valid_(true),
|
||||
ce_(ce),
|
||||
id_(sid),
|
||||
current_content_key_(NULL),
|
||||
session_keys_(NULL),
|
||||
rsa_key_(rsa_key),
|
||||
allowed_schemes_(kSign_RSASSA_PSS),
|
||||
usage_entry_(NULL),
|
||||
srm_requirements_status_(NoSRMVersion),
|
||||
usage_entry_status_(kNoUsageEntry) {}
|
||||
~SessionContext();
|
||||
|
||||
bool isValid() { return valid_; }
|
||||
|
||||
bool DeriveKeys(const std::vector<uint8_t>& master_key,
|
||||
const std::vector<uint8_t>& mac_context,
|
||||
const std::vector<uint8_t>& enc_context);
|
||||
bool RSADeriveKeys(const std::vector<uint8_t>& enc_session_key,
|
||||
const std::vector<uint8_t>& mac_context,
|
||||
const std::vector<uint8_t>& enc_context);
|
||||
bool GenerateSignature(const uint8_t* message, size_t message_length,
|
||||
uint8_t* signature, size_t* signature_length);
|
||||
size_t RSASignatureSize();
|
||||
OEMCryptoResult GenerateRSASignature(const uint8_t* message,
|
||||
size_t message_length,
|
||||
uint8_t* signature,
|
||||
size_t* signature_length,
|
||||
RSA_Padding_Scheme padding_scheme);
|
||||
bool ValidateMessage(const uint8_t* message, size_t message_length,
|
||||
const uint8_t* signature, size_t signature_length);
|
||||
OEMCryptoResult DecryptCENC(const uint8_t* iv, size_t block_offset,
|
||||
const OEMCrypto_CENCEncryptPatternDesc* pattern,
|
||||
const uint8_t* cipher_data,
|
||||
size_t cipher_data_length, bool is_encrypted,
|
||||
uint8_t* clear_data,
|
||||
OEMCryptoBufferType buffer_type);
|
||||
|
||||
OEMCryptoResult Generic_Encrypt(const uint8_t* in_buffer,
|
||||
size_t buffer_length, const uint8_t* iv,
|
||||
OEMCrypto_Algorithm algorithm,
|
||||
uint8_t* out_buffer);
|
||||
OEMCryptoResult Generic_Decrypt(const uint8_t* in_buffer,
|
||||
size_t buffer_length, const uint8_t* iv,
|
||||
OEMCrypto_Algorithm algorithm,
|
||||
uint8_t* out_buffer);
|
||||
OEMCryptoResult Generic_Sign(const uint8_t* in_buffer, size_t buffer_length,
|
||||
OEMCrypto_Algorithm algorithm,
|
||||
uint8_t* signature, size_t* signature_length);
|
||||
OEMCryptoResult Generic_Verify(const uint8_t* in_buffer, size_t buffer_length,
|
||||
OEMCrypto_Algorithm algorithm,
|
||||
const uint8_t* signature,
|
||||
size_t signature_length);
|
||||
void StartTimer();
|
||||
uint32_t CurrentTimer(); // (seconds).
|
||||
OEMCryptoResult LoadKeys(
|
||||
const uint8_t* message, size_t message_length, const uint8_t* signature,
|
||||
size_t signature_length, const uint8_t* enc_mac_key_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,
|
||||
OEMCrypto_LicenseType license_type);
|
||||
OEMCryptoResult LoadEntitledContentKeys(
|
||||
size_t num_keys,
|
||||
const OEMCrypto_EntitledContentKeyObject* key_array);
|
||||
OEMCryptoResult 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);
|
||||
bool InstallRSAEncryptedKey(const uint8_t* encrypted_message_key,
|
||||
size_t encrypted_message_key_length);
|
||||
bool DecryptRSAKey(const uint8_t* enc_rsa_key, size_t enc_rsa_key_length,
|
||||
const uint8_t* wrapped_rsa_key_iv, uint8_t* pkcs8_rsa_key);
|
||||
bool EncryptRSAKey(const uint8_t* pkcs8_rsa_key, size_t enc_rsa_key_length,
|
||||
const uint8_t* enc_rsa_key_iv, uint8_t* enc_rsa_key);
|
||||
bool LoadRSAKey(const uint8_t* pkcs8_rsa_key, size_t rsa_key_length);
|
||||
OEMCryptoResult RefreshKey(const KeyId& key_id,
|
||||
const std::vector<uint8_t>& key_control,
|
||||
const std::vector<uint8_t>& key_control_iv);
|
||||
bool UpdateMacKeys(const std::vector<uint8_t>& mac_keys,
|
||||
const std::vector<uint8_t>& iv);
|
||||
bool QueryKeyControlBlock(const KeyId& key_id, uint32_t* data);
|
||||
OEMCryptoResult SelectContentKey(const KeyId& key_id,
|
||||
OEMCryptoCipherMode cipher_mode);
|
||||
const Key* current_content_key(void) { return current_content_key_; }
|
||||
void set_mac_key_server(const std::vector<uint8_t>& mac_key_server) {
|
||||
mac_key_server_ = mac_key_server;
|
||||
}
|
||||
const std::vector<uint8_t>& mac_key_server() { return mac_key_server_; }
|
||||
void set_mac_key_client(const std::vector<uint8_t>& mac_key_client) {
|
||||
mac_key_client_ = mac_key_client;
|
||||
}
|
||||
const std::vector<uint8_t>& mac_key_client() { return mac_key_client_; }
|
||||
|
||||
void set_encryption_key(const std::vector<uint8_t>& enc_key) {
|
||||
encryption_key_ = enc_key;
|
||||
}
|
||||
const std::vector<uint8_t>& encryption_key() { return encryption_key_; }
|
||||
uint32_t allowed_schemes() const { return allowed_schemes_; }
|
||||
|
||||
void AddNonce(uint32_t nonce);
|
||||
bool CheckNonce(uint32_t nonce);
|
||||
void FlushNonces();
|
||||
|
||||
OEMCryptoResult CreateNewUsageEntry(uint32_t* usage_entry_number);
|
||||
OEMCryptoResult LoadUsageEntry(uint32_t index,
|
||||
const std::vector<uint8_t>& buffer);
|
||||
OEMCryptoResult UpdateUsageEntry(uint8_t* header_buffer,
|
||||
size_t* header_buffer_length,
|
||||
uint8_t* entry_buffer,
|
||||
size_t* entry_buffer_length);
|
||||
OEMCryptoResult DeactivateUsageEntry(const std::vector<uint8_t>& pst);
|
||||
OEMCryptoResult ReportUsage(const std::vector<uint8_t>& pst, uint8_t* buffer,
|
||||
size_t* buffer_length);
|
||||
OEMCryptoResult MoveEntry(uint32_t new_index);
|
||||
OEMCryptoResult CopyOldUsageEntry(const std::vector<uint8_t>& pst);
|
||||
|
||||
private:
|
||||
bool DeriveKey(const std::vector<uint8_t>& key,
|
||||
const std::vector<uint8_t>& context, int counter,
|
||||
std::vector<uint8_t>* out);
|
||||
bool DecryptMessage(const std::vector<uint8_t>& key,
|
||||
const std::vector<uint8_t>& iv,
|
||||
const std::vector<uint8_t>& message,
|
||||
std::vector<uint8_t>* decrypted,
|
||||
uint32_t key_size); // AES key size, in bits.
|
||||
// Either verify the nonce or usage entry, as required by the key control
|
||||
// block.
|
||||
OEMCryptoResult CheckNonceOrEntry(const KeyControlBlock& key_control_block);
|
||||
// If there is a usage entry, check that it is not inactive.
|
||||
// It also updates the status of the entry if needed.
|
||||
bool CheckUsageEntry();
|
||||
// Check that the usage entry status is valid for online use.
|
||||
OEMCryptoResult CheckStatusOnline(uint32_t nonce, uint32_t control);
|
||||
// Check that the usage entry status is valid for offline use.
|
||||
OEMCryptoResult CheckStatusOffline(uint32_t nonce, uint32_t control);
|
||||
OEMCryptoResult DecryptCBC(const uint8_t* key, const uint8_t* iv,
|
||||
const OEMCrypto_CENCEncryptPatternDesc* pattern,
|
||||
const uint8_t* cipher_data,
|
||||
size_t cipher_data_length, uint8_t* clear_data);
|
||||
OEMCryptoResult PatternDecryptCTR(
|
||||
const uint8_t* key, const uint8_t* iv, size_t block_offset,
|
||||
const OEMCrypto_CENCEncryptPatternDesc* pattern,
|
||||
const uint8_t* cipher_data, size_t cipher_data_length,
|
||||
uint8_t* clear_data);
|
||||
OEMCryptoResult DecryptCTR(const uint8_t* key_u8, const uint8_t* iv,
|
||||
size_t block_offset, const uint8_t* cipher_data,
|
||||
size_t cipher_data_length, uint8_t* clear_data);
|
||||
// Checks if the key is allowed for the specified type. If there is a usage
|
||||
// entry, it also checks the usage entry.
|
||||
OEMCryptoResult CheckKeyUse(const std::string& log_string, uint32_t use_type,
|
||||
OEMCryptoBufferType buffer_type);
|
||||
RSA* rsa_key() { return rsa_key_.get(); }
|
||||
|
||||
bool valid_;
|
||||
CryptoEngine* ce_;
|
||||
SessionId id_;
|
||||
std::vector<uint8_t> mac_key_server_;
|
||||
std::vector<uint8_t> mac_key_client_;
|
||||
std::vector<uint8_t> encryption_key_;
|
||||
std::vector<uint8_t> session_key_;
|
||||
const Key* current_content_key_;
|
||||
SessionContextKeys* session_keys_;
|
||||
NonceTable nonce_table_;
|
||||
RSA_shared_ptr rsa_key_;
|
||||
uint32_t allowed_schemes_; // for RSA signatures.
|
||||
time_t timer_start_;
|
||||
UsageTableEntry* usage_entry_;
|
||||
SRMVersionStatus srm_requirements_status_;
|
||||
enum UsageEntryStatus {
|
||||
kNoUsageEntry, // No entry loaded for this session.
|
||||
kUsageEntryNew, // After entry was created.
|
||||
kUsageEntryLoaded, // After loading entry or loading keys.
|
||||
};
|
||||
UsageEntryStatus usage_entry_status_;
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(SessionContext);
|
||||
};
|
||||
|
||||
} // namespace wvoec_ref
|
||||
|
||||
#endif // REF_OEMCRYPTO_SESSION_H_
|
||||
119
libwvdrmengine/oemcrypto/ref/src/oemcrypto_session_key_table.cpp
Normal file
119
libwvdrmengine/oemcrypto/ref/src/oemcrypto_session_key_table.cpp
Normal file
@@ -0,0 +1,119 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// Ref implementation of OEMCrypto APIs
|
||||
//
|
||||
#include "oemcrypto_session_key_table.h"
|
||||
|
||||
#include "keys.h"
|
||||
#include "log.h"
|
||||
|
||||
namespace wvoec_ref {
|
||||
|
||||
SessionKeyTable::~SessionKeyTable() {
|
||||
for (KeyMap::iterator i = keys_.begin(); i != keys_.end(); ++i) {
|
||||
if (NULL != i->second) {
|
||||
delete i->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SessionKeyTable::Insert(const KeyId key_id, const Key& key_data) {
|
||||
if (keys_.find(key_id) != keys_.end()) return false;
|
||||
keys_[key_id] = new Key(key_data);
|
||||
return true;
|
||||
}
|
||||
|
||||
Key* SessionKeyTable::Find(const KeyId key_id) {
|
||||
if (keys_.find(key_id) == keys_.end()) {
|
||||
return NULL;
|
||||
}
|
||||
return keys_[key_id];
|
||||
}
|
||||
|
||||
void SessionKeyTable::Remove(const KeyId key_id) {
|
||||
if (keys_.find(key_id) != keys_.end()) {
|
||||
delete keys_[key_id];
|
||||
keys_.erase(key_id);
|
||||
}
|
||||
}
|
||||
|
||||
void SessionKeyTable::UpdateDuration(const KeyControlBlock& control) {
|
||||
for (KeyMap::iterator it = keys_.begin(); it != keys_.end(); ++it) {
|
||||
it->second->UpdateDuration(control);
|
||||
}
|
||||
}
|
||||
|
||||
bool EntitlementKeyTable::Insert(const KeyId key_id, const Key& key_data) {
|
||||
// |key_id| and |key_data| are for an entitlement key. Insert a new
|
||||
// entitlement key entry.
|
||||
if (keys_.find(key_id) != keys_.end()) return false;
|
||||
keys_[key_id] = new EntitlementKey(key_data);
|
||||
// If this is a new insertion, we don't have a content key assigned yet.
|
||||
return true;
|
||||
}
|
||||
|
||||
Key* EntitlementKeyTable::Find(const KeyId key_id) {
|
||||
// |key_id| refers to a content key.
|
||||
ContentIdToEntitlementIdMap::iterator it =
|
||||
contentid_to_entitlementid_.find(key_id);
|
||||
if (it == contentid_to_entitlementid_.end()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (keys_.find(it->second) == keys_.end()) {
|
||||
return NULL;
|
||||
}
|
||||
return keys_[it->second];
|
||||
}
|
||||
|
||||
void EntitlementKeyTable::Remove(const KeyId key_id) {
|
||||
// |key_id| refers to a content key. No one currently calls Remove so this
|
||||
// method is free to change if needed.
|
||||
ContentIdToEntitlementIdMap::iterator it =
|
||||
contentid_to_entitlementid_.find(key_id);
|
||||
if (it == contentid_to_entitlementid_.end()) {
|
||||
return;
|
||||
}
|
||||
keys_.erase(it->second);
|
||||
contentid_to_entitlementid_.erase(key_id);
|
||||
}
|
||||
|
||||
void EntitlementKeyTable::UpdateDuration(const KeyControlBlock& control) {
|
||||
for (EntitlementKeyMap::iterator it = keys_.begin(); it != keys_.end();
|
||||
++it) {
|
||||
it->second->UpdateDuration(control);
|
||||
}
|
||||
}
|
||||
|
||||
bool EntitlementKeyTable::SetContentKey(
|
||||
const KeyId& entitlement_id, const KeyId& content_key_id,
|
||||
const std::vector<uint8_t> content_key) {
|
||||
EntitlementKeyMap::iterator it = keys_.find(entitlement_id);
|
||||
if (it == keys_.end()) {
|
||||
return false;
|
||||
}
|
||||
contentid_to_entitlementid_.erase(it->second->content_key_id());
|
||||
if (!it->second->SetContentKey(content_key_id, content_key)) {
|
||||
return false;
|
||||
}
|
||||
contentid_to_entitlementid_[content_key_id] = entitlement_id;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EntitlementKeyTable::GetEntitlementKey(
|
||||
const KeyId& entitlement_id,
|
||||
const std::vector<uint8_t>** entitlement_key) {
|
||||
if (!entitlement_key) {
|
||||
return false;
|
||||
}
|
||||
EntitlementKeyMap::iterator it = keys_.find(entitlement_id);
|
||||
if (it == keys_.end()) {
|
||||
return false;
|
||||
}
|
||||
*entitlement_key = &it->second->entitlement_key();
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace wvoec_ref
|
||||
@@ -0,0 +1,71 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// Ref implementation of OEMCrypto APIs
|
||||
//
|
||||
#ifndef REF_OEMCRYPTO_SESSION_KEY_TABLE_H_
|
||||
#define REF_OEMCRYPTO_SESSION_KEY_TABLE_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "disallow_copy_and_assign.h"
|
||||
#include "oemcrypto_key_ref.h"
|
||||
#include "oemcrypto_types.h"
|
||||
|
||||
namespace wvoec_ref {
|
||||
|
||||
class SessionContext;
|
||||
class CryptoEngine;
|
||||
class UsageTable;
|
||||
class UsageTableEntry;
|
||||
|
||||
typedef std::vector<uint8_t> KeyId;
|
||||
typedef std::map<KeyId, Key*> KeyMap;
|
||||
typedef std::map<KeyId, EntitlementKey*> EntitlementKeyMap;
|
||||
|
||||
// SessionKeyTable holds the keys for the current session
|
||||
class SessionKeyTable {
|
||||
public:
|
||||
SessionKeyTable() {}
|
||||
~SessionKeyTable();
|
||||
|
||||
bool Insert(const KeyId key_id, const Key& key_data);
|
||||
Key* Find(const KeyId key_id);
|
||||
void Remove(const KeyId key_id);
|
||||
void UpdateDuration(const KeyControlBlock& control);
|
||||
size_t size() const { return keys_.size(); }
|
||||
|
||||
private:
|
||||
KeyMap keys_;
|
||||
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(SessionKeyTable);
|
||||
};
|
||||
|
||||
class EntitlementKeyTable {
|
||||
typedef std::map<KeyId, KeyId> ContentIdToEntitlementIdMap;
|
||||
|
||||
public:
|
||||
EntitlementKeyTable() {}
|
||||
~EntitlementKeyTable() {}
|
||||
bool Insert(const KeyId key_id, const Key& key_data);
|
||||
Key* Find(const KeyId key_id);
|
||||
void Remove(const KeyId key_id);
|
||||
void UpdateDuration(const KeyControlBlock& control);
|
||||
size_t size() const { return contentid_to_entitlementid_.size(); }
|
||||
bool SetContentKey(const KeyId& entitlement_id, const KeyId& content_key_id,
|
||||
const std::vector<uint8_t> content_key);
|
||||
bool GetEntitlementKey(const KeyId& entitlement_id,
|
||||
const std::vector<uint8_t>** entitlement_key);
|
||||
|
||||
private:
|
||||
EntitlementKeyMap keys_;
|
||||
ContentIdToEntitlementIdMap contentid_to_entitlementid_;
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(EntitlementKeyTable);
|
||||
};
|
||||
|
||||
} // namespace wvoec_ref
|
||||
|
||||
#endif // REF_OEMCRYPTO_SESSION_KEY_TABLE_H_
|
||||
759
libwvdrmengine/oemcrypto/ref/src/oemcrypto_usage_table_ref.cpp
Normal file
759
libwvdrmengine/oemcrypto/ref/src/oemcrypto_usage_table_ref.cpp
Normal file
@@ -0,0 +1,759 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// Ref implementation of OEMCrypto APIs
|
||||
//
|
||||
#include "oemcrypto_usage_table_ref.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#include "file_store.h"
|
||||
#include "log.h"
|
||||
#include "oemcrypto_engine_ref.h"
|
||||
#include "oemcrypto_logging.h"
|
||||
#include "oemcrypto_old_usage_table_ref.h"
|
||||
// TODO(fredgc): Setting the device files base bath is currently broken as
|
||||
// wvcdm::Properties is no longer used by the reference code.
|
||||
//#include "properties.h"
|
||||
#include "pst_report.h"
|
||||
#include "string_conversions.h"
|
||||
|
||||
namespace wvoec_ref {
|
||||
namespace {
|
||||
const size_t kMagicLength = 8;
|
||||
const char* kEntryVerification = "USEENTRY";
|
||||
const char* kHeaderVerification = "USEHEADR";
|
||||
// Offset into a signed block where we start encrypting. We need to
|
||||
// skip the signature and the iv.
|
||||
const size_t kEncryptionOffset = SHA256_DIGEST_LENGTH + SHA256_DIGEST_LENGTH;
|
||||
|
||||
// A structure that holds an usage entry and its signature.
|
||||
struct SignedEntryBlock {
|
||||
uint8_t signature[SHA256_DIGEST_LENGTH];
|
||||
uint8_t iv[SHA256_DIGEST_LENGTH];
|
||||
uint8_t verification[kMagicLength];
|
||||
StoredUsageEntry data;
|
||||
};
|
||||
|
||||
// This has the data in the header of constant size. There is also an array
|
||||
// of generation numbers.
|
||||
struct SignedHeaderBlock {
|
||||
uint8_t signature[SHA256_DIGEST_LENGTH];
|
||||
uint8_t iv[SHA256_DIGEST_LENGTH];
|
||||
uint8_t verification[kMagicLength];
|
||||
int64_t master_generation;
|
||||
uint64_t count;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
UsageTableEntry::UsageTableEntry(UsageTable* table, uint32_t index,
|
||||
int64_t generation)
|
||||
: usage_table_(table), recent_decrypt_(false), forbid_report_(true) {
|
||||
memset(&data_, 0, sizeof(data_));
|
||||
data_.generation_number = generation;
|
||||
data_.index = index;
|
||||
}
|
||||
|
||||
UsageTableEntry::~UsageTableEntry() { usage_table_->ReleaseEntry(data_.index); }
|
||||
|
||||
OEMCryptoResult UsageTableEntry::SetPST(const uint8_t* pst, size_t pst_length) {
|
||||
if (pst_length > kMaxPSTLength) return OEMCrypto_ERROR_BUFFER_TOO_LARGE;
|
||||
data_.pst_length = pst_length;
|
||||
if (!pst) return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
memcpy(data_.pst, pst, pst_length);
|
||||
data_.time_of_license_received = time(NULL);
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
bool UsageTableEntry::VerifyPST(const uint8_t* pst, size_t pst_length) {
|
||||
if (pst_length > kMaxPSTLength) return false;
|
||||
if (data_.pst_length != pst_length) return false;
|
||||
if (!pst) return false;
|
||||
return 0 == memcmp(pst, data_.pst, pst_length);
|
||||
}
|
||||
|
||||
bool UsageTableEntry::VerifyMacKeys(const std::vector<uint8_t>& server,
|
||||
const std::vector<uint8_t>& client) {
|
||||
return (server.size() == wvoec::MAC_KEY_SIZE) &&
|
||||
(client.size() == wvoec::MAC_KEY_SIZE) &&
|
||||
(0 == memcmp(&server[0], data_.mac_key_server, wvoec::MAC_KEY_SIZE)) &&
|
||||
(0 == memcmp(&client[0], data_.mac_key_client, wvoec::MAC_KEY_SIZE));
|
||||
}
|
||||
|
||||
bool UsageTableEntry::SetMacKeys(const std::vector<uint8_t>& server,
|
||||
const std::vector<uint8_t>& client) {
|
||||
if ((server.size() != wvoec::MAC_KEY_SIZE) ||
|
||||
(client.size() != wvoec::MAC_KEY_SIZE))
|
||||
return false;
|
||||
memcpy(data_.mac_key_server, &server[0], wvoec::MAC_KEY_SIZE);
|
||||
memcpy(data_.mac_key_client, &client[0], wvoec::MAC_KEY_SIZE);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UsageTableEntry::CheckForUse() {
|
||||
if (Inactive()) return false;
|
||||
recent_decrypt_ = true;
|
||||
if (data_.status == kUnused) {
|
||||
data_.status = kActive;
|
||||
data_.time_of_first_decrypt = time(NULL);
|
||||
data_.generation_number++;
|
||||
usage_table_->IncrementGeneration();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void UsageTableEntry::Deactivate(const std::vector<uint8_t>& pst) {
|
||||
if (data_.status == kUnused) {
|
||||
data_.status = kInactiveUnused;
|
||||
} else if (data_.status == kActive) {
|
||||
data_.status = kInactiveUsed;
|
||||
}
|
||||
forbid_report_ = true;
|
||||
data_.generation_number++;
|
||||
usage_table_->IncrementGeneration();
|
||||
}
|
||||
|
||||
OEMCryptoResult UsageTableEntry::ReportUsage(const std::vector<uint8_t>& pst,
|
||||
uint8_t* buffer,
|
||||
size_t* buffer_length) {
|
||||
if (forbid_report_) return OEMCrypto_ERROR_ENTRY_NEEDS_UPDATE;
|
||||
if (recent_decrypt_) return OEMCrypto_ERROR_ENTRY_NEEDS_UPDATE;
|
||||
if (pst.size() == 0 || pst.size() > kMaxPSTLength ||
|
||||
pst.size() != data_.pst_length) {
|
||||
LOGE("ReportUsage: bad pst length = %d, should be %d.", pst.size(),
|
||||
data_.pst_length);
|
||||
return OEMCrypto_ERROR_WRONG_PST;
|
||||
}
|
||||
if (memcmp(&pst[0], data_.pst, data_.pst_length)) {
|
||||
LOGE("ReportUsage: wrong pst %s, should be %s.", wvcdm::b2a_hex(pst).c_str(),
|
||||
wvcdm::HexEncode(data_.pst, data_.pst_length).c_str());
|
||||
return OEMCrypto_ERROR_WRONG_PST;
|
||||
}
|
||||
size_t length_needed = wvcdm::Unpacked_PST_Report::report_size(pst.size());
|
||||
if (*buffer_length < length_needed) {
|
||||
*buffer_length = length_needed;
|
||||
return OEMCrypto_ERROR_SHORT_BUFFER;
|
||||
}
|
||||
if (!buffer) {
|
||||
LOGE("ReportUsage: buffer was null pointer.");
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
wvcdm::Unpacked_PST_Report pst_report(buffer);
|
||||
int64_t now = time(NULL);
|
||||
pst_report.set_seconds_since_license_received(now -
|
||||
data_.time_of_license_received);
|
||||
pst_report.set_seconds_since_first_decrypt(now - data_.time_of_first_decrypt);
|
||||
pst_report.set_seconds_since_last_decrypt(now - data_.time_of_last_decrypt);
|
||||
pst_report.set_status(data_.status);
|
||||
pst_report.set_clock_security_level(kSecureTimer);
|
||||
pst_report.set_pst_length(data_.pst_length);
|
||||
memcpy(pst_report.pst(), data_.pst, data_.pst_length);
|
||||
unsigned int md_len = SHA_DIGEST_LENGTH;
|
||||
if (LogCategoryEnabled(kLoggingDumpDerivedKeys)) {
|
||||
std::vector<uint8_t> mac_key_client(
|
||||
data_.mac_key_client,
|
||||
data_.mac_key_client + wvoec::MAC_KEY_SIZE * sizeof(uint8_t));
|
||||
LOGI(("message signed with HMAC and data_.mac_key_client, "
|
||||
"mac_key_client = " +
|
||||
wvcdm::b2a_hex(mac_key_client))
|
||||
.c_str());
|
||||
}
|
||||
if (!HMAC(EVP_sha1(), data_.mac_key_client, wvoec::MAC_KEY_SIZE,
|
||||
buffer + SHA_DIGEST_LENGTH, length_needed - SHA_DIGEST_LENGTH,
|
||||
pst_report.signature(), &md_len)) {
|
||||
LOGE("ReportUsage: could not compute signature.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
void UsageTableEntry::UpdateAndIncrement() {
|
||||
if (recent_decrypt_) {
|
||||
data_.time_of_last_decrypt = time(NULL);
|
||||
recent_decrypt_ = false;
|
||||
}
|
||||
data_.generation_number++;
|
||||
usage_table_->IncrementGeneration();
|
||||
forbid_report_ = false;
|
||||
}
|
||||
|
||||
OEMCryptoResult UsageTableEntry::SaveData(CryptoEngine* ce,
|
||||
SessionContext* session,
|
||||
uint8_t* signed_buffer,
|
||||
size_t buffer_size) {
|
||||
// buffer_size was determined by calling function.
|
||||
if (buffer_size != SignedEntrySize()) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
std::vector<uint8_t> clear_buffer(buffer_size);
|
||||
memset(&clear_buffer[0], 0, buffer_size);
|
||||
memset(signed_buffer, 0, buffer_size);
|
||||
SignedEntryBlock* clear =
|
||||
reinterpret_cast<SignedEntryBlock*>(&clear_buffer[0]);
|
||||
SignedEntryBlock* encrypted =
|
||||
reinterpret_cast<SignedEntryBlock*>(signed_buffer);
|
||||
clear->data = this->data_; // Copy the current data.
|
||||
memcpy(clear->verification, kEntryVerification, kMagicLength);
|
||||
|
||||
// This should be encrypted and signed with a device specific key.
|
||||
// For the reference implementation, I'm just going to use the keybox key.
|
||||
const bool override_to_real = true;
|
||||
const std::vector<uint8_t>& key = ce->DeviceRootKey(override_to_real);
|
||||
|
||||
// Encrypt the entry.
|
||||
RAND_bytes(encrypted->iv, wvoec::KEY_IV_SIZE);
|
||||
uint8_t iv_buffer[wvoec::KEY_IV_SIZE]; // working iv buffer.
|
||||
memcpy(iv_buffer, encrypted->iv, wvoec::KEY_IV_SIZE);
|
||||
AES_KEY aes_key;
|
||||
AES_set_encrypt_key(&key[0], 128, &aes_key);
|
||||
AES_cbc_encrypt(
|
||||
&clear_buffer[kEncryptionOffset], &signed_buffer[kEncryptionOffset],
|
||||
buffer_size - kEncryptionOffset, &aes_key, iv_buffer, AES_ENCRYPT);
|
||||
|
||||
// Sign the entry.
|
||||
unsigned int sig_length = SHA256_DIGEST_LENGTH;
|
||||
if (!HMAC(EVP_sha256(), &key[0], key.size(),
|
||||
&signed_buffer[SHA256_DIGEST_LENGTH],
|
||||
buffer_size - SHA256_DIGEST_LENGTH, encrypted->signature,
|
||||
&sig_length)) {
|
||||
LOGE("SaveUsageEntry: Could not sign entry.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
OEMCryptoResult UsageTableEntry::LoadData(CryptoEngine* ce, uint32_t index,
|
||||
const std::vector<uint8_t>& buffer) {
|
||||
if (buffer.size() < SignedEntrySize()) return OEMCrypto_ERROR_SHORT_BUFFER;
|
||||
if (buffer.size() > SignedEntrySize())
|
||||
LOGW("LoadUsageTableEntry: buffer is large. %d > %d", buffer.size(),
|
||||
SignedEntrySize());
|
||||
std::vector<uint8_t> clear_buffer(buffer.size());
|
||||
SignedEntryBlock* clear =
|
||||
reinterpret_cast<SignedEntryBlock*>(&clear_buffer[0]);
|
||||
const SignedEntryBlock* encrypted =
|
||||
reinterpret_cast<const SignedEntryBlock*>(&buffer[0]);
|
||||
|
||||
// This should be encrypted and signed with a device specific key.
|
||||
// For the reference implementation, I'm just going to use the keybox key.
|
||||
const bool override_to_real = true;
|
||||
const std::vector<uint8_t>& key = ce->DeviceRootKey(override_to_real);
|
||||
|
||||
// Verify the signature of the usage entry. Sign encrypted into clear buffer.
|
||||
unsigned int sig_length = SHA256_DIGEST_LENGTH;
|
||||
if (!HMAC(EVP_sha256(), &key[0], key.size(), &buffer[SHA256_DIGEST_LENGTH],
|
||||
buffer.size() - SHA256_DIGEST_LENGTH, clear->signature,
|
||||
&sig_length)) {
|
||||
LOGE("LoadUsageEntry: Could not sign entry.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
if (memcmp(clear->signature, encrypted->signature, SHA256_DIGEST_LENGTH)) {
|
||||
LOGE("LoadUsageEntry: Signature did not match.");
|
||||
LOGE("LoadUsageEntry: Invalid signature given: %s",
|
||||
wvcdm::HexEncode(encrypted->signature, sig_length).c_str());
|
||||
LOGE("LoadUsageEntry: Invalid signature computed: %s",
|
||||
wvcdm::HexEncode(clear->signature, sig_length).c_str());
|
||||
return OEMCrypto_ERROR_SIGNATURE_FAILURE;
|
||||
}
|
||||
|
||||
// Next, decrypt the entry.
|
||||
uint8_t iv_buffer[wvoec::KEY_IV_SIZE];
|
||||
memcpy(iv_buffer, encrypted->iv, wvoec::KEY_IV_SIZE);
|
||||
AES_KEY aes_key;
|
||||
AES_set_decrypt_key(&key[0], 128, &aes_key);
|
||||
AES_cbc_encrypt(&buffer[kEncryptionOffset], &clear_buffer[kEncryptionOffset],
|
||||
buffer.size() - kEncryptionOffset, &aes_key, iv_buffer,
|
||||
AES_DECRYPT);
|
||||
|
||||
// Check the verification string is correct.
|
||||
if (memcmp(kEntryVerification, clear->verification, kMagicLength)) {
|
||||
LOGE("LoadUsageEntry: Invalid magic: %s=%8.8s expected: %s=%8.8s",
|
||||
wvcdm::HexEncode(clear->verification, kMagicLength).c_str(),
|
||||
clear->verification,
|
||||
wvcdm::HexEncode(reinterpret_cast<const uint8_t*>(kEntryVerification),
|
||||
kMagicLength)
|
||||
.c_str(),
|
||||
reinterpret_cast<const uint8_t*>(kEntryVerification));
|
||||
return OEMCrypto_ERROR_BAD_MAGIC;
|
||||
}
|
||||
|
||||
// Check that the index is correct.
|
||||
if (index != clear->data.index) {
|
||||
LOGE("LoadUsageEntry: entry says index is %d, not %d", clear->data.index,
|
||||
index);
|
||||
return OEMCrypto_ERROR_INVALID_SESSION;
|
||||
}
|
||||
if (clear->data.status > kInactiveUnused) {
|
||||
LOGE("LoadUsageEntry: entry has bad status %d", clear->data.status);
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
this->data_ = clear->data;
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
OEMCryptoResult UsageTableEntry::CopyOldUsageEntry(
|
||||
const std::vector<uint8_t>& pst) {
|
||||
OldUsageTableEntry* old_entry = usage_table_->FindOldUsageEntry(pst);
|
||||
if (!old_entry) return OEMCrypto_ERROR_WRONG_PST;
|
||||
data_.time_of_license_received = old_entry->time_of_license_received_;
|
||||
data_.time_of_first_decrypt = old_entry->time_of_first_decrypt_;
|
||||
data_.time_of_last_decrypt = old_entry->time_of_last_decrypt_;
|
||||
data_.status = old_entry->status_;
|
||||
if (old_entry->mac_key_server_.size() != wvoec::MAC_KEY_SIZE) {
|
||||
LOGE("CopyOldEntry: Old entry has bad server mac key.");
|
||||
} else {
|
||||
memcpy(data_.mac_key_server, &(old_entry->mac_key_server_[0]),
|
||||
wvoec::MAC_KEY_SIZE);
|
||||
}
|
||||
if (old_entry->mac_key_client_.size() != wvoec::MAC_KEY_SIZE) {
|
||||
LOGE("CopyOldEntry: Old entry has bad client mac key.");
|
||||
} else {
|
||||
memcpy(data_.mac_key_client, &(old_entry->mac_key_client_[0]),
|
||||
wvoec::MAC_KEY_SIZE);
|
||||
if (LogCategoryEnabled(kLoggingDumpDerivedKeys)) {
|
||||
std::vector<uint8_t> mac_key_client(
|
||||
data_.mac_key_client,
|
||||
data_.mac_key_client + wvoec::MAC_KEY_SIZE * sizeof(uint8_t));
|
||||
LOGI(("data_.mac_key_client has changed to = " +
|
||||
wvcdm::b2a_hex(mac_key_client)).c_str());
|
||||
}
|
||||
}
|
||||
if (pst.size() > kMaxPSTLength) {
|
||||
LOGE("CopyOldEntry: PST Length was too large. Truncating.");
|
||||
data_.pst_length = kMaxPSTLength;
|
||||
} else {
|
||||
data_.pst_length = pst.size();
|
||||
}
|
||||
memcpy(data_.pst, &pst[0], data_.pst_length);
|
||||
data_.pst[data_.pst_length] = '\0';
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
size_t UsageTableEntry::SignedEntrySize() {
|
||||
size_t base = sizeof(SignedEntryBlock);
|
||||
// round up to make even number of blocks:
|
||||
size_t blocks = (base - 1) / wvoec::KEY_IV_SIZE + 1;
|
||||
return blocks * wvoec::KEY_IV_SIZE;
|
||||
}
|
||||
|
||||
UsageTable::~UsageTable() {
|
||||
if (old_table_) {
|
||||
delete old_table_;
|
||||
old_table_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
size_t UsageTable::SignedHeaderSize(size_t count) {
|
||||
size_t base = sizeof(SignedHeaderBlock) + count * sizeof(int64_t);
|
||||
// round up to make even number of blocks:
|
||||
size_t blocks = (base - 1) / wvoec::KEY_IV_SIZE + 1;
|
||||
return blocks * wvoec::KEY_IV_SIZE;
|
||||
}
|
||||
|
||||
OEMCryptoResult UsageTable::UpdateUsageEntry(SessionContext* session,
|
||||
UsageTableEntry* entry,
|
||||
uint8_t* header_buffer,
|
||||
size_t* header_buffer_length,
|
||||
uint8_t* entry_buffer,
|
||||
size_t* entry_buffer_length) {
|
||||
size_t signed_header_size = SignedHeaderSize(generation_numbers_.size());
|
||||
if (*entry_buffer_length < UsageTableEntry::SignedEntrySize() ||
|
||||
*header_buffer_length < signed_header_size) {
|
||||
*entry_buffer_length = UsageTableEntry::SignedEntrySize();
|
||||
*header_buffer_length = signed_header_size;
|
||||
return OEMCrypto_ERROR_SHORT_BUFFER;
|
||||
}
|
||||
*entry_buffer_length = UsageTableEntry::SignedEntrySize();
|
||||
*header_buffer_length = signed_header_size;
|
||||
if ((!header_buffer) || (!entry_buffer))
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
entry->UpdateAndIncrement();
|
||||
generation_numbers_[entry->index()] = entry->generation_number();
|
||||
OEMCryptoResult result =
|
||||
entry->SaveData(ce_, session, entry_buffer, *entry_buffer_length);
|
||||
if (result != OEMCrypto_SUCCESS) return result;
|
||||
result = SaveUsageTableHeader(header_buffer, *header_buffer_length);
|
||||
return result;
|
||||
}
|
||||
|
||||
OEMCryptoResult UsageTable::CreateNewUsageEntry(SessionContext* session,
|
||||
UsageTableEntry** entry,
|
||||
uint32_t* usage_entry_number) {
|
||||
if (!header_loaded_) {
|
||||
LOGE("CreateNewUsageEntry: Header not loaded.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
if (!entry) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
if (!usage_entry_number) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
uint32_t index = generation_numbers_.size();
|
||||
UsageTableEntry* new_entry =
|
||||
new UsageTableEntry(this, index, master_generation_number_);
|
||||
generation_numbers_.push_back(master_generation_number_);
|
||||
sessions_.push_back(session);
|
||||
master_generation_number_++;
|
||||
*entry = new_entry;
|
||||
*usage_entry_number = index;
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
OEMCryptoResult UsageTable::LoadUsageEntry(SessionContext* session,
|
||||
UsageTableEntry** entry,
|
||||
uint32_t index,
|
||||
const std::vector<uint8_t>& buffer) {
|
||||
if (!header_loaded_) {
|
||||
LOGE("CreateNewUsageEntry: Header not loaded.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
if (!entry) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
if (index >= generation_numbers_.size())
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
if (sessions_[index]) {
|
||||
LOGE("LoadUsageEntry: index %d used by other session.", index);
|
||||
return OEMCrypto_ERROR_INVALID_SESSION;
|
||||
}
|
||||
UsageTableEntry* new_entry =
|
||||
new UsageTableEntry(this, index, master_generation_number_);
|
||||
|
||||
OEMCryptoResult status = new_entry->LoadData(ce_, index, buffer);
|
||||
if (status != OEMCrypto_SUCCESS) {
|
||||
delete new_entry;
|
||||
return status;
|
||||
}
|
||||
if (new_entry->generation_number() != generation_numbers_[index]) {
|
||||
LOGE("Generation SKEW: %ld -> %ld", new_entry->generation_number(),
|
||||
generation_numbers_[index]);
|
||||
if ((new_entry->generation_number() + 1 < generation_numbers_[index]) ||
|
||||
(new_entry->generation_number() - 1 > generation_numbers_[index])) {
|
||||
delete new_entry;
|
||||
return OEMCrypto_ERROR_GENERATION_SKEW;
|
||||
}
|
||||
status = OEMCrypto_WARNING_GENERATION_SKEW;
|
||||
}
|
||||
sessions_[index] = session;
|
||||
*entry = new_entry;
|
||||
return status;
|
||||
}
|
||||
|
||||
OEMCryptoResult UsageTable::ShrinkUsageTableHeader(
|
||||
uint32_t new_table_size, uint8_t* header_buffer,
|
||||
size_t* header_buffer_length) {
|
||||
if (new_table_size > generation_numbers_.size()) {
|
||||
LOGE("OEMCrypto_ShrinkUsageTableHeader: %d > %zd.", new_table_size,
|
||||
generation_numbers_.size());
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
size_t signed_header_size = SignedHeaderSize(new_table_size);
|
||||
if (*header_buffer_length < signed_header_size) {
|
||||
*header_buffer_length = signed_header_size;
|
||||
return OEMCrypto_ERROR_SHORT_BUFFER;
|
||||
}
|
||||
*header_buffer_length = signed_header_size;
|
||||
if (!header_buffer) {
|
||||
LOGE("OEMCrypto_ShrinkUsageTableHeader: buffer null.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
for (size_t i = new_table_size; i < sessions_.size(); ++i) {
|
||||
if (sessions_[i]) {
|
||||
LOGE("ShrinkUsageTableHeader: session open for %d", i);
|
||||
return OEMCrypto_ERROR_ENTRY_IN_USE;
|
||||
}
|
||||
}
|
||||
generation_numbers_.resize(new_table_size);
|
||||
sessions_.resize(new_table_size);
|
||||
master_generation_number_++;
|
||||
return SaveUsageTableHeader(header_buffer, *header_buffer_length);
|
||||
}
|
||||
|
||||
OEMCryptoResult UsageTable::SaveUsageTableHeader(uint8_t* signed_buffer,
|
||||
size_t buffer_size) {
|
||||
if (!SaveGenerationNumber()) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
size_t count = generation_numbers_.size();
|
||||
// buffer_size was determined by calling function.
|
||||
if (buffer_size != SignedHeaderSize(count))
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
std::vector<uint8_t> clear_buffer(buffer_size);
|
||||
memset(&clear_buffer[0], 0, buffer_size);
|
||||
memset(signed_buffer, 0, buffer_size);
|
||||
SignedHeaderBlock* clear =
|
||||
reinterpret_cast<SignedHeaderBlock*>(&clear_buffer[0]);
|
||||
SignedHeaderBlock* encrypted =
|
||||
reinterpret_cast<SignedHeaderBlock*>(signed_buffer);
|
||||
|
||||
// Pack the clear data into the clear buffer.
|
||||
memcpy(clear->verification, kHeaderVerification, kMagicLength);
|
||||
clear->master_generation = master_generation_number_;
|
||||
clear->count = count;
|
||||
// This points to the variable size part of the buffer.
|
||||
int64_t* stored_generations =
|
||||
reinterpret_cast<int64_t*>(&clear_buffer[sizeof(SignedHeaderBlock)]);
|
||||
std::copy(generation_numbers_.begin(), generation_numbers_.begin() + count,
|
||||
stored_generations);
|
||||
|
||||
// This should be encrypted and signed with a device specific key.
|
||||
// For the reference implementation, I'm just going to use the keybox key.
|
||||
const bool override_to_real = true;
|
||||
const std::vector<uint8_t>& key = ce_->DeviceRootKey(override_to_real);
|
||||
|
||||
// Encrypt the entry.
|
||||
RAND_bytes(encrypted->iv, wvoec::KEY_IV_SIZE);
|
||||
uint8_t iv_buffer[wvoec::KEY_IV_SIZE]; // working iv buffer.
|
||||
memcpy(iv_buffer, encrypted->iv, wvoec::KEY_IV_SIZE);
|
||||
AES_KEY aes_key;
|
||||
AES_set_encrypt_key(&key[0], 128, &aes_key);
|
||||
AES_cbc_encrypt(
|
||||
&clear_buffer[kEncryptionOffset], &signed_buffer[kEncryptionOffset],
|
||||
buffer_size - kEncryptionOffset, &aes_key, iv_buffer, AES_ENCRYPT);
|
||||
|
||||
// Sign the entry.
|
||||
unsigned int sig_length = SHA256_DIGEST_LENGTH;
|
||||
if (!HMAC(EVP_sha256(), &key[0], key.size(),
|
||||
&signed_buffer[SHA256_DIGEST_LENGTH],
|
||||
buffer_size - SHA256_DIGEST_LENGTH, encrypted->signature,
|
||||
&sig_length)) {
|
||||
LOGE("SaveUsageHeader: Could not sign entry.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
OEMCryptoResult UsageTable::LoadUsageTableHeader(
|
||||
const std::vector<uint8_t>& buffer) {
|
||||
if (!LoadGenerationNumber(false)) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
|
||||
if (buffer.size() < SignedHeaderSize(0)) return OEMCrypto_ERROR_SHORT_BUFFER;
|
||||
std::vector<uint8_t> clear_buffer(buffer.size());
|
||||
SignedHeaderBlock* clear =
|
||||
reinterpret_cast<SignedHeaderBlock*>(&clear_buffer[0]);
|
||||
const SignedHeaderBlock* encrypted =
|
||||
reinterpret_cast<const SignedHeaderBlock*>(&buffer[0]);
|
||||
|
||||
// This should be encrypted and signed with a device specific key.
|
||||
// For the reference implementation, I'm just going to use the keybox key.
|
||||
const bool override_to_real = true;
|
||||
const std::vector<uint8_t>& key = ce_->DeviceRootKey(override_to_real);
|
||||
|
||||
// Verify the signature of the usage entry. Sign encrypted into clear buffer.
|
||||
unsigned int sig_length = SHA256_DIGEST_LENGTH;
|
||||
if (!HMAC(EVP_sha256(), &key[0], key.size(), &buffer[SHA256_DIGEST_LENGTH],
|
||||
buffer.size() - SHA256_DIGEST_LENGTH, clear->signature,
|
||||
&sig_length)) {
|
||||
LOGE("LoadUsageTableHeader: Could not sign entry.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
if (memcmp(clear->signature, encrypted->signature, SHA256_DIGEST_LENGTH)) {
|
||||
LOGE("LoadUsageTableHeader: Signature did not match.");
|
||||
LOGE("LoadUsageTableHeader: Invalid signature given: %s",
|
||||
wvcdm::HexEncode(encrypted->signature, sig_length).c_str());
|
||||
LOGE("LoadUsageTableHeader: Invalid signature computed: %s",
|
||||
wvcdm::HexEncode(clear->signature, sig_length).c_str());
|
||||
return OEMCrypto_ERROR_SIGNATURE_FAILURE;
|
||||
}
|
||||
|
||||
// Next, decrypt the entry.
|
||||
uint8_t iv_buffer[wvoec::KEY_IV_SIZE];
|
||||
memcpy(iv_buffer, encrypted->iv, wvoec::KEY_IV_SIZE);
|
||||
AES_KEY aes_key;
|
||||
AES_set_decrypt_key(&key[0], 128, &aes_key);
|
||||
AES_cbc_encrypt(&buffer[kEncryptionOffset], &clear_buffer[kEncryptionOffset],
|
||||
buffer.size() - kEncryptionOffset, &aes_key, iv_buffer,
|
||||
AES_DECRYPT);
|
||||
|
||||
// Check the verification string is correct.
|
||||
if (memcmp(kHeaderVerification, clear->verification, kMagicLength)) {
|
||||
LOGE("LoadUsageTableHeader: Invalid magic: %s=%8.8s expected: %s=%8.8s",
|
||||
wvcdm::HexEncode(clear->verification, kMagicLength).c_str(),
|
||||
clear->verification,
|
||||
wvcdm::HexEncode(reinterpret_cast<const uint8_t*>(kHeaderVerification),
|
||||
kMagicLength)
|
||||
.c_str(),
|
||||
reinterpret_cast<const uint8_t*>(kHeaderVerification));
|
||||
return OEMCrypto_ERROR_BAD_MAGIC;
|
||||
}
|
||||
|
||||
// Check that size is correct, now that we know what it should be.
|
||||
if (buffer.size() < SignedHeaderSize(clear->count)) {
|
||||
return OEMCrypto_ERROR_SHORT_BUFFER;
|
||||
}
|
||||
if (buffer.size() > SignedHeaderSize(clear->count)) {
|
||||
LOGW("LoadUsageTableHeader: buffer is large. %d > %d", buffer.size(),
|
||||
SignedHeaderSize(clear->count));
|
||||
}
|
||||
|
||||
OEMCryptoResult status = OEMCrypto_SUCCESS;
|
||||
if (clear->master_generation != master_generation_number_) {
|
||||
LOGE("Generation SKEW: %ld -> %ld", clear->master_generation,
|
||||
master_generation_number_);
|
||||
if ((clear->master_generation + 1 < master_generation_number_) ||
|
||||
(clear->master_generation - 1 > master_generation_number_)) {
|
||||
return OEMCrypto_ERROR_GENERATION_SKEW;
|
||||
}
|
||||
status = OEMCrypto_WARNING_GENERATION_SKEW;
|
||||
}
|
||||
int64_t* stored_generations =
|
||||
reinterpret_cast<int64_t*>(&clear_buffer[0] + sizeof(SignedHeaderBlock));
|
||||
generation_numbers_.assign(stored_generations,
|
||||
stored_generations + clear->count);
|
||||
sessions_.clear();
|
||||
sessions_.resize(clear->count);
|
||||
header_loaded_ = true;
|
||||
return status;
|
||||
}
|
||||
|
||||
OEMCryptoResult UsageTable::MoveEntry(UsageTableEntry* entry,
|
||||
uint32_t new_index) {
|
||||
if (new_index >= generation_numbers_.size()) {
|
||||
LOGE("MoveEntry: index beyond end of usage table %d >= %d", new_index,
|
||||
generation_numbers_.size());
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
if (sessions_[new_index]) {
|
||||
LOGE("MoveEntry: session open for %d", new_index);
|
||||
return OEMCrypto_ERROR_ENTRY_IN_USE;
|
||||
}
|
||||
if (!entry) {
|
||||
LOGE("MoveEntry: null entry");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
sessions_[new_index] = sessions_[entry->index()];
|
||||
sessions_[entry->index()] = 0;
|
||||
|
||||
entry->set_index(new_index);
|
||||
generation_numbers_[new_index] = master_generation_number_;
|
||||
entry->set_generation_number(master_generation_number_);
|
||||
master_generation_number_++;
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
void UsageTable::IncrementGeneration() {
|
||||
master_generation_number_++;
|
||||
SaveGenerationNumber();
|
||||
}
|
||||
|
||||
bool UsageTable::SaveGenerationNumber() {
|
||||
wvcdm::FileSystem* file_system = ce_->file_system();
|
||||
std::string path;
|
||||
// Note: this path is OK for a real implementation, but using security level 1
|
||||
// would be better.
|
||||
// TODO(jfore, rfrias): Address how this property is presented to the ref.
|
||||
// For now, the path is empty.
|
||||
/*if (!Properties::GetDeviceFilesBasePath(kSecurityLevelL3,
|
||||
&path)) {
|
||||
LOGE("UsageTable: Unable to get base path");
|
||||
return false;
|
||||
}*/
|
||||
// On a real implementation, you should NOT put the generation number in
|
||||
// a file in user space. It should be stored in secure memory.
|
||||
std::string filename = path + "GenerationNumber.dat";
|
||||
wvcdm::File* file = file_system->Open(
|
||||
filename, wvcdm::FileSystem::kCreate | wvcdm::FileSystem::kTruncate);
|
||||
if (!file) {
|
||||
LOGE("UsageTable: File open failed: %s", path.c_str());
|
||||
return false;
|
||||
}
|
||||
file->Write(reinterpret_cast<char*>(&master_generation_number_),
|
||||
sizeof(int64_t));
|
||||
file->Close();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UsageTable::LoadGenerationNumber(bool or_make_new_one) {
|
||||
wvcdm::FileSystem* file_system = ce_->file_system();
|
||||
std::string path;
|
||||
// Note: this path is OK for a real implementation, but using security level 1
|
||||
// would be better.
|
||||
// TODO(jfore, rfrias): Address how this property is presented to the ref.
|
||||
// For now, the path is empty.
|
||||
/*if (!Properties::GetDeviceFilesBasePath(kSecurityLevelL3,
|
||||
&path)) {
|
||||
LOGE("UsageTable: Unable to get base path");
|
||||
return false;
|
||||
}*/
|
||||
// On a real implementation, you should NOT put the generation number in
|
||||
// a file in user space. It should be stored in secure memory.
|
||||
std::string filename = path + "GenerationNumber.dat";
|
||||
wvcdm::File* file = file_system->Open(filename, wvcdm::FileSystem::kReadOnly);
|
||||
if (!file) {
|
||||
if (or_make_new_one) {
|
||||
RAND_bytes(reinterpret_cast<uint8_t*>(&master_generation_number_),
|
||||
sizeof(int64_t));
|
||||
return true;
|
||||
}
|
||||
LOGE("UsageTable: File open failed: %s (clearing table)", path.c_str());
|
||||
master_generation_number_ = 0;
|
||||
return false;
|
||||
}
|
||||
file->Read(reinterpret_cast<char*>(&master_generation_number_),
|
||||
sizeof(int64_t));
|
||||
file->Close();
|
||||
return true;
|
||||
}
|
||||
|
||||
OEMCryptoResult UsageTable::CreateUsageTableHeader(
|
||||
uint8_t* header_buffer, size_t* header_buffer_length) {
|
||||
size_t signed_header_size = SignedHeaderSize(0);
|
||||
if (*header_buffer_length < signed_header_size) {
|
||||
*header_buffer_length = signed_header_size;
|
||||
return OEMCrypto_ERROR_SHORT_BUFFER;
|
||||
}
|
||||
*header_buffer_length = signed_header_size;
|
||||
if (!LoadGenerationNumber(true)) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
// Make sure there are no entries that are currently tied to an open session.
|
||||
for (size_t i = 0; i < sessions_.size(); ++i) {
|
||||
if (sessions_[i] != NULL) {
|
||||
LOGE("CreateUsageTableHeader: index %d used by session.", i);
|
||||
return OEMCrypto_ERROR_INVALID_SESSION;
|
||||
}
|
||||
}
|
||||
sessions_.clear();
|
||||
generation_numbers_.clear();
|
||||
header_loaded_ = true;
|
||||
return SaveUsageTableHeader(header_buffer, *header_buffer_length);
|
||||
}
|
||||
|
||||
OldUsageTableEntry* UsageTable::FindOldUsageEntry(
|
||||
const std::vector<uint8_t>& pst) {
|
||||
if (!old_table_) old_table_ = new OldUsageTable(ce_);
|
||||
return old_table_->FindEntry(pst);
|
||||
}
|
||||
|
||||
OEMCryptoResult UsageTable::DeleteOldUsageTable() {
|
||||
if (old_table_) {
|
||||
old_table_->Clear();
|
||||
delete old_table_;
|
||||
old_table_ = NULL;
|
||||
}
|
||||
OldUsageTable::DeleteFile(ce_);
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
OEMCryptoResult UsageTable::CreateOldUsageEntry(
|
||||
uint64_t time_since_license_received, uint64_t time_since_first_decrypt,
|
||||
uint64_t time_since_last_decrypt, OEMCrypto_Usage_Entry_Status status,
|
||||
uint8_t* server_mac_key, uint8_t* client_mac_key, const uint8_t* pst,
|
||||
size_t pst_length) {
|
||||
if (!old_table_) old_table_ = new OldUsageTable(ce_);
|
||||
std::vector<uint8_t> pstv(pst, pst + pst_length);
|
||||
OldUsageTableEntry* old_entry = old_table_->CreateEntry(pstv);
|
||||
|
||||
int64_t now = time(NULL);
|
||||
old_entry->time_of_license_received_ = now - time_since_license_received;
|
||||
old_entry->time_of_first_decrypt_ = now - time_since_first_decrypt;
|
||||
old_entry->time_of_last_decrypt_ = now - time_since_last_decrypt;
|
||||
old_entry->status_ = status;
|
||||
old_entry->mac_key_server_.assign(server_mac_key,
|
||||
server_mac_key + wvoec::MAC_KEY_SIZE);
|
||||
old_entry->mac_key_client_.assign(client_mac_key,
|
||||
client_mac_key + wvoec::MAC_KEY_SIZE);
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace wvoec_ref
|
||||
137
libwvdrmengine/oemcrypto/ref/src/oemcrypto_usage_table_ref.h
Normal file
137
libwvdrmengine/oemcrypto/ref/src/oemcrypto_usage_table_ref.h
Normal file
@@ -0,0 +1,137 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// Ref implementation of OEMCrypto APIs
|
||||
//
|
||||
#ifndef OEMCRYPTO_USAGE_TABLE_REF_H_
|
||||
#define OEMCRYPTO_USAGE_TABLE_REF_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "OEMCryptoCENC.h"
|
||||
#include "openssl/sha.h"
|
||||
#include "oemcrypto_types.h"
|
||||
|
||||
namespace wvoec_ref {
|
||||
|
||||
class SessionContext;
|
||||
class CryptoEngine;
|
||||
class UsageTable;
|
||||
class OldUsageTable;
|
||||
class OldUsageTableEntry;
|
||||
|
||||
const size_t kMaxPSTLength = 255;
|
||||
// This is the data we store offline.
|
||||
struct StoredUsageEntry {
|
||||
int64_t generation_number;
|
||||
int64_t time_of_license_received;
|
||||
int64_t time_of_first_decrypt;
|
||||
int64_t time_of_last_decrypt;
|
||||
enum OEMCrypto_Usage_Entry_Status status;
|
||||
uint8_t mac_key_server[wvoec::MAC_KEY_SIZE];
|
||||
uint8_t mac_key_client[wvoec::MAC_KEY_SIZE];
|
||||
uint32_t index;
|
||||
uint8_t pst[kMaxPSTLength+1]; // add 1 for padding.
|
||||
uint8_t pst_length;
|
||||
};
|
||||
|
||||
class UsageTableEntry {
|
||||
public:
|
||||
UsageTableEntry(UsageTable* table, uint32_t index, int64_t generation);
|
||||
// owner_(owner), session_(session), loaded_(false) {}
|
||||
~UsageTableEntry(); // Free memory, remove reference in header.
|
||||
bool Inactive() { return data_.status >= kInactive; }
|
||||
OEMCryptoResult SetPST(const uint8_t* pst, size_t pst_length);
|
||||
bool VerifyPST(const uint8_t* pst, size_t pst_length);
|
||||
bool VerifyMacKeys(const std::vector<uint8_t>& server,
|
||||
const std::vector<uint8_t>& client);
|
||||
bool SetMacKeys(const std::vector<uint8_t>& server,
|
||||
const std::vector<uint8_t>& client);
|
||||
// Returns false if the entry is inactive. Otherwise, returns true.
|
||||
// If the status was unused, it is updated, and decrypt times are flaged
|
||||
// for update.
|
||||
bool CheckForUse();
|
||||
void Deactivate(const std::vector<uint8_t>& pst);
|
||||
OEMCryptoResult ReportUsage(const std::vector<uint8_t>& pst, uint8_t* buffer,
|
||||
size_t* buffer_length);
|
||||
void UpdateAndIncrement();
|
||||
OEMCryptoResult SaveData(CryptoEngine* ce, SessionContext* session,
|
||||
uint8_t* signed_buffer, size_t buffer_size);
|
||||
OEMCryptoResult LoadData(CryptoEngine* ce, uint32_t index,
|
||||
const std::vector<uint8_t>& buffer);
|
||||
OEMCryptoResult CopyOldUsageEntry(const std::vector<uint8_t>& pst);
|
||||
int64_t generation_number() { return data_.generation_number; }
|
||||
void set_generation_number(int64_t value) { data_.generation_number = value; }
|
||||
void set_index(int32_t index) { data_.index = index; }
|
||||
uint32_t index() { return data_.index; }
|
||||
static size_t SignedEntrySize();
|
||||
const uint8_t* mac_key_server() { return data_.mac_key_server; }
|
||||
const uint8_t* mac_key_client() { return data_.mac_key_client; }
|
||||
|
||||
private:
|
||||
UsageTable* usage_table_; // Owner of this object.
|
||||
bool recent_decrypt_;
|
||||
bool forbid_report_;
|
||||
StoredUsageEntry data_;
|
||||
};
|
||||
|
||||
class UsageTable {
|
||||
public:
|
||||
explicit UsageTable(CryptoEngine* ce)
|
||||
: ce_(ce), header_loaded_(false), old_table_(NULL){};
|
||||
~UsageTable();
|
||||
|
||||
OEMCryptoResult CreateNewUsageEntry(SessionContext* session,
|
||||
UsageTableEntry** entry,
|
||||
uint32_t* usage_entry_number);
|
||||
OEMCryptoResult LoadUsageEntry(SessionContext* session,
|
||||
UsageTableEntry** entry, uint32_t index,
|
||||
const std::vector<uint8_t>& buffer);
|
||||
OEMCryptoResult UpdateUsageEntry(SessionContext* session,
|
||||
UsageTableEntry* entry,
|
||||
uint8_t* header_buffer,
|
||||
size_t* header_buffer_length,
|
||||
uint8_t* entry_buffer,
|
||||
size_t* entry_buffer_length);
|
||||
OEMCryptoResult MoveEntry(UsageTableEntry* entry, uint32_t new_index);
|
||||
OEMCryptoResult CreateUsageTableHeader(uint8_t* header_buffer,
|
||||
size_t* header_buffer_length);
|
||||
OEMCryptoResult LoadUsageTableHeader(const std::vector<uint8_t>& buffer);
|
||||
OEMCryptoResult ShrinkUsageTableHeader(uint32_t new_table_size,
|
||||
uint8_t* header_buffer,
|
||||
size_t* header_buffer_length);
|
||||
void ReleaseEntry(uint32_t index) { sessions_[index] = 0; }
|
||||
void IncrementGeneration();
|
||||
static size_t SignedHeaderSize(size_t count);
|
||||
OldUsageTableEntry* FindOldUsageEntry(const std::vector<uint8_t>& pst);
|
||||
OEMCryptoResult DeleteOldUsageTable();
|
||||
OEMCryptoResult CreateOldUsageEntry(uint64_t time_since_license_received,
|
||||
uint64_t time_since_first_decrypt,
|
||||
uint64_t time_since_last_decrypt,
|
||||
OEMCrypto_Usage_Entry_Status status,
|
||||
uint8_t *server_mac_key,
|
||||
uint8_t *client_mac_key,
|
||||
const uint8_t* pst,
|
||||
size_t pst_length);
|
||||
|
||||
private:
|
||||
OEMCryptoResult SaveUsageTableHeader(uint8_t* signed_buffer,
|
||||
size_t buffer_size);
|
||||
bool SaveGenerationNumber();
|
||||
bool LoadGenerationNumber(bool or_make_new_one);
|
||||
|
||||
CryptoEngine* ce_;
|
||||
bool header_loaded_;
|
||||
int64_t master_generation_number_;
|
||||
std::vector<int64_t> generation_numbers_;
|
||||
std::vector<SessionContext*> sessions_;
|
||||
OldUsageTable *old_table_;
|
||||
};
|
||||
|
||||
} // namespace wvoec_ref
|
||||
|
||||
#endif // OEMCRYPTO_USAGE_TABLE_REF_H_
|
||||
96
libwvdrmengine/oemcrypto/ref/src/wvcrc.cpp
Normal file
96
libwvdrmengine/oemcrypto/ref/src/wvcrc.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// Compute CRC32 Checksum. Needed for verification of WV Keybox.
|
||||
//
|
||||
#include <arpa/inet.h>
|
||||
#include "wvcrc32.h"
|
||||
|
||||
#define INIT_CRC32 0xffffffff
|
||||
|
||||
uint32_t wvrunningcrc32(const uint8_t* p_begin, int i_count, uint32_t i_crc) {
|
||||
static uint32_t CRC32[256] = {
|
||||
0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
|
||||
0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
|
||||
0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
|
||||
0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
|
||||
0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
|
||||
0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
|
||||
0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
|
||||
0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
|
||||
0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
|
||||
0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
|
||||
0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
|
||||
0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
|
||||
0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
|
||||
0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
|
||||
0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
|
||||
0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
|
||||
0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
|
||||
0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
|
||||
0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
|
||||
0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
|
||||
0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
|
||||
0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
|
||||
0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
|
||||
0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
|
||||
0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
|
||||
0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
|
||||
0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
|
||||
0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
|
||||
0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
|
||||
0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
|
||||
0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
|
||||
0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
|
||||
0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
|
||||
0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
|
||||
0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
|
||||
0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
|
||||
0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
|
||||
0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
|
||||
0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
|
||||
0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
|
||||
0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
|
||||
0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
|
||||
0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
|
||||
0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
|
||||
0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
|
||||
0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
|
||||
0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
|
||||
0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
|
||||
0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
|
||||
0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
|
||||
0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
|
||||
0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
|
||||
0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
|
||||
0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
|
||||
0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
|
||||
0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
|
||||
0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
|
||||
0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
|
||||
0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
|
||||
0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
|
||||
0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
|
||||
0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
|
||||
0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
|
||||
0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
|
||||
};
|
||||
|
||||
/* Calculate the CRC */
|
||||
while (i_count > 0) {
|
||||
i_crc = (i_crc << 8) ^ CRC32[(i_crc >> 24) ^ ((uint32_t) * p_begin)];
|
||||
p_begin++;
|
||||
i_count--;
|
||||
}
|
||||
|
||||
return(i_crc);
|
||||
}
|
||||
|
||||
uint32_t wvcrc32(const uint8_t* p_begin, int i_count) {
|
||||
return(wvrunningcrc32(p_begin, i_count, INIT_CRC32));
|
||||
}
|
||||
|
||||
uint32_t wvcrc32n(const uint8_t* p_begin, int i_count) {
|
||||
return htonl(wvrunningcrc32(p_begin, i_count, INIT_CRC32));
|
||||
}
|
||||
17
libwvdrmengine/oemcrypto/ref/src/wvcrc32.h
Normal file
17
libwvdrmengine/oemcrypto/ref/src/wvcrc32.h
Normal file
@@ -0,0 +1,17 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
//
|
||||
// Compute CRC32 Checksum. Needed for verification of WV Keybox.
|
||||
//
|
||||
#ifndef WVCRC32_H_
|
||||
#define WVCRC32_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint32_t wvcrc32(const uint8_t* p_begin, int i_count);
|
||||
|
||||
// Convert to network byte order
|
||||
uint32_t wvcrc32n(const uint8_t* p_begin, int i_count);
|
||||
|
||||
#endif // WVCRC32_H_
|
||||
Reference in New Issue
Block a user