From 42188c007a305d7a7064932ec7de1a1c3696eece Mon Sep 17 00:00:00 2001 From: Fred Gylys-Colwell Date: Thu, 24 Jun 2021 03:36:22 +0000 Subject: [PATCH] Remove OEMCrypto reference Merge from Widevine repo of http://go/wvgerrit/125203 The OEMCrypto reference is not used/built on Android. It was being published to aid OEMs in their development, but now the OPK library is the implementation to be used by OEMs. Bug: 187556088 Bug: 184866351 Test: Ran android/copy_files Change-Id: Ie787bcf9c66a7605700c3dc29a8aa16406926ce3 --- libwvdrmengine/oemcrypto/ref/README.md | 5 - libwvdrmengine/oemcrypto/ref/src/keys.cpp | 10 - libwvdrmengine/oemcrypto/ref/src/keys.h | 11 - libwvdrmengine/oemcrypto/ref/src/oem_cert.cpp | 334 --- libwvdrmengine/oemcrypto/ref/src/oem_cert.h | 21 - .../oemcrypto/ref/src/oemcrypto_auth_ref.cpp | 447 ----- .../oemcrypto/ref/src/oemcrypto_auth_ref.h | 172 -- .../oemcrypto/ref/src/oemcrypto_ecc_key.cpp | 782 -------- .../oemcrypto/ref/src/oemcrypto_ecc_key.h | 245 --- .../oemcrypto_engine_device_properties.cpp | 19 - .../oemcrypto_engine_device_properties_L1.cpp | 40 - ...emcrypto_engine_device_properties_cert.cpp | 37 - ...crypto_engine_device_properties_prov30.cpp | 70 - .../ref/src/oemcrypto_engine_ref.cpp | 279 --- .../oemcrypto/ref/src/oemcrypto_engine_ref.h | 271 --- .../oemcrypto/ref/src/oemcrypto_key_ref.cpp | 71 - .../oemcrypto/ref/src/oemcrypto_key_ref.h | 87 - .../ref/src/oemcrypto_keybox_ref.cpp | 129 -- .../oemcrypto/ref/src/oemcrypto_keybox_ref.h | 66 - .../oemcrypto/ref/src/oemcrypto_oem_cert.cpp | 233 --- .../oemcrypto/ref/src/oemcrypto_oem_cert.h | 104 - .../oemcrypto/ref/src/oemcrypto_ref.cpp | 1768 ---------------- .../oemcrypto/ref/src/oemcrypto_rsa_key.cpp | 1168 ----------- .../oemcrypto/ref/src/oemcrypto_rsa_key.h | 359 ---- .../oemcrypto/ref/src/oemcrypto_session.cpp | 1782 ----------------- .../oemcrypto/ref/src/oemcrypto_session.h | 312 --- .../ref/src/oemcrypto_session_key_table.cpp | 105 - .../ref/src/oemcrypto_session_key_table.h | 73 - .../ref/src/oemcrypto_usage_table_ref.cpp | 710 ------- .../ref/src/oemcrypto_usage_table_ref.h | 132 -- .../oemcrypto/ref/src/scoped_object.h | 71 - libwvdrmengine/oemcrypto/ref/src/wvcrc.cpp | 108 - libwvdrmengine/oemcrypto/ref/src/wvcrc32.h | 23 - .../oemcrypto/ref/test/oem_cert_test.cpp | 536 ----- .../ref/test/oemcrypto_ecc_key_unittest.cpp | 232 --- .../ref/test/oemcrypto_oem_cert_unittest.cpp | 115 -- .../ref/test/oemcrypto_ref_test_utils.cpp | 20 - .../ref/test/oemcrypto_ref_test_utils.h | 21 - .../ref/test/oemcrypto_rsa_key_unittest.cpp | 406 ---- .../ref/test/oemcrypto_wvcrc32_unittest.cpp | 74 - 40 files changed, 11448 deletions(-) delete mode 100644 libwvdrmengine/oemcrypto/ref/README.md delete mode 100644 libwvdrmengine/oemcrypto/ref/src/keys.cpp delete mode 100644 libwvdrmengine/oemcrypto/ref/src/keys.h delete mode 100644 libwvdrmengine/oemcrypto/ref/src/oem_cert.cpp delete mode 100644 libwvdrmengine/oemcrypto/ref/src/oem_cert.h delete mode 100644 libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.cpp delete mode 100644 libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.h delete mode 100644 libwvdrmengine/oemcrypto/ref/src/oemcrypto_ecc_key.cpp delete mode 100644 libwvdrmengine/oemcrypto/ref/src/oemcrypto_ecc_key.h delete mode 100644 libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_device_properties.cpp delete mode 100644 libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_device_properties_L1.cpp delete mode 100644 libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_device_properties_cert.cpp delete mode 100644 libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_device_properties_prov30.cpp delete mode 100644 libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.cpp delete mode 100644 libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.h delete mode 100644 libwvdrmengine/oemcrypto/ref/src/oemcrypto_key_ref.cpp delete mode 100644 libwvdrmengine/oemcrypto/ref/src/oemcrypto_key_ref.h delete mode 100644 libwvdrmengine/oemcrypto/ref/src/oemcrypto_keybox_ref.cpp delete mode 100644 libwvdrmengine/oemcrypto/ref/src/oemcrypto_keybox_ref.h delete mode 100644 libwvdrmengine/oemcrypto/ref/src/oemcrypto_oem_cert.cpp delete mode 100644 libwvdrmengine/oemcrypto/ref/src/oemcrypto_oem_cert.h delete mode 100644 libwvdrmengine/oemcrypto/ref/src/oemcrypto_ref.cpp delete mode 100644 libwvdrmengine/oemcrypto/ref/src/oemcrypto_rsa_key.cpp delete mode 100644 libwvdrmengine/oemcrypto/ref/src/oemcrypto_rsa_key.h delete mode 100644 libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.cpp delete mode 100644 libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.h delete mode 100644 libwvdrmengine/oemcrypto/ref/src/oemcrypto_session_key_table.cpp delete mode 100644 libwvdrmengine/oemcrypto/ref/src/oemcrypto_session_key_table.h delete mode 100644 libwvdrmengine/oemcrypto/ref/src/oemcrypto_usage_table_ref.cpp delete mode 100644 libwvdrmengine/oemcrypto/ref/src/oemcrypto_usage_table_ref.h delete mode 100644 libwvdrmengine/oemcrypto/ref/src/scoped_object.h delete mode 100644 libwvdrmengine/oemcrypto/ref/src/wvcrc.cpp delete mode 100644 libwvdrmengine/oemcrypto/ref/src/wvcrc32.h delete mode 100644 libwvdrmengine/oemcrypto/ref/test/oem_cert_test.cpp delete mode 100644 libwvdrmengine/oemcrypto/ref/test/oemcrypto_ecc_key_unittest.cpp delete mode 100644 libwvdrmengine/oemcrypto/ref/test/oemcrypto_oem_cert_unittest.cpp delete mode 100644 libwvdrmengine/oemcrypto/ref/test/oemcrypto_ref_test_utils.cpp delete mode 100644 libwvdrmengine/oemcrypto/ref/test/oemcrypto_ref_test_utils.h delete mode 100644 libwvdrmengine/oemcrypto/ref/test/oemcrypto_rsa_key_unittest.cpp delete mode 100644 libwvdrmengine/oemcrypto/ref/test/oemcrypto_wvcrc32_unittest.cpp diff --git a/libwvdrmengine/oemcrypto/ref/README.md b/libwvdrmengine/oemcrypto/ref/README.md deleted file mode 100644 index cf8412d0..00000000 --- a/libwvdrmengine/oemcrypto/ref/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Reference OEMCrypto - -This directory contains a testing-only implementation of OEMCrypto. **This -implementation is *NOT* suitable for production use and must *NOT* be released -on devices.** diff --git a/libwvdrmengine/oemcrypto/ref/src/keys.cpp b/libwvdrmengine/oemcrypto/ref/src/keys.cpp deleted file mode 100644 index 380e0324..00000000 --- a/libwvdrmengine/oemcrypto/ref/src/keys.cpp +++ /dev/null @@ -1,10 +0,0 @@ -// 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; diff --git a/libwvdrmengine/oemcrypto/ref/src/keys.h b/libwvdrmengine/oemcrypto/ref/src/keys.h deleted file mode 100644 index e6c0145d..00000000 --- a/libwvdrmengine/oemcrypto/ref/src/keys.h +++ /dev/null @@ -1,11 +0,0 @@ -// This header is used to access the baked-in certificate if one is in use. -#ifndef KEYS_H_ -#define KEYS_H_ - -#include -#include - -extern const uint8_t kPrivateKey[]; -extern const size_t kPrivateKeySize; - -#endif // KEYS_H_ diff --git a/libwvdrmengine/oemcrypto/ref/src/oem_cert.cpp b/libwvdrmengine/oemcrypto/ref/src/oem_cert.cpp deleted file mode 100644 index 0b7ab7f7..00000000 --- a/libwvdrmengine/oemcrypto/ref/src/oem_cert.cpp +++ /dev/null @@ -1,334 +0,0 @@ -// This file contains the test OEM cert. - -#include "oem_cert.h" - -namespace wvoec_ref { - -const uint32_t kOEMSystemId_Prod = 7913; - -// From file test_rsa_key_2_carmichael.pk8 in team shared drive. -// Size is 1216. -const uint8_t kOEMPrivateKey_Prod[] = { - 0x30, 0x82, 0x04, 0xbc, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, - 0x04, 0xa6, 0x30, 0x82, 0x04, 0xa2, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, - 0x01, 0x00, 0xa7, 0x00, 0x36, 0x60, 0x65, 0xdc, 0xbd, 0x54, 0x5a, 0x2a, - 0x40, 0xb4, 0xe1, 0x15, 0x94, 0x58, 0x11, 0x4f, 0x94, 0x58, 0xdd, 0xde, - 0xa7, 0x1f, 0x3c, 0x2c, 0xe0, 0x88, 0x09, 0x29, 0x61, 0x57, 0x67, 0x5e, - 0x56, 0x7e, 0xee, 0x27, 0x8f, 0x59, 0x34, 0x9a, 0x2a, 0xaa, 0x9d, 0xb4, - 0x4e, 0xfa, 0xa7, 0x6a, 0xd4, 0xc9, 0x7a, 0x53, 0xc1, 0x4e, 0x9f, 0xe3, - 0x34, 0xf7, 0x3d, 0xb7, 0xc9, 0x10, 0x47, 0x4f, 0x28, 0xda, 0x3f, 0xce, - 0x31, 0x7b, 0xfd, 0x06, 0x10, 0xeb, 0xf7, 0xbe, 0x92, 0xf9, 0xaf, 0xfb, - 0x3e, 0x68, 0xda, 0xee, 0x1a, 0x64, 0x4c, 0xf3, 0x29, 0xf2, 0x73, 0x9e, - 0x39, 0xd8, 0xf6, 0x6f, 0xd8, 0xb2, 0x80, 0x82, 0x71, 0x8e, 0xb5, 0xa4, - 0xf2, 0xc2, 0x3e, 0xcd, 0x0a, 0xca, 0xb6, 0x04, 0xcd, 0x9a, 0x13, 0x8b, - 0x54, 0x73, 0x54, 0x25, 0x54, 0x8c, 0xbe, 0x98, 0x7a, 0x67, 0xad, 0xda, - 0xb3, 0x4e, 0xb3, 0xfa, 0x82, 0xa8, 0x4a, 0x67, 0x98, 0x56, 0x57, 0x54, - 0x71, 0xcd, 0x12, 0x7f, 0xed, 0xa3, 0x01, 0xc0, 0x6a, 0x8b, 0x24, 0x03, - 0x96, 0x88, 0xbe, 0x97, 0x66, 0x2a, 0xbc, 0x53, 0xc9, 0x83, 0x06, 0x51, - 0x5a, 0x88, 0x65, 0x13, 0x18, 0xe4, 0x3a, 0xed, 0x6b, 0xf1, 0x61, 0x5b, - 0x4c, 0xc8, 0x1e, 0xf4, 0xc2, 0xae, 0x08, 0x5e, 0x2d, 0x5f, 0xf8, 0x12, - 0x7f, 0xa2, 0xfc, 0xbb, 0x21, 0x18, 0x30, 0xda, 0xfe, 0x40, 0xfb, 0x01, - 0xca, 0x2e, 0x37, 0x0e, 0xce, 0xdd, 0x76, 0x87, 0x82, 0x46, 0x0b, 0x3a, - 0x77, 0x8f, 0xc0, 0x72, 0x07, 0x2c, 0x7f, 0x9d, 0x1e, 0x86, 0x5b, 0xed, - 0x27, 0x29, 0xdf, 0x03, 0x97, 0x62, 0xef, 0x44, 0xd3, 0x5b, 0x3d, 0xdb, - 0x9c, 0x5e, 0x1b, 0x7b, 0x39, 0xb4, 0x0b, 0x6d, 0x04, 0x6b, 0xbb, 0xbb, - 0x2c, 0x5f, 0xcf, 0xb3, 0x7a, 0x05, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, - 0x82, 0x01, 0x00, 0x0a, 0xf9, 0x4a, 0x19, 0x72, 0x88, 0x1b, 0x4e, 0xd8, - 0x2f, 0xef, 0x99, 0x93, 0x32, 0xda, 0x51, 0x21, 0x2e, 0x14, 0x06, 0xf4, - 0xe9, 0x65, 0x1c, 0xf9, 0xd4, 0xcf, 0x1a, 0x51, 0x53, 0xcd, 0x48, 0x33, - 0x8c, 0x30, 0xed, 0xdd, 0x53, 0x6f, 0x29, 0x82, 0xf9, 0xe0, 0x74, 0xde, - 0xb1, 0x13, 0x01, 0x88, 0x8f, 0xce, 0x14, 0xc1, 0x3b, 0x90, 0xb7, 0xcc, - 0x6c, 0xdf, 0x35, 0xa1, 0xf2, 0x1a, 0x3d, 0xbe, 0x19, 0xd7, 0x0a, 0xe4, - 0x67, 0x75, 0xbb, 0xfa, 0x87, 0xf4, 0x03, 0xb5, 0x7f, 0x69, 0xe4, 0x0b, - 0x6a, 0xdc, 0x92, 0x82, 0x54, 0x64, 0x1a, 0x94, 0x2d, 0xe4, 0x63, 0x40, - 0xb2, 0xb4, 0x85, 0x6b, 0xc8, 0x34, 0xba, 0xa2, 0x14, 0x30, 0x47, 0x1a, - 0xeb, 0x90, 0x62, 0x30, 0x43, 0x44, 0x02, 0xc7, 0x0c, 0x30, 0xc0, 0x7f, - 0xa9, 0x47, 0xae, 0xde, 0x68, 0x27, 0x92, 0xaa, 0x11, 0x95, 0xf5, 0x6f, - 0xfc, 0x19, 0x8b, 0x49, 0xa0, 0x77, 0x9d, 0xc6, 0x13, 0x5d, 0x73, 0xff, - 0x45, 0xa2, 0x4c, 0x3b, 0xf3, 0xe1, 0x2d, 0xd7, 0xc4, 0x70, 0xe2, 0x6c, - 0x37, 0x99, 0x4c, 0x7a, 0xa9, 0x27, 0xf8, 0x3a, 0xd6, 0xfd, 0xc5, 0xd8, - 0xfa, 0x2d, 0x0e, 0x71, 0x4b, 0x85, 0x7e, 0xce, 0xcb, 0x1c, 0x79, 0x71, - 0xbd, 0xff, 0x63, 0x03, 0x6b, 0x58, 0x68, 0xe0, 0x14, 0xca, 0x5e, 0x85, - 0xfd, 0xd0, 0xb7, 0xe0, 0x68, 0x14, 0xff, 0x2c, 0x82, 0x22, 0x26, 0x8a, - 0x3f, 0xbf, 0xb0, 0x2a, 0x90, 0xff, 0xc7, 0x72, 0xfc, 0x66, 0x51, 0x3e, - 0x51, 0x9f, 0x82, 0x68, 0x0e, 0xf3, 0x65, 0x74, 0x88, 0xab, 0xb7, 0xe5, - 0x97, 0x5f, 0x0f, 0x3e, 0xe5, 0x3a, 0xbc, 0xa4, 0xa1, 0x50, 0xdd, 0x5c, - 0x94, 0x4b, 0x0c, 0x70, 0x71, 0x48, 0x4e, 0xd0, 0xec, 0x46, 0x8f, 0xdf, - 0xa2, 0x9a, 0xfe, 0xd8, 0x35, 0x1a, 0x2f, 0x02, 0x81, 0x81, 0x00, 0xcf, - 0x73, 0x8c, 0xbe, 0x6d, 0x45, 0x2d, 0x0c, 0x0b, 0x5d, 0x5c, 0x6c, 0x75, - 0x78, 0xcc, 0x35, 0x48, 0xb6, 0x98, 0xf1, 0xb9, 0x64, 0x60, 0x8c, 0x43, - 0xeb, 0x85, 0xab, 0x04, 0xb6, 0x7d, 0x1b, 0x71, 0x75, 0x06, 0xe2, 0xda, - 0x84, 0x68, 0x2e, 0x7f, 0x4c, 0xe3, 0x73, 0xb4, 0xde, 0x51, 0x4b, 0xb6, - 0x51, 0x86, 0x7b, 0xd0, 0xe6, 0x4d, 0xf3, 0xd1, 0xcf, 0x1a, 0xfe, 0x7f, - 0x3a, 0x83, 0xba, 0xb3, 0xe1, 0xff, 0x54, 0x13, 0x93, 0xd7, 0x9c, 0x27, - 0x80, 0xb7, 0x1e, 0x64, 0x9e, 0xf7, 0x32, 0x2b, 0x46, 0x29, 0xf7, 0xf8, - 0x18, 0x6c, 0xf7, 0x4a, 0xbe, 0x4b, 0xee, 0x96, 0x90, 0x8f, 0xa2, 0x16, - 0x22, 0x6a, 0xcc, 0x48, 0x06, 0x74, 0x63, 0x43, 0x7f, 0x27, 0x22, 0x44, - 0x3c, 0x2d, 0x3b, 0x62, 0xf1, 0x1c, 0xb4, 0x27, 0x33, 0x85, 0x26, 0x60, - 0x48, 0x16, 0xcb, 0xef, 0xf8, 0xcd, 0x37, 0x02, 0x81, 0x81, 0x00, 0xce, - 0x15, 0x43, 0x6e, 0x4b, 0x0f, 0xf9, 0x3f, 0x87, 0xc3, 0x41, 0x45, 0x97, - 0xb1, 0x49, 0xc2, 0x19, 0x23, 0x87, 0xe4, 0x24, 0x1c, 0x64, 0xe5, 0x28, - 0xcb, 0x43, 0x10, 0x14, 0x14, 0x0e, 0x19, 0xcb, 0xbb, 0xdb, 0xfd, 0x11, - 0x9d, 0x17, 0x68, 0x78, 0x6d, 0x61, 0x70, 0x63, 0x3a, 0xa1, 0xb3, 0xf3, - 0xa7, 0x5b, 0x0e, 0xff, 0xb7, 0x61, 0x11, 0x54, 0x91, 0x99, 0xe5, 0x91, - 0x32, 0x2d, 0xeb, 0x3f, 0xd8, 0x3e, 0xf7, 0xd4, 0xcb, 0xd2, 0xa3, 0x41, - 0xc1, 0xee, 0xc6, 0x92, 0x13, 0xeb, 0x7f, 0x42, 0x58, 0xf4, 0xd0, 0xb2, - 0x74, 0x1d, 0x8e, 0x87, 0x46, 0xcd, 0x14, 0xb8, 0x16, 0xad, 0xb5, 0xbd, - 0x0d, 0x6c, 0x95, 0x5a, 0x16, 0xbf, 0xe9, 0x53, 0xda, 0xfb, 0xed, 0x83, - 0x51, 0x67, 0xa9, 0x55, 0xab, 0x54, 0x02, 0x95, 0x20, 0xa6, 0x68, 0x17, - 0x53, 0xa8, 0xea, 0x43, 0xe5, 0xb0, 0xa3, 0x02, 0x81, 0x80, 0x67, 0x9c, - 0x32, 0x83, 0x39, 0x57, 0xff, 0x73, 0xb0, 0x89, 0x64, 0x8b, 0xd6, 0xf0, - 0x0a, 0x2d, 0xe2, 0xaf, 0x30, 0x1c, 0x2a, 0x97, 0xf3, 0x90, 0x9a, 0xab, - 0x9b, 0x0b, 0x1b, 0x43, 0x79, 0xa0, 0xa7, 0x3d, 0xe7, 0xbe, 0x8d, 0x9c, - 0xeb, 0xdb, 0xad, 0x40, 0xdd, 0xa9, 0x00, 0x80, 0xb8, 0xe1, 0xb3, 0xa1, - 0x6c, 0x25, 0x92, 0xe4, 0x33, 0xb2, 0xbe, 0xeb, 0x4d, 0x74, 0x26, 0x5f, - 0x37, 0x43, 0x9c, 0x6c, 0x17, 0x76, 0x0a, 0x81, 0x20, 0x82, 0xa1, 0x48, - 0x2c, 0x2d, 0x45, 0xdc, 0x0f, 0x62, 0x43, 0x32, 0xbb, 0xeb, 0x59, 0x41, - 0xf9, 0xca, 0x58, 0xce, 0x4a, 0x66, 0x53, 0x54, 0xc8, 0x28, 0x10, 0x1e, - 0x08, 0x71, 0x16, 0xd8, 0x02, 0x71, 0x41, 0x58, 0xd4, 0x56, 0xcc, 0xf5, - 0xb1, 0x31, 0xa3, 0xed, 0x00, 0x85, 0x09, 0xbf, 0x35, 0x95, 0x41, 0x29, - 0x40, 0x19, 0x83, 0x35, 0x24, 0x69, 0x02, 0x81, 0x80, 0x55, 0x10, 0x0b, - 0xcc, 0x3b, 0xa9, 0x75, 0x3d, 0x16, 0xe1, 0xae, 0x50, 0x76, 0x63, 0x94, - 0x49, 0x4c, 0xad, 0x10, 0xcb, 0x47, 0x68, 0x7c, 0xf0, 0xe5, 0xdc, 0xb8, - 0x6a, 0xab, 0x8e, 0xf7, 0x9f, 0x08, 0x2c, 0x1b, 0x8a, 0xa2, 0xb9, 0x8f, - 0xce, 0xec, 0x5e, 0x61, 0xa8, 0xcd, 0x1c, 0x87, 0x60, 0x4a, 0xc3, 0x1a, - 0x5f, 0xdf, 0x87, 0x26, 0xc6, 0xcb, 0x7c, 0x69, 0xe4, 0x8b, 0x01, 0x06, - 0x59, 0x22, 0xfa, 0x34, 0x4b, 0x81, 0x87, 0x3c, 0x03, 0x6d, 0x02, 0x0a, - 0x77, 0xe6, 0x15, 0xd8, 0xcf, 0xa7, 0x68, 0x26, 0x6c, 0xfa, 0x2b, 0xd9, - 0x83, 0x5a, 0x2d, 0x0c, 0x3b, 0x70, 0x1c, 0xd4, 0x48, 0xbe, 0xa7, 0x0a, - 0xd9, 0xbe, 0xdc, 0xc3, 0x0c, 0x21, 0x33, 0xb3, 0x66, 0xff, 0x1c, 0x1b, - 0xc8, 0x96, 0x76, 0xe8, 0x6f, 0x44, 0x74, 0xbc, 0x9b, 0x1c, 0x7d, 0xc8, - 0xac, 0x21, 0xa8, 0x6e, 0x37, 0x02, 0x81, 0x80, 0x2c, 0x7c, 0xad, 0x1e, - 0x75, 0xf6, 0x69, 0x1d, 0xe7, 0xa6, 0xca, 0x74, 0x7d, 0x67, 0xc8, 0x65, - 0x28, 0x66, 0xc4, 0x43, 0xa6, 0xbd, 0x40, 0x57, 0xae, 0xb7, 0x65, 0x2c, - 0x52, 0xf9, 0xe4, 0xc7, 0x81, 0x7b, 0x56, 0xa3, 0xd2, 0x0d, 0xe8, 0x33, - 0x70, 0xcf, 0x06, 0x84, 0xb3, 0x4e, 0x44, 0x50, 0x75, 0x61, 0x96, 0x86, - 0x4b, 0xb6, 0x2b, 0xad, 0xf0, 0xad, 0x57, 0xd0, 0x37, 0x0d, 0x1d, 0x35, - 0x50, 0xcb, 0x69, 0x22, 0x39, 0x29, 0xb9, 0x3a, 0xd3, 0x29, 0x23, 0x02, - 0x60, 0xf7, 0xab, 0x30, 0x40, 0xda, 0x8e, 0x4d, 0x45, 0x70, 0x26, 0xf4, - 0xa2, 0x0d, 0xd0, 0x64, 0x5d, 0x47, 0x3c, 0x18, 0xf4, 0xd4, 0x52, 0x95, - 0x00, 0xae, 0x84, 0x6b, 0x47, 0xb2, 0x3c, 0x82, 0xd3, 0x72, 0x53, 0xde, - 0x72, 0x2c, 0xf7, 0xc1, 0x22, 0x36, 0xd9, 0x18, 0x56, 0xfe, 0x39, 0x28, - 0x33, 0xe0, 0xdb, 0x03 -}; - -const size_t kOEMPrivateKeySize_Prod = sizeof(kOEMPrivateKey_Prod); - -// From the team shared drive file -// oem-7913-leaf-and-intermediate-certs-test-key-2-carmichael.p7b, size 2353. -const uint8_t kOEMPublicCert_Prod[] = { - 0x30, 0x82, 0x09, 0x2d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x07, 0x02, 0xa0, 0x82, 0x09, 0x1e, 0x30, 0x82, 0x09, 0x1a, 0x02, - 0x01, 0x01, 0x31, 0x00, 0x30, 0x0f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, - 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x02, 0x04, 0x00, 0xa0, 0x82, 0x08, - 0xfe, 0x30, 0x82, 0x03, 0x71, 0x30, 0x82, 0x02, 0x59, 0xa0, 0x03, 0x02, - 0x01, 0x02, 0x02, 0x11, 0x00, 0xc2, 0x8d, 0x20, 0x22, 0x82, 0x8b, 0x9e, - 0x63, 0x9d, 0x15, 0x89, 0x2c, 0xa9, 0x8f, 0xd9, 0x5d, 0x30, 0x0d, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, - 0x30, 0x6b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, - 0x0c, 0x02, 0x57, 0x41, 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, - 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x73, 0x79, - 0x73, 0x74, 0x65, 0x6d, 0x20, 0x69, 0x64, 0x3a, 0x20, 0x37, 0x39, 0x31, - 0x33, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x38, 0x30, 0x31, 0x31, 0x31, 0x31, - 0x33, 0x32, 0x36, 0x32, 0x32, 0x5a, 0x17, 0x0d, 0x33, 0x38, 0x30, 0x31, - 0x30, 0x36, 0x31, 0x33, 0x32, 0x36, 0x32, 0x32, 0x5a, 0x30, 0x65, 0x31, - 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x09, 0x37, 0x39, - 0x31, 0x33, 0x2d, 0x6c, 0x65, 0x61, 0x66, 0x31, 0x0b, 0x30, 0x09, 0x06, - 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, - 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, 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, 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, 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, 0xa3, 0x16, - 0x30, 0x14, 0x30, 0x12, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, - 0x79, 0x04, 0x01, 0x01, 0x04, 0x04, 0x02, 0x02, 0x1e, 0xe9, 0x30, 0x0d, - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, - 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x88, 0x95, 0xec, 0xcd, 0x8b, 0xa7, - 0x51, 0xda, 0x74, 0x81, 0xa5, 0x39, 0x62, 0x1a, 0x0e, 0x2e, 0xde, 0x3c, - 0x37, 0xea, 0xad, 0x7c, 0xee, 0x9b, 0x26, 0x8e, 0xe2, 0xd6, 0x34, 0xcd, - 0xb7, 0x70, 0xba, 0xbf, 0xa0, 0xa3, 0xfe, 0xb3, 0x4b, 0xbc, 0xf4, 0x1c, - 0x72, 0x66, 0x81, 0xd5, 0x09, 0x33, 0x78, 0x0c, 0x61, 0x21, 0xa8, 0xf1, - 0xe2, 0xc9, 0xe2, 0x83, 0xc2, 0x19, 0x02, 0xf2, 0xe8, 0xab, 0x17, 0x36, - 0x3a, 0x0b, 0x20, 0xaf, 0x0f, 0xae, 0x2e, 0x73, 0x68, 0xac, 0x15, 0xee, - 0x9c, 0xc0, 0x92, 0x03, 0x7e, 0x95, 0x63, 0xaa, 0xad, 0x15, 0x96, 0x43, - 0x20, 0x3b, 0xe5, 0x9b, 0x1f, 0xca, 0x02, 0xba, 0xf0, 0x07, 0x76, 0x80, - 0xd7, 0xa3, 0x1a, 0xeb, 0xc8, 0xdb, 0x03, 0x7b, 0x43, 0x56, 0xe5, 0x96, - 0x6b, 0x86, 0xfe, 0x08, 0x58, 0x8a, 0x84, 0xbd, 0xe9, 0x47, 0x18, 0xee, - 0xb2, 0xa8, 0x05, 0x7b, 0xf0, 0xfd, 0xaa, 0xb9, 0x85, 0xcd, 0x7a, 0x0e, - 0x6b, 0x6c, 0x9f, 0xc6, 0x75, 0xd2, 0x2a, 0xfe, 0x5b, 0xf3, 0xb7, 0x31, - 0x6c, 0xac, 0xe3, 0x00, 0x9f, 0xe7, 0xdd, 0xe3, 0x81, 0xc1, 0x36, 0xc3, - 0x1c, 0x5f, 0xdf, 0xf2, 0xc3, 0x5e, 0xfa, 0x55, 0x32, 0xd8, 0x5c, 0xa8, - 0xe5, 0xcc, 0xb6, 0x4a, 0xe9, 0xe2, 0xcc, 0x38, 0x44, 0x07, 0x46, 0x59, - 0x34, 0x84, 0x79, 0xf9, 0xee, 0x3c, 0x4b, 0x48, 0x90, 0xab, 0x73, 0xb0, - 0xa1, 0x92, 0xc3, 0xd6, 0x83, 0x87, 0x81, 0xca, 0x12, 0x81, 0xd6, 0x5d, - 0xf7, 0x6f, 0x7a, 0x35, 0x5e, 0x4f, 0x02, 0x66, 0x8a, 0x47, 0x88, 0x82, - 0xab, 0xf0, 0x12, 0x1d, 0xb9, 0x75, 0x3b, 0x7b, 0xa8, 0x36, 0x15, 0xef, - 0xa8, 0x12, 0x0e, 0x53, 0xb4, 0x83, 0x78, 0x53, 0xc0, 0x52, 0xae, 0xa6, - 0x0a, 0xa0, 0x53, 0xdc, 0x1c, 0x15, 0x22, 0xdd, 0x17, 0x98, 0x30, 0x82, - 0x05, 0x85, 0x30, 0x82, 0x03, 0x6d, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, - 0x10, 0x03, 0xb1, 0xf7, 0x58, 0xdf, 0x1d, 0xe3, 0x25, 0x00, 0x0b, 0x10, - 0x3d, 0xd5, 0xe6, 0xe4, 0x64, 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, 0x31, 0x31, - 0x31, 0x38, 0x30, 0x31, 0x31, 0x33, 0x33, 0x35, 0x5a, 0x17, 0x0d, 0x32, - 0x37, 0x31, 0x31, 0x31, 0x38, 0x30, 0x31, 0x31, 0x33, 0x31, 0x33, 0x5a, - 0x30, 0x6b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, - 0x0c, 0x02, 0x57, 0x41, 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, - 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x73, 0x79, - 0x73, 0x74, 0x65, 0x6d, 0x20, 0x69, 0x64, 0x3a, 0x20, 0x37, 0x39, 0x31, - 0x33, 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, 0xae, 0xc8, - 0x71, 0xae, 0x08, 0x0c, 0x06, 0x06, 0x2d, 0x81, 0x7c, 0xa9, 0x8b, 0xb3, - 0xd6, 0x66, 0xe4, 0xf6, 0x08, 0x5e, 0x5a, 0x75, 0xe8, 0x74, 0x61, 0x7a, - 0x88, 0xca, 0x85, 0x14, 0x0d, 0x58, 0xa4, 0x09, 0x19, 0x6c, 0x60, 0xc9, - 0xad, 0x91, 0x1c, 0xbf, 0x04, 0xb3, 0x47, 0x10, 0x63, 0x7f, 0x02, 0x58, - 0xc2, 0x1e, 0xbd, 0xcc, 0x07, 0x77, 0xaa, 0x7e, 0x14, 0xa8, 0xc2, 0x01, - 0xcd, 0xe8, 0x46, 0x60, 0x53, 0x6f, 0x2f, 0xda, 0x17, 0x2d, 0x4d, 0x9d, - 0x0e, 0x5d, 0xb5, 0x50, 0x95, 0xae, 0xab, 0x6e, 0x43, 0xe3, 0xb0, 0x00, - 0x12, 0xb4, 0x05, 0x82, 0x4a, 0x2b, 0x14, 0x63, 0x0d, 0x1f, 0x06, 0x12, - 0xaa, 0xe1, 0x9d, 0xe7, 0xba, 0xda, 0xe3, 0xfc, 0x7c, 0x6c, 0x73, 0xae, - 0x56, 0xf8, 0xab, 0xf7, 0x51, 0x93, 0x31, 0xef, 0x8f, 0xe4, 0xb6, 0x01, - 0x2c, 0xeb, 0x7b, 0xe4, 0xd8, 0xb3, 0xea, 0x70, 0x37, 0x89, 0x05, 0xa9, - 0x51, 0x57, 0x72, 0x98, 0x9e, 0xa8, 0x46, 0xdb, 0xeb, 0x7a, 0x38, 0x2b, - 0x2f, 0xc0, 0x27, 0xb7, 0xc2, 0xe1, 0x9a, 0x17, 0xdf, 0xf5, 0xd6, 0x9c, - 0xd5, 0x8c, 0xb8, 0x66, 0x42, 0xd5, 0x04, 0x1e, 0x7c, 0x36, 0x4c, 0x1e, - 0x3e, 0x45, 0x51, 0x4d, 0x41, 0x72, 0x22, 0x53, 0x3d, 0xf4, 0x57, 0x7c, - 0x6c, 0x33, 0x34, 0x24, 0x45, 0xdf, 0x84, 0x87, 0x4a, 0xa6, 0xcb, 0x7c, - 0x03, 0xa3, 0xaa, 0x8e, 0x2d, 0x82, 0x01, 0x27, 0x87, 0x74, 0x82, 0x1a, - 0xbc, 0x0f, 0x76, 0x69, 0xab, 0xe0, 0x4e, 0x70, 0xbe, 0x37, 0xfc, 0xc8, - 0x2c, 0x91, 0x17, 0x4f, 0xd5, 0x26, 0x3b, 0x7b, 0x90, 0xb5, 0x2d, 0x64, - 0xba, 0xf7, 0xd2, 0x8a, 0xb4, 0x8f, 0x38, 0x9d, 0x8e, 0xba, 0xe7, 0x5c, - 0x52, 0xf1, 0x0a, 0xb8, 0xc0, 0x1b, 0xb6, 0xb1, 0x70, 0x7e, 0x47, 0x59, - 0x94, 0x59, 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, 0x4b, 0xcb, 0xdf, 0xaa, 0x02, 0xde, 0x8d, 0xc3, 0xe7, 0xe5, - 0x85, 0xdb, 0x2e, 0x8a, 0xbe, 0x75, 0x6b, 0x8a, 0x67, 0x58, 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, 0x1e, 0xe9, 0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, - 0x02, 0x01, 0x00, 0x61, 0x3f, 0x2f, 0x43, 0xe4, 0xbe, 0x66, 0x34, 0xef, - 0x92, 0x06, 0xe9, 0x88, 0xba, 0x6a, 0x1d, 0x4f, 0x54, 0x5a, 0x97, 0xb1, - 0x75, 0xd7, 0x93, 0xf8, 0x45, 0xc6, 0x83, 0x92, 0x36, 0xfd, 0x55, 0xa9, - 0x21, 0x0b, 0xdc, 0xf6, 0xae, 0x11, 0xdc, 0x62, 0x21, 0x44, 0xbd, 0x04, - 0x1d, 0x58, 0x2c, 0x03, 0xf8, 0xe4, 0xe2, 0x1e, 0xba, 0xe6, 0xdd, 0x19, - 0xdd, 0x56, 0xfd, 0xce, 0x06, 0x73, 0x5f, 0x94, 0x1e, 0xb6, 0x03, 0xdb, - 0x3d, 0x7b, 0xab, 0xab, 0x72, 0x64, 0x7b, 0xde, 0x7d, 0x4d, 0xcf, 0x7e, - 0xf0, 0x91, 0x29, 0xc1, 0x77, 0x13, 0xc2, 0x6f, 0x80, 0xab, 0x7a, 0xa8, - 0xce, 0xb0, 0x1c, 0x2a, 0xc5, 0x9c, 0xfb, 0x0b, 0xe5, 0x9f, 0x9c, 0x1b, - 0xc9, 0x4b, 0x58, 0xdf, 0x96, 0x18, 0xf7, 0x67, 0x67, 0x89, 0xa4, 0xe9, - 0x14, 0x48, 0xac, 0xfa, 0x9d, 0x86, 0x2a, 0xeb, 0x75, 0x2c, 0x2b, 0xbf, - 0x63, 0x7d, 0xc7, 0x4e, 0x7e, 0xad, 0x39, 0x2d, 0xb4, 0x7c, 0x07, 0xa5, - 0x5a, 0xe8, 0x3a, 0xd4, 0xf5, 0x0c, 0x4f, 0xf3, 0xa2, 0x9c, 0x3c, 0x32, - 0xed, 0x9d, 0x4b, 0x49, 0x05, 0xbc, 0x1f, 0xa0, 0x13, 0xe6, 0xdd, 0x82, - 0x79, 0x06, 0x31, 0x3b, 0xc6, 0x97, 0xec, 0x8d, 0xaa, 0x4f, 0xef, 0x14, - 0x3c, 0x21, 0xf6, 0x72, 0xb2, 0x09, 0x42, 0xc7, 0x74, 0xfe, 0xef, 0x70, - 0xbd, 0xe9, 0x85, 0x41, 0x30, 0x0b, 0xb3, 0x6b, 0x59, 0x0c, 0x0f, 0x11, - 0x75, 0xd4, 0xbb, 0xb1, 0xdf, 0xb1, 0xdf, 0xb3, 0xfa, 0xb3, 0x3a, 0x43, - 0x17, 0x7d, 0x8a, 0x82, 0xae, 0xa2, 0x07, 0xf8, 0x83, 0x51, 0xfb, 0x16, - 0xfb, 0x64, 0xb6, 0x46, 0xda, 0xbe, 0x32, 0x2b, 0xc0, 0xee, 0x78, 0x2a, - 0x84, 0xa9, 0x54, 0x0a, 0xf9, 0x2d, 0x61, 0x65, 0xde, 0xa5, 0x97, 0x66, - 0x79, 0x02, 0xf8, 0x97, 0x17, 0xe2, 0xd4, 0x9f, 0x9e, 0xac, 0xcc, 0xae, - 0x99, 0x9a, 0x03, 0x04, 0xbb, 0x45, 0xfe, 0xb2, 0xf5, 0x80, 0xba, 0xbf, - 0xdd, 0x24, 0xe5, 0xe6, 0x1e, 0x5d, 0x36, 0xa5, 0x87, 0x0c, 0xdf, 0x60, - 0x81, 0x6f, 0xb7, 0x5f, 0xb9, 0x1f, 0xca, 0x75, 0x3c, 0x1a, 0x63, 0xb0, - 0xeb, 0xe6, 0x95, 0x86, 0x0d, 0xae, 0xa6, 0xc9, 0x2a, 0x94, 0xf1, 0xd0, - 0xbe, 0x75, 0xc8, 0xf8, 0x07, 0xd7, 0x88, 0xff, 0xec, 0xf9, 0xcd, 0x49, - 0xc6, 0xfe, 0x4d, 0x7f, 0x44, 0x1e, 0xd8, 0xaf, 0xa9, 0x72, 0x27, 0x98, - 0xe2, 0x5a, 0x08, 0xea, 0x55, 0xd3, 0xb3, 0xea, 0xdc, 0x76, 0x69, 0x51, - 0x10, 0x01, 0x46, 0x7d, 0x33, 0x94, 0x9c, 0x94, 0xef, 0xfe, 0x76, 0x1c, - 0xc6, 0xd7, 0x15, 0x53, 0x3e, 0x8d, 0x3d, 0x29, 0x9a, 0x58, 0x6a, 0xf1, - 0x75, 0x9e, 0xea, 0x1b, 0x4c, 0xf0, 0x47, 0x76, 0xac, 0xc6, 0xa2, 0x32, - 0x44, 0x40, 0xdf, 0xfe, 0xff, 0x9d, 0xf4, 0xe2, 0xc2, 0xfa, 0xa1, 0x5f, - 0x2e, 0x66, 0xe9, 0x97, 0xcb, 0x27, 0x26, 0x6e, 0x53, 0xe4, 0xe8, 0x86, - 0x2c, 0xea, 0xd3, 0x69, 0x6c, 0x61, 0x4f, 0xfe, 0xc1, 0xc9, 0x8b, 0x05, - 0x92, 0x6f, 0x47, 0x96, 0xce, 0xf0, 0x33, 0xfa, 0x7c, 0x78, 0x24, 0x9b, - 0xd7, 0x8d, 0x36, 0x56, 0x37, 0x86, 0xbc, 0x72, 0x5a, 0xf9, 0xb9, 0xb0, - 0x93, 0xf0, 0x81, 0x78, 0x10, 0xf2, 0xb0, 0xc2, 0x79, 0x91, 0x5e, 0xcf, - 0xbc, 0x8c, 0xf2, 0x32, 0x0f, 0xf7, 0x2d, 0x30, 0xd8, 0x13, 0x77, 0x4f, - 0x78, 0x9e, 0x40, 0x8d, 0xe6, 0x3a, 0x98, 0xb2, 0xaa, 0x13, 0x4d, 0x25, - 0x49, 0x34, 0x6c, 0x80, 0x9e, 0x19, 0x03, 0xdb, 0xcd, 0xf5, 0xb1, 0x54, - 0x74, 0x1b, 0x67, 0x3c, 0x46, 0xac, 0x3e, 0x5d, 0xa2, 0xd9, 0x13, 0x83, - 0x30, 0xeb, 0x82, 0x3b, 0x06, 0xab, 0x3c, 0x39, 0x7d, 0xd0, 0x68, 0x31, - 0x00 -}; - -const size_t kOEMPublicCertSize_Prod = sizeof(kOEMPublicCert_Prod); - -// 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 diff --git a/libwvdrmengine/oemcrypto/ref/src/oem_cert.h b/libwvdrmengine/oemcrypto/ref/src/oem_cert.h deleted file mode 100644 index 3d0476b9..00000000 --- a/libwvdrmengine/oemcrypto/ref/src/oem_cert.h +++ /dev/null @@ -1,21 +0,0 @@ -// This header is used to access the OEM certificate if one is in use. -#ifndef OEM_CERT_H_ -#define OEM_CERT_H_ - -#include -#include - -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_ diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.cpp deleted file mode 100644 index 5b92ee0a..00000000 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.cpp +++ /dev/null @@ -1,447 +0,0 @@ -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine -// License Agreement. -// -// Reference implementation of OEMCrypto APIs -// -#include "oemcrypto_auth_ref.h" - -#include - -#include -#include - -#include "keys.h" -#include "log.h" - -namespace wvoec_ref { -namespace { - -// Fake device ID which is to be returned inplace of a real ID. -const std::string kFakeDeviceId = "device_with_no_keybox"; - -// 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 - -bool AuthenticationRoot::Initialize(OEMCrypto_ProvisioningMethod method) { - if (prov_method_ != OEMCrypto_ProvisioningError) { - // If provisioning method is something other than ProvisioningError - // indicates it has already been initialized before. Must - // existing data. - drm_cert_key_.reset(); - test_drm_cert_key_.reset(); - keybox_.reset(); - test_keybox_.reset(); - oem_cert_.reset(); - oem_cert_key_.reset(); - } - prov_method_ = method; - switch (method) { - case OEMCrypto_DrmCertificate: { - std::unique_ptr key = - RsaPrivateKey::Load(kPrivateKey, kPrivateKeySize); - if (key) { - drm_cert_key_ = std::move(key); - } else { - // 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."); - } - return true; - } - case OEMCrypto_Keybox: - case OEMCrypto_OEMCertificate: - // Nothing to do yet. - return true; - case OEMCrypto_ProvisioningError: - default: { - LOGE("Invalid provisioning method: method = %d", - static_cast(method)); - prov_method_ = OEMCrypto_ProvisioningError; - return false; - } - } -} - -bool AuthenticationRoot::IsValid() const { - switch (prov_method_) { - case OEMCrypto_DrmCertificate: { - return HasDrmCertKey() && HasDeviceKey(); - } - case OEMCrypto_Keybox: { - return HasDeviceKey(); - } - case OEMCrypto_OEMCertificate: { - return HasOemCertKey() && HasDeviceKey(); - } - default: { - LOGE("Root of trust is not properly initialized"); - return false; - } - } -} - -OEMCryptoResult AuthenticationRoot::IsKeyboxOrOemCertValid() const { - switch (prov_method_) { - case OEMCrypto_Keybox: { - WvKeybox* kb = keybox(); - if (kb == nullptr) { - LOGW("Null keybox cannot be validated"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - return kb->IsKeyboxValid(); - } - case OEMCrypto_OEMCertificate: { - if (!oem_cert_) { - LOGW("OEM cert is not installed"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - return oem_cert_->IsCertificateValid(); - } - case OEMCrypto_DrmCertificate: { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - default: - LOGE("Root of trust is not properly initialized"); - return OEMCrypto_ERROR_SYSTEM_INVALIDATED; - } -} - -OEMCryptoResult AuthenticationRoot::GetDeviceId( - uint8_t* device_id, size_t* device_id_length) const { - WvKeybox* kb = keybox(); - if (kb != nullptr) { - return kb->GetDeviceId(device_id, device_id_length); - } - if (prov_method_ == OEMCrypto_Keybox) { - // Keybox devices must have keybox for the source of the device - // ID. - LOGE("Expected keybox to be set for a device ID"); - return OEMCrypto_ERROR_NO_DEVICEID; - } - // For non-Keybox devices use fake device ID. - if (device_id_length == nullptr) { - LOGE("Output device ID length is null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (device_id == nullptr && *device_id_length > 0) { - LOGE("Output device ID buffer is null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (*device_id_length < kFakeDeviceId.size()) { - *device_id_length = kFakeDeviceId.size(); - return OEMCrypto_ERROR_SHORT_BUFFER; - } - *device_id_length = kFakeDeviceId.size(); - memcpy(device_id, kFakeDeviceId.data(), kFakeDeviceId.size()); - return OEMCrypto_SUCCESS; -} - -std::vector AuthenticationRoot::DeviceId() const { - WvKeybox* kb = keybox(); - if (kb != nullptr) { - return kb->DeviceId(); - } - if (prov_method_ == OEMCrypto_Keybox) { - LOGE("Expected keybox to be set for a device ID"); - return std::vector(); - } - return std::vector(kFakeDeviceId.begin(), kFakeDeviceId.end()); -} - -std::vector AuthenticationRoot::DeviceKey() const { - WvKeybox* kb = keybox(); - if (kb != nullptr) { - return kb->DeviceKey(); - } - LOGE("No device key has been set"); - return std::vector(); -} - -bool AuthenticationRoot::HasDeviceKey() const { return keybox() != nullptr; } - -void AuthenticationRoot::Clear() { - RemoveTestRsaKey(); - RemoveTestKeybox(); -} - -OEMCryptoResult AuthenticationRoot::LoadTestRsaKey() { - if (prov_method_ != OEMCrypto_DrmCertificate) { - LOGE("System does not support DRM certificates"); - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - if (test_drm_cert_key_) { - LOGE("Test RSA key is already loaded"); - return OEMCrypto_ERROR_INSUFFICIENT_RESOURCES; - } - std::unique_ptr key = - RsaPrivateKey::Load(kTestRSAPKCS8PrivateKeyInfo2_2048, - sizeof(kTestRSAPKCS8PrivateKeyInfo2_2048)); - if (!key) { - LOGE("Failed to load test RSA key"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - test_drm_cert_key_ = std::move(key); - return OEMCrypto_SUCCESS; -} - -OEMCryptoResult AuthenticationRoot::IsKeyboxValid() const { - WvKeybox* kb = keybox(); - if (kb == nullptr) { - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - return kb->IsKeyboxValid(); -} - -OEMCryptoResult AuthenticationRoot::InstallKeybox(const uint8_t* keybox_data, - size_t keybox_length) { - if (keybox_) { - LOGE("Keybox already installed"); - return OEMCrypto_ERROR_INSUFFICIENT_RESOURCES; - } - const OEMCryptoResult result = - WvKeybox::ValidateData(keybox_data, keybox_length); - if (result != OEMCrypto_SUCCESS) { - LOGE("Cannot install an invalid keybox"); - return result; - } - keybox_ = WvKeybox::Create(keybox_data, keybox_length); - return OEMCrypto_SUCCESS; -} - -OEMCryptoResult AuthenticationRoot::InstallTestKeybox( - const uint8_t* keybox_data, size_t keybox_length) { - if (prov_method_ != OEMCrypto_Keybox) { - LOGE("System does not support keybox"); - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - if (test_keybox_) { - LOGE("Test keybox already installed"); - return OEMCrypto_ERROR_INSUFFICIENT_RESOURCES; - } - const OEMCryptoResult result = - WvKeybox::ValidateData(keybox_data, keybox_length); - if (result != OEMCrypto_SUCCESS) { - LOGE("Cannot install an invalid test keybox"); - return result; - } - test_keybox_ = WvKeybox::Create(keybox_data, keybox_length); - return OEMCrypto_SUCCESS; -} - -OEMCryptoResult AuthenticationRoot::GetKeyData(uint8_t* key_data, - size_t* key_data_length) const { - if (prov_method_ != OEMCrypto_Keybox) { - LOGE("System does not support keybox"); - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - WvKeybox* kb = keybox(); - if (kb == nullptr) { - LOGE("No keybox to be set for source of key data"); - return OEMCrypto_ERROR_NO_KEYDATA; - } - return kb->GetKeyData(key_data, key_data_length); -} - -OEMCryptoResult AuthenticationRoot::InstallOemCertificate( - const uint8_t* private_key, size_t private_key_size, - const uint8_t* public_cert, size_t public_cert_size) { - if (prov_method_ != OEMCrypto_OEMCertificate) { - LOGE("System does not support OEM certificates"); - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - if (oem_cert_ || oem_cert_key_) { - LOGE("OEM certificate is already installed"); - return OEMCrypto_ERROR_INSUFFICIENT_RESOURCES; - } - std::unique_ptr oem_cert = OemCertificate::Create( - private_key, private_key_size, public_cert, public_cert_size); - if (!oem_cert) { - LOGE("Failed to install OEM certificate as root of trust"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (oem_cert->key_type() != OemCertificate::kRsa) { - LOGE("Only RSA-based OEM certificates supported"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - std::unique_ptr oem_cert_key = - RsaPrivateKey::Load(oem_cert->GetPrivateKey()); - if (!oem_cert_key) { - LOGE("Failed to parse OEM certificate private key"); - return OEMCrypto_ERROR_INVALID_RSA_KEY; - } - oem_cert_ = std::move(oem_cert); - oem_cert_key_ = std::move(oem_cert_key); - return OEMCrypto_SUCCESS; -} - -OEMCryptoResult AuthenticationRoot::GetOemPublicCertificate( - uint8_t* public_cert, size_t* public_cert_length) const { - if (prov_method_ != OEMCrypto_OEMCertificate) { - LOGE("System does not support OEM certificates"); - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - if (!oem_cert_) { - LOGE("OEM certificate is not installed"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - return oem_cert_->GetPublicCertificate(public_cert, public_cert_length); -} -} // namespace wvoec_ref diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.h b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.h deleted file mode 100644 index c2a88dcd..00000000 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.h +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine -// License Agreement. -// -// Reference implementation of OEMCrypto APIs -// -#ifndef OEMCRYPTO_AUTH_REF_H_ -#define OEMCRYPTO_AUTH_REF_H_ - -#include - -#include -#include - -#include "OEMCryptoCENC.h" // Needed for enums only. -#include "disallow_copy_and_assign.h" -#include "oemcrypto_keybox_ref.h" -#include "oemcrypto_oem_cert.h" -#include "oemcrypto_rsa_key.h" - -namespace wvoec_ref { -// The AuthenticationRoot class contains the OEMCrypto information -// which makes up the "root of trust" of a device. -class AuthenticationRoot { - public: - AuthenticationRoot() {} - ~AuthenticationRoot() {} - - // Initializes the root of authentication for the provided - // |method|. This will clear any previously initialied data. - bool Initialize(OEMCrypto_ProvisioningMethod method); - - // General root of trust API. - - // Checks that the auth root has been properly initialized and can - // be used by the rest of OEMCrypto for the current provisioning - // method. - bool IsValid() const; - - // Checks the validity of the underlying Keybox or OEM Certificate - // depending on the provisioning method. - // Similar to the expected behavior of OEMCrypto_IsKeyboxOrOEMCertValid(). - OEMCryptoResult IsKeyboxOrOemCertValid() const; - - // Gets the device ID from the root of trust. - // Similar to the expected behavior of OEMCrypto_GetDeviceID(). - OEMCryptoResult GetDeviceId(uint8_t* device_id, - size_t* device_id_length) const; - - // Returns the device ID from the root of trust. Intended to be used - // for core message generation. - std::vector DeviceId() const; - - // Returns the device key from the root of trust. For keybox-based - // devices, this is the device key from the keybox (or test keybox - // if installed). For devices that use a non-keybox provisioning - // method, this will be a device specific key. - std::vector DeviceKey() const; - - // Check for the existence of a device key. - bool HasDeviceKey() const; - - // Clears any test data inside this root of trust. - void Clear(); - - // DRM Certificate-based root of trust API. - - // Returns the shared RSA private key from the built-in DRM - // Certificate. - std::shared_ptr ShareDrmCertKey() { - return test_drm_cert_key_ ? test_drm_cert_key_ : drm_cert_key_; - } - RsaPrivateKey* DrmCertKey() const { - return test_drm_cert_key_ ? test_drm_cert_key_.get() : drm_cert_key_.get(); - } - bool HasDrmCertKey() const { return test_drm_cert_key_ || drm_cert_key_; } - - // Loads the system's built-in RSA key. Only implemented for - // devices that are that pre-provisioned with a built-in DRM - // Certificate, - // This method implements the expected behavior of - // OEMCrypto_LoadTestRSAKey(). - OEMCryptoResult LoadTestRsaKey(); - - // Removes any installed test RSA key. - void RemoveTestRsaKey() { test_drm_cert_key_.reset(); } - - // Keybox-based root of trust API. - - // Returns the currently installed keybox (or test keybox) if any - // present. The test keybox takes priority over the standard. - WvKeybox* keybox() const { - return test_keybox_ ? test_keybox_.get() : keybox_.get(); - } - - // Checks the validity of the keybox regardless of the provisioning - // method. - OEMCryptoResult IsKeyboxValid() const; - - // Installs a clear WV keybox as the root of trust. - // A keybox can only be installed once, however, the provisioning - // method stated at initialization remains the same. - // - // This method is similar to the expected behavior of - // OEMCrypto_InstallKeyboxOrOEMCert() for keybox devices except - // that the keybox provided here must be decrypted before installing. - OEMCryptoResult InstallKeybox(const uint8_t* keybox_data, - size_t keybox_length); - - // Installs a clear test WV keybox. Only settable for devices that - // uses a keybox for provisioning. - // - // This method is similar to the expected behavior of - // OEMCrypto_LoadTestKeybox() for keybox devices except that - // the keybox provided here must be decrypted before installing. - OEMCryptoResult InstallTestKeybox(const uint8_t* keybox_data, - size_t keybox_length); - - // Removes any installed test keybox. - void RemoveTestKeybox() { test_keybox_.reset(); } - - // Gets the keybox key data. - // Implements the expected behavior of OEMCrypto_GetKeyData(). - OEMCryptoResult GetKeyData(uint8_t* key_data, size_t* key_data_length) const; - - // OEM Certificate-base root of trust API. - - // Installs an OEM certificate as the root of trust. The provided - // private key and public cert are parsed, but not validated. The - // private key will be made available for sessions to load. - OEMCryptoResult InstallOemCertificate(const uint8_t* private_key, - size_t private_key_size, - const uint8_t* public_cert, - size_t public_cert_size); - - // For OEM Cert-based devices, returns the OEM Public Certificate - // component of the OEM Certificate. - // This method implements the expected behavior of - // OEMCrypto_GetOEMPublicCertificate(). - OEMCryptoResult GetOemPublicCertificate(uint8_t* public_cert, - size_t* public_cert_length) const; - - // Returns the OEM private key. Intended to be used when loading - // the OEM private key into a session. - // Should only be called for devices that use OEM Certificates - // for provisioning. - std::shared_ptr ShareOemCertKey() { return oem_cert_key_; } - RsaPrivateKey* OemCertKey() const { return oem_cert_key_.get(); } - bool HasOemCertKey() const { return static_cast(oem_cert_key_); } - - private: - OEMCrypto_ProvisioningMethod prov_method_ = OEMCrypto_ProvisioningError; - - // DRM certificate. - // If no keybox, this is the private key of the baked-in DRM - // Certificate. - std::shared_ptr drm_cert_key_; - std::shared_ptr test_drm_cert_key_; - - // Keybox data. - std::unique_ptr keybox_; - std::unique_ptr test_keybox_; - - // OEM certificate. - std::unique_ptr oem_cert_; - std::shared_ptr oem_cert_key_; - - CORE_DISALLOW_COPY_AND_ASSIGN(AuthenticationRoot); -}; -} // namespace wvoec_ref - -#endif // OEMCRYPTO_AUTH_REF_H_ diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_ecc_key.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_ecc_key.cpp deleted file mode 100644 index c19f77c0..00000000 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_ecc_key.cpp +++ /dev/null @@ -1,782 +0,0 @@ -// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine License -// Agreement. -// -// Reference implementation of OEMCrypto APIs -// -#include "oemcrypto_ecc_key.h" - -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "log.h" -#include "scoped_object.h" - -namespace wvoec_ref { -namespace { -// Estimated max size (in bytes) of a serialized ECC key (public or -// private). These values are based on rough calculations for -// secp521r1 (largest of the supported curves) and should be slightly -// larger needed. -constexpr size_t kPrivateKeySize = 230; -constexpr size_t kPublicKeySize = 164; - -// 256 bit key, intended to be used with CMAC-AES-256. -constexpr size_t kEccSessionKeySize = 32; - -using ScopedBigNum = ScopedObject; -using ScopedBigNumCtx = ScopedObject; -using ScopedEcKey = ScopedObject; -using ScopedSigPoint = ScopedObject; -using ScopedEvpMdCtx = ScopedObject; - -const EC_GROUP* GetEcGroup(EccCurve curve) { - // Creating a named EC_GROUP is an expensive operation, and they - // are always used in a manner which does not transfer ownership. - // Maintaining a process-wide set of supported EC groups reduces - // the overhead of group operations. - static std::mutex group_mutex; - static EC_GROUP* group_256 = nullptr; - static EC_GROUP* group_384 = nullptr; - static EC_GROUP* group_521 = nullptr; - std::lock_guard group_lock(group_mutex); - switch (curve) { - case kEccSecp256r1: { - if (group_256 == nullptr) { - LOGD("Creating secp256r1 group"); - // The curve secp256r1 was originally named prime256v1 - // in the X9.62 specification. - group_256 = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); - assert(group_256 != nullptr); - } - return group_256; - } - case kEccSecp384r1: { - if (group_384 == nullptr) { - LOGD("Creating secp384r1 group"); - group_384 = EC_GROUP_new_by_curve_name(NID_secp384r1); - assert(group_384 != nullptr); - } - return group_384; - } - case kEccSecp521r1: { - if (group_521 == nullptr) { - LOGD("Creating secp521r1 group"); - group_521 = EC_GROUP_new_by_curve_name(NID_secp521r1); - assert(group_521 != nullptr); - } - return group_521; - } - default: - LOGE("Cannot get EC group for unknown curve: curve = %d", - static_cast(curve)); - return nullptr; - } -} - -// Determines which of the supported ECC curves the provided |key| -// belongs to. -// -// This is intended to be used on keys that have been deserialized -// from an ASN.1 structure which may have contained a key which is -// supported by OpenSSL/BoringSSL but not necessarily by OEMCrypto. -// -// If the key group is unknown to OEMCrypto or if an error occurs, -// kEccCurveUnknown is returned. -EccCurve GetCurveFromKeyGroup(const EC_KEY* key) { - ScopedBigNumCtx ctx(BN_CTX_new()); - if (!ctx) { - LOGE("Failed to allocate BN ctx"); - return kEccCurveUnknown; - } - const EC_GROUP* group = EC_KEY_get0_group(key); - if (group == nullptr) { - LOGE("Provided key does not have a group"); - return kEccCurveUnknown; - } - int rc = EC_GROUP_cmp(group, GetEcGroup(kEccSecp256r1), ctx.get()); - if (rc == 0) { - return kEccSecp256r1; - } - if (rc == -1) { - LOGE("Error occurred while checking against secp256r1"); - return kEccCurveUnknown; - } - - rc = EC_GROUP_cmp(group, GetEcGroup(kEccSecp384r1), ctx.get()); - if (rc == 0) { - return kEccSecp384r1; - } - if (rc == -1) { - LOGE("Error occurred while checking against secp384r1"); - return kEccCurveUnknown; - } - - rc = EC_GROUP_cmp(group, GetEcGroup(kEccSecp521r1), ctx.get()); - if (rc == 0) { - return kEccSecp521r1; - } - if (rc == -1) { - LOGE("Error occurred while checking against secp521r1"); - return kEccCurveUnknown; - } - - LOGW("Unsupported curve group"); - return kEccCurveUnknown; -} - -// Compares the public EC points of both keys to see if they are the -// equal. -// Both |public_key| and |private_key| must be of the same group. -bool IsMatchingKeyPair(const EC_KEY* public_key, const EC_KEY* private_key) { - ScopedBigNumCtx ctx(BN_CTX_new()); - if (!ctx) { - LOGE("Failed to allocate BN ctx"); - return false; - } - // Returns: 1 if not equal, 0 if equal, -1 if error. - const int res = EC_POINT_cmp(EC_KEY_get0_group(public_key), - EC_KEY_get0_public_key(public_key), - EC_KEY_get0_public_key(private_key), ctx.get()); - if (res == -1) { - LOGE("Error occurred comparing keys"); - } - return res == 0; -} - -// Performs a SHA2 digest on the provided |message| and outputs the -// computed hash to |digest|. -// The digest algorithm used depends on which curve is used. -// - secp256r1 -> SHA-256 -// - secp384r1 -> SHA-384 -// - secp521r1 -> SHA-512 -// This function assumes that all parameters are valid. -// Returns true on success, false otherwise. -bool DigestMessage(EccCurve curve, const uint8_t* message, size_t message_size, - std::vector* digest) { - const EVP_MD* md_engine = nullptr; - switch (curve) { - case kEccSecp256r1: { - md_engine = EVP_sha256(); - break; - } - case kEccSecp384r1: { - md_engine = EVP_sha384(); - break; - } - case kEccSecp521r1: { - md_engine = EVP_sha512(); - break; - } - case kEccCurveUnknown: - // This case is to suppress compiler warnings. It will never - // occur. - break; - } - if (md_engine == nullptr) { - LOGE("Failed to get MD engine: curve = %d", static_cast(curve)); - return false; - } - - ScopedEvpMdCtx md_ctx(EVP_MD_CTX_new()); - if (!md_ctx) { - LOGE("Failed to create MD CTX"); - return false; - } - if (!EVP_DigestInit_ex(md_ctx.get(), md_engine, nullptr)) { - LOGE("Failed to init MD CTX"); - return false; - } - if (message_size > 0 && - !EVP_DigestUpdate(md_ctx.get(), message, message_size)) { - LOGE("Failed to update"); - return false; - } - digest->resize(EVP_MD_CTX_size(md_ctx.get()), 0); - const int res = EVP_DigestFinal_ex(md_ctx.get(), digest->data(), nullptr); - if (!res) { - LOGE("Failed to finalize"); - return false; - } - return true; -} - -// This KDF function is defined by OEMCrypto ECC specification. -// Function signature is based on the |kdf| parameter of -// ECDH_compute_key(). This function assumes that all pointer -// parameters are not null. -extern "C" void* WidevineEccKdf(const void* secret, size_t secret_length, - void* key, size_t* key_size) { - if (*key_size < kEccSessionKeySize) { - LOGE("Output buffer is too small: required = %zu, size = %zu", - kEccSessionKeySize, *key_size); - return nullptr; - } - std::vector digest; - if (!DigestMessage(kEccSecp256r1 /* SHA-256 */, - reinterpret_cast(secret), secret_length, - &digest)) { - LOGE("Cannot derive key: Failed to hash secret"); - return nullptr; - } - if (digest.size() != kEccSessionKeySize) { - LOGE("Unexpected hash size: actual = %zu, expected = %zu", digest.size(), - kEccSessionKeySize); - return nullptr; - } - *key_size = kEccSessionKeySize; - memcpy(key, digest.data(), *key_size); - return key; -} -} // namespace - -std::string EccCurveToString(EccCurve curve) { - switch (curve) { - case kEccSecp256r1: - return "secp256r1"; - case kEccSecp384r1: - return "secp384r1"; - case kEccSecp521r1: - return "secp521r1"; - case kEccCurveUnknown: - return "Unknown"; - } - return "Unknown(" + std::to_string(static_cast(curve)) + ")"; -} - -// static -std::unique_ptr EccPublicKey::New( - const EccPrivateKey& private_key) { - std::unique_ptr key(new EccPublicKey()); - if (!key->InitFromPrivateKey(private_key)) { - LOGE("Failed to initialize public key from private key"); - key.reset(); - } - return key; -} - -// static -std::unique_ptr EccPublicKey::Load(const uint8_t* buffer, - size_t length) { - std::unique_ptr key; - if (buffer == nullptr) { - LOGE("Provided public key buffer is null"); - return key; - } - if (length == 0) { - LOGE("Provided public key buffer is zero length"); - return key; - } - key.reset(new EccPublicKey()); - if (!key->InitFromBuffer(buffer, length)) { - LOGE("Failed to initialize public key from buffer"); - key.reset(); - } - return key; -} - -// static -std::unique_ptr EccPublicKey::Load(const std::string& buffer) { - if (buffer.empty()) { - LOGE("Provided public key buffer is empty"); - return std::unique_ptr(); - } - return Load(reinterpret_cast(buffer.data()), buffer.size()); -} - -// static -std::unique_ptr EccPublicKey::Load( - const std::vector& buffer) { - if (buffer.empty()) { - LOGE("Provided public key buffer is empty"); - return std::unique_ptr(); - } - return Load(buffer.data(), buffer.size()); -} - -bool EccPublicKey::IsMatchingPrivateKey( - const EccPrivateKey& private_key) const { - if (private_key.curve() != curve_) { - return false; - } - return IsMatchingKeyPair(GetEcKey(), private_key.GetEcKey()); -} - -OEMCryptoResult EccPublicKey::Serialize(uint8_t* buffer, - size_t* buffer_size) const { - if (buffer_size == nullptr) { - LOGE("Output buffer size is null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (buffer == nullptr && *buffer_size > 0) { - LOGE("Output buffer is null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - uint8_t* der_key = nullptr; - const int der_res = i2d_EC_PUBKEY(key_, &der_key); - if (der_res < 0) { - LOGE("Public key serialization failed"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (der_key == nullptr) { - LOGE("Encoded key is unexpectedly null"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (der_res == 0) { - LOGE("Unexpected DER encoded size"); - OPENSSL_free(der_key); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - const size_t required_size = static_cast(der_res); - if (buffer == nullptr || *buffer_size < required_size) { - *buffer_size = required_size; - OPENSSL_free(der_key); - return OEMCrypto_ERROR_SHORT_BUFFER; - } - memcpy(buffer, der_key, required_size); - *buffer_size = required_size; - OPENSSL_free(der_key); - return OEMCrypto_SUCCESS; -} - -std::vector EccPublicKey::Serialize() const { - size_t key_size = kPublicKeySize; - std::vector key_data(key_size, 0); - const OEMCryptoResult res = Serialize(key_data.data(), &key_size); - if (res != OEMCrypto_SUCCESS) { - LOGE("Failed to serialize public key: result = %d", static_cast(res)); - key_data.clear(); - } else { - key_data.resize(key_size); - } - return key_data; -} - -OEMCryptoResult EccPublicKey::VerifySignature(const uint8_t* message, - size_t message_length, - const uint8_t* signature, - size_t signature_length) const { - if (signature == nullptr || signature_length == 0) { - LOGE("Signature is missing"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (message == nullptr && message_length > 0) { - LOGE("Bad message data"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - // Step 1: Parse signature. - const uint8_t* tp = signature; - ScopedSigPoint sig_point(d2i_ECDSA_SIG(nullptr, &tp, signature_length)); - if (!sig_point) { - LOGE("Failed to parse signature"); - // Most likely an invalid signature than an OpenSSL error. - return OEMCrypto_ERROR_SIGNATURE_FAILURE; - } - // Step 2: Hash message - std::vector digest; - if (!DigestMessage(curve_, message, message_length, &digest)) { - LOGE("Failed to digest message"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - // Step 3: Verify signature - const int res = - ECDSA_do_verify(digest.data(), digest.size(), sig_point.get(), key_); - if (res == -1) { - LOGE("Error occurred checking signature"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (res == 0) { - LOGD("Signature did not match"); - return OEMCrypto_ERROR_SIGNATURE_FAILURE; - } - return OEMCrypto_SUCCESS; -} - -OEMCryptoResult EccPublicKey::VerifySignature( - const std::string& message, const std::string& signature) const { - if (signature.empty()) { - LOGE("Signature should not be empty"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - return VerifySignature( - reinterpret_cast(message.data()), message.size(), - reinterpret_cast(signature.data()), signature.size()); -} - -OEMCryptoResult EccPublicKey::VerifySignature( - const std::vector& message, - const std::vector& signature) const { - if (signature.empty()) { - LOGE("Signature should not be empty"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - return VerifySignature(message.data(), message.size(), signature.data(), - signature.size()); -} - -EccPublicKey::~EccPublicKey() { - if (key_ != nullptr) { - EC_KEY_free(key_); - key_ = nullptr; - } - curve_ = kEccCurveUnknown; -} - -bool EccPublicKey::InitFromBuffer(const uint8_t* buffer, size_t length) { - // Deserialize SubjectPublicKeyInfo - const uint8_t* tp = buffer; - ScopedEcKey key(d2i_EC_PUBKEY(nullptr, &tp, length)); - if (!key) { - LOGE("Failed to parse key"); - return false; - } - curve_ = GetCurveFromKeyGroup(key.get()); - if (curve_ == kEccCurveUnknown) { - LOGE("Failed to determine key group"); - return false; - } - // Required flags for IETF compliance. - EC_KEY_set_asn1_flag(key.get(), OPENSSL_EC_NAMED_CURVE); - EC_KEY_set_conv_form(key.get(), POINT_CONVERSION_UNCOMPRESSED); - key_ = key.release(); - return true; -} - -bool EccPublicKey::InitFromPrivateKey(const EccPrivateKey& private_key) { - ScopedEcKey key(EC_KEY_new()); - if (!key) { - LOGE("Failed to allocate key"); - return false; - } - if (!EC_KEY_set_group(key.get(), EC_KEY_get0_group(private_key.GetEcKey()))) { - LOGE("Failed to set group"); - return false; - } - if (!EC_KEY_set_public_key(key.get(), - EC_KEY_get0_public_key(private_key.GetEcKey()))) { - LOGE("Failed to set public point"); - return false; - } - curve_ = private_key.curve(); - // Required flags for IETF compliance. - EC_KEY_set_asn1_flag(key.get(), OPENSSL_EC_NAMED_CURVE); - EC_KEY_set_conv_form(key.get(), POINT_CONVERSION_UNCOMPRESSED); - key_ = key.release(); - return true; -} - -// static -std::unique_ptr EccPrivateKey::New(EccCurve curve) { - std::unique_ptr key(new EccPrivateKey()); - if (!key->InitFromCurve(curve)) { - LOGE("Failed to initialize private key from curve"); - key.reset(); - } - return key; -} - -// static -std::unique_ptr EccPrivateKey::Load(const uint8_t* buffer, - size_t length) { - std::unique_ptr key; - if (buffer == nullptr) { - LOGE("Provided private key buffer is null"); - return key; - } - if (length == 0) { - LOGE("Provided private key buffer is zero length"); - return key; - } - key.reset(new EccPrivateKey()); - if (!key->InitFromBuffer(buffer, length)) { - LOGE("Failed to initialize private key from buffer"); - key.reset(); - } - return key; -} - -// static -std::unique_ptr EccPrivateKey::Load(const std::string& buffer) { - if (buffer.empty()) { - LOGE("Provided private key buffer is empty"); - return std::unique_ptr(); - } - return Load(reinterpret_cast(buffer.data()), buffer.size()); -} - -// static -std::unique_ptr EccPrivateKey::Load( - const std::vector& buffer) { - if (buffer.empty()) { - LOGE("Provided private key buffer is empty"); - return std::unique_ptr(); - } - return Load(buffer.data(), buffer.size()); -} - -std::unique_ptr EccPrivateKey::MakePublicKey() const { - return EccPublicKey::New(*this); -} - -bool EccPrivateKey::IsMatchingPublicKey(const EccPublicKey& public_key) const { - if (public_key.curve() != curve_) { - return false; - } - return IsMatchingKeyPair(public_key.GetEcKey(), GetEcKey()); -} - -OEMCryptoResult EccPrivateKey::Serialize(uint8_t* buffer, - size_t* buffer_size) const { - if (buffer_size == nullptr) { - LOGE("Output buffer size is null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (buffer == nullptr && *buffer_size > 0) { - LOGE("Output buffer is null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - uint8_t* der_key = nullptr; - const int der_res = i2d_ECPrivateKey(key_, &der_key); - if (der_res < 0) { - LOGE("Private key serialization failed"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (der_key == nullptr) { - LOGE("Encoded key is unexpectedly null"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (der_res == 0) { - LOGE("Unexpected DER encoded size"); - OPENSSL_free(der_key); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - const size_t required_size = static_cast(der_res); - if (*buffer_size < required_size || buffer == nullptr) { - *buffer_size = required_size; - OPENSSL_free(der_key); - return OEMCrypto_ERROR_SHORT_BUFFER; - } - memcpy(buffer, der_key, required_size); - *buffer_size = required_size; - OPENSSL_free(der_key); - return OEMCrypto_SUCCESS; -} - -std::vector EccPrivateKey::Serialize() const { - size_t key_size = kPrivateKeySize; - std::vector key_data(key_size, 0); - const OEMCryptoResult res = Serialize(key_data.data(), &key_size); - if (res != OEMCrypto_SUCCESS) { - LOGE("Failed to serialize private key: result = %d", static_cast(res)); - key_data.clear(); - } else { - key_data.resize(key_size); - } - return key_data; -} - -OEMCryptoResult EccPrivateKey::GenerateSignature( - const uint8_t* message, size_t message_length, uint8_t* signature, - size_t* signature_length) const { - if (signature_length == nullptr) { - LOGE("Output signature size is null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (signature == nullptr && *signature_length > 0) { - LOGE("Output signature is null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (message == nullptr && message_length > 0) { - LOGE("Invalid message data"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - const size_t expected_signature_length = ECDSA_size(key_); - if (*signature_length < expected_signature_length) { - *signature_length = expected_signature_length; - return OEMCrypto_ERROR_SHORT_BUFFER; - } - - // Step 1: Hash message. - std::vector digest; - if (!DigestMessage(curve_, message, message_length, &digest)) { - LOGE("Failed to digest message"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - // Step 2: Generate signature point. - ScopedSigPoint sig_point(ECDSA_do_sign(digest.data(), digest.size(), key_)); - if (!sig_point) { - LOGE("Failed to perform ECDSA"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - // Step 3: Serialize - std::vector temp(expected_signature_length); - uint8_t* sig_ptr = temp.data(); - const int res = i2d_ECDSA_SIG(sig_point.get(), &sig_ptr); - if (res <= 0) { - LOGE("Failed to serialize signature"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - const size_t required_size = static_cast(res); - if (signature == nullptr || *signature_length < required_size) { - *signature_length = required_size; - return OEMCrypto_ERROR_SHORT_BUFFER; - } - memcpy(signature, temp.data(), required_size); - *signature_length = required_size; - return OEMCrypto_SUCCESS; -} - -std::vector EccPrivateKey::GenerateSignature( - const std::string& message) const { - size_t signature_size = SignatureSize(); - std::vector signature(signature_size, 0); - const OEMCryptoResult res = - GenerateSignature(reinterpret_cast(message.data()), - message.size(), signature.data(), &signature_size); - if (res != OEMCrypto_SUCCESS) { - LOGE("Failed to generate signature: result = %d", static_cast(res)); - signature.clear(); - } else { - signature.resize(signature_size); - } - return signature; -} - -std::vector EccPrivateKey::GenerateSignature( - const std::vector& message) const { - size_t signature_size = SignatureSize(); - std::vector signature(signature_size, 0); - const OEMCryptoResult res = GenerateSignature( - message.data(), message.size(), signature.data(), &signature_size); - if (res != OEMCrypto_SUCCESS) { - LOGE("Failed to generate signature: result = %d", static_cast(res)); - signature.clear(); - } else { - signature.resize(signature_size); - } - return signature; -} - -size_t EccPrivateKey::SignatureSize() const { return ECDSA_size(key_); } - -OEMCryptoResult EccPrivateKey::DeriveSessionKey( - const EccPublicKey& public_key, uint8_t* session_key, - size_t* session_key_size) const { - if (public_key.curve() != curve_) { - LOGE("Incompatible ECC keys: public = %s, private = %s", - EccCurveToString(public_key.curve()).c_str(), - EccCurveToString(curve_).c_str()); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (session_key_size == nullptr) { - LOGE("Output session key size buffer is null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (session_key == nullptr && *session_key_size > 0) { - LOGE("Output session key buffer is null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (*session_key_size < kEccSessionKeySize) { - *session_key_size = kEccSessionKeySize; - return OEMCrypto_ERROR_SHORT_BUFFER; - } - const int res = ECDH_compute_key( - session_key, kEccSessionKeySize, - EC_KEY_get0_public_key(public_key.GetEcKey()), key_, WidevineEccKdf); - if (res < 0) { - LOGE("ECDH error occurred"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (static_cast(res) != kEccSessionKeySize) { - LOGE("Unexpected key size: size = %d", res); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - *session_key_size = kEccSessionKeySize; - return OEMCrypto_SUCCESS; -} - -std::vector EccPrivateKey::DeriveSessionKey( - const EccPublicKey& public_key) const { - size_t session_key_size = kEccSessionKeySize; - std::vector session_key(session_key_size, 0); - const OEMCryptoResult res = - DeriveSessionKey(public_key, session_key.data(), &session_key_size); - if (res != OEMCrypto_SUCCESS) { - LOGE("Failed to derive session key: result = %d", static_cast(res)); - session_key.clear(); - } else { - session_key.resize(session_key_size); - } - return session_key; -} - -size_t EccPrivateKey::SessionKeyLength() const { return kEccSessionKeySize; } - -EccPrivateKey::~EccPrivateKey() { - if (key_ != nullptr) { - EC_KEY_free(key_); - key_ = nullptr; - } - curve_ = kEccCurveUnknown; -} - -bool EccPrivateKey::InitFromBuffer(const uint8_t* buffer, size_t length) { - // Deserialize ECPrivateKey - const uint8_t* tp = buffer; - ScopedEcKey key(d2i_ECPrivateKey(nullptr, &tp, length)); - if (!key) { - LOGE("Failed to parse key"); - return false; - } - curve_ = GetCurveFromKeyGroup(key.get()); - if (curve_ == kEccCurveUnknown) { - LOGE("Failed to determine key group"); - return false; - } - // Required flags for IETF compliance. - EC_KEY_set_asn1_flag(key.get(), OPENSSL_EC_NAMED_CURVE); - EC_KEY_set_conv_form(key.get(), POINT_CONVERSION_UNCOMPRESSED); - key_ = key.release(); - return true; -} - -bool EccPrivateKey::InitFromCurve(EccCurve curve) { - const EC_GROUP* group = GetEcGroup(curve); - if (group == nullptr) { - LOGE("Failed to get ECC group"); - return false; - } - ScopedEcKey key(EC_KEY_new()); - if (!key) { - LOGE("Failed to allocate key"); - return false; - } - if (!EC_KEY_set_group(key.get(), group)) { - LOGE("Failed to set group"); - return false; - } - // Generate random key. - if (!EC_KEY_generate_key(key.get())) { - LOGE("Failed to generate random key"); - return false; - } - curve_ = curve; - // Required flags for IETF compliance. - EC_KEY_set_asn1_flag(key.get(), OPENSSL_EC_NAMED_CURVE); - EC_KEY_set_conv_form(key.get(), POINT_CONVERSION_UNCOMPRESSED); - key_ = key.release(); - return true; -} - -} // namespace wvoec_ref diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_ecc_key.h b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_ecc_key.h deleted file mode 100644 index 442adc12..00000000 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_ecc_key.h +++ /dev/null @@ -1,245 +0,0 @@ -// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine License -// Agreement. -// -// Reference implementation of OEMCrypto APIs -// -#ifndef OEMCRYPTO_ECC_KEY_H_ -#define OEMCRYPTO_ECC_KEY_H_ - -#include -#include - -#include -#include -#include - -#include - -#include "OEMCryptoCENCCommon.h" - -namespace wvoec_ref { - -enum EccCurve { - kEccCurveUnknown = 0, - kEccSecp256r1 = 256, - kEccSecp384r1 = 384, - kEccSecp521r1 = 521 -}; - -// Returns the string representation of the provided curve. -// Intended for logging purposes. -std::string EccCurveToString(EccCurve curve); - -class EccPrivateKey; - -class EccPublicKey { - public: - // Creates a new public key equivalent of the provided private key. - static std::unique_ptr New(const EccPrivateKey& private_key); - - // Loads a serialized EC public key. - // The provided |buffer| must contain a valid ASN.1 DER encoded - // SubjectPublicKey. Only supported curves by this API are those - // enumerated by EccCurve. - // - // buffer: SubjectPublicKeyInfo = { - // algorithm: AlgorithmIdentifier = { - // algorithm: OID = id-ecPublicKey, - // parameters: ECParameters = { - // namedCurve: OID = secp256r1 | secp384r1 | secp521r1 - // } - // }, - // subjectPublicKey: BIT STRING = ... -- SEC1 encoded ECPoint - // } - // - // Failure will occur if the provided |buffer| does not contain a - // valid SubjectPublicKey, or if the specified curve is not - // supported. - static std::unique_ptr Load(const uint8_t* buffer, - size_t length); - static std::unique_ptr Load(const std::string& buffer); - static std::unique_ptr Load(const std::vector& buffer); - - EccCurve curve() const { return curve_; } - const EC_KEY* GetEcKey() const { return key_; } - - // Checks if the provided |private_key| is the EC private key of this - // public key. - bool IsMatchingPrivateKey(const EccPrivateKey& private_key) const; - - // Serializes the public key into an ASN.1 DER encoded SubjectPublicKey - // representation. - // On success, |buffer_size| is populated with the number of bytes - // written to |buffer|, and OEMCrypto_SUCCESS is returned. - // If the provided |buffer_size| is too small, ERROR_SHORT_BUFFER - // is returned and |buffer_size| is set to the required buffer size. - OEMCryptoResult Serialize(uint8_t* buffer, size_t* buffer_size) const; - // Same as above, except directly returns the serialized key. - // Returns an empty vector on error. - std::vector Serialize() const; - - // Verifies the |signature| matches the provided |message| by the - // private equivalent of this public key. - // The |signature| should be a valid ASN.1 DER encoded - // ECDSA-Sig-Value. - // This implementation uses ECDSA with the following digest - // algorithms for the supported curve types. - // - SHA-256 / secp256r1 - // - SHA-384 / secp384r1 (optional support) - // - SHA-512 / secp521r1 (optional support) - // Returns: - // OEMCrypto_SUCCESS if signature is valid - // OEMCrypto_ERROR_SIGNATURE_FAILURE if the signature is invalid - // Any other result indicates an unexpected error - OEMCryptoResult VerifySignature(const uint8_t* message, size_t message_length, - const uint8_t* signature, - size_t signature_length) const; - OEMCryptoResult VerifySignature(const std::string& message, - const std::string& signature) const; - OEMCryptoResult VerifySignature(const std::vector& message, - const std::vector& signature) const; - - ~EccPublicKey(); - - EccPublicKey(const EccPublicKey&) = delete; - EccPublicKey(EccPublicKey&&) = delete; - const EccPublicKey& operator=(const EccPublicKey&) = delete; - EccPublicKey& operator=(EccPublicKey&&) = delete; - - private: - EccPublicKey() {} - - // Initializes the public key object using the provided |buffer|. - // In case of any failure, false is return and the key should be - // discarded. - bool InitFromBuffer(const uint8_t* buffer, size_t length); - // Initializes the public key object from a private. - bool InitFromPrivateKey(const EccPrivateKey& private_key); - - // OpenSSL/BoringSSL implementation of an ECC key. - // As a public key, this will only have key point initialized. - EC_KEY* key_ = nullptr; - EccCurve curve_ = kEccCurveUnknown; -}; - -class EccPrivateKey { - public: - // Creates a new, pseudorandom ECC private key belonging to the - // curve specified. - static std::unique_ptr New(EccCurve curve); - - // Loads a serialized ECC private key. - // The provided |buffer| must contain a valid ASN.1 DER encoded - // ECPrivateKey. Only supported curves by this API are those - // enumerated by EccCurve. - // - // buffer: ECPrivateKey = { - // version: INTEGER = ecPrivateKeyVer1, - // privateKey: OCTET STRING = ..., -- I2OSP of private key point - // parameters: ECParameters = { - // namedCurve: OID = secp256r1 | secp384r1 | secp521r1 - // }, - // publicKey: BIT STRING OPTIONAL = ... -- SEC1 encoded ECPoint - // } - // Note: If the public key is not included, then it is computed from - // the private key. - // - // Failure will occur if the provided |buffer| does not contain a - // valid ECPrivateKey, or if the specified curve is not supported. - static std::unique_ptr Load(const uint8_t* buffer, - size_t length); - static std::unique_ptr Load(const std::string& buffer); - static std::unique_ptr Load( - const std::vector& buffer); - - // Creates a new ECC public key of this private key. - // Equivalent to calling EccPublicKey::New with this private - // key. - std::unique_ptr MakePublicKey() const; - - EccCurve curve() const { return curve_; } - const EC_KEY* GetEcKey() const { return key_; } - - // Checks if the provided |public_key| is the EC public key of this - // private key. - bool IsMatchingPublicKey(const EccPublicKey& public_key) const; - - // Serializes the private key into an ASN.1 DER encoded ECPrivateKey - // representation. - // On success, |buffer_size| is populated with the number of bytes - // written to |buffer|, and SUCCESS is returned. - // If the provided |buffer_size| is too small, - // OEMCrypto_ERROR_SHORT_BUFFER is returned and |buffer_size| is - // set to the required buffer size. - OEMCryptoResult Serialize(uint8_t* buffer, size_t* buffer_size) const; - // Same as above, except directly returns the serialized key. - // Returns an empty vector on error. - std::vector Serialize() const; - - // Signs the provided |message| and serializes the signature - // point to |signature| as a ASN.1 DER encoded ECDSA-Sig-Value. - // This implementation uses ECDSA with the following digest - // algorithms for the supported curve types. - // - SHA-256 / secp256r1 - // - SHA-384 / secp384r1 (optional support) - // - SHA-512 / secp521r1 (optional support) - // On success, |signature_length| is populated with the number of - // bytes written to |signature|, and SUCCESS is returned. - // If the provided |signature_length| is too small, - // OEMCrypto_ERROR_SHORT_BUFFER is returned and |signature_length| - // is set to the required signature size. - OEMCryptoResult GenerateSignature(const uint8_t* message, - size_t message_length, uint8_t* signature, - size_t* signature_length) const; - // Same as above, except directly returns the serialized signature. - // Returns an empty vector on error. - std::vector GenerateSignature( - const std::vector& message) const; - std::vector GenerateSignature(const std::string& message) const; - // Returns an upper bound for the signature size. May be larger than - // the actual signature generated by GenerateSignature(). - size_t SignatureSize() const; - - // Derives the OEMCrypto session key used for deriving other keys. - // The provided public key must be of the same curve. - // On success, |session_key_size| is populated with the number of - // bytes written to |session_key|, and OEMCrypto_SUCCESS is returned. - // If the provided |session_key_size| is too small, - // OEMCrypto_ERROR_SHORT_BUFFER is returned and |session_key_size| - // is set to the required buffer size. - OEMCryptoResult DeriveSessionKey(const EccPublicKey& public_key, - uint8_t* session_key, - size_t* session_key_size) const; - // Same as above, except directly returns the derived key. - std::vector DeriveSessionKey(const EccPublicKey& public_key) const; - // Returns the byte length of the symmetric key that would be derived - // by DeriveSymmetricKey(). - size_t SessionKeyLength() const; - - ~EccPrivateKey(); - - EccPrivateKey(const EccPrivateKey&) = delete; - EccPrivateKey(EccPrivateKey&&) = delete; - const EccPrivateKey& operator=(const EccPrivateKey&) = delete; - EccPrivateKey& operator=(EccPrivateKey&&) = delete; - - private: - EccPrivateKey() {} - - // Initializes the public key object using the provided |buffer|. - // In case of any failure, false is return and the key should be - // discarded. - bool InitFromBuffer(const uint8_t* buffer, size_t length); - // Generates a new key based on the provided curve. - bool InitFromCurve(EccCurve curve); - - // OpenSSL/BoringSSL implementation of an ECC key. - // The public point of the key will always be present. - EC_KEY* key_ = nullptr; - EccCurve curve_ = kEccCurveUnknown; -}; - -} // namespace wvoec_ref - -#endif // OEMCRYPTO_EC_KEY_H_ diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_device_properties.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_device_properties.cpp deleted file mode 100644 index 8c4bd22a..00000000 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_device_properties.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine -// License Agreement. -// -// Reference implementation of OEMCrypto APIs -// - -#include "oemcrypto_engine_ref.h" - -#include - -namespace wvoec_ref { - -CryptoEngine* CryptoEngine::MakeCryptoEngine( - std::unique_ptr&& file_system) { - return new CryptoEngine(std::move(file_system)); -} - -} // namespace wvoec_ref diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_device_properties_L1.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_device_properties_L1.cpp deleted file mode 100644 index 9e9b7c51..00000000 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_device_properties_L1.cpp +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine -// License Agreement. -// -// Reference implementation of OEMCrypto APIs -// -// This file contains oemcrypto engine properties that would be for a -// level 1 device. -#include "oemcrypto_engine_ref.h" - -#include - -namespace wvoec_ref { - -class L1CryptoEngine : public CryptoEngine { - public: - explicit L1CryptoEngine(std::unique_ptr&& file_system) - : CryptoEngine(std::move(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( - std::unique_ptr&& file_system) { - return new L1CryptoEngine(std::move(file_system)); -} - -} // namespace wvoec_ref diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_device_properties_cert.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_device_properties_cert.cpp deleted file mode 100644 index 146a8290..00000000 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_device_properties_cert.cpp +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine -// License Agreement. -// -// Reference 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(std::unique_ptr&& file_system) - : CryptoEngine(std::move(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( - std::unique_ptr&& file_system) { - return new CertOnlyCryptoEngine(std::move(file_system)); -} - -} // namespace wvoec_ref diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_device_properties_prov30.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_device_properties_prov30.cpp deleted file mode 100644 index d2115ca1..00000000 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_device_properties_prov30.cpp +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine -// License Agreement. -// -// Reference 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 - -#include - -#include "log.h" -#include "oem_cert.h" - -namespace wvoec_ref { - -class Prov30CryptoEngine : public CryptoEngine { - public: - explicit Prov30CryptoEngine(std::unique_ptr&& file_system) - : CryptoEngine(std::move(file_system)) {} - - bool Initialize() override { - if (!CryptoEngine::Initialize()) { - return false; - } - const OEMCryptoResult result = InstallOemCertificate( - kOEMPrivateKey, kOEMPrivateKeySize, kOEMPublicCert, kOEMPublicCertSize); - return result == OEMCrypto_SUCCESS; - } - - 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; - } - - // 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( - std::unique_ptr&& file_system) { - return new Prov30CryptoEngine(std::move(file_system)); -} - -} // namespace wvoec_ref diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.cpp deleted file mode 100644 index d0f5f581..00000000 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.cpp +++ /dev/null @@ -1,279 +0,0 @@ -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine -// License Agreement. -// -// Reference implementation of OEMCrypto APIs -// -#include "oemcrypto_engine_ref.h" - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "clock.h" -#include "keys.h" -#include "log.h" -#include "oemcrypto_key_ref.h" -#include "string_conversions.h" - -namespace { - -// Lower bits in SessionId are actual session id. The rest higher bits are -// session type. -const uint32_t kSessionIdTypeShift = 28; -const uint32_t kSessionIdMask = (1u << kSessionIdTypeShift) - 1u; -} // namespace - -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(std::unique_ptr&& file_system) - : file_system_(std::move(file_system)), usage_table_() { - ERR_load_crypto_strings(); -} - -CryptoEngine::~CryptoEngine() { - ERR_free_strings(); -} - -bool CryptoEngine::Initialize() { - std::string file_path = GetUsageTimeFileFullPath(); - LoadOfflineTimeInfo(file_path); - usage_table_.reset(MakeUsageTable()); - return root_of_trust_.Initialize(config_provisioning_method()); -} - -void CryptoEngine::Terminate() { - std::string file_path = GetUsageTimeFileFullPath(); - SaveOfflineTimeInfo(file_path); - std::unique_lock lock(session_table_lock_); - ActiveSessions::iterator it; - for (it = sessions_.begin(); it != sessions_.end(); ++it) { - delete it->second; - } - sessions_.clear(); - root_of_trust_.Clear(); -} - -SessionId CryptoEngine::OpenSession() { - std::unique_lock lock(session_table_lock_); - static OEMCrypto_SESSION unique_id = 1; - SessionId id = ++unique_id; - // Check if too many sessions have been opened. - if (SessionTypeBits(id) != 0) { - return 0; - } - // Apply session type to higher bits. - id = (kSessionTypeOEMCrypto << kSessionIdTypeShift) | (id & kSessionIdMask); - sessions_[id] = MakeSession(id); - return id; -} - -SessionContext* CryptoEngine::MakeSession(SessionId sid) { - if (root_of_trust_.HasDrmCertKey()) { - return new SessionContext(this, sid, root_of_trust_.ShareDrmCertKey()); - } - return new SessionContext(this, sid); -} - -UsageTable* CryptoEngine::MakeUsageTable() { return new UsageTable(this); } - -bool CryptoEngine::DestroySession(SessionId sid) { - SessionContext* sctx = FindSession(sid); - std::unique_lock lock(session_table_lock_); - if (sctx) { - sessions_.erase(sid); - delete sctx; - return true; - } else { - return false; - } -} - -SessionContext* CryptoEngine::FindSession(SessionId sid) { - std::unique_lock lock(session_table_lock_); - ActiveSessions::iterator it = sessions_.find(sid); - if (it != sessions_.end()) { - return it->second; - } - return nullptr; -} - -int64_t CryptoEngine::MonotonicTime() { - // Use the monotonic clock for times that don't have to be stable across - // device boots. - int64_t now = - wvcdm::Clock().GetCurrentTime() + offline_time_info_.rollback_offset; - static int64_t then = now; - if (now < then) { - LOGW("Clock rollback detected: %ld seconds", then - now); - offline_time_info_.rollback_offset += then - now; - now = then; - } - then = now; - return now; -} - -int64_t CryptoEngine::SystemTime() { - const int64_t current_time = MonotonicTime(); - // Write time info to disk if kTimeInfoUpdateWindowInSeconds has elapsed since - // last write. - if (current_time - offline_time_info_.previous_time > - kTimeInfoUpdateWindowInSeconds) { - std::string file_path = GetUsageTimeFileFullPath(); - SaveOfflineTimeInfo(file_path); - } - return current_time; -} - -std::string CryptoEngine::GetUsageTimeFileFullPath() const { - std::string file_path; - // Note: file 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 file path is empty. - /*if (!wvcdm::Properties::GetDeviceFilesBasePath(wvcdm::kSecurityLevelL3, - &file_path)) { - LOGE("Unable to get base path"); - }*/ - return file_path + kStoredUsageTimeFileName; -} - -bool CryptoEngine::LoadOfflineTimeInfo(const std::string& file_path) { - memset(&offline_time_info_, 0, sizeof(TimeInfo)); - wvcdm::FileSystem* file_system = file_system_.get(); - if (file_system->Exists(file_path)) { - std::unique_ptr file = - file_system->Open(file_path, wvcdm::FileSystem::kReadOnly); - if (!file) { - // This error is expected at first initialization. - LOGE("File open failed (this is expected on first initialization): %s", - file_path.c_str()); - return false; - } - // Load time info from previous call. - file->Read(reinterpret_cast(&offline_time_info_), sizeof(TimeInfo)); - - // Detect offline time rollback after loading from disk. - // Add any time offsets in the past to the current time. - int64_t current_time = MonotonicTime(); - if (offline_time_info_.previous_time > current_time) { - // Current time is earlier than the previously saved time. Time has been - // rolled back. Update the rollback offset. - offline_time_info_.rollback_offset += - offline_time_info_.previous_time - current_time; - // Keep current time at previous recorded time. - current_time = offline_time_info_.previous_time; - } - // The new previous_time will either stay the same or move forward. - offline_time_info_.previous_time = current_time; - } - return true; -} - -bool CryptoEngine::SaveOfflineTimeInfo(const std::string& file_path) { - // Add any time offsets in the past to the current time. If there was an - // earlier offline rollback, the rollback offset will be updated in - // LoadOfflineTimeInfo(). It guarantees that the current time to be saved - // will never go back. - const int64_t current_time = MonotonicTime(); - // The new previous_time will either stay the same or move forward. - if (current_time > offline_time_info_.previous_time) - offline_time_info_.previous_time = current_time; - - std::unique_ptr file; - wvcdm::FileSystem* file_system = file_system_.get(); - // Write the current time and offset to disk. - file = file_system->Open( - file_path, wvcdm::FileSystem::kCreate | wvcdm::FileSystem::kTruncate); - if (!file) { - LOGE("File open failed: %s", file_path.c_str()); - return false; - } - file->Write(reinterpret_cast(&offline_time_info_), sizeof(TimeInfo)); - return true; -} - -bool CryptoEngine::NonceCollision(uint32_t nonce) { - for (const auto& session_pair : sessions_) { - const SessionContext* session = session_pair.second; - if (nonce == session->nonce()) return true; - } - return false; -} - -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( - const 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.address_length; - break; - case OEMCrypto_BufferType_Secure: - if (out_description.buffer.secure.handle_length < - out_description.buffer.secure.offset) { - LOGE("Secure buffer offset too large: %zu < %zu", - out_description.buffer.secure.handle_length, - out_description.buffer.secure.offset); - return OEMCrypto_ERROR_SHORT_BUFFER; - } - destination_ = - reinterpret_cast(out_description.buffer.secure.handle) + - out_description.buffer.secure.offset; - max_length = out_description.buffer.secure.handle_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_ = nullptr; - break; - default: - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - const size_t max_allowed = max_sample_size(); - if (max_allowed > 0 && - (max_allowed < max_length || max_allowed < data_length)) { - LOGE("Output too large (or buffer too small)."); - return OEMCrypto_ERROR_OUTPUT_TOO_LARGE; - } - - 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_ == nullptr)) { - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - return OEMCrypto_SUCCESS; -} - -uint32_t CryptoEngine::SessionTypeBits(SessionId sid) { - return sid >> kSessionIdTypeShift; -} - -} // namespace wvoec_ref diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.h b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.h deleted file mode 100644 index f7f92c14..00000000 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.h +++ /dev/null @@ -1,271 +0,0 @@ -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine -// License Agreement. -// -// Reference implementation of OEMCrypto APIs -// -#ifndef REF_OEMCRYPTO_ENGINE_REF_H_ -#define REF_OEMCRYPTO_ENGINE_REF_H_ - -#include - -#include -#include -#include -#include - -#include "OEMCryptoCENC.h" -#include "file_store.h" -#include "oemcrypto_auth_ref.h" -#include "oemcrypto_key_ref.h" -#include "oemcrypto_session.h" -#include "oemcrypto_types.h" -#include "oemcrypto_usage_table_ref.h" - -namespace wvoec_ref { - -typedef std::map ActiveSessions; - -static const std::string kStoredUsageTimeFileName = "StoredUsageTime.dat"; - -typedef struct { - // The max time recorded - int64_t previous_time; - // If the wall time is rollbacked to before the previous_time, this member - // is updated to reflect the offset. - int64_t rollback_offset; - // Pad the struct so that TimeInfo is a multiple of 16. - uint8_t padding[16 - (2 * sizeof(time_t)) % 16]; -} TimeInfo; - -// Session types are higher (32 - kSessionIdTypeShift) bits in SessionId. -typedef enum SessionType { - kSessionTypeOEMCrypto = 0, - kSessionTypeEntitledKey = 1, -} SessionType; - -class CryptoEngine { - public: - static const uint32_t kApiVersion = 16; - static const uint32_t kMinorApiVersion = 3; - static const int64_t kTimeInfoUpdateWindowInSeconds = 300; - - // 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( - std::unique_ptr&& file_system); - - virtual ~CryptoEngine(); - - virtual bool Initialize(); - - bool ValidRootOfTrust() const { return root_of_trust_.IsValid(); } - - OEMCryptoResult InstallKeybox(const uint8_t* keybox, size_t keybox_length) { - return root_of_trust_.InstallKeybox(keybox, keybox_length); - } - - OEMCryptoResult InstallTestKeybox(const uint8_t* keybox_data, - size_t keybox_length) { - return root_of_trust_.InstallTestKeybox(keybox_data, keybox_length); - } - - OEMCryptoResult LoadTestRsaKey() { return root_of_trust_.LoadTestRsaKey(); } - - OEMCryptoResult IsKeyboxOrOemCertValid() const { - return root_of_trust_.IsKeyboxOrOemCertValid(); - } - - std::vector DeviceRootKey() const { - return root_of_trust_.DeviceKey(); - } - - OEMCryptoResult GetDeviceRootId(uint8_t* device_id, - size_t* device_id_length) const { - return root_of_trust_.GetDeviceId(device_id, device_id_length); - } - - std::vector DeviceRootId() const { - return root_of_trust_.DeviceId(); - } - - OEMCryptoResult GetRootKeyData(uint8_t* key_data, - size_t* key_data_length) const { - return root_of_trust_.GetKeyData(key_data, key_data_length); - } - - OEMCryptoResult InstallOemCertificate(const uint8_t* private_key, - size_t private_key_size, - const uint8_t* public_cert, - size_t public_cert_size) { - return root_of_trust_.InstallOemCertificate(private_key, private_key_size, - public_cert, public_cert_size); - } - - OEMCryptoResult GetOemPublicCertificate(uint8_t* public_cert, - size_t* public_cert_length) const { - return root_of_trust_.GetOemPublicCertificate(public_cert, - public_cert_length); - } - - std::shared_ptr ShareOemPrivateKey() { - return root_of_trust_.ShareOemCertKey(); - } - - bool HasOemPrivateKey() const { return root_of_trust_.HasOemCertKey(); } - - virtual void Terminate(); - - virtual SessionId OpenSession(); - - virtual 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; - } - - // The OEMCrypto system time. Prevents time rollback. - int64_t SystemTime(); - - // Verify that this nonce does not collide with another nonce in any session. - virtual bool NonceCollision(uint32_t nonce); - - // 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(); - - // Return true if there might be analog video output enabled. - virtual bool analog_display_active() { return !config_local_display_only(); } - - // Return true if there is an analog display, and CGMS A is turned on. - virtual bool cgms_a_active() { return false; } - - // Return the analog output flags. - virtual uint32_t analog_output_flags() { - return config_local_display_only() ? OEMCrypto_No_Analog_Output - : OEMCrypto_Supports_Analog_Output; - } - - UsageTable& usage_table() { return *(usage_table_.get()); } - 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; - } - - // 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 subsample size for - // DecryptCENC. This is not the same as the max sample or buffer size. - virtual size_t max_subsample_size() { return 4 * 1024 * 1024; } // 4 MiB - - // If 0 no restriction, otherwise it's the max sample size for DecryptCENC. - // This is the same as the max input and output buffer size for DecryptCENC - // and CopyBuffer. It is not the same as the max subsample size. - virtual size_t max_sample_size() { return 16 * 1024 * 1024; } // 16 MiB - - 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_forbidden_device_attached() { return false; } - - // Rate limit for nonce generation. Default to 200 nonce/second. - virtual int nonce_flood_count() { return 200; } - - // Limit for size of usage table. If this is zero, then the - // size is unlimited -- or limited only by memory size. - virtual size_t max_usage_table_size() { return 0; } - - virtual uint32_t resource_rating() { return 1; } - - // Set destination pointer based on the output destination description. - OEMCryptoResult SetDestination( - const 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( - const 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( - const OEMCrypto_DestBufferDesc& out_description, - uint8_t subsample_flags) { - return OEMCrypto_SUCCESS; - } - - // Get the session type bits from |sid|. - static uint32_t SessionTypeBits(SessionId sid); - - protected: - // System clock, measuring time in seconds, including anti-rollback offset. - int64_t MonotonicTime(); - - bool LoadOfflineTimeInfo(const std::string& file_path); - bool SaveOfflineTimeInfo(const std::string& file_path); - std::string GetUsageTimeFileFullPath() const; - - explicit CryptoEngine(std::unique_ptr&& file_system); - virtual SessionContext* MakeSession(SessionId sid); - virtual UsageTable* MakeUsageTable(); - uint8_t* destination_; - ActiveSessions sessions_; - AuthenticationRoot root_of_trust_; - std::mutex session_table_lock_; - std::unique_ptr file_system_; - std::unique_ptr usage_table_; - TimeInfo offline_time_info_; - - CORE_DISALLOW_COPY_AND_ASSIGN(CryptoEngine); -}; - -} // namespace wvoec_ref - -#endif // REF_OEMCRYPTO_ENGINE_REF_H_ diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_key_ref.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_key_ref.cpp deleted file mode 100644 index 19a80f28..00000000 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_key_ref.cpp +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine -// License Agreement. -// -// Reference implementation of OEMCrypto APIs -// -#include "oemcrypto_key_ref.h" -#include "oemcrypto_types.h" - -#include -#include - -#include "log.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 - memcmp(verification_, "kc15", 4) && // add in version 15 api - memcmp(verification_, "kc16", 4)) { // add in version 16 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& str, - int idx) { - int bidx = idx * 4; - uint32_t t = static_cast(str[bidx]) << 24; - t |= static_cast(str[bidx + 1]) << 16; - t |= static_cast(str[bidx + 2]) << 8; - t |= static_cast(str[bidx + 3]); - return t; -} - -KeyControlBlock::KeyControlBlock( - const std::vector& key_control_string) { - if (key_control_string.size() < wvoec::KEY_CONTROL_SIZE) { - LOGE("KCB: BAD Size: %zu (not %zu)", 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); - 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 diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_key_ref.h b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_key_ref.h deleted file mode 100644 index a94f24fb..00000000 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_key_ref.h +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine -// License Agreement. -// -// Reference implementation of OEMCrypto APIs -// -#ifndef OEMCRYPTO_KEY_REF_H_ -#define OEMCRYPTO_KEY_REF_H_ - -#include -#include -#include - -namespace wvoec_ref { - -class KeyControlBlock { - public: - KeyControlBlock(const std::vector& 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& 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& key_string, const KeyControlBlock& control) - : value_(key_string), control_(control), ctr_mode_(true){}; - - virtual ~Key() {}; - void UpdateDuration(const KeyControlBlock& control); - virtual const std::vector& 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 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) {} - ~EntitlementKey() override {} - const std::vector& value() const override { return content_key_; } - const std::vector& content_key() { return content_key_; } - const std::vector& content_key_id() { return content_key_id_; } - const std::vector& entitlement_key() { return Key::value(); } - bool SetContentKey(const std::vector& content_key_id, - const std::vector& 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 content_key_; - std::vector content_key_id_; -}; - -} // namespace wvoec_ref - -#endif // OEMCRYPTO_KEY_REF_H_ diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_keybox_ref.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_keybox_ref.cpp deleted file mode 100644 index 987a5103..00000000 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_keybox_ref.cpp +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine -// License Agreement. -// -// Reference implementation of OEMCrypto APIs -// -#include "oemcrypto_keybox_ref.h" - -#include - -#include -#include - -#include "log.h" -#include "oemcrypto_types.h" -#include "platform.h" -#include "wvcrc32.h" - -namespace wvoec_ref { -namespace { -constexpr size_t kKeyboxSize = 128; -constexpr size_t kDeviceIdSize = 32; -constexpr size_t kKeyDataSize = 72; -constexpr size_t kMagicOffset = 120; -const uint8_t kMagic[4] = {'k', 'b', 'o', 'x'}; -constexpr size_t kCrcKeyboxSize = 124; -constexpr size_t kCrcOffset = 124; - -static_assert(sizeof(wvoec::WidevineKeybox) == kKeyboxSize, - "Unexpected keybox size"); - -template -std::vector ToVector(const uint8_t (&field)[N]) { - return std::vector(field, &field[N]); -} -} // namespace - -// static -OEMCryptoResult WvKeybox::ValidateData(const uint8_t* keybox, - size_t keybox_length) { - if (keybox == nullptr) { - LOGE("Keybox data buffer is null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (keybox_length != kKeyboxSize) { - LOGE("Invalid keybox length: length = %zu", keybox_length); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - if (memcmp(&keybox[kMagicOffset], kMagic, sizeof(kMagic))) { - LOGE("Invalid keybox magic"); - return OEMCrypto_ERROR_BAD_MAGIC; - } - uint32_t crc_provided; - memcpy(&crc_provided, &keybox[kCrcOffset], sizeof(crc_provided)); - const uint32_t crc_computed = wvcrc32n(keybox, kCrcKeyboxSize); - if (crc_provided != crc_computed) { - LOGE("Invalid keybox CRC: provided = %08x, computed = %08x", crc_provided, - crc_computed); - return OEMCrypto_ERROR_BAD_CRC; - } - return OEMCrypto_SUCCESS; -} - -// static -std::unique_ptr WvKeybox::Create(const uint8_t* keybox_data, - size_t keybox_length) { - std::unique_ptr keybox; - if (keybox_length != kKeyboxSize) { - LOGE("Invalid keybox length: length = %zu", keybox_length); - return keybox; - } - keybox.reset(new WvKeybox()); - memcpy(reinterpret_cast(&keybox->raw_keybox_), keybox_data, - kKeyboxSize); - return keybox; -} - -OEMCryptoResult WvKeybox::GetDeviceId(uint8_t* device_id, - size_t* device_id_length) const { - if (device_id_length == nullptr) { - LOGE("Output device ID length buffer is null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (device_id == nullptr && *device_id_length > 0) { - LOGE("Output device ID buffer is null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (*device_id_length < kDeviceIdSize) { - *device_id_length = kDeviceIdSize; - return OEMCrypto_ERROR_SHORT_BUFFER; - } - *device_id_length = kDeviceIdSize; - memcpy(device_id, raw_keybox_.device_id_, kDeviceIdSize); - return OEMCrypto_SUCCESS; -} - -std::vector WvKeybox::DeviceId() const { - return ToVector(raw_keybox_.device_id_); -} - -std::vector WvKeybox::DeviceKey() const { - return ToVector(raw_keybox_.device_key_); -} - -OEMCryptoResult WvKeybox::GetKeyData(uint8_t* key_data, - size_t* key_data_length) const { - if (key_data_length == nullptr) { - LOGE("Output key data length buffer is null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (key_data == nullptr && *key_data_length > 0) { - LOGE("Output key data buffer is null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (*key_data_length < kKeyDataSize) { - *key_data_length = kKeyDataSize; - return OEMCrypto_ERROR_SHORT_BUFFER; - } - *key_data_length = kKeyDataSize; - memcpy(key_data, raw_keybox_.data_, kKeyDataSize); - return OEMCrypto_SUCCESS; -} - -OEMCryptoResult WvKeybox::IsKeyboxValid() const { - return ValidateData(reinterpret_cast(&raw_keybox_), - kKeyboxSize); -} - -} // namespace wvoec_ref diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_keybox_ref.h b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_keybox_ref.h deleted file mode 100644 index c9831c60..00000000 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_keybox_ref.h +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine -// License Agreement. -// -// Reference implementation of OEMCrypto APIs -// -#ifndef OEMCRYPTO_KEYBOX_REF_H_ -#define OEMCRYPTO_KEYBOX_REF_H_ - -#include -#include - -#include "OEMCryptoCENCCommon.h" -#include "oemcrypto_types.h" - -namespace wvoec_ref { - -// Widevine keybox -class WvKeybox { - public: - // Validates keybox data using the following rules: - // 1. Data is not null - // 2. Keybox size - // 3. Matching magic - // 4. CRC-32 check - static OEMCryptoResult ValidateData(const uint8_t* keybox_data, - size_t keybox_length); - - // Creates a keybox from the provided keybox data. - // Provided keybox data must be the proper length, but does - // not need to be valid. - // Once created, keyboxes are immutable. - static std::unique_ptr Create(const uint8_t* keybox_data, - size_t keybox_length); - - // Gets the device ID from the keybox. - // Similar to the expected behavior of OEMCrypto_GetDeviceID(). - OEMCryptoResult GetDeviceId(uint8_t* device_id, - size_t* device_id_length) const; - // Returns the keybox device ID directly. Intended to be used - // for core message generation. - std::vector DeviceId() const; - - // Returns the keybox device key directly. Intended to be used - // for key derivation. - std::vector DeviceKey() const; - - // Gets the keybox data. - // Similar to the expected behavior of OEMCrypto_GetKeyData(). - OEMCryptoResult GetKeyData(uint8_t* key_data, size_t* key_data_length) const; - - // Checks the current keybox instantiation that it is valid. - // Similar to the expected behavior of OEMCrypto_IsKeyboxValid(). - OEMCryptoResult IsKeyboxValid() const; - - ~WvKeybox() {} - - private: - WvKeybox() {} - - wvoec::WidevineKeybox raw_keybox_; -}; - -} // namespace wvoec_ref - -#endif // OEMCRYPTO_KEYBOX_REF_H_ diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_oem_cert.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_oem_cert.cpp deleted file mode 100644 index 21b2e0b8..00000000 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_oem_cert.cpp +++ /dev/null @@ -1,233 +0,0 @@ -// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine License -// Agreement. -// -// Reference implementation of OEMCrypto APIs -// -#include "oemcrypto_oem_cert.h" - -#include - -#include -#include -#include - -#include "log.h" -#include "oemcrypto_rsa_key.h" -#include "scoped_object.h" - -namespace wvoec_ref { -namespace { -using ScopedCertificate = ScopedObject; -using ScopedEvpKey = ScopedObject; -using ScopedPkcs7 = ScopedObject; - -constexpr size_t kExpectedCertCount = 2; // Leaf and intermediate. -constexpr int kDeviceCertIndex = 0; - -// Checks that the |public_key| from an X.509 certificate is the -// correct public key of the serialized |private_key_data|. -OEMCryptoResult VerifyRsaKey(const RSA* public_key, - const std::vector& private_key_data) { - if (public_key == nullptr) { - LOGE("RSA key is null"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - std::unique_ptr private_key = - RsaPrivateKey::Load(private_key_data); - if (!private_key) { - LOGE("Failed to parse provided RSA private key"); - return OEMCrypto_ERROR_INVALID_RSA_KEY; - } - if (!RsaKeysAreMatchingPair(public_key, private_key->GetRsaKey())) { - LOGE("OEM certificate keys do not match"); - return OEMCrypto_ERROR_INVALID_RSA_KEY; - } - return OEMCrypto_SUCCESS; -} -} // namespace - -// This utility class encapsulates the minimum functionality of an -// OEM Public Certificate required to verify a device's OEM Public -// Certificate. -class OemPublicCertificate { - public: - // Loads a PKCS #7 signedData message with certificate chain. - // Minimum validation is performed. Only checks that the - // device's public key is of a known type (RSA). - static std::unique_ptr Load(const uint8_t* public_cert, - size_t public_cert_size) { - std::unique_ptr oem_public_cert; - if (public_cert == nullptr) { - LOGE("Public cert buffer is null"); - return oem_public_cert; - } - if (public_cert_size == 0) { - LOGE("Public cert buffer is empty"); - return oem_public_cert; - } - oem_public_cert.reset(new OemPublicCertificate()); - if (!oem_public_cert->InitFromBuffer(public_cert, public_cert_size)) { - oem_public_cert.reset(); - } - return oem_public_cert; - } - - OemCertificate::KeyType key_type() const { return key_type_; } - const std::vector& cert_data() const { return cert_data_; } - - const RSA* GetPublicRsaKey() const { - return EVP_PKEY_get0_RSA(device_public_key_.get()); - } - - ~OemPublicCertificate() = default; - - OemPublicCertificate(const OemPublicCertificate&) = delete; - OemPublicCertificate(OemPublicCertificate&&) = delete; - const OemPublicCertificate& operator=(const OemPublicCertificate&) = delete; - OemPublicCertificate& operator=(OemPublicCertificate&&) = delete; - - private: - OemPublicCertificate() {} - - bool InitFromBuffer(const uint8_t* public_cert, size_t public_cert_size) { - // Step 1: Parse the PKCS7 certificate chain as signedData. - const uint8_t* public_cert_ptr = public_cert; - pkcs7_.reset(d2i_PKCS7(nullptr, &public_cert_ptr, public_cert_size)); - if (!pkcs7_) { - LOGE("Failed to parse PKCS#7 certificate chain"); - return false; - } - if (!PKCS7_type_is_signed(pkcs7_.get())) { - LOGE("OEM Public Certificate is not PKCS#7 signed data"); - return false; - } - PKCS7_SIGNED* signed_data = pkcs7_->d.sign; - // Step 2: Get the leaf certificate. - const size_t cert_count = - static_cast(sk_X509_num(signed_data->cert)); - if (cert_count != kExpectedCertCount) { - LOGE("Unexpected number of certificates: expected = %zu, actual = %zu", - kExpectedCertCount, cert_count); - return false; - } - X509* leaf_cert = sk_X509_value(signed_data->cert, kDeviceCertIndex); - // Step 3a: Get the device's public key. - device_public_key_.reset(X509_get_pubkey(leaf_cert)); - if (!device_public_key_) { - LOGE("Device X.509 certificate is missing a public key"); - return false; - } - // Step 3b: Check key type. - if (EVP_PKEY_get0_RSA(device_public_key_.get()) == nullptr) { - LOGE("Device public key is not RSA"); - return false; - } - key_type_ = OemCertificate::kRsa; - cert_data_.assign(public_cert, public_cert + public_cert_size); - return true; - } - - OemCertificate::KeyType key_type_ = OemCertificate::kNone; - // OpenSSL/BoringSSL's implementation of PKCS7 objects. - ScopedPkcs7 pkcs7_; - ScopedEvpKey device_public_key_; - std::vector cert_data_; -}; - -// ===== ===== ===== OEM Certificate ===== ===== ===== - -// static -std::unique_ptr OemCertificate::Create( - const uint8_t* private_key_data, size_t private_key_size, - const uint8_t* public_cert_data, size_t public_cert_size) { - std::unique_ptr oem_cert; - // Step 1: Verify public cert is well-formed. - std::unique_ptr oem_public_cert = - OemPublicCertificate::Load(public_cert_data, public_cert_size); - if (!oem_public_cert) { - LOGE("Invalid OEM Public Certificate"); - return oem_cert; - } - // Step 2: Verify private key is well-formed. - switch (oem_public_cert->key_type()) { - case kRsa: { - std::unique_ptr oem_private_key = - RsaPrivateKey::Load(private_key_data, private_key_size); - if (!oem_private_key) { - LOGE("Invalid OEM Private Key"); - return oem_cert; - } - } break; - case kNone: // Suppress compiler warnings. - return oem_cert; - } - // Step 3: Copy over data. - oem_cert.reset(new OemCertificate()); - oem_cert->private_key_.assign(private_key_data, - private_key_data + private_key_size); - oem_cert->public_cert_ = std::move(oem_public_cert); - return oem_cert; -} - -// static -std::unique_ptr OemCertificate::Create( - const std::vector& private_key, - const std::vector& public_cert) { - if (private_key.empty()) { - LOGE("Private key buffer is empty"); - return std::unique_ptr(); - } - if (public_cert.empty()) { - LOGE("Public cert buffer is empty"); - return std::unique_ptr(); - } - return Create(private_key.data(), private_key.size(), public_cert.data(), - public_cert.size()); -} - -OemCertificate::KeyType OemCertificate::key_type() const { - return public_cert_->key_type(); -} - -OEMCryptoResult OemCertificate::GetPublicCertificate( - uint8_t* public_cert, size_t* public_cert_length) const { - if (public_cert_length == nullptr) { - LOGE("Output |public_cert_length| is null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (public_cert == nullptr && *public_cert_length > 0) { - LOGE("Output |public_cert| is null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - const std::vector& cert_data = public_cert_->cert_data(); - if (*public_cert_length < cert_data.size()) { - *public_cert_length = cert_data.size(); - return OEMCrypto_ERROR_SHORT_BUFFER; - } - *public_cert_length = cert_data.size(); - memcpy(public_cert, cert_data.data(), cert_data.size()); - return OEMCrypto_SUCCESS; -} - -const std::vector& OemCertificate::GetPublicCertificate() const { - return public_cert_->cert_data(); -} - -OEMCryptoResult OemCertificate::IsCertificateValid() const { - switch (key_type()) { - case kRsa: - return VerifyRsaKey(public_cert_->GetPublicRsaKey(), private_key_); - case kNone: // Suppress compiler warnings. - break; - } - LOGE("Unexpected error key type: type = %d", static_cast(key_type())); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; -} - -// Constructor and destructor do not perform anything special, but -// must be declared within a scope which defines OemPublicCertificate. -OemCertificate::OemCertificate() {} -OemCertificate::~OemCertificate() {} - -} // namespace wvoec_ref diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_oem_cert.h b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_oem_cert.h deleted file mode 100644 index 70c7fffe..00000000 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_oem_cert.h +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine License -// Agreement. -// -// Reference implementation of OEMCrypto APIs -// -#ifndef OEMCRYPTO_OEM_CERT_H_ -#define OEMCRYPTO_OEM_CERT_H_ - -#include -#include - -#include "OEMCryptoCENCCommon.h" - -namespace wvoec_ref { - -class OemPublicCertificate; - -// An OEM Certificate is a factory provisioned root of trust -// certificate which consists of a public certificate and its -// matching private key. -// The public certificate must be an ASN.1 DER encoded PKCS #7 -// ContentInfo of type signedData (RFC2315). The device's X.509 -// certificate must be the first certificate in the chain of -// SignedContent |certificates|. -// The certificates are X.509 Certificate as defined in RFC 5280 -// signed by the device manufacturers certificate which is signed -// by Google. -// The OEM Public Cert should only contain the device's certificate -// and the OEM's intermediate certificate. -// The private key storage format is at the discretion of the OEM; -// the reference implementation uses PKCS8 PrivateKeyInfo. -class OemCertificate { - public: - enum KeyType { - kNone = 0, - // Private key is an ASN.1 DER encoded PrivateKeyInfo specifying - // an RSA encryption key. - kRsa = 1 - }; - - // Creates a new OEM Certificate and performs basic validation - // to ensure that the private key and public cert are well-formed. - // The |public_cert| provided is parsed as an X.509 Certificate - // and the public key is verified against the private key. - // The |private_key| is parsed depending on the key type. - // If any error occurs or if the provided data is malformed, an - // empty pointer is returned. - static std::unique_ptr Create(const uint8_t* private_key, - size_t private_key_size, - const uint8_t* public_cert, - size_t public_cert_size); - static std::unique_ptr Create( - const std::vector& private_key, - const std::vector& public_cert); - - // Returns the key type of the OEM Public key and private key. - // As of OEMCrypto v16, the only supported key type is RSA. - KeyType key_type() const; - - // Returns the private key data. Intended to be used for calls - // to OEMCrypto_LoadOEMPrivateKey(). - const std::vector& GetPrivateKey() const { return private_key_; } - - // Returns a copy of the ASN.1 DER encoded PKCS #7 certificate chain. - // If |*public_cert_length| is large enough, the complete - // certificate is copied to the buffer specified by |public_cert|, - // |*public_cert_length| is adjusted to the actual size of the - // certificate data, and SUCCESS is returned. - // If |*public_cert_length| is not large enough, then it is - // set to size of the certificate and ERROR_SHORT_BUFFER is - // returned. - OEMCryptoResult GetPublicCertificate(uint8_t* public_cert, - size_t* public_cert_length) const; - // Returns the certificate directly. Intended to be used for - // testing. - const std::vector& GetPublicCertificate() const; - - // Verifies that the RSA key included in the OEM Cert is valid. - // The existence of an OemCertificate already ensures that the - // OEM Public Certificate and private key data are well-formed. - // This takes the check another step further and ensures that - // the private key matches the public key in the public cert - // (ie, same modulos and public exponent). - OEMCryptoResult IsCertificateValid() const; - - ~OemCertificate(); - - OemCertificate(const OemCertificate&) = delete; - OemCertificate(OemCertificate&&) = delete; - const OemCertificate& operator=(const OemCertificate&) = delete; - OemCertificate& operator=(OemCertificate&&) = delete; - - private: - OemCertificate(); - - // Serialized private key matching the OEM certificate. - std::vector private_key_; - // Serialized OEM Certificate. - std::unique_ptr public_cert_; -}; -} // namespace wvoec_ref - -#endif // OEMCRYPTO_OEM_CERT_H_ diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_ref.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_ref.cpp deleted file mode 100644 index 6aa2f19e..00000000 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_ref.cpp +++ /dev/null @@ -1,1768 +0,0 @@ -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine -// License Agreement. -// -// Reference implementation of OEMCrypto APIs -// -#include "OEMCryptoCENC.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "file_store.h" -#include "log.h" -#include "odk.h" -#include "oemcrypto_engine_ref.h" -#include "oemcrypto_session.h" -#include "oemcrypto_usage_table_ref.h" -#include "string_conversions.h" - -#if defined(_WIN32) -# define OEMCRYPTO_API extern "C" __declspec(dllexport) -#else // defined(_WIN32) -# define OEMCRYPTO_API extern "C" __attribute__((visibility("default"))) -#endif // defined(_WIN32) - -namespace { -const uint8_t kBakedInCertificateMagicBytes[] = {0xDE, 0xAD, 0xBE, 0xEF}; -// Maximum context key length used for performance reasons, not mandated by -// specification. -const size_t kMaxContextKeyLength = 1024 * 1024; -// Maximum buffer length used by reference implementation for performance -// reasons. This is not mandated by specification. -const size_t kMaxInputMessageBuferLength = 1024 * 1024; -// Maximum signature length used by reference implementation for performance -// reasons. This is not mandated by specification. -const size_t kMaxInputSignatureLength = 10 * 1024; - -// Return uint32 referenced through a potentially unaligned pointer. -// If the pointer is nullptr, return 0. -uint32_t unaligned_dereference_uint32(const void* unaligned_ptr) { - if (unaligned_ptr == nullptr) return 0; - uint32_t value; - const uint8_t* src = reinterpret_cast(unaligned_ptr); - uint8_t* dest = reinterpret_cast(&value); - for (unsigned long i = 0; i < sizeof(value); i++) { - dest[i] = src[i]; - } - return value; -} - -} // namespace - -namespace wvoec_ref { - -static std::unique_ptr crypto_engine; - -typedef struct { - uint8_t signature[wvoec::MAC_KEY_SIZE]; - uint8_t context[wvoec::MAC_KEY_SIZE]; - uint8_t iv[wvoec::KEY_IV_SIZE]; - uint8_t enc_rsa_key[]; -} WrappedRSAKey; - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_Initialize(void) { - if (crypto_engine != nullptr) { - LOGE("------------------------- Calling Initialize without Terminate\n"); - crypto_engine.reset(); - } - // NOTE: This requires a compatible Filesystem implementation. - // NOTE: Ownership of the FileSystem object is transferred to CryptoEngine - std::unique_ptr fs(new wvcdm::FileSystem()); - crypto_engine.reset(CryptoEngine::MakeCryptoEngine(std::move(fs))); - if (crypto_engine == nullptr || !crypto_engine->Initialize()) { - LOGE("[OEMCrypto_Initialize(): failed]"); - return OEMCrypto_ERROR_INIT_FAILED; - } - return OEMCrypto_SUCCESS; -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_SetSandbox( - const uint8_t* /*sandbox_id*/, size_t /*sandbox_id_length*/) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_Terminate(void) { - if (crypto_engine == nullptr) { - LOGE("[OEMCrypto_Terminate(): not initialized]"); - return OEMCrypto_ERROR_TERMINATE_FAILED; - } - crypto_engine->Terminate(); - crypto_engine.reset(); - return OEMCrypto_SUCCESS; -} - -OEMCRYPTO_API OEMCryptoResult -OEMCrypto_OpenSession(OEMCrypto_SESSION* session) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_OpenSession: OEMCrypto not initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (crypto_engine->GetNumberOfOpenSessions() >= - crypto_engine->GetMaxNumberOfSessions()) { - LOGE("[OEMCrypto_OpenSession(): failed due to too many sessions]"); - return OEMCrypto_ERROR_TOO_MANY_SESSIONS; - } - SessionId sid = crypto_engine->OpenSession(); - if (sid == 0) { - LOGE("OEMCrypto_OpenSession: invalid session id returned."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - *session = (OEMCrypto_SESSION)sid; - return OEMCrypto_SUCCESS; -} - -OEMCRYPTO_API OEMCryptoResult -OEMCrypto_CloseSession(OEMCrypto_SESSION session) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_CloseSession: OEMCrypto not initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (!crypto_engine->DestroySession((SessionId)session)) { - return OEMCrypto_ERROR_CLOSE_SESSION_FAILED; - } else { - return OEMCrypto_SUCCESS; - } -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_GenerateDerivedKeys( - OEMCrypto_SESSION session, const uint8_t* mac_key_context, - size_t mac_key_context_length, const uint8_t* enc_key_context, - size_t enc_key_context_length) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_GenerateDerivedKeys: OEMCrypto not initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (crypto_engine->config_provisioning_method() != OEMCrypto_Keybox) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - if (!crypto_engine->ValidRootOfTrust()) { - LOGE("[OEMCrypto_GenerateDerivedKeys(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - if (mac_key_context_length > kMaxContextKeyLength || - enc_key_context_length > kMaxContextKeyLength) { - LOGE("[OEMCrypto_GenerateDerivedKeys(): ERROR_BUFFER_TOO_LARGE]"); - return OEMCrypto_ERROR_BUFFER_TOO_LARGE; - } - - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (session_ctx == nullptr || !session_ctx->isValid()) { - LOGE("[OEMCrypto_GenerateDerivedKeys(): ERROR_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - - const std::vector mac_ctx_str( - mac_key_context, mac_key_context + mac_key_context_length); - const std::vector enc_ctx_str( - enc_key_context, enc_key_context + enc_key_context_length); - - // Generate mac and encryption keys for current session context - return session_ctx->DeriveKeys(crypto_engine->DeviceRootKey(), mac_ctx_str, - enc_ctx_str); -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_GenerateNonce(OEMCrypto_SESSION session, - uint32_t* nonce) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_GenerateNonce: OEMCrypto not initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (session_ctx == nullptr || !session_ctx->isValid()) { - LOGE("[OEMCrypto_GenerateNonce(): ERROR_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - - // Prevent nonce flood. - static std::chrono::steady_clock clock; - const auto now = clock.now().time_since_epoch(); - static auto last_nonce_time = now; - // For testing, we set nonce_flood_count to 1. Since count is initialized to - // 1, the very first nonce after initialization is counted as a flood. - static int nonce_count = 1; - - if (now - last_nonce_time < std::chrono::seconds(1)) { - nonce_count++; - if (nonce_count > crypto_engine->nonce_flood_count()) { - LOGE("[OEMCrypto_GenerateNonce(): Nonce Flood detected]"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - } else { - nonce_count = 1; - last_nonce_time = now; - } - - uint32_t nonce_value = 0; - uint8_t* nonce_string = reinterpret_cast(&nonce_value); - - while (nonce_value == 0 || crypto_engine->NonceCollision(nonce_value)) { - // Generate 4 bytes of random data - if (RAND_bytes(nonce_string, 4) != 1) { - LOGE("[OEMCrypto_GenerateNonce(): Random bytes failure]"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - } - if (!session_ctx->set_nonce(nonce_value)) { - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - *nonce = nonce_value; - return OEMCrypto_SUCCESS; -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_PrepAndSignLicenseRequest( - OEMCrypto_SESSION session, uint8_t* message, size_t message_length, - size_t* core_message_length, uint8_t* signature, size_t* signature_length) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (session_ctx == nullptr || !session_ctx->isValid()) { - LOGE("OEMCrypto_ERROR_INVALID_SESSION"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - return session_ctx->PrepAndSignLicenseRequest(message, message_length, - core_message_length, signature, - signature_length); -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_PrepAndSignRenewalRequest( - OEMCrypto_SESSION session, uint8_t* message, size_t message_length, - size_t* core_message_length, uint8_t* signature, size_t* signature_length) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (session_ctx == nullptr || !session_ctx->isValid()) { - LOGE("OEMCrypto_ERROR_INVALID_SESSION"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - return session_ctx->PrepAndSignRenewalRequest(message, message_length, - core_message_length, signature, - signature_length); -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_PrepAndSignProvisioningRequest( - OEMCrypto_SESSION session, uint8_t* message, size_t message_length, - size_t* core_message_length, uint8_t* signature, size_t* signature_length) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (session_ctx == nullptr || !session_ctx->isValid()) { - LOGE("OEMCrypto_ERROR_INVALID_SESSION"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - return session_ctx->PrepAndSignProvisioningRequest( - message, message_length, core_message_length, signature, - signature_length); -} - -bool RangeCheck(const uint8_t* message, uint32_t message_length, - const uint8_t* field, uint32_t field_length, bool allow_null) { - if (field == nullptr) return allow_null; - if (field < message) return false; - if (field + field_length > message + message_length) return false; - return true; -} - -bool RangeCheck(uint32_t message_length, const OEMCrypto_Substring& substring, - bool allow_null) { - if (!substring.length) return allow_null; - if (substring.offset > message_length) return false; - if (substring.offset + substring.length > message_length) return false; - return true; -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_LoadLicense(OEMCrypto_SESSION session, - const uint8_t* message, - size_t message_length, - size_t core_message_length, - const uint8_t* signature, - size_t signature_length) { - if (crypto_engine == nullptr) { - LOGE("not initialized"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (message == nullptr || message_length == 0 || signature == nullptr || - signature_length == 0) { - LOGE("OEMCrypto_ERROR_INVALID_CONTEXT"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (!crypto_engine->ValidRootOfTrust()) { - LOGE("ERROR_KEYBOX_INVALID"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (session_ctx == nullptr || !session_ctx->isValid()) { - LOGE("ERROR_INVALID_SESSION sid=%u", session); - return OEMCrypto_ERROR_INVALID_SESSION; - } - return session_ctx->LoadLicense(message, message_length, core_message_length, - signature, signature_length); -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_LoadKeys( - OEMCrypto_SESSION session, const uint8_t* message, size_t message_length, - const uint8_t* signature, size_t signature_length, - OEMCrypto_Substring enc_mac_keys_iv, OEMCrypto_Substring enc_mac_keys, - size_t num_keys, const OEMCrypto_KeyObject* key_array, - OEMCrypto_Substring pst, OEMCrypto_Substring srm_restriction_data, - OEMCrypto_LicenseType license_type) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_LoadKeys: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (!crypto_engine->ValidRootOfTrust()) { - LOGE("ERROR_KEYBOX_INVALID"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (session_ctx == nullptr || !session_ctx->isValid()) { - LOGE("ERROR_INVALID_SESSION sid=%u", session); - return OEMCrypto_ERROR_INVALID_SESSION; - } - if (message == nullptr || message_length == 0 || signature == nullptr || - signature_length == 0 || key_array == nullptr || num_keys == 0) { - LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - // Range check - if (!RangeCheck(message_length, enc_mac_keys_iv, true) || - !RangeCheck(message_length, enc_mac_keys, true) || - !RangeCheck(message_length, pst, true) || - !RangeCheck(message_length, srm_restriction_data, true)) { - LOGE( - "[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_CONTEXT - " - "range check.]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - for (size_t i = 0; i < num_keys; i++) { - if (!RangeCheck(message_length, key_array[i].key_id, false) || - !RangeCheck(message_length, key_array[i].key_data, false) || - !RangeCheck(message_length, key_array[i].key_data_iv, false) || - !RangeCheck(message_length, key_array[i].key_control, false) || - !RangeCheck(message_length, key_array[i].key_control_iv, false)) { - LOGE( - "[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_CONTEXT - range " - "check %zu]", - i); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - } - if (enc_mac_keys.offset >= wvoec::KEY_IV_SIZE && enc_mac_keys.length > 0) { - if (enc_mac_keys_iv.offset + wvoec::KEY_IV_SIZE == enc_mac_keys.offset) { - LOGE( - "[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_CONTEXT - " - "range check iv]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } else { - if (CRYPTO_memcmp(message + enc_mac_keys.offset - wvoec::KEY_IV_SIZE, - message + enc_mac_keys_iv.offset, - wvoec::KEY_IV_SIZE) == 0) { - LOGE( - "[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_CONTEXT - " - "suspicious iv]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - } - } - return session_ctx->LoadKeys(message, message_length, signature, - signature_length, enc_mac_keys_iv, enc_mac_keys, - num_keys, key_array, pst, srm_restriction_data, - license_type); -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_LoadEntitledContentKeys( - OEMCrypto_SESSION session, const uint8_t* message, size_t message_length, - size_t key_array_length, - const OEMCrypto_EntitledContentKeyObject* key_array) { - if (key_array_length == 0) { - LOGE("[OEMCrypto_LoadEntitledContentKeys(): key_array is empty."); - return OEMCrypto_SUCCESS; - } - if (key_array == nullptr) { - LOGE("[OEMCrypto_LoadEntitledContentKeys(): missing key_array."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_LoadEntitledContentKeys: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (session_ctx == nullptr || !session_ctx->isValid()) { - LOGE("[OEMCrypto_LoadEntitledContentKeys(): ERROR_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - for (size_t i = 0; i < key_array_length; i++) { - if (!RangeCheck(message_length, key_array[i].entitlement_key_id, false) || - !RangeCheck(message_length, key_array[i].content_key_id, false) || - !RangeCheck(message_length, key_array[i].content_key_data_iv, false) || - !RangeCheck(message_length, key_array[i].content_key_data, false)) { - LOGE( - "[OEMCrypto_LoadEntitledContentKeys(): " - "OEMCrypto_ERROR_INVALID_CONTEXT -range " - "check %zu]", - i); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - } - return session_ctx->LoadEntitledContentKeys(message, message_length, - key_array_length, key_array); -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_LoadRenewal(OEMCrypto_SESSION session, - const uint8_t* message, - size_t message_length, - size_t core_message_length, - const uint8_t* signature, - size_t signature_length) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - - if (!crypto_engine->ValidRootOfTrust()) { - LOGE("ERROR_KEYBOX_INVALID"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (session_ctx == nullptr || !session_ctx->isValid()) { - LOGE("ERROR_INVALID_SESSION"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - - if (message == nullptr || message_length == 0 || signature == nullptr || - signature_length == 0) { - LOGE("ERROR_INVALID_CONTEXT"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - return session_ctx->LoadRenewal(message, message_length, core_message_length, - signature, signature_length); -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_RefreshKeys( - OEMCrypto_SESSION session, const uint8_t* message, size_t message_length, - const uint8_t* signature, size_t signature_length, size_t num_keys, - const OEMCrypto_KeyRefreshObject* key_array) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - - if (!crypto_engine->ValidRootOfTrust()) { - LOGE("ERROR_KEYBOX_INVALID"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (session_ctx == nullptr || !session_ctx->isValid()) { - LOGE("ERROR_INVALID_SESSION"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - - if (message == nullptr || message_length == 0 || signature == nullptr || - signature_length == 0 || num_keys == 0) { - LOGE("ERROR_INVALID_CONTEXT"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - // We only use the first key object to update the entire license. Since we - // know num_keys > 0 after the last if statement, we can assume index is not - // out of bounds. - constexpr size_t kIndex = 0; - - // Range check. - if (!RangeCheck(message_length, key_array[kIndex].key_id, true) || - !RangeCheck(message_length, key_array[kIndex].key_control, false) || - !RangeCheck(message_length, key_array[kIndex].key_control_iv, true)) { - LOGE("Range Check %zu", kIndex); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - // Validate message signature - if (!session_ctx->ValidateMessage(message, message_length, signature, - signature_length)) { - LOGE("Signature was invalid"); - return OEMCrypto_ERROR_SIGNATURE_FAILURE; - } - - // Decrypt and refresh keys in key refresh object - OEMCryptoResult status = OEMCrypto_SUCCESS; - std::vector key_id; - std::vector key_control; - std::vector key_control_iv; - if (key_array[kIndex].key_id.length != 0) { - key_id.assign(message + key_array[kIndex].key_id.offset, - message + key_array[kIndex].key_id.offset + - key_array[kIndex].key_id.length); - key_control.assign(message + key_array[kIndex].key_control.offset, - message + key_array[kIndex].key_control.offset + - wvoec::KEY_CONTROL_SIZE); - if (key_array[kIndex].key_control_iv.length == 0) { - key_control_iv.clear(); - } else { - key_control_iv.assign(message + key_array[kIndex].key_control_iv.offset, - message + key_array[kIndex].key_control_iv.offset + - wvoec::KEY_IV_SIZE); - } - } else { - // key_id could be null if special control key type - // key_control is not encrypted in this case - key_id.clear(); - key_control_iv.clear(); - key_control.assign(message + key_array[kIndex].key_control.offset, - message + key_array[kIndex].key_control.offset + - wvoec::KEY_CONTROL_SIZE); - } - - status = session_ctx->RefreshKey(key_id, key_control, key_control_iv); - if (status != OEMCrypto_SUCCESS) { - return status; - } - return OEMCrypto_SUCCESS; -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_QueryKeyControl( - OEMCrypto_SESSION session, const uint8_t* key_id, size_t key_id_length, - uint8_t* key_control_block, size_t* key_control_block_length) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_QueryKeyControl: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - uint32_t* block = reinterpret_cast(key_control_block); - if ((key_control_block_length == nullptr) || - (*key_control_block_length < wvoec::KEY_CONTROL_SIZE)) { - LOGE("[OEMCrypto_QueryKeyControl(): OEMCrypto_ERROR_SHORT_BUFFER]"); - return OEMCrypto_ERROR_SHORT_BUFFER; - } - *key_control_block_length = wvoec::KEY_CONTROL_SIZE; - if (key_id == nullptr) { - LOGE( - "[OEMCrypto_QueryKeyControl(): key_id null. " - "OEMCrypto_ERROR_UNKNOWN_FAILURE]"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (session_ctx == nullptr || !session_ctx->isValid()) { - LOGE("[OEMCrypto_QueryKeyControl(): ERROR_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - const std::vector key_id_str = - std::vector(key_id, key_id + key_id_length); - if (!session_ctx->QueryKeyControlBlock(key_id_str, block)) { - LOGE("[OEMCrypto_QueryKeyControl(): FAIL]"); - return OEMCrypto_ERROR_NO_CONTENT_KEY; - } - return OEMCrypto_SUCCESS; -} - -OEMCRYPTO_API OEMCryptoResult -OEMCrypto_SelectKey(const OEMCrypto_SESSION session, const uint8_t* key_id, - size_t key_id_length, OEMCryptoCipherMode cipher_mode) { -#ifndef NDEBUG - if (!crypto_engine->ValidRootOfTrust()) { - LOGE("[OEMCrypto_SelectKey(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } -#endif - - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (session_ctx == nullptr || !session_ctx->isValid()) { - LOGE("[OEMCrypto_SelectKey(): ERROR_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - - const std::vector key_id_str = - std::vector(key_id, key_id + key_id_length); - return session_ctx->SelectContentKey(key_id_str, cipher_mode); -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_DecryptCENC( - OEMCrypto_SESSION session, const OEMCrypto_SampleDescription* samples, - size_t samples_length, const OEMCrypto_CENCEncryptPatternDesc* pattern) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_DecryptCENC: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (samples == nullptr || samples_length == 0) { - LOGE("[OEMCrypto_DecryptCENC(): No samples]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (pattern == nullptr) { - LOGE("[OEMCrypto_DecryptCENC(): No pattern]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (session_ctx == nullptr || !session_ctx->isValid()) { - LOGE("[OEMCrypto_DecryptCENC(): ERROR_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - -#ifndef NDEBUG - if (!crypto_engine->ValidRootOfTrust()) { - LOGE("[OEMCrypto_DecryptCENC(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } -#endif - // The maximum subsample and sample sizes we use -- if 0, we just pick a - // very large size for a validity check. - const size_t max_subsample_size = crypto_engine->max_subsample_size() > 0 - ? crypto_engine->max_subsample_size() - : 100 * 1024 * 1024; - const size_t max_sample_size = crypto_engine->max_subsample_size() > 0 - ? crypto_engine->max_subsample_size() - : 1000 * 1024 * 1024; - // Iterate through all the samples and validate them before doing any decrypt - for (size_t sample_index = 0; sample_index < samples_length; ++sample_index) { - const OEMCrypto_SampleDescription& sample = samples[sample_index]; - - if (sample.buffers.input_data == nullptr || - sample.buffers.input_data_length == 0) { - LOGE("[OEMCrypto_DecryptCENC(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (crypto_engine->max_sample_size() > 0 && - sample.buffers.input_data_length > crypto_engine->max_sample_size()) { - // For testing reasons only, pretend that this integration only supports - // the given buffer size. - LOGE("[OEMCrypto_DecryptCENC(): Sample too large]"); - return OEMCrypto_ERROR_BUFFER_TOO_LARGE; - } - // Iterate through all the subsamples and sum their lengths - size_t subsample_length_tally = 0; - for (size_t subsample_index = 0; subsample_index < sample.subsamples_length; - ++subsample_index) { - const OEMCrypto_SubSampleDescription& subsample = - sample.subsamples[subsample_index]; - // Compute the length now, but we check for possible overflow in the next - // if statement. - const size_t length = - subsample.num_bytes_clear + subsample.num_bytes_encrypted; - if (subsample.num_bytes_clear > max_subsample_size || - subsample.num_bytes_encrypted > max_subsample_size || - length > max_subsample_size || - subsample_length_tally > max_sample_size) { - // For testing reasons only, pretend that this integration only supports - // the given buffer size. - LOGE("[OEMCrypto_DecryptCENC(): Subsample too large]"); - return OEMCrypto_ERROR_BUFFER_TOO_LARGE; - } - subsample_length_tally += length; - } - if (subsample_length_tally != sample.buffers.input_data_length) { - LOGE( - "[OEMCrypto_DecryptCENC(): Sample and subsample lengths do not " - "match.]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - } - - return session_ctx->DecryptSamples(samples, samples_length, pattern); -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_CopyBuffer( - OEMCrypto_SESSION session, const uint8_t* data_addr, size_t data_length, - const OEMCrypto_DestBufferDesc* out_buffer_descriptor, - uint8_t subsample_flags) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_CopyBuffer: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (data_addr == nullptr || out_buffer_descriptor == nullptr) { - LOGE("[OEMCrypto_CopyBuffer(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (crypto_engine->max_subsample_size() > 0 && - data_length > crypto_engine->max_subsample_size()) { - // For testing reasons only, pretend that this integration only supports - // the minimum possible buffer size. - LOGE("[OEMCrypto_CopyBuffer(): OEMCrypto_ERROR_BUFFER_TOO_LARGE]"); - return OEMCrypto_ERROR_BUFFER_TOO_LARGE; - } - OEMCryptoResult status = crypto_engine->SetDestination( - *out_buffer_descriptor, data_length, subsample_flags); - if (status != OEMCrypto_SUCCESS) return status; - if (crypto_engine->destination() != nullptr) { - memmove(crypto_engine->destination(), data_addr, data_length); - } - return crypto_engine->PushDestination(*out_buffer_descriptor, - subsample_flags); -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_WrapKeyboxOrOEMCert( - const uint8_t* keybox, size_t keyBoxLength, uint8_t* wrappedKeybox, - size_t* wrappedKeyBoxLength, const uint8_t* transportKey, - size_t transportKeyLength) { - if (crypto_engine->config_provisioning_method() != OEMCrypto_Keybox) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - if (!keybox || !wrappedKeybox || !wrappedKeyBoxLength || - (keyBoxLength != *wrappedKeyBoxLength)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - // This implementation ignores the transport key. For test keys, we - // don't need to encrypt the keybox. - memcpy(wrappedKeybox, keybox, keyBoxLength); - return OEMCrypto_SUCCESS; -} - -OEMCRYPTO_API OEMCryptoResult -OEMCrypto_InstallKeyboxOrOEMCert(const uint8_t* keybox, size_t keybox_length) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_InstallKeyboxOrOEMCert: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (crypto_engine->config_provisioning_method() != OEMCrypto_Keybox) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - return crypto_engine->InstallKeybox(keybox, keybox_length); -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_LoadTestKeybox(const uint8_t* buffer, - size_t length) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_LoadTestKeybox: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (crypto_engine->config_provisioning_method() != OEMCrypto_Keybox) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - return crypto_engine->InstallTestKeybox(buffer, length); -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_IsKeyboxOrOEMCertValid(void) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_IsKeyboxOrOEMCertValid: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - switch (crypto_engine->config_provisioning_method()) { - case OEMCrypto_DrmCertificate: - return OEMCrypto_SUCCESS; - case OEMCrypto_Keybox: - case OEMCrypto_OEMCertificate: - return crypto_engine->IsKeyboxOrOemCertValid(); - default: - LOGE("Invalid provisioning method: %d.", - crypto_engine->config_provisioning_method()); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } -} - -OEMCRYPTO_API OEMCrypto_ProvisioningMethod OEMCrypto_GetProvisioningMethod() { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_GetProvisioningMethod: OEMCrypto Not Initialized."); - return OEMCrypto_ProvisioningError; - } - return crypto_engine->config_provisioning_method(); -} - -OEMCRYPTO_API OEMCryptoResult -OEMCrypto_LoadOEMPrivateKey(OEMCrypto_SESSION session) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (crypto_engine->config_provisioning_method() != OEMCrypto_OEMCertificate) { - LOGE("Unexpected provisioning method = %d.", - crypto_engine->config_provisioning_method()); - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (session_ctx == nullptr || !session_ctx->isValid()) { - LOGE("OEMCrypto_ERROR_INVALID_SESSION"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - return session_ctx->LoadOemPrivateKey(); -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetOEMPublicCertificate( - uint8_t* public_cert, size_t* public_cert_length) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (crypto_engine->config_provisioning_method() != OEMCrypto_OEMCertificate) { - LOGE("Unexpected provisioning method = %d.", - crypto_engine->config_provisioning_method()); - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - return crypto_engine->GetOemPublicCertificate(public_cert, - public_cert_length); -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* device_id, - size_t* device_id_length) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_GetDeviceID: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - return crypto_engine->GetDeviceRootId(device_id, device_id_length); -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetKeyData(uint8_t* key_data, - size_t* key_data_length) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_GetKeyData: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (crypto_engine->config_provisioning_method() != OEMCrypto_Keybox) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - return crypto_engine->GetRootKeyData(key_data, key_data_length); -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetRandom(uint8_t* randomData, - size_t dataLength) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_GetRandom: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (!randomData) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (RAND_bytes(randomData, dataLength) == 1) { - return OEMCrypto_SUCCESS; - } - return OEMCrypto_ERROR_UNKNOWN_FAILURE; -} - -// This function is no longer exported -- it is only used by LoadProvisioning. -static OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey30( - OEMCrypto_SESSION session, const uint32_t* unaligned_nonce, - const uint8_t* encrypted_message_key, size_t encrypted_message_key_length, - const uint8_t* enc_rsa_key, size_t enc_rsa_key_length, - const uint8_t* enc_rsa_key_iv, uint8_t* wrapped_rsa_key, - size_t* wrapped_rsa_key_length) { - uint32_t nonce = unaligned_dereference_uint32(unaligned_nonce); - if (unaligned_nonce == nullptr) { - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_RewrapDeviceRSAKey30: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (wrapped_rsa_key_length == nullptr) { - LOGE("[OEMCrypto_RewrapDeviceRSAKey30(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (!crypto_engine->ValidRootOfTrust()) { - LOGE("[OEMCrypto_RewrapDeviceRSAKey30(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (session_ctx == nullptr || !session_ctx->isValid()) { - LOGE("[OEMCrypto_RewrapDeviceRSAKey30(): ERROR_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - if (encrypted_message_key == nullptr || encrypted_message_key_length == 0 || - enc_rsa_key == nullptr || enc_rsa_key_iv == nullptr || - unaligned_nonce == nullptr) { - LOGE("[OEMCrypto_RewrapDeviceRSAKey30(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - // Validate nonce - if (!session_ctx->CheckNonce(nonce)) { - return OEMCrypto_ERROR_INVALID_NONCE; - } - - const std::vector enc_encryption_key( - encrypted_message_key, - encrypted_message_key + encrypted_message_key_length); - if (!session_ctx->InstallRSAEncryptedKey(enc_encryption_key)) { - LOGE( - "OEMCrypto_RewrapDeviceRSAKey30: " - "Error loading encrypted_message_key."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - - // Decrypt RSA key. - std::vector pkcs8_rsa_key(enc_rsa_key_length); - if (!session_ctx->DecryptRSAKey(enc_rsa_key, enc_rsa_key_length, - enc_rsa_key_iv, pkcs8_rsa_key.data())) { - return OEMCrypto_ERROR_INVALID_RSA_KEY; - } - if (!session_ctx->LoadRsaDrmKey(pkcs8_rsa_key.data(), enc_rsa_key_length)) { - LOGE("Failed to load RSA DRM key"); - return OEMCrypto_ERROR_INVALID_RSA_KEY; - } - - // Now we generate a wrapped keybox. - WrappedRSAKey* wrapped = reinterpret_cast(wrapped_rsa_key); - // Pick a random context and IV for generating keys. - if (RAND_bytes(wrapped->context, sizeof(wrapped->context)) != 1) { - LOGE("[_RewrapDeviceRSAKey30(): RAND_bytes failed."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (RAND_bytes(wrapped->iv, sizeof(wrapped->iv)) != 1) { - LOGE("[_RewrapDeviceRSAKey30(): RAND_bytes failed."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - const std::vector context( - wrapped->context, wrapped->context + sizeof(wrapped->context)); - // Generate mac and encryption keys for encrypting the signature. - const OEMCryptoResult derive_key_result = - session_ctx->DeriveKeys(crypto_engine->DeviceRootKey(), context, context); - if (derive_key_result != OEMCrypto_SUCCESS) { - LOGE("[_RewrapDeviceRSAKey30(): DeriveKeys failed."); - return derive_key_result; - } - - // Encrypt rsa key with keybox. - if (!session_ctx->EncryptRSAKey(pkcs8_rsa_key.data(), enc_rsa_key_length, - wrapped->iv, wrapped->enc_rsa_key)) { - LOGE("[_RewrapDeviceRSAKey30(): EncrypteRSAKey failed."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - const size_t buffer_size = enc_rsa_key_length + sizeof(WrappedRSAKey); - // The wrapped keybox must be signed with the same key we verify with. - // Reference implementation uses the server key. - unsigned int sig_length = sizeof(wrapped->signature); - if (!HMAC(EVP_sha256(), session_ctx->mac_key_server().data(), - session_ctx->mac_key_server().size(), wrapped->context, - buffer_size - sizeof(wrapped->signature), wrapped->signature, - &sig_length)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - return OEMCrypto_SUCCESS; -} - -// This function is no longer exported -- it is only used by LoadProvisioning. -static OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey( - OEMCrypto_SESSION session, const uint8_t* message, size_t message_length, - const uint8_t* signature, size_t signature_length, - const uint32_t* unaligned_nonce, const uint8_t* enc_rsa_key, - size_t enc_rsa_key_length, const uint8_t* enc_rsa_key_iv, - uint8_t* wrapped_rsa_key, size_t* wrapped_rsa_key_length) { - uint32_t nonce = unaligned_dereference_uint32(unaligned_nonce); - if (unaligned_nonce == nullptr) { - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_RewrapDeviceRSAKey: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (crypto_engine->config_provisioning_method() != OEMCrypto_Keybox) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - if (wrapped_rsa_key_length == nullptr) { - LOGE("[OEMCrypto_RewrapDeviceRSAKey(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (!crypto_engine->ValidRootOfTrust()) { - LOGE("[OEMCrypto_RewrapDeviceRSAKey(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (session_ctx == nullptr || !session_ctx->isValid()) { - LOGE("[OEMCrypto_RewrapDeviceRSAKey(): ERROR_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - if (message == nullptr || message_length == 0 || signature == nullptr || - signature_length == 0 || unaligned_nonce == nullptr || - enc_rsa_key == nullptr) { - LOGE("[OEMCrypto_RewrapDeviceRSAKey(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - // verify signature. - if (!session_ctx->ValidateMessage(message, message_length, signature, - signature_length)) { - LOGE("[RewrapDeviceRSAKey(): Could not verify signature]"); - return OEMCrypto_ERROR_SIGNATURE_FAILURE; - } - - // Range check performed by ODK library. - - // Validate nonce - if (!session_ctx->CheckNonce(nonce)) { - return OEMCrypto_ERROR_INVALID_NONCE; - } - - // Decrypt RSA key and verify it. - std::vector pkcs8_rsa_key(enc_rsa_key_length); - if (!session_ctx->DecryptRSAKey(enc_rsa_key, enc_rsa_key_length, - enc_rsa_key_iv, pkcs8_rsa_key.data())) { - return OEMCrypto_ERROR_INVALID_RSA_KEY; - } - if (!session_ctx->LoadRsaDrmKey(pkcs8_rsa_key.data(), enc_rsa_key_length)) { - return OEMCrypto_ERROR_INVALID_RSA_KEY; - } - - // Now we generate a wrapped keybox. - WrappedRSAKey* wrapped = reinterpret_cast(wrapped_rsa_key); - // Pick a random context and IV for generating keys. - if (RAND_bytes(wrapped->context, sizeof(wrapped->context)) != 1) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (RAND_bytes(wrapped->iv, sizeof(wrapped->iv)) != 1) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - const std::vector context( - wrapped->context, wrapped->context + sizeof(wrapped->context)); - // Generate mac and encryption keys for encrypting the signature. - const OEMCryptoResult derive_key_result = - session_ctx->DeriveKeys(crypto_engine->DeviceRootKey(), context, context); - if (derive_key_result != OEMCrypto_SUCCESS) { - return derive_key_result; - } - - // Encrypt rsa key with keybox. - if (!session_ctx->EncryptRSAKey(pkcs8_rsa_key.data(), enc_rsa_key_length, - wrapped->iv, wrapped->enc_rsa_key)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - const size_t buffer_size = enc_rsa_key_length + sizeof(WrappedRSAKey); - // The wrapped keybox must be signed with the same key we verify with. - // Reference implementation uses the server key. - unsigned int sig_length = sizeof(wrapped->signature); - if (!HMAC(EVP_sha256(), session_ctx->mac_key_server().data(), - session_ctx->mac_key_server().size(), wrapped->context, - buffer_size - sizeof(wrapped->signature), wrapped->signature, - &sig_length)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - return OEMCrypto_SUCCESS; -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_LoadProvisioning( - OEMCrypto_SESSION session, const uint8_t* message, size_t message_length, - size_t core_message_length, const uint8_t* signature, - size_t signature_length, uint8_t* wrapped_private_key, - size_t* wrapped_private_key_length) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto Not Initialized"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (wrapped_private_key_length == nullptr || message == nullptr || - message_length == 0 || signature == nullptr || signature_length == 0) { - LOGE("OEMCrypto_ERROR_INVALID_CONTEXT"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (!crypto_engine->ValidRootOfTrust()) { - LOGE("OEMCrypto_ERROR_KEYBOX_INVALID"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (session_ctx == nullptr || !session_ctx->isValid()) { - LOGE("OEMCrypto_ERROR_INVALID_SESSION"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - std::vector device_id = crypto_engine->DeviceRootId(); - ODK_ParsedProvisioning parsed_response; - const uint32_t nonce = session_ctx->nonce(); - const OEMCryptoResult result = - ODK_ParseProvisioning(message, message_length, core_message_length, - &(session_ctx->nonce_values()), device_id.data(), - device_id.size(), &parsed_response); - if (result != OEMCrypto_SUCCESS) { - LOGE("ODK Error %d", result); - return result; - } - if (parsed_response.enc_private_key_iv.length != wvoec::KEY_IV_SIZE) { - LOGE("Encrypted private key iv has invalid length: %zu", - parsed_response.enc_private_key_iv.length); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - // For the reference implementation, the wrapped key and the encrypted - // key are the same size -- just encrypted with different keys. - // We add 32 bytes for a context, 32 for iv, and 32 bytes for a signature. - // Important: This layout must match OEMCrypto_LoadDRMPrivateKey below. - const size_t buffer_size = - parsed_response.enc_private_key.length + sizeof(WrappedRSAKey); - - if (wrapped_private_key == nullptr || - *wrapped_private_key_length < buffer_size) { - *wrapped_private_key_length = buffer_size; - return OEMCrypto_ERROR_SHORT_BUFFER; - } - *wrapped_private_key_length = - buffer_size; // Tell caller how much space we used. - const uint8_t* message_body = message + core_message_length; - if (crypto_engine->config_provisioning_method() == OEMCrypto_Keybox) { - return OEMCrypto_RewrapDeviceRSAKey( - session, message, message_length, signature, signature_length, &nonce, - message_body + parsed_response.enc_private_key.offset, - parsed_response.enc_private_key.length, - message_body + parsed_response.enc_private_key_iv.offset, - wrapped_private_key, wrapped_private_key_length); - } else if (crypto_engine->config_provisioning_method() == - OEMCrypto_OEMCertificate) { - return OEMCrypto_RewrapDeviceRSAKey30( - session, &nonce, - message_body + parsed_response.encrypted_message_key.offset, - parsed_response.encrypted_message_key.length, - message_body + parsed_response.enc_private_key.offset, - parsed_response.enc_private_key.length, - message_body + parsed_response.enc_private_key_iv.offset, - wrapped_private_key, wrapped_private_key_length); - } else { - LOGE("Invalid provisioning method: %d.", - crypto_engine->config_provisioning_method()); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_LoadDRMPrivateKey( - OEMCrypto_SESSION session, OEMCrypto_PrivateKeyType key_type, - const uint8_t* wrapped_rsa_key, size_t wrapped_rsa_key_length) { - if (wrapped_rsa_key == nullptr) { - LOGE("OEMCrypto_ERROR_INVALID_CONTEXT nullptr"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (crypto_engine == nullptr) { - LOGE("OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (key_type != OEMCrypto_RSA_Private_Key) { - LOGE("ECC keys not yet supported in reference code."); - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - if (crypto_engine->config_provisioning_method() == OEMCrypto_DrmCertificate) { - // If we are using a baked in cert, the "wrapped RSA key" should actually be - // the magic value for baked-in certificates. - if (wrapped_rsa_key_length != sizeof(kBakedInCertificateMagicBytes) || - memcmp(kBakedInCertificateMagicBytes, wrapped_rsa_key, - wrapped_rsa_key_length) != 0) { - LOGE("Baked in Cert has wrong size."); - return OEMCrypto_ERROR_INVALID_RSA_KEY; - } else { - return OEMCrypto_SUCCESS; - } - } - if (wrapped_rsa_key_length < sizeof(WrappedRSAKey)) { - LOGE("RSA Key has wrong size."); - return OEMCrypto_ERROR_INVALID_RSA_KEY; - } - const WrappedRSAKey* wrapped = - reinterpret_cast(wrapped_rsa_key); - if (!crypto_engine->ValidRootOfTrust()) { - LOGE("ERROR_KEYBOX_INVALID"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (session_ctx == nullptr || !session_ctx->isValid()) { - LOGE("ERROR_INVALID_SESSION"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - const std::vector context( - wrapped->context, wrapped->context + sizeof(wrapped->context)); - // Generate mac and encryption keys for encrypting the signature. - const OEMCryptoResult derive_key_result = - session_ctx->DeriveKeys(crypto_engine->DeviceRootKey(), context, context); - if (derive_key_result != OEMCrypto_SUCCESS) { - return derive_key_result; - } - // verify signature. - if (!session_ctx->ValidateMessage( - wrapped->context, wrapped_rsa_key_length - sizeof(wrapped->signature), - wrapped->signature, sizeof(wrapped->signature))) { - LOGE("Could not verify signature"); - return OEMCrypto_ERROR_SIGNATURE_FAILURE; - } - // Decrypt RSA key. - std::vector pkcs8_rsa_key(wrapped_rsa_key_length - - sizeof(wrapped->signature)); - size_t enc_rsa_key_length = wrapped_rsa_key_length - sizeof(WrappedRSAKey); - if (!session_ctx->DecryptRSAKey(wrapped->enc_rsa_key, enc_rsa_key_length, - wrapped->iv, pkcs8_rsa_key.data())) { - return OEMCrypto_ERROR_INVALID_RSA_KEY; - } - size_t padding = pkcs8_rsa_key[enc_rsa_key_length - 1]; - if (padding > 16) { - // Do not return an error at this point, to avoid a padding oracle attack. - padding = 0; - } - size_t rsa_key_length = enc_rsa_key_length - padding; - if (!session_ctx->LoadRsaDrmKey(pkcs8_rsa_key.data(), rsa_key_length)) { - return OEMCrypto_ERROR_INVALID_RSA_KEY; - } - return OEMCrypto_SUCCESS; -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_LoadTestRSAKey() { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_LoadTestRSAKey: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - return crypto_engine->LoadTestRsaKey(); -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_GenerateRSASignature( - OEMCrypto_SESSION session, const uint8_t* message, size_t message_length, - uint8_t* signature, size_t* signature_length, - RSA_Padding_Scheme padding_scheme) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_GenerateRSASignature: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - - if (signature_length == 0) { - LOGE("[OEMCrypto_GenerateRSASignature(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (session_ctx == nullptr || !session_ctx->isValid()) { - LOGE("[OEMCrypto_GenerateRSASignature(): ERROR_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - return session_ctx->GenerateRSASignature(message, message_length, signature, - signature_length, padding_scheme); -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_DeriveKeysFromSessionKey( - OEMCrypto_SESSION session, const uint8_t* enc_session_key, - size_t enc_session_key_length, const uint8_t* mac_key_context, - size_t mac_key_context_length, const uint8_t* enc_key_context, - size_t enc_key_context_length) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_DeriveKeysFromSessionKey: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (!crypto_engine->ValidRootOfTrust()) { - LOGE("[OEMCrypto_DeriveKeysFromSessionKey(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - if (mac_key_context_length > kMaxContextKeyLength || - enc_key_context_length > kMaxContextKeyLength || - enc_session_key_length > kMaxContextKeyLength) { - LOGE("[OEMCrypto_DeriveKeysFromSessionKey(): ERROR_BUFFER_TOO_LARGE]"); - return OEMCrypto_ERROR_BUFFER_TOO_LARGE; - } - - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (session_ctx == nullptr || !session_ctx->isValid()) { - LOGE("[OEMCrypto_DeriveKeysFromSessionKey(): ERROR_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - - const std::vector ssn_key_str( - enc_session_key, enc_session_key + enc_session_key_length); - const std::vector mac_ctx_str( - mac_key_context, mac_key_context + mac_key_context_length); - const std::vector enc_ctx_str( - enc_key_context, enc_key_context + enc_key_context_length); - - // Generate mac and encryption keys for current session context - return session_ctx->RSADeriveKeys(ssn_key_str, mac_ctx_str, enc_ctx_str); -} - -OEMCRYPTO_API uint32_t OEMCrypto_APIVersion() { - return CryptoEngine::kApiVersion; -} - -OEMCRYPTO_API uint32_t OEMCrypto_MinorAPIVersion() { - return CryptoEngine::kMinorApiVersion; -} - -OEMCRYPTO_API uint8_t OEMCrypto_Security_Patch_Level() { - uint8_t security_patch_level = crypto_engine->config_security_patch_level(); - return security_patch_level; -} - -OEMCRYPTO_API const char* OEMCrypto_SecurityLevel() { - const char* security_level = crypto_engine->config_security_level(); - return security_level; -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetHDCPCapability( - OEMCrypto_HDCP_Capability* current, OEMCrypto_HDCP_Capability* maximum) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_GetHDCPCapability: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (current == nullptr) return OEMCrypto_ERROR_UNKNOWN_FAILURE; - if (maximum == nullptr) return OEMCrypto_ERROR_UNKNOWN_FAILURE; - *current = crypto_engine->config_current_hdcp_capability(); - *maximum = crypto_engine->config_maximum_hdcp_capability(); - return OEMCrypto_SUCCESS; -} - -OEMCRYPTO_API uint32_t OEMCrypto_GetAnalogOutputFlags() { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_GetAnalogOutputFlags: OEMCrypto Not Initialized."); - return 0; - } - return crypto_engine->analog_output_flags(); -} - -OEMCRYPTO_API const char* OEMCrypto_BuildInformation() { - return "OEMCrypto Ref Code " __DATE__ " " __TIME__; -} - -OEMCRYPTO_API uint32_t OEMCrypto_ResourceRatingTier() { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_ResourceRatingTier: OEMCrypto Not Initialized."); - return 0; - } - return crypto_engine->resource_rating(); -} - -OEMCRYPTO_API bool OEMCrypto_SupportsUsageTable() { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_SupportsUsageTable: OEMCrypto Not Initialized."); - return 0; - } - bool supports_usage = crypto_engine->config_supports_usage_table(); - return supports_usage; -} - -OEMCRYPTO_API size_t OEMCrypto_MaximumUsageTableHeaderSize() { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_MaximumUsageTableHeaderSize: OEMCrypto Not Initialized."); - return 0; - } - return crypto_engine->max_usage_table_size(); -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetNumberOfOpenSessions(size_t* count) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_GetNumberOfOpenSessions: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (count == nullptr) return OEMCrypto_ERROR_UNKNOWN_FAILURE; - *count = crypto_engine->GetNumberOfOpenSessions(); - return OEMCrypto_SUCCESS; -} - -OEMCRYPTO_API OEMCryptoResult -OEMCrypto_GetMaxNumberOfSessions(size_t* maximum) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_GetMaxNumberOfSessions: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (maximum == nullptr) return OEMCrypto_ERROR_UNKNOWN_FAILURE; - *maximum = crypto_engine->GetMaxNumberOfSessions(); - return OEMCrypto_SUCCESS; -} - -OEMCRYPTO_API bool OEMCrypto_IsAntiRollbackHwPresent() { - bool anti_rollback_hw_present = - crypto_engine->config_is_anti_rollback_hw_present(); - - return anti_rollback_hw_present; -} - -OEMCRYPTO_API uint32_t OEMCrypto_SupportedCertificates() { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_GetProvisioningMethod: OEMCrypto Not Initialized."); - return 0; - } - if (crypto_engine->config_provisioning_method() == OEMCrypto_DrmCertificate) { - return 0; - } - return OEMCrypto_Supports_RSA_2048bit | OEMCrypto_Supports_RSA_3072bit | - OEMCrypto_Supports_RSA_CAST; -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_Generic_Encrypt( - OEMCrypto_SESSION session, const uint8_t* in_buffer, size_t buffer_length, - const uint8_t* iv, OEMCrypto_Algorithm algorithm, uint8_t* out_buffer) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_Generic_Encrypt: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (!crypto_engine->ValidRootOfTrust()) { - LOGE("[OEMCrypto_Generic_Encrypt(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (session_ctx == nullptr || !session_ctx->isValid()) { - LOGE("[OEMCrypto_Generic_Encrypt(): ERROR_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - if (in_buffer == nullptr || buffer_length == 0 || iv == nullptr || - out_buffer == nullptr) { - LOGE("[OEMCrypto_Generic_Encrypt(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (buffer_length > kMaxInputMessageBuferLength) { - LOGE("[OEMCrypto_Generic_Encrypt(): ERROR_BUFFER_TOO_LARGE]"); - return OEMCrypto_ERROR_BUFFER_TOO_LARGE; - } - - OEMCryptoResult sts = session_ctx->Generic_Encrypt(in_buffer, buffer_length, - iv, algorithm, out_buffer); - return sts; -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_Generic_Decrypt( - OEMCrypto_SESSION session, const uint8_t* in_buffer, size_t buffer_length, - const uint8_t* iv, OEMCrypto_Algorithm algorithm, uint8_t* out_buffer) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_Generic_Decrypt: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (!crypto_engine->ValidRootOfTrust()) { - LOGE("[OEMCrypto_Generic_Decrypt(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (session_ctx == nullptr || !session_ctx->isValid()) { - LOGE("[OEMCrypto_Generic_Decrypt(): ERROR_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - if (in_buffer == nullptr || buffer_length == 0 || iv == nullptr || - out_buffer == nullptr) { - LOGE("[OEMCrypto_Generic_Decrypt(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (buffer_length > kMaxInputMessageBuferLength) { - LOGE("[OEMCrypto_Generic_Encrypt(): ERROR_BUFFER_TOO_LARGE]"); - return OEMCrypto_ERROR_BUFFER_TOO_LARGE; - } - OEMCryptoResult sts = session_ctx->Generic_Decrypt(in_buffer, buffer_length, - iv, algorithm, out_buffer); - return sts; -} - -OEMCRYPTO_API OEMCryptoResult -OEMCrypto_Generic_Sign(OEMCrypto_SESSION session, const uint8_t* in_buffer, - size_t buffer_length, OEMCrypto_Algorithm algorithm, - uint8_t* signature, size_t* signature_length) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_Generic_Sign: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (!crypto_engine->ValidRootOfTrust()) { - LOGE("[OEMCrypto_Generic_Sign(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (session_ctx == nullptr || !session_ctx->isValid()) { - LOGE("[OEMCrypto_Generic_Sign(): ERROR_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - if (*signature_length < SHA256_DIGEST_LENGTH) { - *signature_length = SHA256_DIGEST_LENGTH; - return OEMCrypto_ERROR_SHORT_BUFFER; - } - if (in_buffer == nullptr || buffer_length == 0 || signature == nullptr) { - LOGE("[OEMCrypto_Generic_Sign(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (buffer_length > kMaxInputMessageBuferLength) { - LOGE("[OEMCrypto_Generic_Sign(): ERROR_BUFFER_TOO_LARGE]"); - return OEMCrypto_ERROR_BUFFER_TOO_LARGE; - } - OEMCryptoResult sts = session_ctx->Generic_Sign( - in_buffer, buffer_length, algorithm, signature, signature_length); - return sts; -} - -OEMCRYPTO_API OEMCryptoResult -OEMCrypto_Generic_Verify(OEMCrypto_SESSION session, const uint8_t* in_buffer, - size_t buffer_length, OEMCrypto_Algorithm algorithm, - const uint8_t* signature, size_t signature_length) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_Generic_Verify: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (!crypto_engine->ValidRootOfTrust()) { - LOGE("[OEMCrypto_Generic_Verify(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (session_ctx == nullptr || !session_ctx->isValid()) { - LOGE("[OEMCrypto_Generic_Verify(): ERROR_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - if (signature_length != SHA256_DIGEST_LENGTH) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (in_buffer == nullptr || buffer_length == 0 || signature == nullptr || - signature_length > kMaxInputSignatureLength) { - LOGE("[OEMCrypto_Generic_Verify(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (buffer_length > kMaxInputMessageBuferLength) { - LOGE("[OEMCrypto_Generic_Verify(): ERROR_BUFFER_TOO_LARGE]"); - return OEMCrypto_ERROR_BUFFER_TOO_LARGE; - } - return session_ctx->Generic_Verify(in_buffer, buffer_length, algorithm, - signature, signature_length); -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_DeactivateUsageEntry( - OEMCrypto_SESSION session, const uint8_t* pst, size_t pst_length) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_DeactivateUsageEntry: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (!crypto_engine->config_supports_usage_table()) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (session_ctx == nullptr || !session_ctx->isValid()) { - LOGE("[OEMCrypto_DeactivateUsageEntry(): ERROR_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - std::vector pstv(pst, pst + pst_length); - return session_ctx->DeactivateUsageEntry(pstv); -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_ReportUsage(OEMCrypto_SESSION session, - const uint8_t* pst, - size_t pst_length, - uint8_t* buffer, - size_t* buffer_length) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_ReportUsage: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (!crypto_engine->config_supports_usage_table()) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - if (!buffer_length) { - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (session_ctx == nullptr || !session_ctx->isValid()) { - LOGE("[OEMCrypto_ReportUsage(): ERROR_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - std::vector pstv(pst, pst + pst_length); - OEMCryptoResult sts = session_ctx->ReportUsage(pstv, buffer, buffer_length); - return sts; -} - -OEMCRYPTO_API bool OEMCrypto_IsSRMUpdateSupported() { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_IsSRMUpdateSupported: OEMCrypto Not Initialized."); - return false; - } - bool result = crypto_engine->srm_update_supported(); - return result; -} - -OEMCRYPTO_API OEMCryptoResult -OEMCrypto_GetCurrentSRMVersion(uint16_t* version) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_GetCurrentSRMVersion: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (crypto_engine->config_local_display_only()) { - return OEMCrypto_LOCAL_DISPLAY_ONLY; - } - OEMCryptoResult result = crypto_engine->current_srm_version(version); - return result; -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_LoadSRM(const uint8_t* buffer, - size_t buffer_length) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_LoadSRM: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - return crypto_engine->load_srm(buffer, buffer_length); -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_RemoveSRM() { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_RemoveSRM: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - return crypto_engine->remove_srm(); -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_CreateUsageTableHeader( - uint8_t* header_buffer, size_t* header_buffer_length) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_CreateUsageTableHeader: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (!crypto_engine->config_supports_usage_table()) { - LOGE("OEMCrypto_CreateUsageTableHeader: Configured without Usage Tables."); - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - return crypto_engine->usage_table().CreateUsageTableHeader( - header_buffer, header_buffer_length); -} - -OEMCRYPTO_API OEMCryptoResult -OEMCrypto_LoadUsageTableHeader(const uint8_t* buffer, size_t buffer_length) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_LoadUsageTableHeader: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (!crypto_engine->config_supports_usage_table()) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - if (!buffer) { - LOGE("OEMCrypto_LoadUsageTableHeader: buffer null."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - std::vector bufferv(buffer, buffer + buffer_length); - return crypto_engine->usage_table().LoadUsageTableHeader(bufferv); -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_CreateNewUsageEntry( - OEMCrypto_SESSION session, uint32_t* usage_entry_number) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_CreateNewUsageEntry: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (!crypto_engine->config_supports_usage_table()) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (session_ctx == nullptr || !session_ctx->isValid()) { - LOGE("[OEMCrypto_CreateNewUsageEntry(): ERROR_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - if (!usage_entry_number) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - OEMCryptoResult sts = session_ctx->CreateNewUsageEntry(usage_entry_number); - return sts; -} - -OEMCRYPTO_API OEMCryptoResult -OEMCrypto_LoadUsageEntry(OEMCrypto_SESSION session, uint32_t index, - const uint8_t* buffer, size_t buffer_size) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_LoadUsageEntry: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (!crypto_engine->config_supports_usage_table()) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (session_ctx == nullptr || !session_ctx->isValid()) { - LOGE("[OEMCrypto_LoadUsageEntry(): ERROR_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - if (!buffer) { - LOGE("[OEMCrypto_LoadUsageEntry(): buffer null]"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - std::vector bufferv(buffer, buffer + buffer_size); - return session_ctx->LoadUsageEntry(index, bufferv); -} - -OEMCRYPTO_API OEMCryptoResult -OEMCrypto_UpdateUsageEntry(OEMCrypto_SESSION session, uint8_t* header_buffer, - size_t* header_buffer_length, uint8_t* entry_buffer, - size_t* entry_buffer_length) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_UpdateUsageEntry: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (!crypto_engine->config_supports_usage_table()) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - if (!header_buffer_length || !entry_buffer_length) { - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (session_ctx == nullptr || !session_ctx->isValid()) { - LOGE("[OEMCrypto_UpdateUsageEntry(): ERROR_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - return session_ctx->UpdateUsageEntry(header_buffer, header_buffer_length, - entry_buffer, entry_buffer_length); -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_ShrinkUsageTableHeader( - uint32_t new_table_size, uint8_t* header_buffer, - size_t* header_buffer_length) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_ShrinkUsageTableHeader: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (!crypto_engine->config_supports_usage_table()) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - return crypto_engine->usage_table().ShrinkUsageTableHeader( - new_table_size, header_buffer, header_buffer_length); -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_MoveEntry(OEMCrypto_SESSION session, - uint32_t new_index) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_MoveEntry: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (!crypto_engine->config_supports_usage_table()) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (session_ctx == nullptr || !session_ctx->isValid()) { - LOGE("[OEMCrypto_MoveEntry(): ERROR_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - return session_ctx->MoveEntry(new_index); -} - -OEMCRYPTO_API uint32_t OEMCrypto_SupportsDecryptHash() { - return OEMCrypto_CRC_Clear_Buffer; -} - -OEMCRYPTO_API OEMCryptoResult -OEMCrypto_SetDecryptHash(OEMCrypto_SESSION session, uint32_t frame_number, - const uint8_t* hash, size_t hash_length) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_SetDecryptHash: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (session_ctx == nullptr || !session_ctx->isValid()) { - LOGE("[OEMCrypto_SetDecryptHash(): ERROR_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - return session_ctx->SetDecryptHash(frame_number, hash, hash_length); -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetHashErrorCode( - OEMCrypto_SESSION session, uint32_t* failed_frame_number) { - if (crypto_engine == nullptr) { - LOGE("OEMCrypto_GetHashErrorCode: OEMCrypto Not Initialized."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - SessionContext* session_ctx = crypto_engine->FindSession(session); - if (session_ctx == nullptr || !session_ctx->isValid()) { - LOGE("[OEMCrypto_GetHashErrorCode(): ERROR_INVALID_SESSION]"); - return OEMCrypto_ERROR_INVALID_SESSION; - } - return session_ctx->GetHashErrorCode(failed_frame_number); -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_AllocateSecureBuffer( - OEMCrypto_SESSION session, size_t buffer_size, - OEMCrypto_DestBufferDesc* output_descriptor, int* secure_fd) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; -} - -OEMCRYPTO_API OEMCryptoResult OEMCrypto_FreeSecureBuffer( - OEMCrypto_SESSION session, OEMCrypto_DestBufferDesc* output_descriptor, - int secure_fd) { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; -} - -} // namespace wvoec_ref diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_rsa_key.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_rsa_key.cpp deleted file mode 100644 index 6a9c2af2..00000000 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_rsa_key.cpp +++ /dev/null @@ -1,1168 +0,0 @@ -// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine License -// Agreement. -// -// Reference implementation of OEMCrypto APIs -// -#include "oemcrypto_rsa_key.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "OEMCryptoCENC.h" -#include "log.h" -#include "oemcrypto_types.h" -#include "scoped_object.h" - -namespace wvoec_ref { -namespace { -// Estimated size of an RSA private key. -// The private key constists of: -// n : Modulos : byteSize(n) ~= bitSize(n)/8 -// e : Public exponent : 4 bytes -// d : Private exponent : ~byteSize(n) -// p : Prime 1 : ~byteSize(n)/2 -// q : Prime 2 : ~byteSize(n)/2 -// d (mod p-1) : Exponent 1 : ~byteSize(n)/2 -// d (mod q-1) : Exponent 2 : ~byteSize(n)/2 -// q^-1 (mod p) : Coefficient : ~byteSize(n)/2 -// And the ASN.1 tags for each component (roughly 25 bytes). -constexpr size_t kPrivateKeySize = (3072 / 8) * 5 + 25; -// Estimated size of an RSA public key. -// The public key constists of: -// The private key constists of: -// n : Modulos : byteSize(n) ~= bitSize(n)/8 -// e : Public exponent : 4 bytes -// And the ASN.1 tags + outer structure. -constexpr size_t kPublicKeySize = (3072 / 8) + 100; - -// 128 bit key, intended to be used with CMAC-AES-128. -constexpr size_t kRsaSessionKeySize = 16; -// Encryption key used by OEMCrypto session for encrypting and -// decrypting data. -constexpr size_t kEncryptionKeySize = wvoec::KEY_SIZE; - -// Salt length used by OEMCrypto's RSASSA-PSS implementation. -// See description of kRsaPssDefault for more information. -constexpr size_t kPssSaltLength = 20; -// Requirement of CAST receivers. -constexpr size_t kRsaPkcs1CastMaxMessageSize = 83; - -using ScopedBio = ScopedObject; -using ScopedBigNum = ScopedObject; -using ScopedEvpMdCtx = ScopedObject; -using ScopedEvpPkey = ScopedObject; -using ScopedRsaKey = ScopedObject; -using ScopedRsaPrivKeyInfo = - ScopedObject; - -// Estimates the RSA rough field size from the real bit size of the -// RSA modulos. The actual bit length could vary by a few bits. -RsaFieldSize RealBitSizeToFieldSize(int bits) { - if (bits > 1800 && bits < 2200) { - return kRsa2048Bit; - } - if (bits > 2800 && bits < 3200) { - return kRsa3072Bit; - } - return kRsaFieldUnknown; -} -} // namespace - -std::string RsaFieldSizeToString(RsaFieldSize field_size) { - switch (field_size) { - case kRsa2048Bit: - return "RSA-2048"; - case kRsa3072Bit: - return "RSA-3072"; - case kRsaFieldUnknown: - return "Unknown"; - } - return "Unknown(" + std::to_string(static_cast(field_size)) + ")"; -} - -bool RsaKeysAreMatchingPair(const RSA* public_key, const RSA* private_key) { - if (public_key == nullptr) { - LOGE("Public key is null"); - return false; - } - if (private_key == nullptr) { - LOGE("Private key is null"); - return false; - } - // Step 1: Extract public key components. - const BIGNUM* public_n = nullptr; - const BIGNUM* public_e = nullptr; - const BIGNUM* d = nullptr; - RSA_get0_key(public_key, &public_n, &public_e, &d); - if (public_n == nullptr || public_e == nullptr) { - LOGE("Failed to get RSA public key components"); - return false; - } - // Step 2: Extract private key components. - const BIGNUM* private_n = nullptr; - const BIGNUM* private_e = nullptr; - RSA_get0_key(private_key, &private_n, &private_e, &d); - if (private_n == nullptr || private_e == nullptr) { - LOGE("Failed to get RSA private key components"); - return false; - } - // Step 3: Compare RSA components. - if (BN_cmp(public_n, private_n)) { - LOGD("RSA modulos do not match"); - return false; - } - if (BN_cmp(public_e, private_e)) { - LOGD("RSA exponents do not match"); - return false; - } - return true; -} - -// ===== ===== ===== RSA Public Key ===== ===== ===== - -// static -std::unique_ptr RsaPublicKey::New( - const RsaPrivateKey& private_key) { - std::unique_ptr key(new RsaPublicKey()); - if (!key->InitFromPrivateKey(private_key)) { - LOGE("Failed to initialize public key from private key"); - key.reset(); - } - return key; -} - -// static -std::unique_ptr RsaPublicKey::Load(const uint8_t* buffer, - size_t length) { - std::unique_ptr key; - if (buffer == nullptr) { - LOGE("Provided public key buffer is null"); - return key; - } - if (length == 0) { - LOGE("Provided public key buffer is zero length"); - return key; - } - key.reset(new RsaPublicKey()); - if (!key->InitFromBuffer(buffer, length)) { - LOGE("Failed to initialize public key from buffer"); - key.reset(); - } - return key; -} - -// static -std::unique_ptr RsaPublicKey::Load(const std::string& buffer) { - if (buffer.empty()) { - LOGE("Provided public key buffer is empty"); - return std::unique_ptr(); - } - return Load(reinterpret_cast(buffer.data()), buffer.size()); -} - -// static -std::unique_ptr RsaPublicKey::Load( - const std::vector& buffer) { - std::unique_ptr key; - if (buffer.empty()) { - LOGE("Provided public key buffer is empty"); - return std::unique_ptr(); - } - return Load(buffer.data(), buffer.size()); -} - -bool RsaPublicKey::IsMatchingPrivateKey( - const RsaPrivateKey& private_key) const { - if (private_key.field_size() != field_size_) { - return false; - } - return RsaKeysAreMatchingPair(GetRsaKey(), private_key.GetRsaKey()); -} - -OEMCryptoResult RsaPublicKey::Serialize(uint8_t* buffer, - size_t* buffer_size) const { - if (buffer_size == nullptr) { - LOGE("Output buffer size is null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (buffer == nullptr && *buffer_size > 0) { - LOGE("Output buffer is null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - uint8_t* der_key = nullptr; - const int der_res = i2d_RSA_PUBKEY(key_, &der_key); - if (der_res < 0) { - LOGE("Public key serialization failed"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (der_key == nullptr) { - LOGE("Encoded key is unexpectedly null"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (der_res == 0) { - LOGE("Unexpected DER encoded size"); - OPENSSL_free(der_key); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - const size_t required_size = static_cast(der_res); - if (buffer == nullptr || *buffer_size < required_size) { - *buffer_size = required_size; - OPENSSL_free(der_key); - return OEMCrypto_ERROR_SHORT_BUFFER; - } - memcpy(buffer, der_key, required_size); - *buffer_size = required_size; - OPENSSL_free(der_key); - return OEMCrypto_SUCCESS; -} - -std::vector RsaPublicKey::Serialize() const { - size_t key_size = kPublicKeySize; - std::vector key_data(key_size, 0); - const OEMCryptoResult res = Serialize(key_data.data(), &key_size); - if (res != OEMCrypto_SUCCESS) { - LOGE("Failed to serialize public key: result = %d", static_cast(res)); - key_data.clear(); - } else { - key_data.resize(key_size); - } - return key_data; -} - -OEMCryptoResult RsaPublicKey::VerifySignature( - const uint8_t* message, size_t message_length, const uint8_t* signature, - size_t signature_length, RsaSignatureAlgorithm algorithm) const { - if (signature == nullptr || signature_length == 0) { - LOGE("Signature is missing"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (message == nullptr && message_length > 0) { - LOGE("Bad message data"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - switch (algorithm) { - case kRsaPssDefault: - return VerifySignaturePss(message, message_length, signature, - signature_length); - case kRsaPkcs1Cast: - return VerifySignaturePkcs1Cast(message, message_length, signature, - signature_length); - } - LOGE("Unknown RSA signature algorithm: %d", static_cast(algorithm)); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; -} - -OEMCryptoResult RsaPublicKey::VerifySignature( - const std::string& message, const std::string& signature, - RsaSignatureAlgorithm algorithm) const { - if (signature.empty()) { - LOGE("Signature should not be empty"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - return VerifySignature(reinterpret_cast(message.data()), - message.size(), - reinterpret_cast(signature.data()), - signature.size(), algorithm); -} - -OEMCryptoResult RsaPublicKey::VerifySignature( - const std::vector& message, const std::vector& signature, - RsaSignatureAlgorithm algorithm) const { - if (signature.empty()) { - LOGE("Signature should not be empty"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - return VerifySignature(message.data(), message.size(), signature.data(), - signature.size(), algorithm); -} - -OEMCryptoResult RsaPublicKey::EncryptSessionKey( - const uint8_t* session_key, size_t session_key_size, - uint8_t* enc_session_key, size_t* enc_session_key_size) const { - if (session_key == nullptr) { - LOGE("Session key is null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (session_key_size != kRsaSessionKeySize) { - LOGE("Unexpected session key size: expected = %zu, actual = %zu", - kRsaSessionKeySize, session_key_size); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (enc_session_key_size == nullptr) { - LOGE("Output encrypted session key size is null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (enc_session_key == nullptr && *enc_session_key_size > 0) { - LOGE("Output encrypted session key is null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - return EncryptOaep(session_key, session_key_size, enc_session_key, - enc_session_key_size); -} - -std::vector RsaPublicKey::EncryptSessionKey( - const std::vector& session_key) const { - if (session_key.empty()) { - LOGE("Session key is empty"); - return std::vector(); - } - size_t enc_session_key_size = static_cast(RSA_size(key_)); - std::vector enc_session_key(enc_session_key_size); - const OEMCryptoResult res = - EncryptSessionKey(session_key.data(), session_key.size(), - enc_session_key.data(), &enc_session_key_size); - if (res != OEMCrypto_SUCCESS) { - LOGE("Failed to encrypt session key: result = %d", static_cast(res)); - enc_session_key.clear(); - } else { - enc_session_key.resize(enc_session_key_size); - } - return enc_session_key; -} - -std::vector RsaPublicKey::EncryptSessionKey( - const std::string& session_key) const { - if (session_key.empty()) { - LOGE("Session key is empty"); - return std::vector(); - } - size_t enc_session_key_size = static_cast(RSA_size(key_)); - std::vector enc_session_key(enc_session_key_size); - const OEMCryptoResult res = EncryptSessionKey( - reinterpret_cast(session_key.data()), session_key.size(), - enc_session_key.data(), &enc_session_key_size); - if (res != OEMCrypto_SUCCESS) { - LOGE("Failed to encrypt session key: result = %d", static_cast(res)); - enc_session_key.clear(); - } else { - enc_session_key.resize(enc_session_key_size); - } - return enc_session_key; -} - -OEMCryptoResult RsaPublicKey::EncryptEncryptionKey( - const uint8_t* encryption_key, size_t encryption_key_size, - uint8_t* enc_encryption_key, size_t* enc_encryption_key_size) const { - if (encryption_key == nullptr) { - LOGE("Encryption key is null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (encryption_key_size != kEncryptionKeySize) { - LOGE("Unexpected encryption key size: expected = %zu, actual = %zu", - kEncryptionKeySize, encryption_key_size); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (enc_encryption_key_size == nullptr) { - LOGE("Output encrypted encryption key size is null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (enc_encryption_key == nullptr && *enc_encryption_key_size > 0) { - LOGE("Output encrypted encryption key is null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - return EncryptOaep(encryption_key, encryption_key_size, enc_encryption_key, - enc_encryption_key_size); -} - -std::vector RsaPublicKey::EncryptEncryptionKey( - const std::vector& encryption_key) const { - if (encryption_key.empty()) { - LOGE("Session key is empty"); - return std::vector(); - } - size_t enc_encryption_key_size = static_cast(RSA_size(key_)); - std::vector enc_encryption_key(enc_encryption_key_size); - const OEMCryptoResult res = - EncryptSessionKey(encryption_key.data(), encryption_key.size(), - enc_encryption_key.data(), &enc_encryption_key_size); - if (res != OEMCrypto_SUCCESS) { - LOGE("Failed to encrypt encryption key: result = %d", - static_cast(res)); - enc_encryption_key.clear(); - } else { - enc_encryption_key.resize(enc_encryption_key_size); - } - return enc_encryption_key; -} - -std::vector RsaPublicKey::EncryptEncryptionKey( - const std::string& encryption_key) const { - if (encryption_key.empty()) { - LOGE("Session key is empty"); - return std::vector(); - } - size_t enc_encryption_key_size = static_cast(RSA_size(key_)); - std::vector enc_encryption_key(enc_encryption_key_size); - const OEMCryptoResult res = - EncryptSessionKey(reinterpret_cast(encryption_key.data()), - encryption_key.size(), enc_encryption_key.data(), - &enc_encryption_key_size); - if (res != OEMCrypto_SUCCESS) { - LOGE("Failed to encrypt encryption key: result = %d", - static_cast(res)); - enc_encryption_key.clear(); - } else { - enc_encryption_key.resize(enc_encryption_key_size); - } - return enc_encryption_key; -} - -RsaPublicKey::~RsaPublicKey() { - if (key_ != nullptr) { - RSA_free(key_); - key_ = nullptr; - } - allowed_schemes_ = 0; - field_size_ = kRsaFieldUnknown; -} - -bool RsaPublicKey::InitFromBuffer(const uint8_t* buffer, size_t length) { - // Step 1: Deserialize SubjectPublicKeyInfo as RSA key. - const uint8_t* tp = buffer; - ScopedRsaKey key(d2i_RSA_PUBKEY(nullptr, &tp, length)); - if (!key) { - LOGE("Failed to parse key"); - return false; - } - // Step 2: Verify key. - const int bits = RSA_bits(key.get()); - field_size_ = RealBitSizeToFieldSize(bits); - if (field_size_ == kRsaFieldUnknown) { - LOGE("Unsupported RSA key size: bits = %d", bits); - return false; - } - allowed_schemes_ = kSign_RSASSA_PSS; - key_ = key.release(); - return true; -} - -bool RsaPublicKey::InitFromPrivateKey(const RsaPrivateKey& private_key) { - ScopedRsaKey key(RSA_new()); - if (!key) { - LOGE("Failed to allocate key"); - return false; - } - const BIGNUM* n = nullptr; - const BIGNUM* e = nullptr; - const BIGNUM* d = nullptr; - RSA_get0_key(private_key.GetRsaKey(), &n, &e, &d); - if (n == nullptr || e == nullptr) { - LOGE("Failed to get RSA private key components"); - return false; - } - ScopedBigNum dub_n(BN_dup(n)); - ScopedBigNum dub_e(BN_dup(e)); - if (!dub_n || !dub_e) { - LOGE("Failed to duplicate RSA public key components"); - return false; - } - if (!RSA_set0_key(key.get(), dub_n.get(), dub_e.get(), nullptr)) { - LOGE("Failed to RSA public key components"); - return false; - } - // Ownership has transferred to the RSA key. - dub_n.release(); - dub_e.release(); - - key_ = key.release(); - allowed_schemes_ = private_key.allowed_schemes(); - field_size_ = private_key.field_size(); - return true; -} - -OEMCryptoResult RsaPublicKey::VerifySignaturePss( - const uint8_t* message, size_t message_length, const uint8_t* signature, - size_t signature_length) const { - // Step 0: Ensure the signature algorithm is supported by key. - if (!(allowed_schemes_ & kSign_RSASSA_PSS)) { - LOGE("RSA key cannot verify using PSS"); - return OEMCrypto_ERROR_INVALID_RSA_KEY; - } - // Step 1: Create a high-level key from RSA key. - ScopedEvpPkey pkey(EVP_PKEY_new()); - if (!pkey) { - LOGE("Failed to allocate PKEY"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (!EVP_PKEY_set1_RSA(pkey.get(), key_)) { - LOGE("Failed to set PKEY RSA key"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - // Step 2a: Setup a EVP MD CTX for PSS Verification. - ScopedEvpMdCtx md_ctx = EVP_MD_CTX_new(); - if (!md_ctx) { - LOGE("Failed to allocate MD CTX"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - EVP_PKEY_CTX* pkey_ctx = nullptr; // Ownership is maintained by |md_ctx| - int res = EVP_DigestVerifyInit(md_ctx.get(), &pkey_ctx, EVP_sha1(), nullptr, - pkey.get()); - if (res != 1) { - LOGE("Failed to initialize MD CTX for verification"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (pkey_ctx == nullptr) { - LOGE("PKEY CTX is unexpectedly null"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - // Step 2b: Configure OEMCrypto RSASSA-PSS options. - res = EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING); - if (res != 1) { - LOGE("Failed to set PSS padding"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - res = EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, kPssSaltLength); - if (res != 1) { - LOGE("Failed to set PSS salt length"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - res = EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, EVP_sha1()); - if (res != 1) { - LOGE("Failed to set PSS MGF1 MD"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - // Step 3: Digest message. - if (message_length > 0) { - res = EVP_DigestVerifyUpdate(md_ctx.get(), message, message_length); - if (res != 1) { - LOGE("Failed to update MD"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - } - // Step 4: Verify message. - res = EVP_DigestVerifyFinal(md_ctx.get(), signature, signature_length); - if (res < 0) { - LOGE("Failed to perform RSASSA-PSS-VERIFY"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - return res ? OEMCrypto_SUCCESS : OEMCrypto_ERROR_SIGNATURE_FAILURE; -} - -OEMCryptoResult RsaPublicKey::VerifySignaturePkcs1Cast( - const uint8_t* message, size_t message_length, const uint8_t* signature, - size_t signature_length) const { - // Step 0: Ensure the signature algorithm is supported by key. - if (!(allowed_schemes_ & kSign_PKCS1_Block1)) { - LOGE("RSA key cannot verify using PKCS1"); - return OEMCrypto_ERROR_INVALID_RSA_KEY; - } - if (message_length > kRsaPkcs1CastMaxMessageSize) { - LOGE("Message is too large for CAST PKCS1 signature: size = %zu", - message_length); - return OEMCrypto_ERROR_SIGNATURE_FAILURE; - } - // Step 1: Convert encrypted blob into digest. - std::vector digest(RSA_size(key_)); - const int res = RSA_public_decrypt(signature_length, signature, digest.data(), - key_, RSA_PKCS1_PADDING); - if (res <= 0) { - LOGE("Failed to perform public decryption"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - // Step 2: Compare digests. - const size_t digest_size = static_cast(res); - if (digest_size != message_length) { - LOGD("Digest size does not match"); - return OEMCrypto_ERROR_SIGNATURE_FAILURE; - } - digest.resize(digest_size); - for (size_t i = 0; i < digest_size; i++) { - if (message[i] != digest[i]) { - return OEMCrypto_ERROR_SIGNATURE_FAILURE; - } - } - return OEMCrypto_SUCCESS; -} - -OEMCryptoResult RsaPublicKey::EncryptOaep(const uint8_t* message, - size_t message_size, - uint8_t* enc_message, - size_t* enc_message_length) const { - // Step 1: Encrypt using RSAES-OAEP. - std::vector encrypt_buffer(RSA_size(key_)); - const int enc_res = - RSA_public_encrypt(message_size, message, encrypt_buffer.data(), key_, - RSA_PKCS1_OAEP_PADDING); - if (enc_res < 0) { - LOGE("Failed to perform RSAES-OAEP encrypt"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - // Step 2: Copy encrypted data key. - const size_t enc_size = static_cast(enc_res); - if (*enc_message_length < enc_size) { - *enc_message_length = enc_size; - return OEMCrypto_ERROR_SHORT_BUFFER; - } - *enc_message_length = enc_size; - memcpy(enc_message, encrypt_buffer.data(), enc_size); - return OEMCrypto_SUCCESS; -} - -// ===== ===== ===== RSA Private Key ===== ===== ===== - -// static -std::unique_ptr RsaPrivateKey::New(RsaFieldSize field_size) { - std::unique_ptr key(new RsaPrivateKey()); - if (!key->InitFromFieldSize(field_size)) { - LOGE("Failed to initialize private key from field size"); - key.reset(); - } - return key; -} - -// static -std::unique_ptr RsaPrivateKey::Load(const uint8_t* buffer, - size_t length) { - std::unique_ptr key; - if (buffer == nullptr) { - LOGE("Provided private key buffer is null"); - return key; - } - if (length == 0) { - LOGE("Provided private key buffer is zero length"); - return key; - } - key.reset(new RsaPrivateKey()); - if (!key->InitFromBuffer(buffer, length)) { - LOGE("Failed to initialize private key from buffer"); - key.reset(); - } - return key; -} - -// static -std::unique_ptr RsaPrivateKey::Load(const std::string& buffer) { - if (buffer.empty()) { - LOGE("Provided private key buffer is empty"); - return std::unique_ptr(); - } - return Load(reinterpret_cast(buffer.data()), buffer.size()); -} - -// static -std::unique_ptr RsaPrivateKey::Load( - const std::vector& buffer) { - if (buffer.empty()) { - LOGE("Provided private key buffer is empty"); - return std::unique_ptr(); - } - return Load(buffer.data(), buffer.size()); -} - -std::unique_ptr RsaPrivateKey::MakePublicKey() const { - return RsaPublicKey::New(*this); -} - -bool RsaPrivateKey::IsMatchingPublicKey(const RsaPublicKey& public_key) const { - return RsaKeysAreMatchingPair(public_key.GetRsaKey(), GetRsaKey()); -} - -OEMCryptoResult RsaPrivateKey::Serialize(uint8_t* buffer, - size_t* buffer_size) const { - if (buffer_size == nullptr) { - LOGE("Output buffer size is null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (buffer == nullptr && *buffer_size > 0) { - LOGE("Output buffer is null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - // Step 1: Convert RSA key to EVP. - ScopedEvpPkey pkey(EVP_PKEY_new()); - if (!pkey) { - LOGE("Failed to allocate EVP"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (!EVP_PKEY_set1_RSA(pkey.get(), key_)) { - LOGE("Failed to set EVP RSA key"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - // Step 2: Convert RSA EVP to PKCS8 format. - ScopedRsaPrivKeyInfo priv_info(EVP_PKEY2PKCS8(pkey.get())); - if (!priv_info) { - LOGE("Failed to convert RSA key to PKCS8 info"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - // Step 3: Serialize PKCS8 to DER encoding. - ScopedBio bio(BIO_new(BIO_s_mem())); - if (!bio) { - LOGE("Failed to allocate IO buffer for RSA key"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (!i2d_PKCS8_PRIV_KEY_INFO_bio(bio.get(), priv_info.get())) { - LOGE("Failed to serialize RSA key"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - // Step 4: Determine key size and copy. - char* key_ptr = nullptr; - const long key_size = BIO_get_mem_data(bio.get(), &key_ptr); - if (key_size < 0) { - LOGE("Failed to get RSA key size"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - const size_t required_size = - static_cast(key_size) + (explicit_schemes_ ? 8 : 0); - if (*buffer_size < required_size) { - *buffer_size = required_size; - return OEMCrypto_ERROR_SHORT_BUFFER; - } - *buffer_size = required_size; - if (explicit_schemes_) { - memcpy(buffer, "SIGN", 4); - const uint32_t allowed_schemes = htonl(allowed_schemes_); - memcpy(&buffer[4], &allowed_schemes, 4); - memcpy(&buffer[8], key_ptr, required_size - 8); - } else { - memcpy(buffer, key_ptr, required_size); - } - return OEMCrypto_SUCCESS; -} - -std::vector RsaPrivateKey::Serialize() const { - size_t key_size = kPrivateKeySize; - std::vector key_data(key_size, 0); - OEMCryptoResult res = Serialize(key_data.data(), &key_size); - if (res == OEMCrypto_ERROR_SHORT_BUFFER) { - LOGD( - "Actual RSA private key size is larger than expected: " - "expected = %zu, actual = %zu", - kPrivateKeySize, key_size); - key_data.resize(key_size); - res = Serialize(key_data.data(), &key_size); - } - if (res != OEMCrypto_SUCCESS) { - LOGE("Failed to serialize private key: result = %d", static_cast(res)); - key_data.clear(); - } else { - key_data.resize(key_size); - } - return key_data; -} - -OEMCryptoResult RsaPrivateKey::GenerateSignature( - const uint8_t* message, size_t message_length, - RsaSignatureAlgorithm algorithm, uint8_t* signature, - size_t* signature_length) const { - if (signature_length == nullptr) { - LOGE("Output signature size is null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (signature == nullptr && *signature_length > 0) { - LOGE("Output signature is null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (message == nullptr && message_length > 0) { - LOGE("Invalid message data"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - switch (algorithm) { - case kRsaPssDefault: - return GenerateSignaturePss(message, message_length, signature, - signature_length); - case kRsaPkcs1Cast: - return GenerateSignaturePkcs1Cast(message, message_length, signature, - signature_length); - } - LOGE("Unknown RSA signature algorithm: %d", static_cast(algorithm)); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; -} - -std::vector RsaPrivateKey::GenerateSignature( - const std::string& message, RsaSignatureAlgorithm algorithm) const { - size_t signature_size = SignatureSize(); - std::vector signature(signature_size); - const OEMCryptoResult res = GenerateSignature( - reinterpret_cast(message.data()), message.size(), - algorithm, signature.data(), &signature_size); - if (res != OEMCrypto_SUCCESS) { - LOGE("Failed to generate signature: result = %d", static_cast(res)); - signature.clear(); - } else { - signature.resize(signature_size); - } - return signature; -} - -std::vector RsaPrivateKey::GenerateSignature( - const std::vector& message, - RsaSignatureAlgorithm algorithm) const { - size_t signature_size = SignatureSize(); - std::vector signature(signature_size, 0); - const OEMCryptoResult res = - GenerateSignature(message.data(), message.size(), algorithm, - signature.data(), &signature_size); - if (res != OEMCrypto_SUCCESS) { - LOGE("Failed to generate signature: result = %d", static_cast(res)); - signature.clear(); - } else { - signature.resize(signature_size); - } - return signature; -} - -size_t RsaPrivateKey::SignatureSize() const { return RSA_size(key_); } - -OEMCryptoResult RsaPrivateKey::DecryptSessionKey( - const uint8_t* enc_session_key, size_t enc_session_key_size, - uint8_t* session_key, size_t* session_key_size) const { - if (enc_session_key == nullptr || enc_session_key_size == 0) { - LOGE("Encrypted session key is %s", enc_session_key ? "empty" : "null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (session_key_size == nullptr) { - LOGE("Output session key size buffer is null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (session_key == nullptr && *session_key_size > 0) { - LOGE("Output session key buffer is null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (*session_key_size < kRsaSessionKeySize) { - *session_key_size = kRsaSessionKeySize; - return OEMCrypto_ERROR_SHORT_BUFFER; - } - const OEMCryptoResult result = DecryptOaep( - enc_session_key, enc_session_key_size, session_key, kRsaSessionKeySize); - if (result == OEMCrypto_SUCCESS) { - *session_key_size = kRsaSessionKeySize; - } else { - LOGE("Failed to decrypt session key"); - } - return result; -} - -std::vector RsaPrivateKey::DecryptSessionKey( - const std::vector& enc_session_key) const { - size_t session_key_size = kRsaSessionKeySize; - std::vector session_key(session_key_size, 0); - const OEMCryptoResult res = - DecryptSessionKey(enc_session_key.data(), enc_session_key.size(), - session_key.data(), &session_key_size); - if (res != OEMCrypto_SUCCESS) { - session_key.clear(); - } else { - session_key.resize(session_key_size); - } - return session_key; -} - -std::vector RsaPrivateKey::DecryptSessionKey( - const std::string& enc_session_key) const { - size_t session_key_size = kRsaSessionKeySize; - std::vector session_key(session_key_size, 0); - const OEMCryptoResult res = DecryptSessionKey( - reinterpret_cast(enc_session_key.data()), - enc_session_key.size(), session_key.data(), &session_key_size); - if (res != OEMCrypto_SUCCESS) { - session_key.clear(); - } else { - session_key.resize(session_key_size); - } - return session_key; -} - -size_t RsaPrivateKey::SessionKeyLength() const { return kRsaSessionKeySize; } - -OEMCryptoResult RsaPrivateKey::DecryptEncryptionKey( - const uint8_t* enc_encryption_key, size_t enc_encryption_key_size, - uint8_t* encryption_key, size_t* encryption_key_size) const { - if (enc_encryption_key == nullptr || enc_encryption_key_size == 0) { - LOGE("Encrypted encryption key is %s", - enc_encryption_key ? "empty" : "null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (encryption_key_size == nullptr) { - LOGE("Output encryption key size buffer is null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (encryption_key == nullptr && *encryption_key_size > 0) { - LOGE("Output encryption key buffer is null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (*encryption_key_size < kEncryptionKeySize) { - *encryption_key_size = kEncryptionKeySize; - return OEMCrypto_ERROR_SHORT_BUFFER; - } - const OEMCryptoResult result = - DecryptOaep(enc_encryption_key, enc_encryption_key_size, encryption_key, - kEncryptionKeySize); - if (result == OEMCrypto_SUCCESS) { - *encryption_key_size = kEncryptionKeySize; - } else { - LOGE("Failed to decrypt encryption key"); - } - return result; -} - -std::vector RsaPrivateKey::DecryptEncryptionKey( - const std::vector& enc_encryption_key) const { - size_t encryption_key_size = kEncryptionKeySize; - std::vector encryption_key(encryption_key_size, 0); - const OEMCryptoResult res = - DecryptEncryptionKey(enc_encryption_key.data(), enc_encryption_key.size(), - encryption_key.data(), &encryption_key_size); - if (res != OEMCrypto_SUCCESS) { - encryption_key.clear(); - } else { - encryption_key.resize(encryption_key_size); - } - return encryption_key; -} - -std::vector RsaPrivateKey::DecryptEncryptionKey( - const std::string& enc_encryption_key) const { - size_t encryption_key_size = kEncryptionKeySize; - std::vector encryption_key(encryption_key_size, 0); - const OEMCryptoResult res = DecryptEncryptionKey( - reinterpret_cast(enc_encryption_key.data()), - enc_encryption_key.size(), encryption_key.data(), &encryption_key_size); - if (res != OEMCrypto_SUCCESS) { - encryption_key.clear(); - } else { - encryption_key.resize(encryption_key_size); - } - return encryption_key; -} - -RsaPrivateKey::~RsaPrivateKey() { - if (key_ != nullptr) { - RSA_free(key_); - key_ = nullptr; - } - allowed_schemes_ = 0; - explicit_schemes_ = false; - field_size_ = kRsaFieldUnknown; -} - -bool RsaPrivateKey::InitFromBuffer(const uint8_t* buffer, size_t length) { - if (length < 8) { - LOGE("Public key is too small: length = %zu", length); - return false; - } - ScopedBio bio; - // Check allowed scheme type. - if (!memcmp("SIGN", buffer, 4)) { - uint32_t allowed_schemes; - memcpy(&allowed_schemes, reinterpret_cast(&buffer[4]), 4); - allowed_schemes_ = ntohl(allowed_schemes); - bio.reset(BIO_new_mem_buf(&buffer[8], length - 8)); - explicit_schemes_ = true; - } else { - allowed_schemes_ = kSign_RSASSA_PSS; - bio.reset(BIO_new_mem_buf(buffer, length)); - } - if (!bio) { - LOGE("Failed to allocate BIO buffer"); - return false; - } - // Step 1: Deserializes PKCS8 RSA private key info. - ScopedRsaPrivKeyInfo priv_info( - d2i_PKCS8_PRIV_KEY_INFO_bio(bio.get(), nullptr)); - if (!priv_info) { - LOGE("Failed to parse private key"); - return false; - } - // Step 2: Convert to RSA key. - ScopedEvpPkey pkey(EVP_PKCS82PKEY(priv_info.get())); - if (!pkey) { - LOGE("Failed to convert PKCS8 to EVP"); - return false; - } - ScopedRsaKey key(EVP_PKEY_get1_RSA(pkey.get())); - if (!key) { - LOGE("Failed to get RSA key"); - return false; - } - const int check = RSA_check_key(key.get()); - if (check == 0) { - LOGE("RSA key parameters are invalid"); - return false; - } else if (check == -1) { - LOGE("Failed to check RSA key"); - return false; - } - // Step 3: Verify field width. - const int bits = RSA_bits(key.get()); - field_size_ = RealBitSizeToFieldSize(bits); - if (field_size_ == kRsaFieldUnknown) { - LOGE("Unsupported RSA key size: bits = %d", bits); - return false; - } - key_ = key.release(); - return true; -} - -bool RsaPrivateKey::InitFromFieldSize(RsaFieldSize field_size) { - if (field_size != kRsa2048Bit && field_size != kRsa3072Bit) { - LOGE("Unsupported RSA field size: bits = %d", static_cast(field_size)); - return false; - } - // Step 1: Create exponent. - ScopedBigNum exp(BN_new()); - if (!exp) { - LOGE("Failed to allocate RSA exponent"); - return false; - } - if (!BN_set_word(exp.get(), RSA_F4)) { - LOGE("Failed to set RSA exponent"); - return false; - } - // Step 2: Generate RSA key. - ScopedRsaKey key(RSA_new()); - if (!key) { - LOGE("Failed to allocate RSA key"); - return false; - } - if (!RSA_generate_key_ex(key.get(), static_cast(field_size), exp.get(), - nullptr)) { - LOGE("Failed to generate RSA key"); - return false; - } - key_ = key.release(); - allowed_schemes_ = kSign_RSASSA_PSS; - field_size_ = field_size; - return true; -} - -OEMCryptoResult RsaPrivateKey::GenerateSignaturePss( - const uint8_t* message, size_t message_length, uint8_t* signature, - size_t* signature_length) const { - // Step 0: Ensure the signature algorithm is supported by key. - if (!(allowed_schemes_ & kSign_RSASSA_PSS)) { - LOGE("RSA key cannot sign using PSS"); - return OEMCrypto_ERROR_INVALID_RSA_KEY; - } - // Step 1: Create a high-level key from RSA key. - ScopedEvpPkey pkey(EVP_PKEY_new()); - if (!pkey) { - LOGE("Failed to allocate PKEY"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (!EVP_PKEY_set1_RSA(pkey.get(), key_)) { - LOGE("Failed to set PKEY RSA key"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - // Step 2a: Setup a EVP MD CTX for PSS Signature Generation. - ScopedEvpMdCtx md_ctx(EVP_MD_CTX_new()); - if (!md_ctx) { - LOGE("Failed to allocate MD CTX"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - EVP_PKEY_CTX* pkey_ctx = nullptr; // Ownership is maintained by |md_ctx| - int res = EVP_DigestSignInit(md_ctx.get(), &pkey_ctx, EVP_sha1(), nullptr, - pkey.get()); - if (res != 1) { - LOGE("Failed to initialize MD CTX for signing"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (pkey_ctx == nullptr) { - LOGE("PKEY CTX is unexpectedly null"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - // Step 2b: Configure OEMCrypto RSASSA-PSS options. - res = EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING); - if (res != 1) { - LOGE("Failed to set PSS padding"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - res = EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, kPssSaltLength); - if (res != 1) { - LOGE("Failed to set PSS salt length"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - res = EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, EVP_sha1()); - if (res != 1) { - LOGE("Failed to set PSS MGF1 MD"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - // Step 3: Digest message. - if (message_length > 0) { - res = EVP_DigestSignUpdate(md_ctx.get(), message, message_length); - if (res != 1) { - LOGE("Failed to update MD"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - } - // Step 4a: Determine size of signature. - size_t actual_signature_length = 0; - res = EVP_DigestSignFinal(md_ctx.get(), nullptr, &actual_signature_length); - if (res != 1) { - LOGE("Failed to determine signature length"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (*signature_length < actual_signature_length) { - *signature_length = actual_signature_length; - return OEMCrypto_ERROR_SHORT_BUFFER; - } - // Step 4b: Generate signature. - res = EVP_DigestSignFinal(md_ctx.get(), signature, signature_length); - if (res != 1) { - LOGE("Failed to perform RSASSA-PSS-SIGN"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - return OEMCrypto_SUCCESS; -} - -OEMCryptoResult RsaPrivateKey::GenerateSignaturePkcs1Cast( - const uint8_t* message, size_t message_length, uint8_t* signature, - size_t* signature_length) const { - // Step 0: Ensure the signature algorithm is supported by key. - if (!(allowed_schemes_ & kSign_PKCS1_Block1)) { - LOGE("RSA key cannot sign PKCS1"); - return OEMCrypto_ERROR_INVALID_RSA_KEY; - } - if (message_length > kRsaPkcs1CastMaxMessageSize) { - LOGE("Message is too large for CAST PKCS1 signature: size = %zu", - message_length); - return OEMCrypto_ERROR_SIGNATURE_FAILURE; - } - // Step 1: Ensure signature buffer is large enough. - const size_t expected_signature_size = static_cast(RSA_size(key_)); - if (*signature_length < expected_signature_size) { - *signature_length = expected_signature_size; - return OEMCrypto_ERROR_SHORT_BUFFER; - } - // Step 2: Encrypt with PKCS1 padding. - const int enc_res = RSA_private_encrypt(message_length, message, signature, - key_, RSA_PKCS1_PADDING); - if (enc_res < 0) { - LOGE("Failed to perform private encryption"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - *signature_length = expected_signature_size; - return OEMCrypto_SUCCESS; -} - -OEMCryptoResult RsaPrivateKey::DecryptOaep( - const uint8_t* enc_message, size_t enc_message_size, uint8_t* message, - size_t expected_message_length) const { - // Step 1: Decrypt using RSAES-OAEP. - std::vector decrypt_buffer(RSA_size(key_)); - const int dec_res = - RSA_private_decrypt(enc_message_size, enc_message, decrypt_buffer.data(), - key_, RSA_PKCS1_OAEP_PADDING); - if (dec_res < 0) { - LOGE("Failed to perform RSAES-OAEP decrypt"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (static_cast(dec_res) != expected_message_length) { - LOGE("Unexpected key size: expected = %zu, actual = %d", - expected_message_length, dec_res); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - // Step 2: Copy decrypted data key. - memcpy(message, decrypt_buffer.data(), expected_message_length); - return OEMCrypto_SUCCESS; -} - -} // namespace wvoec_ref diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_rsa_key.h b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_rsa_key.h deleted file mode 100644 index 478b4bd7..00000000 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_rsa_key.h +++ /dev/null @@ -1,359 +0,0 @@ -// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine License -// Agreement. -// -// Reference implementation of OEMCrypto APIs -// -#ifndef OEMCRYPTO_RSA_KEY_H_ -#define OEMCRYPTO_RSA_KEY_H_ - -#include -#include - -#include -#include -#include - -#include - -#include "OEMCryptoCENCCommon.h" - -namespace wvoec_ref { - -enum RsaFieldSize { - kRsaFieldUnknown = 0, - kRsa2048Bit = 2048, - kRsa3072Bit = 3084 -}; - -// Identifies the RSA signature algorithm to be used when signing -// messages or verifying message signatures. -// The two standard signing algorithms specified by PKCS1 RSA V2.1 -// are RSASSA-PKCS1 and RSASSA-PSS. Each require agreement on a -// set of options. For OEMCrypto, only one set of options are agreed -// upon for each RSA signature scheme. CAST receivers specify a -// special implementation of PKCS1 where the message is already -// digested and encoded when provided. -enum RsaSignatureAlgorithm { - // RSASSA-PSS with default options: - // Hash algorithm: SHA-1 - // MGF: MGF1 with SHA-1 - // Salt length: 20 bytes - // Trailer field: 0xbc - kRsaPssDefault = 0, - // RSASSA-PKCS1 for CAST receivers. - // Assumes message is already digested & encoded. Max message length - // is 83 bytes. - kRsaPkcs1Cast = 1 -}; - -// Returns the string representation of the provided RSA field size. -// Intended for logging purposes. -std::string RsaFieldSizeToString(RsaFieldSize field_size); - -// Compares two OpenSSL/BoringSSL RSA keys to see if their public RSA -// components are matching. -// This function assumes both keys are valid. -// Returns true if they are matching, false otherwise. -bool RsaKeysAreMatchingPair(const RSA* public_key, const RSA* private_key); - -class RsaPrivateKey; - -class RsaPublicKey { - public: - // Creates a new public key equivalent of the provided private key. - static std::unique_ptr New(const RsaPrivateKey& private_key); - - // Loads a serialized RSA public key. - // The provided |buffer| must contain a valid ASN.1 DER encoded - // SubjectPublicKey. This API will reject any RSA key that is not - // approximately to 2048bits or 3072bits. - // - // buffer: SubjectPublicKeyInfo = { - // algorithm: AlgorithmIdentifier = { - // algorithm: OID = rsaEncryption, - // parameters: NULL = null - // }, - // subjectPublicKey: BIT STRING = ... -- ASN.1 DER encoded RSAPublicKey - // } - // - // Failure will occur if the provided |buffer| does not contain a - // valid SubjectPublicKey, or if the specified curve is not - // supported. - static std::unique_ptr Load(const uint8_t* buffer, - size_t length); - static std::unique_ptr Load(const std::string& buffer); - static std::unique_ptr Load(const std::vector& buffer); - - RsaFieldSize field_size() const { return field_size_; } - uint32_t allowed_schemes() const { return allowed_schemes_; } - const RSA* GetRsaKey() const { return key_; } - - // Checks if the provided |private_key| is the RSA private key of this - // public key. - bool IsMatchingPrivateKey(const RsaPrivateKey& private_key) const; - - // Serializes the public key into an ASN.1 DER encoded SubjectPublicKey - // representation. - // On success, |buffer_size| is populated with the number of bytes - // written to |buffer|, and OEMCrypto_SUCCESS is returned. - // If the provided |buffer_size| is too small, - // OEMCrypto_ERROR_SHORT_BUFFER is returned and |buffer_size| is set - // to the required buffer size. - OEMCryptoResult Serialize(uint8_t* buffer, size_t* buffer_size) const; - // Same as above, except directly returns the serialized key. - // Returns an empty vector on error. - std::vector Serialize() const; - - // Verifies the |signature| matches the provided |message| by the - // private equivalent of this public key. - // The signature algorithm can be specified via the |algorithm| field. - // See RsaSignatureAlgorithm for details on each algorithm. - // - // Returns: - // OEMCrypto_SUCCESS if signature is valid - // OEMCrypto_ERROR_SIGNATURE_FAILURE if the signature is invalid - // OEMCrypto_ERROR_UNKNOWN_FAILURE if any error occurs - OEMCryptoResult VerifySignature( - const uint8_t* message, size_t message_length, const uint8_t* signature, - size_t signature_length, - RsaSignatureAlgorithm algorithm = kRsaPssDefault) const; - OEMCryptoResult VerifySignature( - const std::string& message, const std::string& signature, - RsaSignatureAlgorithm algorithm = kRsaPssDefault) const; - OEMCryptoResult VerifySignature( - const std::vector& message, - const std::vector& signature, - RsaSignatureAlgorithm algorithm = kRsaPssDefault) const; - - // Encrypts the OEMCrypto session key used for deriving other keys. - // On success, |enc_session_key_size| is populated with the number - // of bytes written to |enc_session_key|, and OEMCrypto_SUCCESS is - // returned. If the provided |enc_session_key_size| is too small, - // OEMCrypto_ERROR_SHORT_BUFFER is returned and - // |enc_session_key_size| is set to the required buffer size. - OEMCryptoResult EncryptSessionKey(const uint8_t* session_key, - size_t session_key_size, - uint8_t* enc_session_key, - size_t* enc_session_key_size) const; - // Same as above, except directly returns the encrypted key. - std::vector EncryptSessionKey( - const std::vector& session_key) const; - std::vector EncryptSessionKey(const std::string& session_key) const; - - // Encrypts the OEMCrypto encryption key used for encrypting the - // DRM private key. - // On success, |enc_encryption_key_size| is populated with the - // number of bytes written to |enc_encryption_key|, and - // OEMCrypto_SUCCESS is returned. - // If the provided |enc_encryption_key_size| is too small, - // OEMCrypto_ERROR_SHORT_BUFFER is returned and - // |enc_encryption_key_size| is set to the required buffer size. - OEMCryptoResult EncryptEncryptionKey(const uint8_t* encryption_key, - size_t encryption_key_size, - uint8_t* enc_encryption_key, - size_t* enc_encryption_key_size) const; - // Same as above, except directly returns the encrypted key. - std::vector EncryptEncryptionKey( - const std::vector& encryption_key) const; - std::vector EncryptEncryptionKey( - const std::string& encryption_key) const; - - ~RsaPublicKey(); - - RsaPublicKey(const RsaPublicKey&) = delete; - RsaPublicKey(RsaPublicKey&&) = delete; - const RsaPublicKey& operator=(const RsaPublicKey&) = delete; - RsaPublicKey& operator=(RsaPublicKey&&) = delete; - - private: - RsaPublicKey() {} - - // Initializes the public key object using the provided |buffer|. - // In case of any failure, false is return and the key should be - // discarded. - bool InitFromBuffer(const uint8_t* buffer, size_t length); - // Initializes the public key object from a private. - bool InitFromPrivateKey(const RsaPrivateKey& private_key); - - // Signature specialization functions. - OEMCryptoResult VerifySignaturePss(const uint8_t* message, - size_t message_length, - const uint8_t* signature, - size_t signature_length) const; - OEMCryptoResult VerifySignaturePkcs1Cast(const uint8_t* message, - size_t message_length, - const uint8_t* signature, - size_t signature_length) const; - - // RSAES-OAEP encrypt. - OEMCryptoResult EncryptOaep(const uint8_t* message, size_t message_size, - uint8_t* enc_message, - size_t* enc_message_length) const; - - // OpenSSL/BoringSSL implementation of an RSA key. - // Will only include components of an RSA public key. - RSA* key_ = nullptr; - uint32_t allowed_schemes_ = 0; - RsaFieldSize field_size_ = kRsaFieldUnknown; -}; - -class RsaPrivateKey { - public: - // Creates a new, pseudorandom RSA private key. - static std::unique_ptr New(RsaFieldSize field_size); - - // Loads a serialized RSA private key. - // The provided |buffer| must contain a valid ASN.1 DER encoded - // PrivateKeyInfo (RFC 5208). - // - // buffer: PrivateKeyInfo = { - // version: INTEGER = v1(0), - // privateKeyAlgorithm: OID = rsaEncryption, - // privateKey: OCTET STRING = ..., - // -- BER encoding of RSAPrivateKey (RFC 3447) - // attributes: Attributes = ... -- Optional, not used by OEMCrypto - // } - // Note: If the public key is not included, then it is computed from - // the private. - // - // Failure will occur if the provided |buffer| does not contain a - // valid ECPrivateKey, or if the specified curve is not supported. - static std::unique_ptr Load(const uint8_t* buffer, - size_t length); - static std::unique_ptr Load(const std::string& buffer); - static std::unique_ptr Load( - const std::vector& buffer); - - // Creates a new RSA public key of this private key. - // Equivalent to calling RsaPublicKey::New with this private - // key. - std::unique_ptr MakePublicKey() const; - - RsaFieldSize field_size() const { return field_size_; } - uint32_t allowed_schemes() const { return allowed_schemes_; } - const RSA* GetRsaKey() const { return key_; } - - // Checks if the provided |public_key| is the RSA public key of this - // private key. - bool IsMatchingPublicKey(const RsaPublicKey& public_key) const; - - // Serializes the private key into an ASN.1 DER encoded X - // representation. - // On success, |buffer_size| is populated with the number of bytes - // written to |buffer|, and OEMCrypto_SUCCESS is returned. - // If the provided |buffer_size| is too small, - // OEMCrypto_ERROR_SHORT_BUFFER is returned and |buffer_size| is - // set to the required buffer size. - OEMCryptoResult Serialize(uint8_t* buffer, size_t* buffer_size) const; - // Same as above, except directly returns the serialized key. - // Returns an empty vector on error. - std::vector Serialize() const; - - // Signs the provided |message| using the RSA signing algorithm - // specified by |algorithm|. See RsaSignatureAlgorithm for - // details on each algorithm. - // - // On success, |signature_length| is populated with the number of - // bytes written to |signature|, and OEMCrypto_SUCCESS is returned. - // If the provided |signature_length| is too small, - // OEMCrypto_ERROR_SHORT_BUFFER is returned and |signature_length| - // is set to the required signature size. - OEMCryptoResult GenerateSignature(const uint8_t* message, - size_t message_length, - RsaSignatureAlgorithm algorithm, - uint8_t* signature, - size_t* signature_length) const; - // Same as above, except directly returns the serialized signature. - // Returns an empty vector on error. - std::vector GenerateSignature( - const std::vector& message, - RsaSignatureAlgorithm algorithm = kRsaPssDefault) const; - std::vector GenerateSignature( - const std::string& message, - RsaSignatureAlgorithm algorithm = kRsaPssDefault) const; - // Returns an upper bound for the signature size. May be larger than - // the actual signature generated by GenerateSignature(). - size_t SignatureSize() const; - - // Decrypts the OEMCrypto session key used for deriving other keys. - // On success, |session_key_size| is populated with the number of - // bytes written to |session_key|, and OEMCrypto_SUCCESS is returned. - // If the provided |session_key_size| is too small, - // OEMCrypto_ERROR_SHORT_BUFFER is returned and |session_key_size| - // is set to the required buffer size. - OEMCryptoResult DecryptSessionKey(const uint8_t* enc_session_key, - size_t enc_session_key_size, - uint8_t* session_key, - size_t* session_key_size) const; - // Same as above, except directly returns the decrypted key. - std::vector DecryptSessionKey( - const std::vector& enc_session_key) const; - std::vector DecryptSessionKey( - const std::string& enc_session_key) const; - // Returns the byte length of the symmetric key that would be derived - // by DecryptSessionKey(). - size_t SessionKeyLength() const; - - // Decrypts the OEMCrypto encryption key used for decrypting DRM - // private key. - // On success, |encryption_key_size| is populated with the number of - // bytes written to |encryption_key|, and OEMCrypto_SUCCESS is - // returned. - // If the provided |encryption_key_size| is too small, - // OEMCrypto_ERROR_SHORT_BUFFER is returned and |encryption_key_size| - // is set to the required buffer size. - OEMCryptoResult DecryptEncryptionKey(const uint8_t* enc_encryption_key, - size_t enc_encryption_key_size, - uint8_t* encryption_key, - size_t* encryption_key_size) const; - // Same as above, except directly returns the decrypted key. - std::vector DecryptEncryptionKey( - const std::vector& enc_encryption_key) const; - std::vector DecryptEncryptionKey( - const std::string& enc_encryption_key) const; - - ~RsaPrivateKey(); - - RsaPrivateKey(const RsaPrivateKey&) = delete; - RsaPrivateKey(RsaPrivateKey&&) = delete; - const RsaPrivateKey& operator=(const RsaPrivateKey&) = delete; - RsaPrivateKey& operator=(RsaPrivateKey&&) = delete; - - private: - RsaPrivateKey() {} - - // Initializes the public key object using the provided |buffer|. - // In case of any failure, false is return and the key should be - // discarded. - bool InitFromBuffer(const uint8_t* buffer, size_t length); - // Generates a new key based on the provided field size. - bool InitFromFieldSize(RsaFieldSize field_size); - - // Signature specialization functions. - OEMCryptoResult GenerateSignaturePss(const uint8_t* message, - size_t message_length, - uint8_t* signature, - size_t* signature_length) const; - OEMCryptoResult GenerateSignaturePkcs1Cast(const uint8_t* message, - size_t message_length, - uint8_t* signature, - size_t* signature_length) const; - - // RSAES-OAEP decrypt. - OEMCryptoResult DecryptOaep(const uint8_t* enc_message, - size_t enc_message_size, uint8_t* message, - size_t expected_message_length) const; - - // OpenSSL/BoringSSL implementation of an RSA key. - // Will include all components of an RSA private key. - RSA* key_ = nullptr; - uint32_t allowed_schemes_ = 0; - // Set true if the deserialized key contained an allowed schemes. - bool explicit_schemes_ = false; - RsaFieldSize field_size_ = kRsaFieldUnknown; -}; - -} // namespace wvoec_ref - -#endif // OEMCRYPTO_RSA_KEY_H_ diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.cpp deleted file mode 100644 index 657867aa..00000000 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.cpp +++ /dev/null @@ -1,1782 +0,0 @@ -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine -// License Agreement. -// -// Reference implementation of OEMCrypto APIs -// -#include "oemcrypto_session.h" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "advance_iv_ctr.h" -#include "keys.h" -#include "log.h" -#include "odk.h" -#include "oemcrypto_engine_ref.h" -#include "oemcrypto_key_ref.h" -#include "oemcrypto_types.h" -#include "platform.h" -#include "string_conversions.h" -#include "wvcrc32.h" - -namespace wvoec_ref { -namespace { - -// Increment counter for AES-CTR. The CENC spec specifies we increment only -// the low 64 bits of the IV counter, and leave the high 64 bits alone. -void ctr128_inc64(uint8_t* counter) { - uint32_t n = 16; - do { - if (++counter[--n] != 0) return; - } while (n > 8); -} - -void advance_dest_buffer(OEMCrypto_DestBufferDesc* dest_buffer, size_t bytes) { - switch (dest_buffer->type) { - case OEMCrypto_BufferType_Clear: - dest_buffer->buffer.clear.address += bytes; - dest_buffer->buffer.clear.address_length -= bytes; - break; - - case OEMCrypto_BufferType_Secure: - dest_buffer->buffer.secure.offset += bytes; - break; - - case OEMCrypto_BufferType_Direct: - // Nothing to do for this buffer type. - break; - } -} -} // namespace - -/***************************************/ - -class ContentKeysContext : public SessionContextKeys { - public: - explicit ContentKeysContext() {} - ~ContentKeysContext() override {} - size_t size() override { return session_keys_.size(); } - bool Insert(const KeyId& key_id, const Key& key_data) override; - Key* Find(const KeyId& key_id) override; - Key* FirstKey() override; - void Remove(const KeyId& key_id) override; - void UpdateDuration(const KeyControlBlock& control) override; - - OEMCrypto_LicenseType type() override { return OEMCrypto_ContentLicense; } - - bool SetContentKey(const KeyId& entitlement_id, const KeyId& content_key_id, - const std::vector& content_key) override; - EntitlementKey* GetEntitlementKey(const KeyId& entitlement_id) override; - - private: - SessionKeyTable session_keys_; - CORE_DISALLOW_COPY_AND_ASSIGN(ContentKeysContext); -}; - -bool ContentKeysContext::Insert(const KeyId& key_id, const Key& key_data) { - return session_keys_.Insert(key_id, key_data); -} - -Key* ContentKeysContext::Find(const KeyId& key_id) { - return session_keys_.Find(key_id); -} - -Key* ContentKeysContext::FirstKey() { return session_keys_.FirstKey(); } - -void ContentKeysContext::Remove(const KeyId& key_id) { - session_keys_.Remove(key_id); -} - -void ContentKeysContext::UpdateDuration(const KeyControlBlock& control) { - session_keys_.UpdateDuration(control); -} - -bool ContentKeysContext::SetContentKey( - const KeyId& entitlement_id, const KeyId& content_key_id, - const std::vector& content_key) { - // Unsupported action for this type. - return false; -} - -EntitlementKey* ContentKeysContext::GetEntitlementKey( - const KeyId& entitlement_id) { - // Unsupported action for this type. - return nullptr; -} - -/***************************************/ - -class EntitlementKeysContext : public SessionContextKeys { - public: - EntitlementKeysContext() {} - ~EntitlementKeysContext() override {} - size_t size() override { return session_keys_.size(); } - bool Insert(const KeyId& key_id, const Key& key_data) override; - Key* Find(const KeyId& key_id) override; - Key* FirstKey() override; - void Remove(const KeyId& key_id) override; - void UpdateDuration(const KeyControlBlock& control) override; - bool SetContentKey(const KeyId& entitlement_id, const KeyId& content_key_id, - const std::vector& content_key) override; - EntitlementKey* GetEntitlementKey(const KeyId& entitlement_id) override; - - OEMCrypto_LicenseType type() override { return OEMCrypto_EntitlementLicense; } - - private: - EntitlementKeyTable session_keys_; - CORE_DISALLOW_COPY_AND_ASSIGN(EntitlementKeysContext); -}; - -bool EntitlementKeysContext::Insert(const KeyId& key_id, const Key& key_data) { - return session_keys_.Insert(key_id, key_data); -} - -Key* EntitlementKeysContext::Find(const KeyId& key_id) { - return session_keys_.Find(key_id); -} - -Key* EntitlementKeysContext::FirstKey() { return session_keys_.FirstKey(); } - -void EntitlementKeysContext::Remove(const KeyId& key_id) { - session_keys_.Remove(key_id); -} - -void EntitlementKeysContext::UpdateDuration(const KeyControlBlock& control) { - session_keys_.UpdateDuration(control); -} - -bool EntitlementKeysContext::SetContentKey( - const KeyId& entitlement_id, const KeyId& content_key_id, - const std::vector& content_key) { - return session_keys_.SetContentKey(entitlement_id, content_key_id, - content_key); -} - -EntitlementKey* EntitlementKeysContext::GetEntitlementKey( - const KeyId& entitlement_id) { - return session_keys_.GetEntitlementKey(entitlement_id); -} - -/***************************************/ - -SessionContext::SessionContext(CryptoEngine* ce, SessionId sid) - : valid_(ce != nullptr), ce_(ce), id_(sid) { - ODK_InitializeSessionValues(&timer_limits_, &clock_values_, &nonce_values_, - CryptoEngine::kApiVersion, sid); - memset(license_request_hash_, 0, sizeof(license_request_hash_)); -} - -SessionContext::SessionContext(CryptoEngine* ce, SessionId sid, - std::shared_ptr&& rsa_key) - : SessionContext(ce, sid) { - rsa_key_ = std::move(rsa_key); -} - -SessionContext::~SessionContext() {} - -// Internal utility function to derive key using CMAC-128 -bool SessionContext::DeriveKey(const std::vector& key, - const std::vector& context, int counter, - std::vector* out) { - if (key.empty() || counter > 4 || context.empty() || out == nullptr) { - LOGE("[DeriveKey(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return false; - } - - const EVP_CIPHER* cipher = EVP_aes_128_cbc(); - CMAC_CTX* cmac_ctx = CMAC_CTX_new(); - - if (!cmac_ctx) { - LOGE("[DeriveKey(): OEMCrypto_ERROR_CMAC_FAILURE]"); - return false; - } - - if (!CMAC_Init(cmac_ctx, &key[0], key.size(), cipher, 0)) { - LOGE("[DeriveKey(): OEMCrypto_ERROR_CMAC_FAILURE]"); - CMAC_CTX_free(cmac_ctx); - return false; - } - - std::vector message; - message.push_back(counter); - message.insert(message.end(), context.begin(), context.end()); - - if (!CMAC_Update(cmac_ctx, &message[0], message.size())) { - LOGE("[DeriveKey(): OEMCrypto_ERROR_CMAC_FAILURE]"); - CMAC_CTX_free(cmac_ctx); - return false; - } - - size_t reslen; - uint8_t res[128]; - if (!CMAC_Final(cmac_ctx, res, &reslen)) { - LOGE("[DeriveKey(): OEMCrypto_ERROR_CMAC_FAILURE]"); - CMAC_CTX_free(cmac_ctx); - return false; - } - - out->assign(res, res + reslen); - - CMAC_CTX_free(cmac_ctx); - - return true; -} - -OEMCryptoResult SessionContext::DeriveKeys( - const std::vector& master_key, - const std::vector& mac_key_context, - const std::vector& enc_key_context) { - // Generate derived key for mac key - std::vector mac_key_server; - std::vector mac_key_client; - std::vector mac_key_part2; - if (!DeriveKey(master_key, mac_key_context, 1, &mac_key_server)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (!DeriveKey(master_key, mac_key_context, 2, &mac_key_part2)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - mac_key_server.insert(mac_key_server.end(), mac_key_part2.begin(), - mac_key_part2.end()); - - if (!DeriveKey(master_key, mac_key_context, 3, &mac_key_client)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (!DeriveKey(master_key, mac_key_context, 4, &mac_key_part2)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - mac_key_client.insert(mac_key_client.end(), mac_key_part2.begin(), - mac_key_part2.end()); - - // Generate derived key for encryption key - std::vector enc_key; - if (!DeriveKey(master_key, enc_key_context, 1, &enc_key)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - - set_mac_key_server(mac_key_server); - set_mac_key_client(mac_key_client); - set_encryption_key(enc_key); - return OEMCrypto_SUCCESS; -} - -OEMCryptoResult SessionContext::RSADeriveKeys( - const std::vector& enc_session_key, - const std::vector& mac_key_context, - const std::vector& enc_key_context) { - if (!rsa_key_) { - LOGE("No RSA key set"); - return OEMCrypto_ERROR_DEVICE_NOT_RSA_PROVISIONED; - } - if (!(rsa_key_->allowed_schemes() & kSign_RSASSA_PSS)) { - LOGE("Key cannot be used for session key decryption"); - return OEMCrypto_ERROR_INVALID_RSA_KEY; - } - session_key_ = rsa_key_->DecryptSessionKey(enc_session_key); - if (session_key_.empty()) { - LOGE("Failed decrypt session key"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - return DeriveKeys(session_key_, mac_key_context, enc_key_context); -} - -OEMCryptoResult SessionContext::LoadOemPrivateKey() { - if (!ce_->HasOemPrivateKey()) { - LOGE("No OEM private key"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - rsa_key_ = ce_->ShareOemPrivateKey(); - return OEMCrypto_SUCCESS; -} - -OEMCryptoResult SessionContext::PrepAndSignLicenseRequest( - uint8_t* message, size_t message_length, size_t* core_message_length, - uint8_t* signature, size_t* signature_length) { - if (signature_length == nullptr || core_message_length == nullptr) { - LOGE("Output length parameters are null"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (!rsa_key_) { - LOGE("No DRM key available for signature"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - const size_t required_signature_size = CertSignatureSize(); - OEMCryptoResult result = ODK_PrepareCoreLicenseRequest( - message, message_length, core_message_length, &nonce_values_); - if (*signature_length < required_signature_size || - result == OEMCrypto_ERROR_SHORT_BUFFER) { - *signature_length = required_signature_size; - return OEMCrypto_ERROR_SHORT_BUFFER; - } - if (result != OEMCrypto_SUCCESS) { - LOGE("ODK error: %d", static_cast(result)); - return result; - } - if (message == nullptr || message_length < *core_message_length || - signature == nullptr) { - LOGE("OEMCrypto_ERROR_INVALID_CONTEXT"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (state_request_signed_) { - LOGE("Attempt to sign two license requests"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - // For backwards compatibility, we only sign the message body, and we compute - // a SHA256 of the core message. - SHA256(message, *core_message_length, license_request_hash_); - const uint8_t* message_body = message + *core_message_length; - const size_t message_body_length = message_length - *core_message_length; - result = GenerateCertSignature(message_body, message_body_length, signature, - signature_length); - if (result == OEMCrypto_SUCCESS) { - state_request_signed_ = true; - result = ODK_InitializeClockValues(&clock_values_, ce_->SystemTime()); - } - return result; -} - -OEMCryptoResult SessionContext::PrepAndSignRenewalRequest( - uint8_t* message, size_t message_length, size_t* core_message_length, - uint8_t* signature, size_t* signature_length) { - if (signature_length == nullptr || core_message_length == nullptr) { - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - // If we have signed a request, but have not loaded it, something is wrong. - // On the other hand, we can sign a license release using the mac keys from - // the usage table. So it is OK if we have never signed a license request. - if (state_request_signed_ && !state_response_loaded_) { - LOGE("Attempt to sign renewal before load"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - const size_t required_signature_size = SHA256_DIGEST_LENGTH; - const uint64_t now = ce_->SystemTime(); - const OEMCryptoResult result = ODK_PrepareCoreRenewalRequest( - message, message_length, core_message_length, &nonce_values_, - &clock_values_, now); - if (*signature_length < required_signature_size || - result == OEMCrypto_ERROR_SHORT_BUFFER) { - *signature_length = required_signature_size; - return OEMCrypto_ERROR_SHORT_BUFFER; - } - if (result != OEMCrypto_SUCCESS) { - LOGE("ODK error: %d", static_cast(result)); - return result; - } - if (message == nullptr || message_length < *core_message_length || - signature == nullptr) { - LOGE("OEMCrypto_ERROR_INVALID_CONTEXT"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - // If we are talking to an old license server, then we only sign the message - // body. - if (nonce_values_.api_major_version < 16) { - const uint8_t* message_body = message + *core_message_length; - const size_t message_body_length = message_length - *core_message_length; - return GenerateSignature(message_body, message_body_length, signature, - signature_length); - } else { - return GenerateSignature(message, message_length, signature, - signature_length); - } -} - -OEMCryptoResult SessionContext::PrepAndSignProvisioningRequest( - uint8_t* message, size_t message_length, size_t* core_message_length, - uint8_t* signature, size_t* signature_length) { - if (signature_length == nullptr || core_message_length == nullptr) { - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (!rsa_key_ && mac_key_client_.empty()) { - LOGE("Session cannot sign request"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (state_request_signed_) { - LOGE("Attempt to sign prov request after license request"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - const size_t required_signature_size = ROTSignatureSize(); - if (required_signature_size == 0) return OEMCrypto_ERROR_UNKNOWN_FAILURE; - const std::vector device_id = ce_->DeviceRootId(); - OEMCryptoResult result = ODK_PrepareCoreProvisioningRequest( - message, message_length, core_message_length, &nonce_values_, - device_id.data(), device_id.size()); - if (*signature_length < required_signature_size || - result == OEMCrypto_ERROR_SHORT_BUFFER) { - *signature_length = required_signature_size; - return OEMCrypto_ERROR_SHORT_BUFFER; - } - if (result != OEMCrypto_SUCCESS) { - LOGE("ODK error: %d", static_cast(result)); - return result; - } - if (message == nullptr || message_length == 0 || signature == nullptr) { - LOGE("OEMCrypto_ERROR_INVALID_CONTEXT"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (ce_->config_provisioning_method() == OEMCrypto_Keybox) { - result = - GenerateSignature(message, message_length, signature, signature_length); - } else if (ce_->config_provisioning_method() == OEMCrypto_OEMCertificate) { - result = GenerateCertSignature(message, message_length, signature, - signature_length); - } else { - LOGE("Bad prov method = %d", - static_cast(ce_->config_provisioning_method())); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (result == OEMCrypto_SUCCESS) state_request_signed_ = true; - return result; -} - -// Utility function to generate a message signature -OEMCryptoResult SessionContext::GenerateSignature(const uint8_t* message, - size_t message_length, - uint8_t* signature, - size_t* signature_length) { - if (message == nullptr || message_length == 0 || signature == nullptr || - signature_length == nullptr) { - LOGE("OEMCrypto_ERROR_INVALID_CONTEXT"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (mac_key_client_.size() != wvoec::MAC_KEY_SIZE) { - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (*signature_length != SHA256_DIGEST_LENGTH) { - *signature_length = SHA256_DIGEST_LENGTH; - return OEMCrypto_ERROR_SHORT_BUFFER; - } - unsigned int md_len = *signature_length; - if (HMAC(EVP_sha256(), &mac_key_client_[0], wvoec::MAC_KEY_SIZE, message, - message_length, signature, &md_len)) { - *signature_length = md_len; - return OEMCrypto_SUCCESS; - } - return OEMCrypto_ERROR_UNKNOWN_FAILURE; -} - -size_t SessionContext::CertSignatureSize() const { - if (!rsa_key_) { - LOGE("No RSA key set"); - return 0; - } - return rsa_key_->SignatureSize(); -} - -size_t SessionContext::ROTSignatureSize() const { - if (ce_->config_provisioning_method() == OEMCrypto_Keybox) - return SHA256_DIGEST_LENGTH; - if (ce_->config_provisioning_method() == OEMCrypto_OEMCertificate) { - return CertSignatureSize(); - } - LOGE("Bad prov method = %d", - static_cast(ce_->config_provisioning_method())); - return 0; -} - -OEMCryptoResult SessionContext::GenerateCertSignature( - const uint8_t* message, size_t message_length, uint8_t* signature, - size_t* signature_length) { - if (!rsa_key_) { - LOGE("No RSA key set"); - return OEMCrypto_ERROR_INVALID_RSA_KEY; - } - return rsa_key_->GenerateSignature(message, message_length, kRsaPssDefault, - signature, signature_length); -} - -OEMCryptoResult SessionContext::GenerateRSASignature( - const uint8_t* message, size_t message_length, uint8_t* signature, - size_t* signature_length, RSA_Padding_Scheme padding_scheme) { - if (padding_scheme != kSign_PKCS1_Block1) { - LOGE("Only PKCS1 block1 padding scheme allowed"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (!rsa_key_) { - LOGE("No RSA key set"); - return OEMCrypto_ERROR_INVALID_RSA_KEY; - } - return rsa_key_->GenerateSignature(message, message_length, kRsaPkcs1Cast, - signature, signature_length); -} - -// Validate message signature -bool SessionContext::ValidateMessage(const uint8_t* given_message, - size_t message_length, - const uint8_t* given_signature, - size_t signature_length) { - if (signature_length != SHA256_DIGEST_LENGTH) { - return false; - } - uint8_t computed_signature[SHA256_DIGEST_LENGTH]; - memset(computed_signature, 0, SHA256_DIGEST_LENGTH); - unsigned int md_len = SHA256_DIGEST_LENGTH; - if (!HMAC(EVP_sha256(), mac_key_server_.data(), mac_key_server_.size(), - given_message, message_length, computed_signature, &md_len)) { - LOGE("ValidateMessage: Could not compute signature"); - return false; - } - if (CRYPTO_memcmp(given_signature, computed_signature, signature_length)) { - LOGE("Invalid signature given: %s", - wvcdm::HexEncode(given_signature, signature_length).c_str()); - LOGE("Invalid signature computed: %s", - wvcdm::HexEncode(computed_signature, signature_length).c_str()); - return false; - } - return true; -} - -OEMCryptoResult SessionContext::CheckStatusOnline(uint32_t nonce, - uint32_t control) { - if (!(control & wvoec::kControlNonceEnabled)) { - LOGE("LoadKeys: Server provided Nonce_Required but Nonce_Enabled = 0"); - // Server error. Continue, and assume nonce required. - } - if (!CheckNonce(nonce)) return OEMCrypto_ERROR_INVALID_NONCE; - switch (usage_entry_status_) { - case kNoUsageEntry: - LOGE("LoadKeys: Session did not create usage entry"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - case kUsageEntryLoaded: - LOGE("LoadKeys: Session reloaded existing entry"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - case kUsageEntryNew: - return OEMCrypto_SUCCESS; - default: // invalid status. - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } -} - -OEMCryptoResult SessionContext::CheckStatusOffline(uint32_t nonce, - uint32_t control) { - if (control & wvoec::kControlNonceEnabled) { - LOGE("KCB: Server provided NonceOrEntry but Nonce_Enabled = 1"); - // Server error. Continue, and assume nonce required. - } - switch (usage_entry_status_) { - case kNoUsageEntry: - LOGE("LoadKeys: Session did not create or load usage entry"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - case kUsageEntryLoaded: - // Repeat load. Calling function will verify pst and keys. - return OEMCrypto_SUCCESS; - case kUsageEntryNew: - // First load. Verify nonce. - if (!CheckNonce(nonce)) return OEMCrypto_ERROR_INVALID_NONCE; - return OEMCrypto_SUCCESS; - default: // invalid status. - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } -} - -OEMCryptoResult SessionContext::CheckNonceOrEntry( - const KeyControlBlock& key_control_block) { - switch (key_control_block.control_bits() & wvoec::kControlReplayMask) { - case wvoec::kControlNonceRequired: // Online license. Nonce always - // required. - return CheckStatusOnline(key_control_block.nonce(), - key_control_block.control_bits()); - break; - case wvoec::kControlNonceOrEntry: // Offline license. Nonce required on - // first use. - return CheckStatusOffline(key_control_block.nonce(), - key_control_block.control_bits()); - break; - default: - if ((key_control_block.control_bits() & wvoec::kControlNonceEnabled) && - (!CheckNonce(key_control_block.nonce()))) { - LOGE("LoadKeys: BAD Nonce"); - return OEMCrypto_ERROR_INVALID_NONCE; - } - } - return OEMCrypto_SUCCESS; -} - -OEMCryptoResult SessionContext::LoadLicense(const uint8_t* message, - size_t message_length, - size_t core_message_length, - const uint8_t* signature, - size_t signature_length) { - // Check state before we check signature. State is change in - // LoadKeysNoSignature. - if (state_response_loaded_) { - return OEMCrypto_ERROR_LICENSE_RELOAD; - } - ODK_ParsedLicense parsed_response; - const bool initial_license_load = (usage_entry_status_ != kUsageEntryLoaded); - const OEMCryptoResult result = ODK_ParseLicense( - message, message_length, core_message_length, initial_license_load, - usage_entry_present(), license_request_hash_, &timer_limits_, - &clock_values_, &nonce_values_, &parsed_response); - if (result != OEMCrypto_SUCCESS) { - LOGE("ODK Error %d", static_cast(result)); - return result; - } - // Validate message signature - if (!ValidateMessage(message, message_length, signature, signature_length)) { - return OEMCrypto_ERROR_SIGNATURE_FAILURE; - } - const uint8_t* message_body = message + core_message_length; - const size_t message_body_length = message_length - core_message_length; - return LoadKeysNoSignature( - message_body, message_body_length, parsed_response.enc_mac_keys_iv, - parsed_response.enc_mac_keys, parsed_response.key_array_length, - parsed_response.key_array, parsed_response.pst, - parsed_response.srm_restriction_data, - static_cast(parsed_response.license_type)); -} - -OEMCryptoResult SessionContext::LoadKeys( - const uint8_t* message, size_t message_length, const uint8_t* signature, - size_t signature_length, OEMCrypto_Substring enc_mac_keys_iv, - OEMCrypto_Substring enc_mac_keys, size_t num_keys, - const OEMCrypto_KeyObject* key_array, OEMCrypto_Substring pst, - OEMCrypto_Substring srm_restriction_data, - OEMCrypto_LicenseType license_type) { - // Check state before we check signature. State is change in - // LoadKeysNoSignature. - if (state_response_loaded_) { - return OEMCrypto_ERROR_LICENSE_RELOAD; - } - // Validate message signature - if (!ValidateMessage(message, message_length, signature, signature_length)) { - return OEMCrypto_ERROR_SIGNATURE_FAILURE; - } - OEMCryptoResult result = LoadKeysNoSignature( - message, message_length, enc_mac_keys_iv, enc_mac_keys, num_keys, - key_array, pst, srm_restriction_data, license_type); - if (result != OEMCrypto_SUCCESS) return result; - Key* key = session_keys_->FirstKey(); - uint32_t duration = key ? key->control().duration() : 0; - result = ODK_InitializeV15Values(&timer_limits_, &clock_values_, - &nonce_values_, duration, ce_->SystemTime()); - // TODO(b/140765227): clear session on errors - return result; -} - -OEMCryptoResult SessionContext::LoadKeysNoSignature( - const uint8_t* message, size_t message_length, - OEMCrypto_Substring enc_mac_keys_iv, OEMCrypto_Substring enc_mac_keys, - size_t num_keys, const OEMCrypto_KeyObject* key_array, - OEMCrypto_Substring pst, OEMCrypto_Substring srm_restriction_data, - OEMCrypto_LicenseType license_type) { - if (state_response_loaded_) { - return OEMCrypto_ERROR_LICENSE_RELOAD; - } - state_response_loaded_ = true; - if (num_keys < 1) return OEMCrypto_ERROR_INVALID_CONTEXT; - - if (session_keys_ == nullptr) { - switch (license_type) { - case OEMCrypto_ContentLicense: - session_keys_.reset(new ContentKeysContext()); - break; - - case OEMCrypto_EntitlementLicense: - session_keys_.reset(new EntitlementKeysContext()); - break; - - default: - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - } else { - if (session_keys_->type() != license_type) { - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - } - if (srm_restriction_data.length != 0) { - const std::string kSRMVerificationString = "HDCPDATA"; - if (memcmp(message + srm_restriction_data.offset, - kSRMVerificationString.c_str(), kSRMVerificationString.size())) { - LOGE("SRM Requirement Data has bad verification string: %8s", - message + srm_restriction_data.offset); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - const uint32_t minimum_version = htonl(*reinterpret_cast( - message + srm_restriction_data.offset + 8)); - uint16_t current_version = 0; - if (OEMCrypto_SUCCESS != ce_->current_srm_version(¤t_version)) { - LOGW("[LoadKeys: SRM Version not available"); - srm_requirements_status_ = InvalidSRMVersion; - } else if (current_version < minimum_version) { - LOGW("[LoadKeys: SRM Version is too small %u, required: %u", - current_version, minimum_version); - srm_requirements_status_ = InvalidSRMVersion; - } else if (ce_->srm_forbidden_device_attached()) { - LOGW("[LoadKeys: SRM forbidden device attached]"); - srm_requirements_status_ = InvalidSRMVersion; - } else { - LOGI("[LoadKeys: SRM Versions is %u, required: %u]", current_version, - minimum_version); - srm_requirements_status_ = ValidSRMVersion; - } - } - - // Decrypt and install keys in key object - // Each key will have a key control block. They will all have the same nonce. - OEMCryptoResult status = OEMCrypto_SUCCESS; - std::vector key_id; - std::vector enc_key_data; - std::vector key_data_iv; - std::vector key_control; - std::vector key_control_iv; - for (unsigned int i = 0; i < num_keys; i++) { - key_id.assign( - message + key_array[i].key_id.offset, - message + key_array[i].key_id.offset + key_array[i].key_id.length); - enc_key_data.assign( - message + key_array[i].key_data.offset, - message + key_array[i].key_data.offset + key_array[i].key_data.length); - key_data_iv.assign( - message + key_array[i].key_data_iv.offset, - message + key_array[i].key_data_iv.offset + wvoec::KEY_IV_SIZE); - if (key_array[i].key_control.length == 0) { - status = OEMCrypto_ERROR_UNKNOWN_FAILURE; - break; - } - key_control.assign( - message + key_array[i].key_control.offset, - message + key_array[i].key_control.offset + wvoec::KEY_CONTROL_SIZE); - key_control_iv.assign( - message + key_array[i].key_control_iv.offset, - message + key_array[i].key_control_iv.offset + wvoec::KEY_IV_SIZE); - - OEMCryptoResult result = InstallKey(key_id, enc_key_data, key_data_iv, - key_control, key_control_iv); - if (result != OEMCrypto_SUCCESS) { - status = result; - break; - } - } - if (status != OEMCrypto_SUCCESS) return status; - - // enc_mac_key can be nullptr if license renewal is not supported - if (enc_mac_keys.length != 0) { - // V2.1 license protocol: update mac keys after processing license response - const std::vector enc_mac_keys_str = std::vector( - message + enc_mac_keys.offset, - message + enc_mac_keys.offset + 2 * wvoec::MAC_KEY_SIZE); - const std::vector enc_mac_key_iv_str = std::vector( - message + enc_mac_keys_iv.offset, - message + enc_mac_keys_iv.offset + wvoec::KEY_IV_SIZE); - - if (!UpdateMacKeys(enc_mac_keys_str, enc_mac_key_iv_str)) { - LOGE("Failed to update mac keys."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - } else { - // If the mac keys are not updated, we will not need them again. - mac_key_server_.resize(0); - mac_key_client_.resize(0); - } - - if (usage_entry_) { - OEMCryptoResult result = OEMCrypto_SUCCESS; - switch (usage_entry_status_) { - case kNoUsageEntry: - if (pst.length > 0) { - LOGE("LoadKeys: PST specified but no usage entry loaded"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - break; // no extra check. - case kUsageEntryNew: - result = usage_entry_->SetPST(message + pst.offset, pst.length); - if (result != OEMCrypto_SUCCESS) { - return result; - } - if (!usage_entry_->SetMacKeys(mac_key_server_, mac_key_client_)) { - LOGE("LoadKeys: Usage table can't set keys."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - break; - case kUsageEntryLoaded: - if (!usage_entry_->VerifyPST(message + pst.offset, pst.length)) { - return OEMCrypto_ERROR_WRONG_PST; - } - if (!usage_entry_->VerifyMacKeys(mac_key_server_, mac_key_client_)) { - LOGE("LoadKeys: Usage table entry mac keys do not match."); - return OEMCrypto_ERROR_WRONG_KEYS; - } - if (usage_entry_->Inactive()) return OEMCrypto_ERROR_LICENSE_INACTIVE; - break; - } - } - encryption_key_.clear(); - return OEMCrypto_SUCCESS; -} - -OEMCryptoResult SessionContext::LoadEntitledContentKeys( - const uint8_t* message, size_t message_length, size_t key_array_length, - const OEMCrypto_EntitledContentKeyObject* key_array) { - if (!key_array) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (session_keys_ == nullptr || - session_keys_->type() != OEMCrypto_EntitlementLicense) { - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - for (size_t i = 0; i < key_array_length; ++i) { - const OEMCrypto_EntitledContentKeyObject* key_data = &key_array[i]; - std::vector entitlement_key_id; - entitlement_key_id.assign(message + key_data->entitlement_key_id.offset, - message + key_data->entitlement_key_id.offset + - key_data->entitlement_key_id.length); - - EntitlementKey* entitlement_key = - session_keys_->GetEntitlementKey(entitlement_key_id); - if (entitlement_key == nullptr) { - return OEMCrypto_KEY_NOT_ENTITLED; - } - std::vector content_key; - std::vector iv; - std::vector encrypted_content_key; - std::vector content_key_id; - - iv.assign(message + key_data->content_key_data_iv.offset, - message + key_data->content_key_data_iv.offset + 16); - encrypted_content_key.assign(message + key_data->content_key_data.offset, - message + key_data->content_key_data.offset + - key_data->content_key_data.length); - content_key_id.assign(message + key_data->content_key_id.offset, - message + key_data->content_key_id.offset + - key_data->content_key_id.length); - if (!DecryptMessage(entitlement_key->entitlement_key(), iv, - encrypted_content_key, &content_key, - 256 /* key size */)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (!session_keys_->SetContentKey(entitlement_key_id, content_key_id, - content_key)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - } - return OEMCrypto_SUCCESS; -} - -OEMCryptoResult SessionContext::InstallKey( - const KeyId& key_id, const std::vector& key_data, - const std::vector& key_data_iv, - const std::vector& key_control, - const std::vector& key_control_iv) { - // Decrypt encrypted key_data using derived encryption key and offered iv - std::vector content_key; - std::vector key_control_str; - - if (!DecryptMessage(encryption_key_, key_data_iv, key_data, &content_key, - 128 /* key size */)) { - LOGE("[Installkey(): Could not decrypt key data]"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - - // Key control must be supplied by license server - if (key_control.empty()) { - LOGE("[Installkey(): WARNING: No Key Control]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (key_control_iv.empty()) { - LOGE("[Installkey(): ERROR: No Key Control IV]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (!DecryptMessage(content_key, key_control_iv, key_control, - &key_control_str, 128 /* key size */)) { - LOGE("[Installkey(): ERROR: Could not decrypt content key]"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - - KeyControlBlock key_control_block(key_control_str); - if (!key_control_block.valid()) { - LOGE("Error parsing key control"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if ((key_control_block.control_bits() & - wvoec::kControlRequireAntiRollbackHardware) && - !ce_->config_is_anti_rollback_hw_present()) { - LOGE("Anti-rollback hardware is required but hardware not present"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - const uint8_t minimum_patch_level = (key_control_block.control_bits() & - wvoec::kControlSecurityPatchLevelMask) >> - wvoec::kControlSecurityPatchLevelShift; - if (minimum_patch_level > OEMCrypto_Security_Patch_Level()) { - LOGE("[InstallKey(): security_patch_level = %u, minimum_patch_level = %u]", - OEMCrypto_Security_Patch_Level(), minimum_patch_level); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - OEMCryptoResult result = CheckNonceOrEntry(key_control_block); - if (result != OEMCrypto_SUCCESS) { - LOGE("LoadKeys: Failed Nonce/PST check"); - return result; - } - if (key_control_block.control_bits() & wvoec::kControlSRMVersionRequired) { - if (srm_requirements_status_ == NoSRMVersion) { - LOGE("[LoadKeys: control bit says SRM version required]"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (srm_requirements_status_ == InvalidSRMVersion) { - // If the SRM version is too small, treat this key as local display only. - key_control_block.RequireLocalDisplay(); - } - } - - Key key(content_key, key_control_block); - if (session_keys_ == nullptr) { - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - session_keys_->Insert(key_id, key); - return OEMCrypto_SUCCESS; -} - -bool SessionContext::InstallRSAEncryptedKey( - const std::vector& enc_encryption_key) { - if (!rsa_key_) { - LOGE("Session does not have an OEM cert key"); - return false; - } - - std::vector encryption_key = - rsa_key_->DecryptEncryptionKey(enc_encryption_key); - if (encryption_key.empty()) { - LOGE("Failed to decrypt session encryption key"); - return false; - } - encryption_key_ = std::move(encryption_key); - return true; -} - -OEMCryptoResult SessionContext::LoadRenewal(const uint8_t* message, - size_t message_length, - size_t core_message_length, - const uint8_t* signature, - size_t signature_length) { - if (session_keys_ == nullptr) { - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (!ValidateMessage(message, message_length, signature, signature_length)) { - LOGE("Signature was invalid"); - return OEMCrypto_ERROR_SIGNATURE_FAILURE; - } - - // The reference implementation does not use a hardware timer. - uint64_t* timer_value = nullptr; - const OEMCryptoResult result = ODK_ParseRenewal( - message, message_length, core_message_length, &nonce_values_, - ce_->SystemTime(), &timer_limits_, &clock_values_, timer_value); - if (result == ODK_SET_TIMER || result == ODK_DISABLE_TIMER) - return OEMCrypto_SUCCESS; - if (result == ODK_TIMER_EXPIRED) return OEMCrypto_ERROR_KEY_EXPIRED; - // All other errors are returned to the caller. - return result; -} - -OEMCryptoResult SessionContext::RefreshKey( - const KeyId& key_id, const std::vector& key_control, - const std::vector& key_control_iv) { - if (session_keys_ == nullptr) { - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (key_control.empty()) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - std::vector decrypted_key_control; - if (key_id.empty()) { - // Key control is not encrypted if key id is NULL - decrypted_key_control = key_control; - } else { - Key* content_key = session_keys_->Find(key_id); - if (nullptr == content_key) { - LOGE("Key ID not found."); - return OEMCrypto_ERROR_NO_CONTENT_KEY; - } - const std::vector content_key_value = content_key->value(); - // Decrypt encrypted key control block - if (key_control_iv.empty()) { - decrypted_key_control = key_control; - } else { - if (!DecryptMessage(content_key_value, key_control_iv, key_control, - &decrypted_key_control, 128 /* key size */)) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - } - } - KeyControlBlock key_control_block(decrypted_key_control); - if (!key_control_block.valid()) { - LOGE("Parse key control error."); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - uint32_t new_key_duration = key_control_block.duration(); - uint64_t* timer_value = nullptr; - const OEMCryptoResult result = - ODK_RefreshV15Values(&timer_limits_, &clock_values_, &nonce_values_, - ce_->SystemTime(), new_key_duration, timer_value); - if (result == ODK_SET_TIMER || result == ODK_DISABLE_TIMER) - return OEMCrypto_SUCCESS; - if (result == ODK_TIMER_EXPIRED) return OEMCrypto_ERROR_KEY_EXPIRED; - return result; -} - -bool SessionContext::DecryptRSAKey(const uint8_t* enc_rsa_key, - size_t enc_rsa_key_length, - const uint8_t* enc_rsa_key_iv, - uint8_t* pkcs8_rsa_key) { - if (enc_rsa_key_length % AES_BLOCK_SIZE != 0) { - LOGE("[DecryptRSAKey(): bad buffer size]"); - return false; - } - // Decrypt rsa key with keybox. - uint8_t iv_buffer[wvoec::KEY_IV_SIZE]; - memcpy(iv_buffer, enc_rsa_key_iv, wvoec::KEY_IV_SIZE); - AES_KEY aes_key; - AES_set_decrypt_key(&encryption_key_[0], 128, &aes_key); - AES_cbc_encrypt(enc_rsa_key, pkcs8_rsa_key, enc_rsa_key_length, &aes_key, - iv_buffer, AES_DECRYPT); - return true; -} - -bool SessionContext::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) { - if (enc_rsa_key_length % AES_BLOCK_SIZE != 0) { - LOGE("[EncryptRSAKey(): bad buffer size]"); - return false; - } - // Encrypt rsa key with keybox. - uint8_t iv_buffer[wvoec::KEY_IV_SIZE]; - memcpy(iv_buffer, enc_rsa_key_iv, wvoec::KEY_IV_SIZE); - AES_KEY aes_key; - AES_set_encrypt_key(&encryption_key_[0], 128, &aes_key); - AES_cbc_encrypt(pkcs8_rsa_key, enc_rsa_key, enc_rsa_key_length, &aes_key, - iv_buffer, AES_ENCRYPT); - return true; -} - -bool SessionContext::LoadRsaDrmKey(const uint8_t* pkcs8_rsa_key, - size_t rsa_key_length) { - std::unique_ptr key = - RsaPrivateKey::Load(pkcs8_rsa_key, rsa_key_length); - if (!key) { - LOGE("Failed to parse RSA key"); - return false; - } - constexpr uint8_t kAllSchemes = kSign_RSASSA_PSS | kSign_PKCS1_Block1; - if (key->allowed_schemes() == 0 || - (key->allowed_schemes() & kAllSchemes) == kAllSchemes) { - LOGE("RSA DRM key has an invalid set of schemes: allowed_schemes = 0x%08x", - key->allowed_schemes()); - return false; - } - rsa_key_ = std::move(key); - return true; -} - -OEMCryptoResult SessionContext::CheckKeyUse(const std::string& log_string, - uint32_t use_type, - OEMCryptoBufferType buffer_type) { - const KeyControlBlock& control = current_content_key()->control(); - if (use_type && (!(control.control_bits() & use_type))) { - LOGE("[%s(): control bit says not allowed", log_string.c_str()); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (control.control_bits() & wvoec::kControlDataPathSecure) { - if (!ce_->config_closed_platform() && - buffer_type == OEMCrypto_BufferType_Clear) { - LOGE("[%s(): Secure key with insecure buffer]", log_string.c_str()); - return OEMCrypto_ERROR_DECRYPT_FAILED; - } - } - if (!ce_->config_local_display_only()) { - // Only look at HDCP restrictions if the display can be non-local. - if (control.control_bits() & wvoec::kControlHDCPRequired) { - uint8_t required_hdcp = - (control.control_bits() & wvoec::kControlHDCPVersionMask) >> - wvoec::kControlHDCPVersionShift; - if (ce_->srm_forbidden_device_attached()) { - required_hdcp = HDCP_NO_DIGITAL_OUTPUT; - } - // For reference implementation, we pretend we can handle the current - // HDCP version. - if (required_hdcp > ce_->config_current_hdcp_capability() || - ce_->config_current_hdcp_capability() == 0) { - return OEMCrypto_ERROR_INSUFFICIENT_HDCP; - } - } - } - // Return an error if analog displays should be disabled. - if ((control.control_bits() & wvoec::kControlDisableAnalogOutput) && - ce_->analog_display_active()) { - LOGE("[%s(): control bit says disable analog", log_string.c_str()); - return OEMCrypto_ERROR_ANALOG_OUTPUT; - } - // Check if CGMS is required. - if (control.control_bits() & wvoec::kControlCGMSMask) { - if (ce_->analog_display_active() && !ce_->cgms_a_active()) { - LOGE("[%s(): control bit says CGMS required", log_string.c_str()); - return OEMCrypto_ERROR_ANALOG_OUTPUT; - } - } - if (!decrypt_started_) { - // The reference implementation does not have a hardware timer. - uint64_t* timer_expiration = nullptr; - const OEMCryptoResult result = ODK_AttemptFirstPlayback( - ce_->SystemTime(), &timer_limits_, &clock_values_, timer_expiration); - if (result == ODK_TIMER_EXPIRED) return OEMCrypto_ERROR_KEY_EXPIRED; - if (usage_entry_ != nullptr) usage_entry_->ForbidReport(); - } else { - // Continued playback. - const OEMCryptoResult result = ODK_UpdateLastPlaybackTime( - ce_->SystemTime(), &timer_limits_, &clock_values_); - if (result == ODK_TIMER_EXPIRED) return OEMCrypto_ERROR_KEY_EXPIRED; - if (usage_entry_ != nullptr) usage_entry_->set_recent_decrypt(true); - } - decrypt_started_ = true; // First playback for session. - return OEMCrypto_SUCCESS; -} - -OEMCryptoResult SessionContext::Generic_Encrypt(const uint8_t* in_buffer, - size_t buffer_length, - const uint8_t* iv, - OEMCrypto_Algorithm algorithm, - uint8_t* out_buffer) { - // Check there is a content key - if (current_content_key() == nullptr) { - LOGE("[Generic_Encrypt(): OEMCrypto_ERROR_NO_CONTENT_KEY]"); - return OEMCrypto_ERROR_NO_CONTENT_KEY; - } - const std::vector& key = current_content_key()->value(); - // Set the AES key. - if (static_cast(key.size()) != AES_BLOCK_SIZE) { - LOGE("[Generic_Encrypt(): CONTENT_KEY has wrong size: %zu", key.size()); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - OEMCryptoResult result = - CheckKeyUse("Generic_Encrypt", wvoec::kControlAllowEncrypt, - OEMCrypto_BufferType_Clear); - if (result != OEMCrypto_SUCCESS) return result; - if (algorithm != OEMCrypto_AES_CBC_128_NO_PADDING) { - LOGE("[Generic_Encrypt(): algorithm bad"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (buffer_length % AES_BLOCK_SIZE != 0) { - LOGE("[Generic_Encrypt(): buffers size bad"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - const uint8_t* key_u8 = &key[0]; - AES_KEY aes_key; - if (AES_set_encrypt_key(key_u8, AES_BLOCK_SIZE * 8, &aes_key) != 0) { - LOGE("[Generic_Encrypt(): FAILURE]"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - uint8_t iv_buffer[wvoec::KEY_IV_SIZE]; - memcpy(iv_buffer, iv, wvoec::KEY_IV_SIZE); - AES_cbc_encrypt(in_buffer, out_buffer, buffer_length, &aes_key, iv_buffer, - AES_ENCRYPT); - return OEMCrypto_SUCCESS; -} - -OEMCryptoResult SessionContext::Generic_Decrypt(const uint8_t* in_buffer, - size_t buffer_length, - const uint8_t* iv, - OEMCrypto_Algorithm algorithm, - uint8_t* out_buffer) { - // Check there is a content key - if (current_content_key() == nullptr) { - LOGE("[Generic_Decrypt(): OEMCrypto_ERROR_NO_CONTENT_KEY]"); - return OEMCrypto_ERROR_NO_CONTENT_KEY; - } - const std::vector& key = current_content_key()->value(); - // Set the AES key. - if (static_cast(key.size()) != AES_BLOCK_SIZE) { - LOGE("[Generic_Decrypt(): CONTENT_KEY has wrong size"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - OEMCryptoResult result = - CheckKeyUse("Generic_Decrypt", wvoec::kControlAllowDecrypt, - OEMCrypto_BufferType_Clear); - if (result != OEMCrypto_SUCCESS) return result; - - if (algorithm != OEMCrypto_AES_CBC_128_NO_PADDING) { - LOGE("[Generic_Decrypt(): bad algorithm"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (buffer_length % AES_BLOCK_SIZE != 0) { - LOGE("[Generic_Decrypt(): bad buffer size"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - const uint8_t* key_u8 = &key[0]; - AES_KEY aes_key; - if (AES_set_decrypt_key(key_u8, AES_BLOCK_SIZE * 8, &aes_key) != 0) { - LOGE("[Generic_Decrypt(): FAILURE]"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - uint8_t iv_buffer[wvoec::KEY_IV_SIZE]; - memcpy(iv_buffer, iv, wvoec::KEY_IV_SIZE); - AES_cbc_encrypt(in_buffer, out_buffer, buffer_length, &aes_key, iv_buffer, - AES_DECRYPT); - return OEMCrypto_SUCCESS; -} - -OEMCryptoResult SessionContext::Generic_Sign(const uint8_t* in_buffer, - size_t buffer_length, - OEMCrypto_Algorithm algorithm, - uint8_t* signature, - size_t* signature_length) { - // Check there is a content key - if (current_content_key() == nullptr) { - LOGE("[Generic_Sign(): OEMCrypto_ERROR_NO_CONTENT_KEY]"); - return OEMCrypto_ERROR_NO_CONTENT_KEY; - } - if (*signature_length < SHA256_DIGEST_LENGTH) { - *signature_length = SHA256_DIGEST_LENGTH; - LOGE("[Generic_Sign(): bad signature length"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - const std::vector& key = current_content_key()->value(); - if (static_cast(key.size()) != SHA256_DIGEST_LENGTH) { - LOGE("[Generic_Sign(): CONTENT_KEY has wrong size: %zu", key.size()); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - OEMCryptoResult result = CheckKeyUse("Generic_Sign", wvoec::kControlAllowSign, - OEMCrypto_BufferType_Clear); - if (result != OEMCrypto_SUCCESS) return result; - if (algorithm != OEMCrypto_HMAC_SHA256) { - LOGE("[Generic_Sign(): bad algorithm"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - unsigned int md_len = *signature_length; - if (HMAC(EVP_sha256(), &key[0], key.size(), in_buffer, buffer_length, - signature, &md_len)) { - *signature_length = md_len; - return OEMCrypto_SUCCESS; - } - LOGE("[Generic_Sign(): hmac failed"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; -} - -OEMCryptoResult SessionContext::Generic_Verify(const uint8_t* in_buffer, - size_t buffer_length, - OEMCrypto_Algorithm algorithm, - const uint8_t* signature, - size_t signature_length) { - // Check there is a content key - if (current_content_key() == nullptr) { - LOGE("[Decrypt_Verify(): OEMCrypto_ERROR_NO_CONTENT_KEY]"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (signature_length < SHA256_DIGEST_LENGTH) { - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - const std::vector& key = current_content_key()->value(); - if (static_cast(key.size()) != SHA256_DIGEST_LENGTH) { - LOGE("[Generic_Verify(): CONTENT_KEY has wrong size: %zu", key.size()); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - OEMCryptoResult result = CheckKeyUse( - "Generic_Verify", wvoec::kControlAllowVerify, OEMCrypto_BufferType_Clear); - if (result != OEMCrypto_SUCCESS) return result; - if (algorithm != OEMCrypto_HMAC_SHA256) { - LOGE("[Generic_Verify(): bad algorithm"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - unsigned int md_len = signature_length; - uint8_t computed_signature[SHA256_DIGEST_LENGTH]; - if (HMAC(EVP_sha256(), &key[0], key.size(), in_buffer, buffer_length, - computed_signature, &md_len)) { - if (0 == - CRYPTO_memcmp(signature, computed_signature, SHA256_DIGEST_LENGTH)) { - return OEMCrypto_SUCCESS; - } else { - return OEMCrypto_ERROR_SIGNATURE_FAILURE; - } - } - LOGE("[Generic_Verify(): HMAC failed"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; -} - -bool SessionContext::UpdateMacKeys(const std::vector& enc_mac_keys, - const std::vector& iv) { - // Decrypt mac key from enc_mac_key using device_keya - std::vector mac_keys; - if (!DecryptMessage(encryption_key_, iv, enc_mac_keys, &mac_keys, - 128 /* key size */)) { - return false; - } - mac_key_server_ = std::vector( - mac_keys.begin(), mac_keys.begin() + wvoec::MAC_KEY_SIZE); - mac_key_client_ = std::vector(mac_keys.begin() + wvoec::MAC_KEY_SIZE, - mac_keys.end()); - return true; -} - -bool SessionContext::QueryKeyControlBlock(const KeyId& key_id, uint32_t* data) { - if (session_keys_ == nullptr) { - return false; - } - const Key* content_key = session_keys_->Find(key_id); - if (content_key == nullptr) { - LOGE("[QueryKeyControlBlock(): No key matches key id]"); - return false; - } - data[0] = 0; // verification optional. - data[1] = htonl(content_key->control().duration()); - data[2] = 0; // nonce optional. - data[3] = htonl(content_key->control().control_bits()); - return true; -} - -OEMCryptoResult SessionContext::SelectContentKey( - const KeyId& key_id, OEMCryptoCipherMode cipher_mode) { - if (session_keys_ == nullptr) { - LOGE("Select Key: no session keys"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - Key* content_key = session_keys_->Find(key_id); - if (content_key == nullptr) { - LOGE("No key matches key id"); - return OEMCrypto_ERROR_NO_CONTENT_KEY; - } - content_key->set_ctr_mode(cipher_mode == OEMCrypto_CipherMode_CTR); - current_content_key_ = content_key; - return OEMCrypto_SUCCESS; -} - -OEMCryptoResult SessionContext::CreateNewUsageEntry( - uint32_t* usage_entry_number) { - if (usage_entry_) { - // Can only load one entry per session. - return OEMCrypto_ERROR_MULTIPLE_USAGE_ENTRIES; - } - OEMCryptoResult result = ce_->usage_table().CreateNewUsageEntry( - this, &usage_entry_, usage_entry_number); - if (usage_entry_) { - usage_entry_status_ = kUsageEntryNew; - } - return result; -} - -OEMCryptoResult SessionContext::LoadUsageEntry( - uint32_t index, const std::vector& buffer) { - if (usage_entry_) { - // Can only load one entry per session. - return OEMCrypto_ERROR_MULTIPLE_USAGE_ENTRIES; - } - const OEMCryptoResult result = ce_->usage_table().LoadUsageEntry( - this, &usage_entry_, index, buffer, &clock_values_); - if ((result != OEMCrypto_SUCCESS) && - (result != OEMCrypto_WARNING_GENERATION_SKEW)) - return result; - if (!usage_entry_) return OEMCrypto_ERROR_UNKNOWN_FAILURE; - - usage_entry_status_ = kUsageEntryLoaded; - // Copy the mac keys to the current session. - mac_key_server_ = std::vector( - usage_entry_->mac_key_server(), - usage_entry_->mac_key_server() + wvoec::MAC_KEY_SIZE); - mac_key_client_ = std::vector( - usage_entry_->mac_key_client(), - usage_entry_->mac_key_client() + wvoec::MAC_KEY_SIZE); - return result; -} - -OEMCryptoResult SessionContext::UpdateUsageEntry(uint8_t* header_buffer, - size_t* header_buffer_length, - uint8_t* entry_buffer, - size_t* entry_buffer_length) { - if (!usage_entry_) { - LOGE("UpdateUsageEntry: Session has no entry"); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - return ce_->usage_table().UpdateUsageEntry( - this, usage_entry_.get(), header_buffer, header_buffer_length, - entry_buffer, entry_buffer_length, &clock_values_); -} - -OEMCryptoResult SessionContext::DeactivateUsageEntry( - const std::vector& pst) { - if (!usage_entry_) return OEMCrypto_ERROR_INVALID_CONTEXT; - usage_entry_->ForbidReport(); - return ODK_DeactivateUsageEntry(&clock_values_); -} - -OEMCryptoResult SessionContext::ReportUsage(const std::vector& pst, - uint8_t* buffer, - size_t* buffer_length) { - if (!usage_entry_) return OEMCrypto_ERROR_INVALID_CONTEXT; - return usage_entry_->ReportUsage(pst, buffer, buffer_length); -} - -OEMCryptoResult SessionContext::MoveEntry(uint32_t new_index) { - if (!usage_entry_) return OEMCrypto_ERROR_INVALID_CONTEXT; - return ce_->usage_table().MoveEntry(usage_entry_.get(), new_index); -} - -// Internal utility function to decrypt the message -bool SessionContext::DecryptMessage(const std::vector& key, - const std::vector& iv, - const std::vector& message, - std::vector* decrypted, - uint32_t key_size) { - if (key.empty() || iv.empty() || message.empty() || !decrypted) { - LOGE("[DecryptMessage(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return false; - } - if (message.size() % AES_BLOCK_SIZE != 0) { - LOGE("[DecryptMessage(): bad buffer size]"); - return false; - } - - decrypted->resize(message.size()); - uint8_t iv_buffer[16]; - memcpy(iv_buffer, &iv[0], 16); - AES_KEY aes_key; - AES_set_decrypt_key(&key[0], key_size, &aes_key); - AES_cbc_encrypt(&message[0], &(decrypted->front()), message.size(), &aes_key, - iv_buffer, AES_DECRYPT); - return true; -} - -OEMCryptoResult SessionContext::DecryptSamples( - const OEMCrypto_SampleDescription* samples, size_t samples_length, - const OEMCrypto_CENCEncryptPatternDesc* pattern) { - // Iterate through all the samples and decrypt each one - for (size_t sample_index = 0; sample_index < samples_length; ++sample_index) { - const OEMCrypto_SampleDescription& sample = samples[sample_index]; - - // Iterate through all the subsamples and decrypt each one. A production - // implementation may be able to do something more efficient, like - // decrypting all the encrypted portions in one pass. - const uint8_t* subsample_source = sample.buffers.input_data; - OEMCrypto_DestBufferDesc subsample_dest = sample.buffers.output_descriptor; - uint8_t subsample_iv[wvoec::KEY_IV_SIZE]; - static_assert(sizeof(sample.iv) == wvoec::KEY_IV_SIZE, - "The IV in OEMCrypto_SampleDescription is the wrong length."); - // Per its type, sizeof(subsample_iv) == wvoec::KEY_IV_SIZE - memcpy(subsample_iv, sample.iv, wvoec::KEY_IV_SIZE); - for (size_t subsample_index = 0; subsample_index < sample.subsamples_length; - ++subsample_index) { - const OEMCrypto_SubSampleDescription& subsample = - sample.subsamples[subsample_index]; - const size_t subsample_length = - subsample.num_bytes_clear + subsample.num_bytes_encrypted; - - OEMCryptoResult result = ce_->SetDestination( - subsample_dest, subsample_length, subsample.subsample_flags); - if (result != OEMCrypto_SUCCESS) { - LOGE("SetDestination status: %d", static_cast(result)); - return result; - } - - result = DecryptSubsample(subsample, subsample_source, ce_->destination(), - subsample_dest.type, subsample_iv, pattern); - if (result != OEMCrypto_SUCCESS) { - LOGE("DecryptSubsample status: %d", static_cast(result)); - return result; - } - - result = ce_->PushDestination(subsample_dest, subsample.subsample_flags); - if (result != OEMCrypto_SUCCESS) { - LOGE("PushDestination status: %d", static_cast(result)); - return result; - } - - // Advance the source buffer, the dest buffer, and (if necessary) the IV - subsample_source += subsample_length; - advance_dest_buffer(&subsample_dest, subsample_length); - if (subsample.num_bytes_encrypted > 0 && - current_content_key()->ctr_mode()) { - wvcdm::AdvanceIvCtr(&subsample_iv, subsample.block_offset + - subsample.num_bytes_encrypted); - } - } // Subsample loop - } // Sample loop - - return OEMCrypto_SUCCESS; -} - -OEMCryptoResult SessionContext::DecryptSubsample( - const OEMCrypto_SubSampleDescription& subsample, const uint8_t* cipher_data, - uint8_t* clear_data, OEMCryptoBufferType buffer_type, - const uint8_t (&iv)[wvoec::KEY_IV_SIZE], - const OEMCrypto_CENCEncryptPatternDesc* pattern) { - // Handle the clear portion of the subsample. - if (subsample.num_bytes_clear > 0) { - if (buffer_type != OEMCrypto_BufferType_Direct) { - memmove(clear_data, cipher_data, subsample.num_bytes_clear); - } - // For the reference implementation, we quietly drop the clear direct video. - } - - // Handle the encrypted portion of the subsample. - OEMCryptoResult result = OEMCrypto_SUCCESS; - if (subsample.num_bytes_encrypted > 0) { - const uint8_t* source = cipher_data + subsample.num_bytes_clear; - uint8_t* dest = clear_data + subsample.num_bytes_clear; - result = ChooseDecrypt(iv, subsample.block_offset, pattern, source, - subsample.num_bytes_encrypted, dest, buffer_type); - } - - // Compute hash for FDPT. - if (compute_hash_) { - if (current_content_key() == nullptr || - (current_content_key()->control().control_bits() & - wvoec::kControlAllowHashVerification) == 0) { - LOGE("[DecryptCENC(): OEMCrypto_ERROR_UNKNOWN_FAILURE]"); - hash_error_ = OEMCrypto_ERROR_UNKNOWN_FAILURE; - compute_hash_ = false; - current_hash_ = 0; - current_frame_number_ = 0; - } else { - if (OEMCrypto_FirstSubsample & subsample.subsample_flags) { - current_hash_ = wvcrc32Init(); - } - current_hash_ = wvcrc32Cont( - clear_data, subsample.num_bytes_clear + subsample.num_bytes_encrypted, - current_hash_); - if (OEMCrypto_LastSubsample & subsample.subsample_flags) { - if (current_hash_ != given_hash_) { - LOGE("CRC for frame %u is %08x, should be %08x\n", - current_frame_number_, current_hash_, given_hash_); - // Update bad_frame_number_ only if this is the first bad frame. - if (hash_error_ == OEMCrypto_SUCCESS) { - bad_frame_number_ = current_frame_number_; - hash_error_ = OEMCrypto_ERROR_BAD_HASH; - } - } - compute_hash_ = false; - } - } - } - - // Return the result of the previous ChooseDecrypt() call after computing the - // hash. - return result; -} - -OEMCryptoResult SessionContext::ChooseDecrypt( - 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, - OEMCryptoBufferType buffer_type) { - // Check there is a content key - if (current_content_key() == nullptr) { - LOGE("[DecryptCTR(): OEMCrypto_ERROR_NO_CONTENT_KEY]"); - return OEMCrypto_ERROR_DECRYPT_FAILED; - } - - OEMCryptoResult result = CheckKeyUse("DecryptCENC", 0, buffer_type); - if (result != OEMCrypto_SUCCESS) return result; - - const std::vector& content_key = current_content_key()->value(); - - // Set the AES key. - if (static_cast(content_key.size()) != AES_BLOCK_SIZE) { - LOGE("[DecryptCTR(): CONTENT_KEY has wrong size: %zu", content_key.size()); - return OEMCrypto_ERROR_DECRYPT_FAILED; - } - const uint8_t* key_u8 = &content_key[0]; - - if (buffer_type == OEMCrypto_BufferType_Direct) { - // For reference implementation, we quietly drop the decrypted direct video. - return OEMCrypto_SUCCESS; - } - - if (!current_content_key()->ctr_mode()) { - if (block_offset > 0 || pattern->encrypt == 0) { - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - return PatternDecryptCBC(key_u8, iv, pattern, cipher_data, - cipher_data_length, clear_data); - } else { - if (pattern->skip != 0 || pattern->encrypt != 0) { - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - return DecryptCTR(key_u8, iv, block_offset, cipher_data, cipher_data_length, - clear_data); - } -} - -OEMCryptoResult SessionContext::PatternDecryptCBC( - const uint8_t* key, const uint8_t* initial_iv, - const OEMCrypto_CENCEncryptPatternDesc* pattern, const uint8_t* cipher_data, - size_t cipher_data_length, uint8_t* clear_data) { - AES_KEY aes_key; - AES_set_decrypt_key(&key[0], AES_BLOCK_SIZE * 8, &aes_key); - uint8_t iv[AES_BLOCK_SIZE]; - uint8_t next_iv[AES_BLOCK_SIZE]; - memcpy(iv, &initial_iv[0], AES_BLOCK_SIZE); - - const size_t pattern_length = pattern->encrypt + pattern->skip; - if (pattern_length <= 0) return OEMCrypto_ERROR_INVALID_CONTEXT; - - size_t l = 0; - size_t pattern_offset = 0; - while (l < cipher_data_length) { - const size_t size = - std::min(cipher_data_length - l, static_cast(AES_BLOCK_SIZE)); - const bool skip_block = (pattern_offset >= pattern->encrypt); - pattern_offset = (pattern_offset + 1) % pattern_length; - if (skip_block || (size < AES_BLOCK_SIZE)) { - // If we are decrypting in-place, then this block is already correct and - // can be skipped. - if (clear_data != cipher_data) { - memcpy(&clear_data[l], &cipher_data[l], size); - } - } else { - uint8_t aes_output[AES_BLOCK_SIZE]; - // Save the iv for the next block, in case cipher_data is in the same - // buffer as clear_data. - memcpy(next_iv, &cipher_data[l], AES_BLOCK_SIZE); - AES_decrypt(&cipher_data[l], aes_output, &aes_key); - for (size_t n = 0; n < AES_BLOCK_SIZE; n++) { - clear_data[l + n] = aes_output[n] ^ iv[n]; - } - memcpy(iv, next_iv, AES_BLOCK_SIZE); - } - l += size; - } - return OEMCrypto_SUCCESS; -} - -OEMCryptoResult SessionContext::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) { - if (block_offset >= AES_BLOCK_SIZE) return OEMCrypto_ERROR_INVALID_CONTEXT; - - // Local copy (will be modified). - // Allocated as 64-bit ints to enforce 64-bit alignment for later access as a - // 64-bit value. - uint64_t aes_iv[2]; - assert(sizeof(aes_iv) == AES_BLOCK_SIZE); - // The double-cast is needed to comply with strict aliasing rules. - uint8_t* aes_iv_u8 = - reinterpret_cast(reinterpret_cast(aes_iv)); - memcpy(aes_iv_u8, &iv[0], AES_BLOCK_SIZE); - - // The CENC spec specifies we increment only the low 64 bits of the IV - // counter, and leave the high 64 bits alone. This is different from the - // OpenSSL implementation, which increments the entire 128 bit iv. That is - // why we implement the CTR loop ourselves. - size_t l = 0; - if (block_offset > 0 && l < cipher_data_length) { - // Encrypt the IV. - uint8_t ecount_buf[AES_BLOCK_SIZE]; - - AES_KEY aes_key; - if (AES_set_encrypt_key(key_u8, AES_BLOCK_SIZE * 8, &aes_key) != 0) { - LOGE("[DecryptCTR(): FAILURE]"); - return OEMCrypto_ERROR_DECRYPT_FAILED; - } - AES_encrypt(aes_iv_u8, ecount_buf, &aes_key); - for (int n = block_offset; n < AES_BLOCK_SIZE && l < cipher_data_length; - ++n, ++l) { - clear_data[l] = cipher_data[l] ^ ecount_buf[n]; - } - ctr128_inc64(aes_iv_u8); - block_offset = 0; - } - - uint64_t remaining = cipher_data_length - l; - int out_len = 0; - - while (remaining) { - EVP_CIPHER_CTX* evp_cipher_ctx = EVP_CIPHER_CTX_new(); - EVP_CIPHER_CTX_set_padding(evp_cipher_ctx, 0); - if (!EVP_DecryptInit_ex(evp_cipher_ctx, EVP_aes_128_ctr(), nullptr, key_u8, - aes_iv_u8)) { - LOGE("[DecryptCTR(): EVP_INIT ERROR]"); - EVP_CIPHER_CTX_free(evp_cipher_ctx); - return OEMCrypto_ERROR_DECRYPT_FAILED; - } - - // Test the MSB of the counter portion of the initialization vector. If the - // value is 0xFF the counter is near wrapping. In this case we calculate - // the number of bytes we can safely decrypt before the counter wraps. - uint64_t decrypt_length = 0; - if (aes_iv_u8[8] == 0xFF) { - uint64_t bottom_64_bits = wvcdm::ntohll64(aes_iv[1]); - uint64_t bytes_before_iv_wrap = (~bottom_64_bits + 1) * AES_BLOCK_SIZE; - decrypt_length = - bytes_before_iv_wrap < remaining ? bytes_before_iv_wrap : remaining; - } else { - decrypt_length = remaining; - } - - if (!EVP_DecryptUpdate(evp_cipher_ctx, &clear_data[l], &out_len, - &cipher_data[l], decrypt_length)) { - LOGE("[DecryptCTR(): EVP_UPDATE_ERROR]"); - EVP_CIPHER_CTX_free(evp_cipher_ctx); - return OEMCrypto_ERROR_DECRYPT_FAILED; - } - l += decrypt_length; - remaining = cipher_data_length - l; - - int final; - if (!EVP_DecryptFinal_ex(evp_cipher_ctx, - &clear_data[cipher_data_length - remaining], - &final)) { - LOGE("[DecryptCTR(): EVP_FINAL_ERROR]"); - EVP_CIPHER_CTX_free(evp_cipher_ctx); - return OEMCrypto_ERROR_DECRYPT_FAILED; - } - EVP_CIPHER_CTX_free(evp_cipher_ctx); - - // If remaining is not zero, reset the iv before the second pass. - if (remaining) { - memcpy(aes_iv_u8, &iv[0], AES_BLOCK_SIZE); - memset(&aes_iv_u8[8], 0, AES_BLOCK_SIZE / 2); - } - } - return OEMCrypto_SUCCESS; -} - -OEMCryptoResult SessionContext::SetDecryptHash(uint32_t frame_number, - const uint8_t* hash, - size_t hash_length) { - if (hash_length < sizeof(uint32_t)) { - LOGE("[SetDecryptHash(): short buffer]"); - return OEMCrypto_ERROR_SHORT_BUFFER; - } - if (hash_length > sizeof(uint32_t)) { - LOGE("[SetDecryptHash(): long buffer]"); - return OEMCrypto_ERROR_BUFFER_TOO_LARGE; - } - compute_hash_ = true; - current_frame_number_ = frame_number; - given_hash_ = *reinterpret_cast(hash); - return OEMCrypto_SUCCESS; -} - -OEMCryptoResult SessionContext::GetHashErrorCode( - uint32_t* failed_frame_number) { - if (failed_frame_number == nullptr) return OEMCrypto_ERROR_UNKNOWN_FAILURE; - if (hash_error_ != OEMCrypto_SUCCESS) - *failed_frame_number = bad_frame_number_; - return hash_error_; -} - -bool SessionContext::set_nonce(uint32_t nonce) { - if (state_nonce_created_) return false; - if (nonce == 0) return false; - state_nonce_created_ = true; - ODK_SetNonceValues(&nonce_values_, nonce); - return true; -} - -} // namespace wvoec_ref diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.h b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.h deleted file mode 100644 index 8811b9eb..00000000 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.h +++ /dev/null @@ -1,312 +0,0 @@ -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine -// License Agreement. -// -// Reference implementation of OEMCrypto APIs -// -#ifndef REF_OEMCRYPTO_SESSION_H_ -#define REF_OEMCRYPTO_SESSION_H_ - -#include -#include -#include -#include - -#include - -#include "OEMCryptoCENC.h" -#include "odk_structs.h" -#include "oemcrypto_auth_ref.h" -#include "oemcrypto_key_ref.h" -#include "oemcrypto_rsa_key.h" -#include "oemcrypto_session_key_table.h" -#include "oemcrypto_types.h" -#include "oemcrypto_usage_table_ref.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 Key* FirstKey() = 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& content_key) = 0; - virtual EntitlementKey* GetEntitlementKey(const KeyId& entitlement_id) = 0; - - virtual ~SessionContextKeys() {} - - protected: - SessionContextKeys() {} - - private: - CORE_DISALLOW_COPY_AND_ASSIGN(SessionContextKeys); -}; - -class SessionContext { - public: - SessionContext(CryptoEngine* ce, SessionId sid); - SessionContext(CryptoEngine* ce, SessionId sid, - std::shared_ptr&& rsa_key); - SessionContext() = delete; - virtual ~SessionContext(); - - bool isValid() const { return valid_; } - - virtual OEMCryptoResult DeriveKeys(const std::vector& master_key, - const std::vector& mac_context, - const std::vector& enc_context); - virtual OEMCryptoResult RSADeriveKeys( - const std::vector& enc_session_key, - const std::vector& mac_context, - const std::vector& enc_context); - - virtual OEMCryptoResult LoadOemPrivateKey(); - - virtual OEMCryptoResult PrepAndSignLicenseRequest(uint8_t* message, - size_t message_length, - size_t* core_message_length, - uint8_t* signature, - size_t* signature_length); - virtual OEMCryptoResult PrepAndSignRenewalRequest(uint8_t* message, - size_t message_length, - size_t* core_message_length, - uint8_t* signature, - size_t* signature_length); - virtual OEMCryptoResult PrepAndSignProvisioningRequest( - uint8_t* message, size_t message_length, size_t* core_message_length, - uint8_t* signature, size_t* signature_length); - // Restricted to CAST receivers using PKCS1 block padding only. - virtual OEMCryptoResult GenerateRSASignature( - const uint8_t* message, size_t message_length, uint8_t* signature, - size_t* signature_length, RSA_Padding_Scheme padding_scheme); - virtual bool ValidateMessage(const uint8_t* message, size_t message_length, - const uint8_t* signature, - size_t signature_length); - OEMCryptoResult DecryptSamples( - const OEMCrypto_SampleDescription* samples, size_t samples_length, - const OEMCrypto_CENCEncryptPatternDesc* pattern); - - 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); - virtual OEMCryptoResult LoadLicense(const uint8_t* message, - size_t message_length, - size_t core_message_length, - const uint8_t* signature, - size_t signature_length); - virtual OEMCryptoResult LoadKeys( - const uint8_t* message, size_t message_length, const uint8_t* signature, - size_t signature_length, OEMCrypto_Substring enc_mac_keys_iv, - OEMCrypto_Substring enc_mac_keys, size_t num_keys, - const OEMCrypto_KeyObject* key_array, OEMCrypto_Substring pst, - OEMCrypto_Substring srm_restriction_data, - OEMCrypto_LicenseType license_type); - virtual OEMCryptoResult LoadKeysNoSignature( - const uint8_t* message, size_t message_length, - OEMCrypto_Substring enc_mac_keys_iv, OEMCrypto_Substring enc_mac_keys, - size_t num_keys, const OEMCrypto_KeyObject* key_array, - OEMCrypto_Substring pst, OEMCrypto_Substring srm_restriction_data, - OEMCrypto_LicenseType license_type); - virtual OEMCryptoResult LoadEntitledContentKeys( - const uint8_t* message, size_t message_length, size_t key_array_length, - const OEMCrypto_EntitledContentKeyObject* key_array); - virtual OEMCryptoResult InstallKey( - const KeyId& key_id, const std::vector& key_data, - const std::vector& key_data_iv, - const std::vector& key_control, - const std::vector& key_control_iv); - bool InstallRSAEncryptedKey(const std::vector& enc_encryption_key); - 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 LoadRsaDrmKey(const uint8_t* pkcs8_rsa_key, size_t rsa_key_length); - virtual OEMCryptoResult LoadRenewal(const uint8_t* message, - size_t message_length, - size_t core_message_length, - const uint8_t* signature, - size_t signature_length); - virtual OEMCryptoResult RefreshKey( - const KeyId& key_id, const std::vector& key_control, - const std::vector& key_control_iv); - virtual bool UpdateMacKeys(const std::vector& mac_keys, - const std::vector& iv); - virtual bool QueryKeyControlBlock(const KeyId& key_id, uint32_t* data); - virtual OEMCryptoResult SelectContentKey(const KeyId& key_id, - OEMCryptoCipherMode cipher_mode); - virtual OEMCryptoResult SetDecryptHash(uint32_t frame_number, - const uint8_t* hash, - size_t hash_length); - virtual OEMCryptoResult GetHashErrorCode(uint32_t* failed_frame_number); - const Key* current_content_key(void) { return current_content_key_; } - void set_mac_key_server(const std::vector& mac_key_server) { - mac_key_server_ = mac_key_server; - } - const std::vector& mac_key_server() { return mac_key_server_; } - void set_mac_key_client(const std::vector& mac_key_client) { - mac_key_client_ = mac_key_client; - } - const std::vector& mac_key_client() { return mac_key_client_; } - - void set_encryption_key(const std::vector& enc_key) { - encryption_key_ = enc_key; - } - const std::vector& encryption_key() { return encryption_key_; } - - // Return true if nonce was set. - bool set_nonce(uint32_t nonce); - uint32_t nonce() const { return nonce_values_.nonce; } - ODK_NonceValues& nonce_values() { return nonce_values_; } - - bool CheckNonce(uint32_t nonce) const { - return nonce != 0 && nonce == nonce_values_.nonce; - }; - - virtual OEMCryptoResult CreateNewUsageEntry(uint32_t* usage_entry_number); - virtual OEMCryptoResult LoadUsageEntry(uint32_t index, - const std::vector& buffer); - virtual OEMCryptoResult UpdateUsageEntry(uint8_t* header_buffer, - size_t* header_buffer_length, - uint8_t* entry_buffer, - size_t* entry_buffer_length); - virtual OEMCryptoResult DeactivateUsageEntry(const std::vector& pst); - virtual OEMCryptoResult ReportUsage(const std::vector& pst, - uint8_t* buffer, size_t* buffer_length); - OEMCryptoResult MoveEntry(uint32_t new_index); - bool usage_entry_present() const { return usage_entry_ != nullptr; } - - protected: - // Signature size of the currently loaded private key. - size_t CertSignatureSize() const; - // Signature size when using a keybox or OEM Cert's private key. - size_t ROTSignatureSize() const; - virtual OEMCryptoResult GenerateCertSignature(const uint8_t* message, - size_t message_length, - uint8_t* signature, - size_t* signature_length); - virtual OEMCryptoResult GenerateSignature(const uint8_t* message, - size_t message_length, - uint8_t* signature, - size_t* signature_length); - bool DeriveKey(const std::vector& key, - const std::vector& context, int counter, - std::vector* out); - bool DecryptMessage(const std::vector& key, - const std::vector& iv, - const std::vector& message, - std::vector* 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 DecryptSubsample( - const OEMCrypto_SubSampleDescription& subsample, - const uint8_t* cipher_data, uint8_t* clear_data, - OEMCryptoBufferType buffer_type, const uint8_t (&iv)[wvoec::KEY_IV_SIZE], - const OEMCrypto_CENCEncryptPatternDesc* pattern); - OEMCryptoResult ChooseDecrypt(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, - OEMCryptoBufferType buffer_type); - OEMCryptoResult PatternDecryptCBC( - 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 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); - - bool valid_ = false; - CryptoEngine* ce_ = nullptr; - SessionId id_; - - // Message keys. - std::shared_ptr rsa_key_; - std::vector mac_key_server_; - std::vector mac_key_client_; - std::vector encryption_key_; - std::vector session_key_; - - ODK_NonceValues nonce_values_; - uint8_t license_request_hash_[ODK_SHA256_HASH_SIZE]; - - // Content/entitlement keys. - const Key* current_content_key_ = nullptr; - std::unique_ptr session_keys_; - - bool decrypt_started_ = - false; // If the license has been used in this session. - ODK_TimerLimits timer_limits_; - ODK_ClockValues clock_values_; - std::unique_ptr usage_entry_; - SRMVersionStatus srm_requirements_status_ = NoSRMVersion; - 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_ = kNoUsageEntry; - - // These are used when doing full decrypt path testing. - bool compute_hash_ = false; // True if the current frame needs a hash. - uint32_t current_hash_ = 0; // Running CRC hash of frame. - uint32_t given_hash_ = 0; // True CRC hash of frame. - uint32_t current_frame_number_ = 0; // Current frame for CRC hash. - uint32_t bad_frame_number_ = 0; // Frame number with bad hash. - OEMCryptoResult hash_error_ = - OEMCrypto_SUCCESS; // Error code for first bad frame. - - // The bare minimum state machine is to only call each of these function - // categories at most once. - bool state_nonce_created_ = false; - bool state_request_signed_ = false; - bool state_response_loaded_ = false; - - CORE_DISALLOW_COPY_AND_ASSIGN(SessionContext); -}; - -} // namespace wvoec_ref - -#endif // REF_OEMCRYPTO_SESSION_H_ diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session_key_table.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session_key_table.cpp deleted file mode 100644 index 0247bec4..00000000 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session_key_table.cpp +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine -// License Agreement. -// -// Reference implementation of OEMCrypto APIs -// -#include "oemcrypto_session_key_table.h" - -#include "keys.h" -#include "log.h" - -namespace wvoec_ref { - -bool SessionKeyTable::Insert(const KeyId key_id, const Key& key_data) { - if (keys_.find(key_id) != keys_.end()) return false; - keys_[key_id] = std::unique_ptr(new Key(key_data)); - return true; -} - -Key* SessionKeyTable::Find(const KeyId key_id) { - if (keys_.find(key_id) == keys_.end()) { - return nullptr; - } - return keys_[key_id].get(); -} - -void SessionKeyTable::Remove(const KeyId key_id) { - if (keys_.find(key_id) != keys_.end()) { - 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] = std::unique_ptr(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 nullptr; - } - - if (keys_.find(it->second) == keys_.end()) { - return nullptr; - } - return keys_[it->second].get(); -} - -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 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; -} - -EntitlementKey* EntitlementKeyTable::GetEntitlementKey( - const KeyId& entitlement_id) { - EntitlementKeyMap::iterator it = keys_.find(entitlement_id); - if (it == keys_.end()) { - return nullptr; - } - return it->second.get(); -} - -} // namespace wvoec_ref diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session_key_table.h b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session_key_table.h deleted file mode 100644 index d534510d..00000000 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session_key_table.h +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine -// License Agreement. -// -// Reference implementation of OEMCrypto APIs -// -#ifndef REF_OEMCRYPTO_SESSION_KEY_TABLE_H_ -#define REF_OEMCRYPTO_SESSION_KEY_TABLE_H_ - -#include -#include -#include -#include - -#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 KeyId; -typedef std::map> KeyMap; -typedef std::map> 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); - Key* FirstKey() { return keys_.begin()->second.get(); } - 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 ContentIdToEntitlementIdMap; - - public: - EntitlementKeyTable() {} - ~EntitlementKeyTable() {} - bool Insert(const KeyId key_id, const Key& key_data); - Key* Find(const KeyId key_id); - Key* FirstKey() { return keys_.begin()->second.get(); } - 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 content_key); - EntitlementKey* GetEntitlementKey(const KeyId& entitlement_id); - - private: - EntitlementKeyMap keys_; - ContentIdToEntitlementIdMap contentid_to_entitlementid_; - CORE_DISALLOW_COPY_AND_ASSIGN(EntitlementKeyTable); -}; - -} // namespace wvoec_ref - -#endif // REF_OEMCRYPTO_SESSION_KEY_TABLE_H_ diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_usage_table_ref.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_usage_table_ref.cpp deleted file mode 100644 index b3750c1f..00000000 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_usage_table_ref.cpp +++ /dev/null @@ -1,710 +0,0 @@ -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine -// License Agreement. -// -// Reference implementation of OEMCrypto APIs -// -#include "oemcrypto_usage_table_ref.h" - -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#include "file_store.h" -#include "log.h" -#include "odk.h" -#include "oemcrypto_engine_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 || !pst_length) return OEMCrypto_ERROR_INVALID_CONTEXT; - memcpy(data_.pst, pst, pst_length); - data_.time_of_license_received = usage_table_->ce_->SystemTime(); - 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 || !pst_length) return false; - return 0 == CRYPTO_memcmp(pst, data_.pst, pst_length); -} - -bool UsageTableEntry::VerifyMacKeys(const std::vector& server, - const std::vector& client) { - return (server.size() == wvoec::MAC_KEY_SIZE) && - (client.size() == wvoec::MAC_KEY_SIZE) && - (0 == CRYPTO_memcmp(&server[0], data_.mac_key_server, - wvoec::MAC_KEY_SIZE)) && - (0 == - CRYPTO_memcmp(&client[0], data_.mac_key_client, wvoec::MAC_KEY_SIZE)); -} - -bool UsageTableEntry::SetMacKeys(const std::vector& server, - const std::vector& 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; -} - -void UsageTableEntry::ForbidReport() { - forbid_report_ = true; - data_.generation_number++; - usage_table_->IncrementGeneration(); -} - -OEMCryptoResult UsageTableEntry::ReportUsage(const std::vector& 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 = %zu, should be %u.", pst.size(), - data_.pst_length); - return OEMCrypto_ERROR_WRONG_PST; - } - if (CRYPTO_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; - } - const 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); - const int64_t now = usage_table_->ce_->SystemTime(); - 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 (!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(ODK_ClockValues* clock_values) { - if (recent_decrypt_) { - data_.time_of_last_decrypt = usage_table_->ce_->SystemTime(); - recent_decrypt_ = false; - } - data_.time_of_license_received = clock_values->time_of_license_signed; - data_.time_of_first_decrypt = clock_values->time_of_first_decrypt; - // Use the most recent time_of_last_decrypt. - if (static_cast(data_.time_of_last_decrypt) < - clock_values->time_of_last_decrypt) { - // For the reference implementation, we update the clock_values on every - // decrypt. - data_.time_of_last_decrypt = clock_values->time_of_last_decrypt; - } else { - // For this reference implementation of OEMCrypto, we regularly update - // clock_values->time_of_last_decrypt and we could just update - // data_.time_of_last_decrypt here. However, I'm including the line below to - // make it clear that you could do it the other way around. When this - // function is called, the two values should be synced so that the usage - // entry can be saved with the correct value. - clock_values->time_of_last_decrypt = data_.time_of_last_decrypt; - } - data_.status = clock_values->status; - 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 clear_buffer(buffer_size); - memset(&clear_buffer[0], 0, buffer_size); - memset(signed_buffer, 0, buffer_size); - SignedEntryBlock* clear = - reinterpret_cast(&clear_buffer[0]); - SignedEntryBlock* encrypted = - reinterpret_cast(signed_buffer); - clear->data = 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 std::vector& key = ce->DeviceRootKey(); - if (key.empty()) { - LOGE("SaveUsageEntry: DeviceRootKey is unexpectedly empty."); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - // Encrypt the entry. - if (RAND_bytes(encrypted->iv, wvoec::KEY_IV_SIZE) != 1) { - LOGE("SaveUsageEntry: Could not generate iv."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - 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& buffer, - ODK_ClockValues* clock_values) { - if (buffer.size() < SignedEntrySize()) return OEMCrypto_ERROR_SHORT_BUFFER; - if (buffer.size() > SignedEntrySize()) - LOGW("LoadUsageTableEntry: buffer is large. %zu > %zu", buffer.size(), - SignedEntrySize()); - std::vector clear_buffer(buffer.size()); - SignedEntryBlock* clear = - reinterpret_cast(&clear_buffer[0]); - const SignedEntryBlock* encrypted = - reinterpret_cast(&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 std::vector& key = ce->DeviceRootKey(); - if (key.empty()) { - LOGE("LoadUsageEntry: DeviceRootKey is unexpectedly empty."); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - // 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 (CRYPTO_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(kEntryVerification), - kMagicLength) - .c_str(), - reinterpret_cast(kEntryVerification)); - return OEMCrypto_ERROR_BAD_MAGIC; - } - - // Check that the index is correct. - if (index != clear->data.index) { - LOGE("LoadUsageEntry: entry says index is %u, not %u", 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; - } - data_ = clear->data; - return ODK_ReloadClockValues( - clock_values, data_.time_of_license_received, data_.time_of_first_decrypt, - data_.time_of_last_decrypt, data_.status, ce->SystemTime()); -} - -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() {} - -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, ODK_ClockValues* clock_values) { - 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(clock_values); - 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; -} - -UsageTableEntry* UsageTable::MakeEntry(uint32_t index) { - return new UsageTableEntry(this, index, master_generation_number_); -} - -OEMCryptoResult UsageTable::CreateNewUsageEntry( - SessionContext* session, std::unique_ptr* 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; - const size_t index = generation_numbers_.size(); - const size_t max = ce_->max_usage_table_size(); - if (max > 0 && index >= max) { - LOGE("Too many usage entries: %zu/%zu", index, max); - return OEMCrypto_ERROR_INSUFFICIENT_RESOURCES; - } - UsageTableEntry* new_entry = MakeEntry(index); - generation_numbers_.push_back(master_generation_number_); - sessions_.push_back(session); - master_generation_number_++; - entry->reset(new_entry); - *usage_entry_number = index; - return OEMCrypto_SUCCESS; -} - -OEMCryptoResult UsageTable::LoadUsageEntry( - SessionContext* session, std::unique_ptr* entry, - uint32_t index, const std::vector& buffer, - ODK_ClockValues* clock_values) { - if (!header_loaded_) { - LOGE("LoadUsageEntry: 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 %u used by other session.", index); - return OEMCrypto_ERROR_INVALID_SESSION; - } - const size_t max = ce_->max_usage_table_size(); - if (max > 0 && index >= max) { - LOGE("Too many usage entries: %u/%zu", index, max); - return OEMCrypto_ERROR_INSUFFICIENT_RESOURCES; - } - std::unique_ptr new_entry(MakeEntry(index)); - - OEMCryptoResult status = - new_entry->LoadData(ce_, index, buffer, clock_values); - if (status != OEMCrypto_SUCCESS) { - 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])) { - return OEMCrypto_ERROR_GENERATION_SKEW; - } - status = OEMCrypto_WARNING_GENERATION_SKEW; - } - sessions_[index] = session; - *entry = std::move(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: %u > %zu", 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 %zu", 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 clear_buffer(buffer_size); - memset(&clear_buffer[0], 0, buffer_size); - memset(signed_buffer, 0, buffer_size); - SignedHeaderBlock* clear = - reinterpret_cast(&clear_buffer[0]); - SignedHeaderBlock* encrypted = - reinterpret_cast(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(&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 std::vector& key = ce_->DeviceRootKey(); - if (key.empty()) { - LOGE("SaveUsageTableHeader: DeviceRootKey is unexpectedly empty."); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - // Encrypt the entry. - if (RAND_bytes(encrypted->iv, wvoec::KEY_IV_SIZE) != 1) { - LOGE("SaveUsageHeader: Could not generate iv entry."); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - 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& buffer) { - if (!LoadGenerationNumber(false)) return OEMCrypto_ERROR_UNKNOWN_FAILURE; - - if (buffer.size() < SignedHeaderSize(0)) return OEMCrypto_ERROR_SHORT_BUFFER; - size_t max = ce_->max_usage_table_size(); - if (max > 0 && buffer.size() > SignedHeaderSize(max)) { - LOGE("Header too big: %zu bytes/%zu bytes", buffer.size(), - SignedHeaderSize(max)); - return OEMCrypto_ERROR_INSUFFICIENT_RESOURCES; - } - std::vector clear_buffer(buffer.size()); - SignedHeaderBlock* clear = - reinterpret_cast(&clear_buffer[0]); - const SignedHeaderBlock* encrypted = - reinterpret_cast(&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 std::vector& key = ce_->DeviceRootKey(); - if (key.empty()) { - LOGE("LoadUsageTableHeader: DeviceRootKey is unexpectedly empty."); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - - // 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 (CRYPTO_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(kHeaderVerification), - kMagicLength) - .c_str(), - reinterpret_cast(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. %zu > %zu", 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(&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 %u >= %zu", new_index, - generation_numbers_.size()); - return OEMCrypto_ERROR_INVALID_CONTEXT; - } - if (sessions_[new_index]) { - LOGE("MoveEntry: session open for %u", 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"; - auto 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(&master_generation_number_), - sizeof(int64_t)); - 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"; - auto file = file_system->Open(filename, wvcdm::FileSystem::kReadOnly); - if (!file) { - if (or_make_new_one) { - return RAND_bytes(reinterpret_cast(&master_generation_number_), - sizeof(int64_t)) == 1; - } - LOGE("UsageTable: File open failed: %s (clearing table)", path.c_str()); - master_generation_number_ = 0; - return false; - } - file->Read(reinterpret_cast(&master_generation_number_), - sizeof(int64_t)); - 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] != nullptr) { - LOGE("CreateUsageTableHeader: index %zu used by session.", i); - return OEMCrypto_ERROR_INVALID_SESSION; - } - } - sessions_.clear(); - generation_numbers_.clear(); - header_loaded_ = true; - return SaveUsageTableHeader(header_buffer, *header_buffer_length); -} - -} // namespace wvoec_ref diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_usage_table_ref.h b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_usage_table_ref.h deleted file mode 100644 index 7fdd1785..00000000 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_usage_table_ref.h +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine -// License Agreement. -// -// Reference implementation of OEMCrypto APIs -// -#ifndef OEMCRYPTO_USAGE_TABLE_REF_H_ -#define OEMCRYPTO_USAGE_TABLE_REF_H_ - -#include -#include -#include -#include -#include - -#include "OEMCryptoCENC.h" -#include "odk_structs.h" -#include "oemcrypto_types.h" -#include "openssl/sha.h" - -namespace wvoec_ref { - -class SessionContext; -class CryptoEngine; -class UsageTable; - -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); - virtual ~UsageTableEntry(); // Free memory, remove reference in header. - bool Inactive() { return data_.status >= kInactive; } - // Mark this entry as modified and forbid a usage report until the data has - // been saved. This is done on important events like first decrypt and - // deactivation. - void ForbidReport(); - 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& server, - const std::vector& client); - bool SetMacKeys(const std::vector& server, - const std::vector& client); - virtual OEMCryptoResult ReportUsage(const std::vector& pst, - uint8_t* buffer, size_t* buffer_length); - virtual void UpdateAndIncrement(ODK_ClockValues* clock_values); - // Save all data to the given buffer. This should be called after updating the - // data. - OEMCryptoResult SaveData(CryptoEngine* ce, SessionContext* session, - uint8_t* signed_buffer, size_t buffer_size); - // Load all data from the buffer, and then update clock_values. - OEMCryptoResult LoadData(CryptoEngine* ce, uint32_t index, - const std::vector& buffer, - ODK_ClockValues* clock_values); - 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; } - void set_recent_decrypt(bool recent_decrypt) { - recent_decrypt_ = recent_decrypt; - } - static size_t SignedEntrySize(); - const uint8_t* mac_key_server() const { return data_.mac_key_server; } - const uint8_t* mac_key_client() const { return data_.mac_key_client; } - - protected: - 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){}; - virtual ~UsageTable(); - - OEMCryptoResult CreateNewUsageEntry(SessionContext* session, - std::unique_ptr* entry, - uint32_t* usage_entry_number); - OEMCryptoResult LoadUsageEntry(SessionContext* session, - std::unique_ptr* entry, - uint32_t index, - const std::vector& buffer, - ODK_ClockValues* clock_values); - OEMCryptoResult UpdateUsageEntry( - SessionContext* session, UsageTableEntry* entry, uint8_t* header_buffer, - size_t* header_buffer_length, uint8_t* entry_buffer, - size_t* entry_buffer_length, ODK_ClockValues* clock_values); - OEMCryptoResult MoveEntry(UsageTableEntry* entry, uint32_t new_index); - OEMCryptoResult CreateUsageTableHeader(uint8_t* header_buffer, - size_t* header_buffer_length); - OEMCryptoResult LoadUsageTableHeader(const std::vector& 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); - - protected: - virtual UsageTableEntry* MakeEntry(uint32_t index); - virtual OEMCryptoResult SaveUsageTableHeader(uint8_t* signed_buffer, - size_t buffer_size); - virtual bool SaveGenerationNumber(); - virtual bool LoadGenerationNumber(bool or_make_new_one); - - CryptoEngine* ce_; - bool header_loaded_; - int64_t master_generation_number_; - std::vector generation_numbers_; - std::vector sessions_; - - friend class UsageTableEntry; -}; - -} // namespace wvoec_ref - -#endif // OEMCRYPTO_USAGE_TABLE_REF_H_ diff --git a/libwvdrmengine/oemcrypto/ref/src/scoped_object.h b/libwvdrmengine/oemcrypto/ref/src/scoped_object.h deleted file mode 100644 index 5acdc0a9..00000000 --- a/libwvdrmengine/oemcrypto/ref/src/scoped_object.h +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine License -// Agreement. -// -// Reference implementation of OEMCrypto APIs -// -#ifndef SCOPED_OBJECT_H_ -#define SCOPED_OBJECT_H_ - -namespace wvoec_ref { - -// A generic wrapper around pointer. This allows for automatic -// memory clean up when the ScopedObject variable goes out of scope. -// This is intended to be used with OpenSSL/BoringSSL structs. -template -class ScopedObject { - public: - ScopedObject() : ptr_(nullptr) {} - ScopedObject(Type* ptr) : ptr_(ptr) {} - ~ScopedObject() { - if (ptr_) { - Destructor(ptr_); - ptr_ = nullptr; - } - } - - // Copy construction and assignment are not allowed. - ScopedObject(const ScopedObject& other) = delete; - ScopedObject& operator=(const ScopedObject& other) = delete; - - // Move construction and assignment are allowed. - ScopedObject(ScopedObject&& other) : ptr_(other.ptr_) { - other.ptr_ = nullptr; - } - ScopedObject& operator=(ScopedObject&& other) { - if (ptr_) { - Destructor(ptr_); - } - ptr_ = other.ptr_; - other.ptr_ = nullptr; - return *this; - } - - explicit operator bool() const { return ptr_ != nullptr; } - - Type& operator*() { return *ptr_; } - Type* get() const { return ptr_; } - Type* operator->() const { return ptr_; } - - // Releasing the pointer will remove the responsibility of the - // ScopedObject to clean up the pointer. - Type* release() { - Type* temp = ptr_; - ptr_ = nullptr; - return temp; - } - - void reset(Type* ptr = nullptr) { - if (ptr_) { - Destructor(ptr_); - } - ptr_ = ptr; - } - - private: - Type* ptr_ = nullptr; -}; - -} // namespace wvoec_ref - -#endif // SCOPED_OBJECT_H_ diff --git a/libwvdrmengine/oemcrypto/ref/src/wvcrc.cpp b/libwvdrmengine/oemcrypto/ref/src/wvcrc.cpp deleted file mode 100644 index 000ac260..00000000 --- a/libwvdrmengine/oemcrypto/ref/src/wvcrc.cpp +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine -// License Agreement. -// -// Compute CRC32/MPEG2 Checksum. Needed for verification of WV Keybox. -// -#include "platform.h" -#include "wvcrc32.h" - -namespace wvoec_ref { - -#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 wvcrc32Init() { - return INIT_CRC32; -} - -uint32_t wvcrc32Cont(const uint8_t* p_begin, int i_count, uint32_t prev_crc) { - return(wvrunningcrc32(p_begin, i_count, prev_crc)); -} - -uint32_t wvcrc32n(const uint8_t* p_begin, int i_count) { - return htonl(wvrunningcrc32(p_begin, i_count, INIT_CRC32)); -} - -} // namespace wvoec_ref diff --git a/libwvdrmengine/oemcrypto/ref/src/wvcrc32.h b/libwvdrmengine/oemcrypto/ref/src/wvcrc32.h deleted file mode 100644 index b1e0ee6b..00000000 --- a/libwvdrmengine/oemcrypto/ref/src/wvcrc32.h +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine -// License Agreement. -// -// Compute CRC32 Checksum. Needed for verification of WV Keybox. -// -#ifndef WVCRC32_H_ -#define WVCRC32_H_ - -#include - -namespace wvoec_ref { - -uint32_t wvcrc32(const uint8_t* p_begin, int i_count); -uint32_t wvcrc32Init(); -uint32_t wvcrc32Cont(const uint8_t* p_begin, int i_count, uint32_t prev_crc); - -// Convert to network byte order -uint32_t wvcrc32n(const uint8_t* p_begin, int i_count); - -} // namespace wvoec_ref - -#endif // WVCRC32_H_ diff --git a/libwvdrmengine/oemcrypto/ref/test/oem_cert_test.cpp b/libwvdrmengine/oemcrypto/ref/test/oem_cert_test.cpp deleted file mode 100644 index e7e4ffca..00000000 --- a/libwvdrmengine/oemcrypto/ref/test/oem_cert_test.cpp +++ /dev/null @@ -1,536 +0,0 @@ -// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine License -// Agreement. - -#include "oem_cert.h" - -namespace wvoec_ref { -namespace { -const uint32_t kTestOemSystemId = 7913; - -// clang-format off - -// OEM Certificate private key. -// RSA Private-Key: (2048 bit, 2 primes). -const uint8_t kTestOemPrivateKey[] = { - 0x30, 0x82, 0x04, 0xbd, 0x02, 0x01, 0x00, 0x30, - 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, - 0x04, 0xa7, 0x30, 0x82, 0x04, 0xa3, 0x02, 0x01, - 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xa8, 0x75, - 0xd5, 0x3d, 0xd3, 0xf3, 0x59, 0xd1, 0x63, 0x0f, - 0x5d, 0x5f, 0x2c, 0xaf, 0x80, 0x4e, 0x9a, 0xef, - 0x9a, 0x8f, 0x88, 0x37, 0xe5, 0x56, 0xf8, 0x66, - 0xcb, 0xa6, 0x61, 0xab, 0xc1, 0xa9, 0x04, 0xc2, - 0x12, 0x9d, 0xa6, 0x0c, 0x2c, 0xcb, 0x42, 0x09, - 0xd0, 0x36, 0xf0, 0x85, 0x01, 0xdf, 0xd5, 0xbd, - 0xaf, 0x82, 0xbb, 0x25, 0xa1, 0x61, 0x17, 0xfe, - 0xa1, 0x65, 0x34, 0xda, 0x91, 0xee, 0x91, 0x46, - 0xd6, 0x63, 0x47, 0x6a, 0xa5, 0x32, 0x62, 0xe2, - 0x4c, 0x7c, 0xf7, 0x76, 0x59, 0xe1, 0x2b, 0x47, - 0x8d, 0x1c, 0xe6, 0xa0, 0xbd, 0xc3, 0xc9, 0x36, - 0x0e, 0x90, 0x75, 0xba, 0x1c, 0xbd, 0xca, 0x85, - 0x0a, 0x4e, 0xcc, 0xfe, 0x91, 0x3f, 0x22, 0x42, - 0x96, 0xae, 0xa0, 0x87, 0x82, 0x63, 0x3b, 0x22, - 0x54, 0xbc, 0x28, 0xa3, 0x45, 0x4b, 0x34, 0x12, - 0x4e, 0xeb, 0x04, 0x4d, 0x29, 0xb3, 0x05, 0x62, - 0x0d, 0x51, 0x16, 0x46, 0x98, 0x21, 0xc8, 0x59, - 0x96, 0x53, 0x43, 0x38, 0x95, 0x1a, 0x42, 0x94, - 0x8b, 0x49, 0x5d, 0x1b, 0x8a, 0xd5, 0x82, 0x6a, - 0x32, 0x6f, 0x0e, 0x5a, 0x85, 0x3b, 0xd5, 0x42, - 0xc0, 0x4c, 0x34, 0x43, 0x7c, 0x4f, 0xef, 0xca, - 0x02, 0x99, 0x38, 0xf9, 0xa5, 0xc0, 0xd8, 0x1d, - 0xe7, 0x9e, 0x8c, 0x4d, 0x9c, 0x40, 0xcd, 0x4b, - 0x5e, 0x44, 0x37, 0x8d, 0xc5, 0x96, 0xd4, 0xf7, - 0xb3, 0x37, 0x4c, 0x2e, 0x2d, 0x30, 0xca, 0x97, - 0x39, 0xed, 0xe8, 0x73, 0xc5, 0xe7, 0xcb, 0x95, - 0xf0, 0x84, 0x4a, 0x5a, 0x9e, 0x13, 0x19, 0x5f, - 0x98, 0xe5, 0xbe, 0x31, 0x5b, 0xff, 0xed, 0x29, - 0x26, 0xc4, 0x93, 0x54, 0x49, 0x84, 0xd2, 0xeb, - 0x21, 0x40, 0x19, 0x5f, 0xf7, 0x32, 0x67, 0x93, - 0xe0, 0xda, 0x77, 0xfc, 0xda, 0x5e, 0xc4, 0x5b, - 0x95, 0x2e, 0x46, 0xf3, 0xce, 0xfd, 0x02, 0x03, - 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x01, 0x00, - 0x9e, 0x6d, 0x82, 0xc8, 0x0c, 0xc6, 0xb5, 0xd7, - 0xa7, 0xb3, 0xd1, 0x7a, 0x2a, 0x8a, 0x3a, 0xbe, - 0xb2, 0x13, 0x58, 0x66, 0x58, 0x13, 0x49, 0x4a, - 0x0b, 0x7e, 0x91, 0x53, 0xbe, 0x53, 0x4b, 0x63, - 0xeb, 0x27, 0xa1, 0x5e, 0x45, 0xc4, 0xf9, 0x73, - 0x86, 0x7d, 0xb8, 0x25, 0x92, 0xf9, 0x63, 0x93, - 0xe0, 0x6d, 0xed, 0xdb, 0xa2, 0xa9, 0x77, 0x25, - 0xda, 0xed, 0x0b, 0x58, 0x24, 0xe6, 0xd1, 0x8b, - 0x6d, 0x71, 0x13, 0x3a, 0x76, 0xf5, 0xa2, 0xba, - 0xca, 0x28, 0x4d, 0x0a, 0xd1, 0xa7, 0xaa, 0x4b, - 0x8a, 0xea, 0x55, 0x99, 0xb2, 0x83, 0xc5, 0x33, - 0x95, 0xcd, 0x92, 0xd0, 0xe5, 0x06, 0xcc, 0xf4, - 0xe8, 0xbb, 0x49, 0xc0, 0x66, 0x25, 0x9a, 0xef, - 0xa7, 0x06, 0xbc, 0xb3, 0x2a, 0x21, 0x86, 0xcc, - 0x4f, 0xd6, 0xaf, 0x9d, 0xed, 0x11, 0xef, 0x9f, - 0x14, 0x2f, 0x8b, 0xac, 0x96, 0x75, 0x03, 0x1a, - 0xe4, 0x5c, 0x48, 0x81, 0x3a, 0x4b, 0x21, 0x6e, - 0xad, 0xb3, 0x27, 0x51, 0xe9, 0x35, 0xbe, 0xed, - 0x42, 0x5f, 0x8f, 0x83, 0xf0, 0x99, 0xb0, 0xaf, - 0xa9, 0x9c, 0x2f, 0xee, 0x5f, 0xee, 0x39, 0x2b, - 0x1d, 0xb0, 0xb1, 0xf8, 0x7b, 0x69, 0x38, 0x68, - 0xae, 0xa0, 0x36, 0x2a, 0xf5, 0xed, 0x96, 0xfa, - 0x7c, 0x1c, 0x59, 0x29, 0xbf, 0xb3, 0x9e, 0x14, - 0x97, 0x06, 0xc2, 0x40, 0x30, 0x00, 0x6a, 0x95, - 0xd3, 0x86, 0x86, 0xb9, 0x4c, 0xf5, 0x51, 0xa3, - 0x6d, 0x5a, 0xd1, 0x46, 0x43, 0x24, 0xa4, 0xa9, - 0x59, 0xcf, 0xa2, 0xa7, 0x4e, 0x50, 0x7a, 0xa3, - 0x14, 0xe4, 0x4e, 0x32, 0x4d, 0xd4, 0xc2, 0xcf, - 0x2d, 0x74, 0xfb, 0x51, 0x34, 0x98, 0x68, 0xc3, - 0xd2, 0xb1, 0xd9, 0x38, 0x94, 0x91, 0x28, 0xb1, - 0x69, 0x9a, 0xbf, 0xbf, 0x1a, 0xdf, 0xd3, 0xb6, - 0x21, 0x38, 0x94, 0x1b, 0x81, 0x00, 0xb5, 0x39, - 0x02, 0x81, 0x81, 0x00, 0xdb, 0xe4, 0x83, 0xc5, - 0x7a, 0xe0, 0xcf, 0xeb, 0x07, 0x37, 0xfb, 0xf6, - 0xfe, 0xb3, 0x62, 0x72, 0x86, 0xd0, 0x12, 0x96, - 0x9d, 0xf4, 0x93, 0x90, 0xdc, 0xf6, 0xc6, 0x03, - 0x0c, 0x46, 0xb8, 0x66, 0x60, 0xf3, 0x46, 0x5b, - 0xab, 0x9f, 0x9d, 0x81, 0xac, 0x26, 0x8f, 0xd7, - 0xa3, 0xbd, 0x16, 0xbb, 0xb4, 0x4e, 0xf6, 0xc0, - 0x12, 0xb6, 0x99, 0x4a, 0xf5, 0xc1, 0x6c, 0x40, - 0x72, 0x18, 0x71, 0x02, 0x65, 0x77, 0xb1, 0xfb, - 0xec, 0x19, 0xbb, 0x8c, 0x03, 0xea, 0x7b, 0x17, - 0x63, 0xc9, 0xb9, 0x3b, 0x10, 0x56, 0x19, 0xef, - 0x86, 0x69, 0x4d, 0x61, 0x03, 0xac, 0x30, 0x65, - 0x63, 0xe5, 0xe1, 0x0f, 0xd6, 0xf6, 0x5b, 0xc9, - 0x7c, 0xde, 0x9b, 0x26, 0xca, 0x98, 0xda, 0x0c, - 0x5b, 0x6f, 0x91, 0x88, 0xbf, 0x98, 0xc3, 0xbc, - 0x72, 0x21, 0xa0, 0x07, 0x0a, 0x5e, 0xc7, 0x61, - 0x4a, 0xb3, 0x32, 0xc7, 0x02, 0x81, 0x81, 0x00, - 0xc4, 0x1f, 0x4a, 0x23, 0xa6, 0x0b, 0xb9, 0xd5, - 0xc7, 0xe9, 0x1a, 0x24, 0xe8, 0x2b, 0xf2, 0x1f, - 0x17, 0xc3, 0xe6, 0x14, 0x76, 0x71, 0x11, 0x76, - 0x8f, 0xfc, 0x66, 0xb8, 0x8c, 0xe2, 0xf5, 0x46, - 0x89, 0x0d, 0xd7, 0xe3, 0x56, 0x19, 0xd7, 0x1a, - 0xfe, 0x1c, 0xd4, 0x0f, 0x8b, 0x72, 0xd1, 0x20, - 0xb0, 0xa4, 0xbe, 0x6b, 0x6b, 0x01, 0x57, 0xe8, - 0x6b, 0xdf, 0x89, 0x55, 0x3f, 0x10, 0x41, 0x63, - 0xb0, 0x62, 0xa5, 0x7f, 0x4f, 0xe7, 0x42, 0x54, - 0xe4, 0x0e, 0x55, 0xae, 0xa2, 0x53, 0x3d, 0xb8, - 0x4a, 0xff, 0xeb, 0xe2, 0x8a, 0x71, 0x17, 0x54, - 0x20, 0x05, 0x51, 0xed, 0xae, 0xb0, 0xca, 0x7e, - 0xc6, 0xd7, 0x09, 0xa8, 0x39, 0x88, 0xac, 0x7f, - 0x4b, 0xe0, 0x49, 0xd5, 0x6c, 0x89, 0xf0, 0xbc, - 0xe4, 0xe9, 0xb0, 0x29, 0x73, 0x6c, 0x55, 0x7d, - 0x8f, 0xbe, 0x32, 0x31, 0x14, 0xd2, 0xec, 0x1b, - 0x02, 0x81, 0x80, 0x67, 0xf6, 0x55, 0x5a, 0xa3, - 0xaa, 0xf0, 0x82, 0x75, 0x2a, 0x41, 0xe5, 0x58, - 0x2c, 0x65, 0xaa, 0x32, 0x14, 0xe4, 0x04, 0xf3, - 0xef, 0x33, 0x69, 0x75, 0x1e, 0xf3, 0x25, 0x73, - 0xc3, 0x67, 0xe1, 0x77, 0x8a, 0xed, 0x43, 0xe0, - 0x13, 0x99, 0xfb, 0x39, 0xf2, 0x0d, 0x65, 0xed, - 0x93, 0x33, 0xd1, 0x51, 0x01, 0x58, 0x66, 0x1d, - 0x32, 0xd9, 0xac, 0xf8, 0x1e, 0x17, 0xd9, 0x2c, - 0x58, 0x63, 0xed, 0xb7, 0x1d, 0x6d, 0x37, 0xe7, - 0x3b, 0x8f, 0x51, 0x36, 0x74, 0xc0, 0xf7, 0xa1, - 0x05, 0x39, 0x9f, 0x34, 0x2d, 0x11, 0x1c, 0x0e, - 0xd7, 0x70, 0x6f, 0x22, 0xb6, 0x61, 0x37, 0x3e, - 0x90, 0xeb, 0xe4, 0x7a, 0x44, 0x85, 0xc6, 0xf0, - 0x53, 0xaa, 0xd5, 0x1f, 0x4a, 0x3f, 0x25, 0x42, - 0x81, 0xb0, 0x34, 0x10, 0x29, 0xe0, 0xb9, 0x12, - 0xd8, 0xd4, 0xf9, 0x1f, 0x2d, 0x0a, 0x64, 0xf4, - 0x55, 0x5e, 0xf7, 0x02, 0x81, 0x80, 0x3d, 0x06, - 0x1f, 0x63, 0x88, 0x3f, 0x0d, 0xcb, 0xdf, 0x30, - 0x40, 0xda, 0x4b, 0x03, 0xa1, 0x8a, 0xdb, 0x32, - 0x31, 0x5d, 0x1c, 0x9d, 0x81, 0xf9, 0x8a, 0x43, - 0xd7, 0x12, 0x85, 0x83, 0xf9, 0x1d, 0xc1, 0x77, - 0x75, 0x3d, 0x5f, 0x85, 0x1a, 0xd1, 0x63, 0x50, - 0x45, 0x0b, 0xb1, 0x30, 0x40, 0xb2, 0x13, 0x44, - 0xaf, 0x9b, 0x6c, 0xe8, 0x36, 0x1a, 0x33, 0xb6, - 0x92, 0x5c, 0xdc, 0x0a, 0x8a, 0xce, 0x22, 0x0c, - 0x0f, 0xc2, 0xd5, 0x71, 0xf7, 0xc9, 0xc2, 0x4c, - 0x53, 0x8c, 0xcb, 0x25, 0x6b, 0x86, 0xf4, 0x8f, - 0x3d, 0x2e, 0x78, 0x35, 0x48, 0x34, 0xfc, 0xe1, - 0xaa, 0xe4, 0x71, 0xfe, 0xc0, 0x83, 0x42, 0x0b, - 0x97, 0x0d, 0xa9, 0x19, 0x45, 0xd3, 0x36, 0x20, - 0xcb, 0xd8, 0x84, 0xb5, 0x47, 0x1a, 0xff, 0x7f, - 0x57, 0x39, 0x0e, 0x99, 0x1e, 0xe0, 0xba, 0xe1, - 0x4b, 0x6c, 0xca, 0x35, 0xf7, 0x11, 0x02, 0x81, - 0x80, 0x5a, 0x59, 0xf0, 0x8e, 0x07, 0x9c, 0x1a, - 0x83, 0x2b, 0x28, 0xc4, 0x82, 0xcc, 0xb7, 0x9e, - 0x41, 0xa5, 0x15, 0xa2, 0x37, 0xa7, 0x0c, 0x77, - 0x09, 0x73, 0xf5, 0xb1, 0x3f, 0x7a, 0x55, 0x9f, - 0x15, 0x90, 0xa3, 0x5e, 0x6e, 0x19, 0x46, 0x6d, - 0x1f, 0x28, 0x64, 0xad, 0xa0, 0xb5, 0xca, 0x7d, - 0x06, 0x44, 0x88, 0xae, 0x2b, 0x80, 0x21, 0x84, - 0x3d, 0x8d, 0xa5, 0x09, 0x4f, 0xa1, 0xd9, 0x7d, - 0x7c, 0x9a, 0x8b, 0x64, 0x8f, 0xf6, 0xa5, 0xce, - 0x56, 0x65, 0xba, 0xcb, 0x30, 0x38, 0x53, 0xf8, - 0x1b, 0x89, 0x8f, 0xdf, 0xb5, 0xc3, 0x86, 0x3c, - 0x24, 0xef, 0xbc, 0xc0, 0xfc, 0x6c, 0xa4, 0xc6, - 0x74, 0xbb, 0xeb, 0x79, 0xa9, 0x8e, 0xe5, 0x25, - 0xc0, 0x0a, 0xe5, 0x90, 0x08, 0x43, 0x82, 0xec, - 0x17, 0x5e, 0x9e, 0xa2, 0x05, 0xc5, 0x03, 0x20, - 0x12, 0xf7, 0x86, 0x2e, 0x7e, 0x8e, 0x11, 0xf7, - 0x14 -}; - -const size_t kTestOemPrivateKeySize = sizeof(kTestOemPrivateKey); - -// OEM Certificate public cert data. -// Leaf (device) certificate: -// version: 2 -// serialNumber: 61412119066269531030714093834591281593 -// signature algorithm: sha256WithRSAEncryption (1.2.840.113549.1.1.11) -// issuer: -// C=US, ST=WA, L=Kirkland, O=Google, OU=Widevine, CN=system id: 7913 -// validity: -// notBefore: Jan 27 15:55:47 2021 GMT -// notAfter: Jan 25 15:55:47 2031 GMT -// subject: -// CN=7913-leaf, C=US, ST=WA, L=Kirkland, O=Google, OU=Widevine -// key: RSA Public key -// extensions: -// - object: Widevine System Id (1.3.6.1.4.1.11129.4.1.1) -// critical: BOOL ABSENT -// value: 02 02 1e e9 (7913) -// sig_alg: sha256WithRSAEncryption (1.2.840.113549.1.1.11) -// signature: ... -// -// Intermediate (manufacturer) certificate: -// version: 2 -// serialNumber: 4911737327617104025470773024969385060 -// signature: sha256WithRSAEncryption (1.2.840.113549.1.1.11) -// issuer: -// C=US, ST=Washington, L=Kirkland, O=Google, OU=Widevine, -// CN=widevine.com/oem-root-prod -// validity: -// notBefore: Nov 18 01:13:35 2017 GMT -// notAfter: Nov 18 01:13:13 2027 GMT -// subject: -// C=US, ST=WA, L=Kirkland, O=Google, OU=Widevine, CN=system id: 7913 -// key: RSA Public key -// extensions: -// - object: X509v3 Basic Constraints (2.5.29.19) -// critical: TRUE -// value: 30 06 01 01 ff 02 01 00 -// - object: X509v3 Key Usage (2.5.29.15) -// critical: TRUE -// value: 03 02 02 04 -// - object: X509v3 Subject Key Identifier (2.5.29.14) -// critical: BOOL ABSENT -// value: -// 04 14 4b cb df aa 02 de 8d c3 e7 e5 85 db 2e 8a be 75 6b 8a 67-58 -// - object: X509v3 Authority Key Identifier (2.5.29.35) -// critical: BOOL ABSENT -// value: ... -// - object: Widevine System Id (1.3.6.1.4.1.11129.4.1.1) -// critical: BOOL ABSENT -// value: 02 02 1e e9 (7913) -// sig_alg: sha256WithRSAEncryption (1.2.840.113549.1.1.11) -// signature: ... -const uint8_t kTestOemPublicCert[] = { - 0x30, 0x82, 0x09, 0x28, 0x06, 0x09, 0x2a, 0x86, - 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, - 0x82, 0x09, 0x19, 0x30, 0x82, 0x09, 0x15, 0x02, - 0x01, 0x01, 0x31, 0x00, 0x30, 0x0b, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, - 0x01, 0xa0, 0x82, 0x08, 0xfd, 0x30, 0x82, 0x03, - 0x70, 0x30, 0x82, 0x02, 0x58, 0xa0, 0x03, 0x02, - 0x01, 0x02, 0x02, 0x10, 0x2e, 0x33, 0x8b, 0x3d, - 0x69, 0x18, 0x4c, 0xf7, 0x78, 0x2e, 0x3b, 0x3b, - 0x43, 0xb4, 0x21, 0xb9, 0x30, 0x0d, 0x06, 0x09, - 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, - 0x0b, 0x05, 0x00, 0x30, 0x6b, 0x31, 0x0b, 0x30, - 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, - 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, - 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, 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, 0x18, - 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, - 0x0f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20, - 0x69, 0x64, 0x3a, 0x20, 0x37, 0x39, 0x31, 0x33, - 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x31, 0x30, 0x31, - 0x32, 0x37, 0x31, 0x35, 0x35, 0x35, 0x34, 0x37, - 0x5a, 0x17, 0x0d, 0x33, 0x31, 0x30, 0x31, 0x32, - 0x35, 0x31, 0x35, 0x35, 0x35, 0x34, 0x37, 0x5a, - 0x30, 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, - 0x55, 0x04, 0x03, 0x0c, 0x09, 0x37, 0x39, 0x31, - 0x33, 0x2d, 0x6c, 0x65, 0x61, 0x66, 0x31, 0x0b, - 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, - 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, - 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, - 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, 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, - 0xa8, 0x75, 0xd5, 0x3d, 0xd3, 0xf3, 0x59, 0xd1, - 0x63, 0x0f, 0x5d, 0x5f, 0x2c, 0xaf, 0x80, 0x4e, - 0x9a, 0xef, 0x9a, 0x8f, 0x88, 0x37, 0xe5, 0x56, - 0xf8, 0x66, 0xcb, 0xa6, 0x61, 0xab, 0xc1, 0xa9, - 0x04, 0xc2, 0x12, 0x9d, 0xa6, 0x0c, 0x2c, 0xcb, - 0x42, 0x09, 0xd0, 0x36, 0xf0, 0x85, 0x01, 0xdf, - 0xd5, 0xbd, 0xaf, 0x82, 0xbb, 0x25, 0xa1, 0x61, - 0x17, 0xfe, 0xa1, 0x65, 0x34, 0xda, 0x91, 0xee, - 0x91, 0x46, 0xd6, 0x63, 0x47, 0x6a, 0xa5, 0x32, - 0x62, 0xe2, 0x4c, 0x7c, 0xf7, 0x76, 0x59, 0xe1, - 0x2b, 0x47, 0x8d, 0x1c, 0xe6, 0xa0, 0xbd, 0xc3, - 0xc9, 0x36, 0x0e, 0x90, 0x75, 0xba, 0x1c, 0xbd, - 0xca, 0x85, 0x0a, 0x4e, 0xcc, 0xfe, 0x91, 0x3f, - 0x22, 0x42, 0x96, 0xae, 0xa0, 0x87, 0x82, 0x63, - 0x3b, 0x22, 0x54, 0xbc, 0x28, 0xa3, 0x45, 0x4b, - 0x34, 0x12, 0x4e, 0xeb, 0x04, 0x4d, 0x29, 0xb3, - 0x05, 0x62, 0x0d, 0x51, 0x16, 0x46, 0x98, 0x21, - 0xc8, 0x59, 0x96, 0x53, 0x43, 0x38, 0x95, 0x1a, - 0x42, 0x94, 0x8b, 0x49, 0x5d, 0x1b, 0x8a, 0xd5, - 0x82, 0x6a, 0x32, 0x6f, 0x0e, 0x5a, 0x85, 0x3b, - 0xd5, 0x42, 0xc0, 0x4c, 0x34, 0x43, 0x7c, 0x4f, - 0xef, 0xca, 0x02, 0x99, 0x38, 0xf9, 0xa5, 0xc0, - 0xd8, 0x1d, 0xe7, 0x9e, 0x8c, 0x4d, 0x9c, 0x40, - 0xcd, 0x4b, 0x5e, 0x44, 0x37, 0x8d, 0xc5, 0x96, - 0xd4, 0xf7, 0xb3, 0x37, 0x4c, 0x2e, 0x2d, 0x30, - 0xca, 0x97, 0x39, 0xed, 0xe8, 0x73, 0xc5, 0xe7, - 0xcb, 0x95, 0xf0, 0x84, 0x4a, 0x5a, 0x9e, 0x13, - 0x19, 0x5f, 0x98, 0xe5, 0xbe, 0x31, 0x5b, 0xff, - 0xed, 0x29, 0x26, 0xc4, 0x93, 0x54, 0x49, 0x84, - 0xd2, 0xeb, 0x21, 0x40, 0x19, 0x5f, 0xf7, 0x32, - 0x67, 0x93, 0xe0, 0xda, 0x77, 0xfc, 0xda, 0x5e, - 0xc4, 0x5b, 0x95, 0x2e, 0x46, 0xf3, 0xce, 0xfd, - 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, 0x1e, 0xe9, 0x30, 0x0d, 0x06, - 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, - 0x00, 0x04, 0x9e, 0xbb, 0x41, 0x3e, 0x1b, 0x35, - 0xca, 0x24, 0xe3, 0xa7, 0x62, 0xf7, 0xbf, 0x54, - 0x88, 0x1d, 0xa3, 0x6c, 0x30, 0x1f, 0xb7, 0xe4, - 0x2b, 0x76, 0x54, 0x4f, 0xb1, 0x30, 0xba, 0x86, - 0x21, 0x12, 0xc3, 0xd9, 0x25, 0xfd, 0x94, 0xab, - 0x3c, 0x9d, 0x4d, 0xbc, 0x2b, 0xdc, 0x68, 0x01, - 0x8d, 0x59, 0x4f, 0x81, 0xe8, 0x87, 0xbe, 0x05, - 0x75, 0x3e, 0x24, 0xd9, 0xf1, 0x55, 0xe3, 0x56, - 0x75, 0xa4, 0x7f, 0xb4, 0x50, 0x41, 0x4b, 0x88, - 0x0e, 0x8f, 0x6e, 0x10, 0x13, 0x25, 0x24, 0xda, - 0x4c, 0x97, 0x0a, 0xdc, 0xbf, 0x2a, 0x1d, 0x4d, - 0x02, 0xb3, 0x4b, 0x6a, 0x96, 0xe6, 0x0e, 0xd1, - 0x61, 0x80, 0x78, 0xab, 0xf0, 0x7b, 0x8b, 0x1e, - 0x99, 0x48, 0x84, 0x31, 0xd2, 0xaf, 0x23, 0x32, - 0x01, 0x5e, 0x11, 0x55, 0x06, 0x6e, 0x0e, 0xed, - 0x69, 0x7b, 0xb8, 0x41, 0x63, 0x3b, 0x30, 0x05, - 0x1e, 0xcd, 0x3e, 0x49, 0xb8, 0x0c, 0x83, 0x50, - 0x26, 0x4e, 0xd8, 0x97, 0x9d, 0x89, 0x30, 0x15, - 0xb9, 0x20, 0x20, 0xba, 0x5d, 0x8b, 0xad, 0x3d, - 0x7f, 0x52, 0xcd, 0x1e, 0xc0, 0x0e, 0xe1, 0xdc, - 0x21, 0x9b, 0xb0, 0x89, 0xa0, 0x20, 0xc6, 0x8c, - 0x56, 0x39, 0xc3, 0x40, 0x30, 0x40, 0x52, 0x2f, - 0x3b, 0x87, 0x96, 0xe2, 0x4d, 0x80, 0x57, 0xb3, - 0xb3, 0xe0, 0xb7, 0x5c, 0x55, 0x6a, 0x0f, 0x44, - 0x91, 0xe8, 0x98, 0xb3, 0xb4, 0xd3, 0x07, 0x8e, - 0x85, 0x8e, 0xc0, 0xcb, 0x85, 0x92, 0x0e, 0xca, - 0x7c, 0x03, 0x23, 0xa0, 0x1f, 0x4e, 0x75, 0x01, - 0x95, 0x61, 0x2c, 0x21, 0x2f, 0x4f, 0x6d, 0x55, - 0xa3, 0xcc, 0x23, 0x62, 0x7f, 0xcb, 0x0a, 0x8a, - 0x8b, 0x82, 0xb5, 0x8c, 0x8a, 0xaa, 0x88, 0xb4, - 0x65, 0x82, 0x6d, 0x12, 0x4a, 0x06, 0xe7, 0xde, - 0xcd, 0x3c, 0xf9, 0x1c, 0x02, 0x9c, 0xf8, 0x21, - 0x20, 0x30, 0x82, 0x05, 0x85, 0x30, 0x82, 0x03, - 0x6d, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, - 0x03, 0xb1, 0xf7, 0x58, 0xdf, 0x1d, 0xe3, 0x25, - 0x00, 0x0b, 0x10, 0x3d, 0xd5, 0xe6, 0xe4, 0x64, - 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, 0x31, 0x31, 0x31, - 0x38, 0x30, 0x31, 0x31, 0x33, 0x33, 0x35, 0x5a, - 0x17, 0x0d, 0x32, 0x37, 0x31, 0x31, 0x31, 0x38, - 0x30, 0x31, 0x31, 0x33, 0x31, 0x33, 0x5a, 0x30, - 0x6b, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, - 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, - 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, - 0x02, 0x57, 0x41, 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, 0x18, 0x30, 0x16, 0x06, 0x03, - 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x73, 0x79, 0x73, - 0x74, 0x65, 0x6d, 0x20, 0x69, 0x64, 0x3a, 0x20, - 0x37, 0x39, 0x31, 0x33, 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, 0xae, 0xc8, 0x71, - 0xae, 0x08, 0x0c, 0x06, 0x06, 0x2d, 0x81, 0x7c, - 0xa9, 0x8b, 0xb3, 0xd6, 0x66, 0xe4, 0xf6, 0x08, - 0x5e, 0x5a, 0x75, 0xe8, 0x74, 0x61, 0x7a, 0x88, - 0xca, 0x85, 0x14, 0x0d, 0x58, 0xa4, 0x09, 0x19, - 0x6c, 0x60, 0xc9, 0xad, 0x91, 0x1c, 0xbf, 0x04, - 0xb3, 0x47, 0x10, 0x63, 0x7f, 0x02, 0x58, 0xc2, - 0x1e, 0xbd, 0xcc, 0x07, 0x77, 0xaa, 0x7e, 0x14, - 0xa8, 0xc2, 0x01, 0xcd, 0xe8, 0x46, 0x60, 0x53, - 0x6f, 0x2f, 0xda, 0x17, 0x2d, 0x4d, 0x9d, 0x0e, - 0x5d, 0xb5, 0x50, 0x95, 0xae, 0xab, 0x6e, 0x43, - 0xe3, 0xb0, 0x00, 0x12, 0xb4, 0x05, 0x82, 0x4a, - 0x2b, 0x14, 0x63, 0x0d, 0x1f, 0x06, 0x12, 0xaa, - 0xe1, 0x9d, 0xe7, 0xba, 0xda, 0xe3, 0xfc, 0x7c, - 0x6c, 0x73, 0xae, 0x56, 0xf8, 0xab, 0xf7, 0x51, - 0x93, 0x31, 0xef, 0x8f, 0xe4, 0xb6, 0x01, 0x2c, - 0xeb, 0x7b, 0xe4, 0xd8, 0xb3, 0xea, 0x70, 0x37, - 0x89, 0x05, 0xa9, 0x51, 0x57, 0x72, 0x98, 0x9e, - 0xa8, 0x46, 0xdb, 0xeb, 0x7a, 0x38, 0x2b, 0x2f, - 0xc0, 0x27, 0xb7, 0xc2, 0xe1, 0x9a, 0x17, 0xdf, - 0xf5, 0xd6, 0x9c, 0xd5, 0x8c, 0xb8, 0x66, 0x42, - 0xd5, 0x04, 0x1e, 0x7c, 0x36, 0x4c, 0x1e, 0x3e, - 0x45, 0x51, 0x4d, 0x41, 0x72, 0x22, 0x53, 0x3d, - 0xf4, 0x57, 0x7c, 0x6c, 0x33, 0x34, 0x24, 0x45, - 0xdf, 0x84, 0x87, 0x4a, 0xa6, 0xcb, 0x7c, 0x03, - 0xa3, 0xaa, 0x8e, 0x2d, 0x82, 0x01, 0x27, 0x87, - 0x74, 0x82, 0x1a, 0xbc, 0x0f, 0x76, 0x69, 0xab, - 0xe0, 0x4e, 0x70, 0xbe, 0x37, 0xfc, 0xc8, 0x2c, - 0x91, 0x17, 0x4f, 0xd5, 0x26, 0x3b, 0x7b, 0x90, - 0xb5, 0x2d, 0x64, 0xba, 0xf7, 0xd2, 0x8a, 0xb4, - 0x8f, 0x38, 0x9d, 0x8e, 0xba, 0xe7, 0x5c, 0x52, - 0xf1, 0x0a, 0xb8, 0xc0, 0x1b, 0xb6, 0xb1, 0x70, - 0x7e, 0x47, 0x59, 0x94, 0x59, 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, 0x4b, 0xcb, 0xdf, 0xaa, 0x02, 0xde, 0x8d, - 0xc3, 0xe7, 0xe5, 0x85, 0xdb, 0x2e, 0x8a, 0xbe, - 0x75, 0x6b, 0x8a, 0x67, 0x58, 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, 0x1e, 0xe9, 0x30, 0x0d, - 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, - 0x01, 0x00, 0x61, 0x3f, 0x2f, 0x43, 0xe4, 0xbe, - 0x66, 0x34, 0xef, 0x92, 0x06, 0xe9, 0x88, 0xba, - 0x6a, 0x1d, 0x4f, 0x54, 0x5a, 0x97, 0xb1, 0x75, - 0xd7, 0x93, 0xf8, 0x45, 0xc6, 0x83, 0x92, 0x36, - 0xfd, 0x55, 0xa9, 0x21, 0x0b, 0xdc, 0xf6, 0xae, - 0x11, 0xdc, 0x62, 0x21, 0x44, 0xbd, 0x04, 0x1d, - 0x58, 0x2c, 0x03, 0xf8, 0xe4, 0xe2, 0x1e, 0xba, - 0xe6, 0xdd, 0x19, 0xdd, 0x56, 0xfd, 0xce, 0x06, - 0x73, 0x5f, 0x94, 0x1e, 0xb6, 0x03, 0xdb, 0x3d, - 0x7b, 0xab, 0xab, 0x72, 0x64, 0x7b, 0xde, 0x7d, - 0x4d, 0xcf, 0x7e, 0xf0, 0x91, 0x29, 0xc1, 0x77, - 0x13, 0xc2, 0x6f, 0x80, 0xab, 0x7a, 0xa8, 0xce, - 0xb0, 0x1c, 0x2a, 0xc5, 0x9c, 0xfb, 0x0b, 0xe5, - 0x9f, 0x9c, 0x1b, 0xc9, 0x4b, 0x58, 0xdf, 0x96, - 0x18, 0xf7, 0x67, 0x67, 0x89, 0xa4, 0xe9, 0x14, - 0x48, 0xac, 0xfa, 0x9d, 0x86, 0x2a, 0xeb, 0x75, - 0x2c, 0x2b, 0xbf, 0x63, 0x7d, 0xc7, 0x4e, 0x7e, - 0xad, 0x39, 0x2d, 0xb4, 0x7c, 0x07, 0xa5, 0x5a, - 0xe8, 0x3a, 0xd4, 0xf5, 0x0c, 0x4f, 0xf3, 0xa2, - 0x9c, 0x3c, 0x32, 0xed, 0x9d, 0x4b, 0x49, 0x05, - 0xbc, 0x1f, 0xa0, 0x13, 0xe6, 0xdd, 0x82, 0x79, - 0x06, 0x31, 0x3b, 0xc6, 0x97, 0xec, 0x8d, 0xaa, - 0x4f, 0xef, 0x14, 0x3c, 0x21, 0xf6, 0x72, 0xb2, - 0x09, 0x42, 0xc7, 0x74, 0xfe, 0xef, 0x70, 0xbd, - 0xe9, 0x85, 0x41, 0x30, 0x0b, 0xb3, 0x6b, 0x59, - 0x0c, 0x0f, 0x11, 0x75, 0xd4, 0xbb, 0xb1, 0xdf, - 0xb1, 0xdf, 0xb3, 0xfa, 0xb3, 0x3a, 0x43, 0x17, - 0x7d, 0x8a, 0x82, 0xae, 0xa2, 0x07, 0xf8, 0x83, - 0x51, 0xfb, 0x16, 0xfb, 0x64, 0xb6, 0x46, 0xda, - 0xbe, 0x32, 0x2b, 0xc0, 0xee, 0x78, 0x2a, 0x84, - 0xa9, 0x54, 0x0a, 0xf9, 0x2d, 0x61, 0x65, 0xde, - 0xa5, 0x97, 0x66, 0x79, 0x02, 0xf8, 0x97, 0x17, - 0xe2, 0xd4, 0x9f, 0x9e, 0xac, 0xcc, 0xae, 0x99, - 0x9a, 0x03, 0x04, 0xbb, 0x45, 0xfe, 0xb2, 0xf5, - 0x80, 0xba, 0xbf, 0xdd, 0x24, 0xe5, 0xe6, 0x1e, - 0x5d, 0x36, 0xa5, 0x87, 0x0c, 0xdf, 0x60, 0x81, - 0x6f, 0xb7, 0x5f, 0xb9, 0x1f, 0xca, 0x75, 0x3c, - 0x1a, 0x63, 0xb0, 0xeb, 0xe6, 0x95, 0x86, 0x0d, - 0xae, 0xa6, 0xc9, 0x2a, 0x94, 0xf1, 0xd0, 0xbe, - 0x75, 0xc8, 0xf8, 0x07, 0xd7, 0x88, 0xff, 0xec, - 0xf9, 0xcd, 0x49, 0xc6, 0xfe, 0x4d, 0x7f, 0x44, - 0x1e, 0xd8, 0xaf, 0xa9, 0x72, 0x27, 0x98, 0xe2, - 0x5a, 0x08, 0xea, 0x55, 0xd3, 0xb3, 0xea, 0xdc, - 0x76, 0x69, 0x51, 0x10, 0x01, 0x46, 0x7d, 0x33, - 0x94, 0x9c, 0x94, 0xef, 0xfe, 0x76, 0x1c, 0xc6, - 0xd7, 0x15, 0x53, 0x3e, 0x8d, 0x3d, 0x29, 0x9a, - 0x58, 0x6a, 0xf1, 0x75, 0x9e, 0xea, 0x1b, 0x4c, - 0xf0, 0x47, 0x76, 0xac, 0xc6, 0xa2, 0x32, 0x44, - 0x40, 0xdf, 0xfe, 0xff, 0x9d, 0xf4, 0xe2, 0xc2, - 0xfa, 0xa1, 0x5f, 0x2e, 0x66, 0xe9, 0x97, 0xcb, - 0x27, 0x26, 0x6e, 0x53, 0xe4, 0xe8, 0x86, 0x2c, - 0xea, 0xd3, 0x69, 0x6c, 0x61, 0x4f, 0xfe, 0xc1, - 0xc9, 0x8b, 0x05, 0x92, 0x6f, 0x47, 0x96, 0xce, - 0xf0, 0x33, 0xfa, 0x7c, 0x78, 0x24, 0x9b, 0xd7, - 0x8d, 0x36, 0x56, 0x37, 0x86, 0xbc, 0x72, 0x5a, - 0xf9, 0xb9, 0xb0, 0x93, 0xf0, 0x81, 0x78, 0x10, - 0xf2, 0xb0, 0xc2, 0x79, 0x91, 0x5e, 0xcf, 0xbc, - 0x8c, 0xf2, 0x32, 0x0f, 0xf7, 0x2d, 0x30, 0xd8, - 0x13, 0x77, 0x4f, 0x78, 0x9e, 0x40, 0x8d, 0xe6, - 0x3a, 0x98, 0xb2, 0xaa, 0x13, 0x4d, 0x25, 0x49, - 0x34, 0x6c, 0x80, 0x9e, 0x19, 0x03, 0xdb, 0xcd, - 0xf5, 0xb1, 0x54, 0x74, 0x1b, 0x67, 0x3c, 0x46, - 0xac, 0x3e, 0x5d, 0xa2, 0xd9, 0x13, 0x83, 0x30, - 0xeb, 0x82, 0x3b, 0x06, 0xab, 0x3c, 0x39, 0x7d, - 0xd0, 0x68, 0x31, 0x00 -}; - -// clang-format on - -} // namespace - -const size_t kTestOemPublicCertSize = sizeof(kTestOemPublicCert); - -const uint32_t kOEMSystemId = kTestOemSystemId; - -const uint8_t* kOEMPrivateKey = kTestOemPrivateKey; -const uint8_t* kOEMPublicCert = kTestOemPublicCert; - -const size_t kOEMPrivateKeySize = kTestOemPrivateKeySize; -const size_t kOEMPublicCertSize = kTestOemPublicCertSize; - -} // namespace wvoec_ref diff --git a/libwvdrmengine/oemcrypto/ref/test/oemcrypto_ecc_key_unittest.cpp b/libwvdrmengine/oemcrypto/ref/test/oemcrypto_ecc_key_unittest.cpp deleted file mode 100644 index 2fa92749..00000000 --- a/libwvdrmengine/oemcrypto/ref/test/oemcrypto_ecc_key_unittest.cpp +++ /dev/null @@ -1,232 +0,0 @@ -// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine License -// Agreement. -// -// Reference implementation of OEMCrypto APIs -// -#include - -#include "OEMCryptoCENCCommon.h" -#include "oemcrypto_ecc_key.h" -#include "oemcrypto_ref_test_utils.h" - -namespace wvoec_ref { -constexpr size_t kMessageSize = 4 * 1024; // 4 kB - -class OEMCryptoEccKeyTest : public ::testing::TestWithParam { - public: - void SetUp() override { key_ = EccPrivateKey::New(GetParam()); } - - void TearDown() override { key_.reset(); } - - protected: - std::unique_ptr key_; -}; - -// Basic verification of ECC private key generation. -TEST_P(OEMCryptoEccKeyTest, KeyProperties) { - ASSERT_TRUE(key_); - const EccCurve expected_curve = GetParam(); - - EXPECT_EQ(key_->curve(), expected_curve); - EXPECT_NE(nullptr, key_->GetEcKey()); -} - -// Checks that the private key serialization APIs are compatible -// and performing in a manner that is similar to other OEMCrypto methods -// that retrieve data. -TEST_P(OEMCryptoEccKeyTest, SerializePrivateKey) { - ASSERT_TRUE(key_); - - constexpr size_t kInitialBufferSize = 10; // Definitely too small. - size_t buffer_size = kInitialBufferSize; - std::vector buffer(buffer_size); - - EXPECT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, - key_->Serialize(buffer.data(), &buffer_size)); - EXPECT_GT(buffer_size, kInitialBufferSize); - - buffer.resize(buffer_size); - EXPECT_EQ(OEMCrypto_SUCCESS, key_->Serialize(buffer.data(), &buffer_size)); - buffer.resize(buffer_size); - - const std::vector direct_key_data = key_->Serialize(); - EXPECT_FALSE(direct_key_data.empty()); - ASSERT_EQ(buffer.size(), direct_key_data.size()); - for (size_t i = 0; i < buffer.size(); i++) { - ASSERT_EQ(buffer[i], direct_key_data[i]) << "i = " << i; - } -} - -// Checks that a private key that is serialized can be deserialized and -// reload. Also checks that the serialization of a key produces the -// same data to ensure consistency. -TEST_P(OEMCryptoEccKeyTest, SerializeAndReloadPrivateKey) { - ASSERT_TRUE(key_); - - const std::vector key_data = key_->Serialize(); - std::unique_ptr loaded_key = EccPrivateKey::Load(key_data); - ASSERT_TRUE(loaded_key); - - EXPECT_EQ(key_->curve(), loaded_key->curve()); - - const std::vector loaded_key_data = loaded_key->Serialize(); - ASSERT_EQ(key_data.size(), loaded_key_data.size()); - for (size_t i = 0; i < key_data.size(); i++) { - ASSERT_EQ(key_data[i], loaded_key_data[i]) << "i = " << i; - } -} - -// Checks that a public key can be created from the private key. -TEST_P(OEMCryptoEccKeyTest, DerivePublicKey) { - ASSERT_TRUE(key_); - - std::unique_ptr pub_key = key_->MakePublicKey(); - ASSERT_TRUE(pub_key); - - EXPECT_TRUE(key_->IsMatchingPublicKey(*pub_key)); -} - -// Checks that a public key that is serialized can be deserialized and -// reload. Also checks that the serialization of a key produces the -// same data to ensure consistency. -TEST_P(OEMCryptoEccKeyTest, SerializePublicKey) { - ASSERT_TRUE(key_); - - std::unique_ptr pub_key = key_->MakePublicKey(); - ASSERT_TRUE(pub_key); - - constexpr size_t kInitialBufferSize = 10; // Definitely too small. - size_t buffer_size = kInitialBufferSize; - std::vector buffer(buffer_size); - - EXPECT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, - pub_key->Serialize(buffer.data(), &buffer_size)); - EXPECT_GT(buffer_size, kInitialBufferSize); - - buffer.resize(buffer_size); - EXPECT_EQ(OEMCrypto_SUCCESS, pub_key->Serialize(buffer.data(), &buffer_size)); - buffer.resize(buffer_size); - - const std::vector direct_key_data = pub_key->Serialize(); - EXPECT_FALSE(direct_key_data.empty()); - ASSERT_EQ(buffer.size(), direct_key_data.size()); - for (size_t i = 0; i < buffer.size(); i++) { - ASSERT_EQ(buffer[i], direct_key_data[i]) << "i = " << i; - } -} - -// Checks that a public key that is serialized can be deserialized and -// reload. Also checks that the serialization of a key produces the -// same data to ensure consistency. -// It is anticipated that OEMCrypto will need to parse the licensing -// server's ephemerial key when deriving the session key. -TEST_P(OEMCryptoEccKeyTest, SerializeAndReloadPublicKey) { - ASSERT_TRUE(key_); - - std::unique_ptr pub_key = key_->MakePublicKey(); - ASSERT_TRUE(pub_key); - - const std::vector key_data = pub_key->Serialize(); - - std::unique_ptr loaded_key = EccPublicKey::Load(key_data); - ASSERT_TRUE(loaded_key); - - EXPECT_EQ(pub_key->curve(), loaded_key->curve()); - - const std::vector loaded_key_data = loaded_key->Serialize(); - ASSERT_EQ(key_data.size(), loaded_key_data.size()); - for (size_t i = 0; i < key_data.size(); i++) { - ASSERT_EQ(key_data[i], loaded_key_data[i]) << "i = " << i; - } -} - -// Checks that the ECC signature generating API operates similar to -// existing signature generation functions. -TEST_P(OEMCryptoEccKeyTest, GenerateSignature) { - ASSERT_TRUE(key_); - - const std::vector message = RandomData(kMessageSize); - ASSERT_FALSE(message.empty()) << "CdmRandom failed"; - - constexpr size_t kInitialBufferSize = 10; // Definitely too small. - size_t signature_size = kInitialBufferSize; - std::vector signature(signature_size); - EXPECT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, - key_->GenerateSignature(message.data(), message.size(), - signature.data(), &signature_size)); - EXPECT_GT(signature_size, kInitialBufferSize); - - signature.resize(signature_size); - EXPECT_EQ(OEMCrypto_SUCCESS, - key_->GenerateSignature(message.data(), message.size(), - signature.data(), &signature_size)); - signature.resize(signature_size); - - EXPECT_LE(signature_size, key_->SignatureSize()); -} - -// Checks that ECC signatures can be verified by an ECC public key. -TEST_P(OEMCryptoEccKeyTest, VerifySignature) { - ASSERT_TRUE(key_); - const std::vector message = RandomData(kMessageSize); - ASSERT_FALSE(message.empty()) << "CdmRandom failed"; - - const std::vector signature = key_->GenerateSignature(message); - - std::unique_ptr pub_key = key_->MakePublicKey(); - ASSERT_TRUE(pub_key); - - EXPECT_EQ(OEMCrypto_SUCCESS, pub_key->VerifySignature(message, signature)); - - // Check with different message. - const std::vector message_two = RandomData(kMessageSize); - EXPECT_EQ(OEMCrypto_ERROR_SIGNATURE_FAILURE, - pub_key->VerifySignature(message_two, signature)); - - // Check with bad signature. - const std::vector bad_signature = RandomData(signature.size()); - EXPECT_EQ(OEMCrypto_ERROR_SIGNATURE_FAILURE, - pub_key->VerifySignature(message, bad_signature)); -} - -// Verifies the session key exchange protocol used by the licensing -// server. -TEST_P(OEMCryptoEccKeyTest, DeriveSessionKey) { - ASSERT_TRUE(key_); - // Set up Alice. - EccPrivateKey* alice_private_key = key_.get(); - std::unique_ptr alice_public_key = - alice_private_key->MakePublicKey(); - ASSERT_TRUE(alice_public_key); - // Set up Bob. - std::unique_ptr bob_private_key = - EccPrivateKey::New(alice_private_key->curve()); - ASSERT_TRUE(bob_private_key); - std::unique_ptr bob_public_key = - bob_private_key->MakePublicKey(); - ASSERT_TRUE(bob_public_key); - - const size_t session_key_length = alice_private_key->SessionKeyLength(); - EXPECT_EQ(session_key_length, bob_private_key->SessionKeyLength()); - // From Alice's perspective. - const std::vector alice_session_key = - alice_private_key->DeriveSessionKey(*bob_public_key); - - // From Bob's perspective. - const std::vector bob_session_key = - bob_private_key->DeriveSessionKey(*alice_public_key); - - // Both should have the same session key. - ASSERT_EQ(session_key_length, alice_session_key.size()); - ASSERT_EQ(session_key_length, bob_session_key.size()); - for (size_t i = 0; i < session_key_length; i++) { - ASSERT_EQ(alice_session_key[i], bob_session_key[i]) << "i = " << i; - } -} - -INSTANTIATE_TEST_CASE_P(AllCurves, OEMCryptoEccKeyTest, - ::testing::Values(kEccSecp256r1, kEccSecp384r1, - kEccSecp521r1)); - -} // namespace wvoec_ref diff --git a/libwvdrmengine/oemcrypto/ref/test/oemcrypto_oem_cert_unittest.cpp b/libwvdrmengine/oemcrypto/ref/test/oemcrypto_oem_cert_unittest.cpp deleted file mode 100644 index 6afa51d3..00000000 --- a/libwvdrmengine/oemcrypto/ref/test/oemcrypto_oem_cert_unittest.cpp +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine License -// Agreement. -// -// Reference implementation of OEMCrypto APIs -// -#include - -#include "OEMCryptoCENCCommon.h" -#include "oem_cert.h" -#include "oemcrypto_oem_cert.h" -#include "oemcrypto_rsa_key.h" - -namespace wvoec_ref { -namespace { -const std::vector kOEMPrivateKeyVector(kOEMPrivateKey, - kOEMPrivateKey + - kOEMPrivateKeySize); - -const std::vector kOEMPublicCertVector(kOEMPublicCert, - kOEMPublicCert + - kOEMPublicCertSize); -} // namespace - -// Creates an OemCertificate wrapper around the built-in reference -// OEM cert. -// Creating the OemCertificate should succeed so long as the data -// is well-formed. -// Validating the OEM cert should succeed (assuming built-in cert+key -// are valid). -TEST(OEMCryptoOemCertTest, CreateFromArray) { - std::unique_ptr oem_cert = OemCertificate::Create( - kOEMPrivateKey, kOEMPrivateKeySize, kOEMPublicCert, kOEMPublicCertSize); - ASSERT_TRUE(oem_cert); - - EXPECT_EQ(OemCertificate::kRsa, oem_cert->key_type()); - - const std::vector private_key = oem_cert->GetPrivateKey(); - EXPECT_EQ(kOEMPrivateKeyVector, private_key); - - size_t public_cert_size = 10; - std::vector public_cert(public_cert_size, 0); - EXPECT_EQ( - OEMCrypto_ERROR_SHORT_BUFFER, - oem_cert->GetPublicCertificate(public_cert.data(), &public_cert_size)); - public_cert.resize(public_cert_size); - EXPECT_EQ(OEMCrypto_SUCCESS, oem_cert->GetPublicCertificate( - public_cert.data(), &public_cert_size)); - EXPECT_EQ(kOEMPublicCertSize, public_cert_size); - EXPECT_EQ(kOEMPublicCertVector, public_cert); - - EXPECT_EQ(OEMCrypto_SUCCESS, oem_cert->IsCertificateValid()); -} - -TEST(OEMCryptoOemCertTest, CreateFromVector) { - std::unique_ptr oem_cert = - OemCertificate::Create(kOEMPrivateKeyVector, kOEMPublicCertVector); - ASSERT_TRUE(oem_cert); - - EXPECT_EQ(OemCertificate::kRsa, oem_cert->key_type()); - - const std::vector private_key = oem_cert->GetPrivateKey(); - EXPECT_EQ(kOEMPrivateKeyVector, private_key); - - const std::vector public_cert = oem_cert->GetPublicCertificate(); - EXPECT_EQ(kOEMPublicCertVector, public_cert); - - EXPECT_EQ(OEMCrypto_SUCCESS, oem_cert->IsCertificateValid()); -} - -// Creation of OemCertificate wrapper should fail if the provided -// key is not well-formed. -TEST(OEMCryptoOemCertTest, CreateWithABadPrivateKey) { - static const uint8_t kBadPrivateKeyData[] = {'n', 'o', 't', ' ', 'a', ' ', - 'p', 'r', 'i', 'v', 'a', 't', - 'e', 'k', 'e', 'y'}; - std::unique_ptr oem_cert = - OemCertificate::Create(kBadPrivateKeyData, sizeof(kBadPrivateKeyData), - kOEMPublicCert, kOEMPublicCertSize); - EXPECT_FALSE(oem_cert); -} - -// Creation of OemCertificate wrapper should fail if the provided -// OEM Public Cert is not well-formed. -TEST(OEMCryptoOemCertTest, CreateWithABadPublicCert) { - static const uint8_t kBadPublicCert[] = {'n', 'o', 't', ' ', 'a', ' ', 'o', - 'e', 'm', ' ', 'p', 'u', 'b', 'l', - 'i', 'c', ' ', 'c', 'e', 'r', 't'}; - std::unique_ptr oem_cert = - OemCertificate::Create(kOEMPrivateKey, kOEMPrivateKeySize, kBadPublicCert, - sizeof(kBadPublicCert)); - EXPECT_FALSE(oem_cert); -} - -// It is possible to create an OEM Certificate using a non-matching -// public-private key pair so long as the key types are the same. -// However, OEM Cert validation should catch the problem. -TEST(OEMCryptoOemCertTest, CreateWithDifferentPrivateRsaKey) { - std::unique_ptr key = RsaPrivateKey::New(kRsa2048Bit); - ASSERT_TRUE(key); - const std::vector private_key = key->Serialize(); - ASSERT_FALSE(private_key.empty()); - - // Creating the OEM Certificate should succeed. - std::unique_ptr oem_cert = - OemCertificate::Create(private_key, kOEMPublicCertVector); - ASSERT_TRUE(oem_cert); - - EXPECT_EQ(OemCertificate::kRsa, oem_cert->key_type()); - - // Validating key should return an error. - EXPECT_EQ(OEMCrypto_ERROR_INVALID_RSA_KEY, oem_cert->IsCertificateValid()); -} - -} // namespace wvoec_ref diff --git a/libwvdrmengine/oemcrypto/ref/test/oemcrypto_ref_test_utils.cpp b/libwvdrmengine/oemcrypto/ref/test/oemcrypto_ref_test_utils.cpp deleted file mode 100644 index 27415482..00000000 --- a/libwvdrmengine/oemcrypto/ref/test/oemcrypto_ref_test_utils.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine License -// Agreement. -// -// Reference implementation of OEMCrypto APIs -// -#include "oemcrypto_ref_test_utils.h" - -#include - -#include "cdm_random.h" - -namespace wvoec_ref { - -std::vector RandomData(size_t length) { - const std::string data = wvcdm::CdmRandom::RandomData(length); - return std::vector(data.begin(), data.end()); -} - -} // namespace wvoec_ref diff --git a/libwvdrmengine/oemcrypto/ref/test/oemcrypto_ref_test_utils.h b/libwvdrmengine/oemcrypto/ref/test/oemcrypto_ref_test_utils.h deleted file mode 100644 index e229077b..00000000 --- a/libwvdrmengine/oemcrypto/ref/test/oemcrypto_ref_test_utils.h +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine License -// Agreement. -// -// Reference implementation of OEMCrypto APIs -// -#ifndef OEMCRYPTO_REF_TEST_UTILS_H_ -#define OEMCRYPTO_REF_TEST_UTILS_H_ - -#include - -#include - -namespace wvoec_ref { - -// Returns a vector of random bytes. -std::vector RandomData(size_t length); - -} // namespace wvoec_ref - -#endif // OEMCRYPTO_REF_TEST_UTILS_H_ diff --git a/libwvdrmengine/oemcrypto/ref/test/oemcrypto_rsa_key_unittest.cpp b/libwvdrmengine/oemcrypto/ref/test/oemcrypto_rsa_key_unittest.cpp deleted file mode 100644 index 021a6e51..00000000 --- a/libwvdrmengine/oemcrypto/ref/test/oemcrypto_rsa_key_unittest.cpp +++ /dev/null @@ -1,406 +0,0 @@ -// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine License -// Agreement. -// -// Reference implementation of OEMCrypto APIs -// -#include - -#include - -#include - -#include "OEMCryptoCENC.h" -#include "log.h" -#include "oemcrypto_ref_test_utils.h" -#include "oemcrypto_rsa_key.h" - -namespace wvoec_ref { -constexpr size_t kMessageSize = 4 * 1024; // 4 kB -constexpr size_t kCastMessageSize = 83; // Special max size. - -class OEMCryptoRsaKeyTest : public ::testing::TestWithParam { - public: - void SetUp() override { - // RSA key generation is slow (~2 seconds) compared to the - // operations they perform (<50 ms). Each key type is generated - // once and globally stored in serialized form. - // Caching the instance may result in test failures for - // memory-leak detection. - const RsaFieldSize field_size = GetParam(); - std::lock_guard rsa_key_lock(rsa_key_mutex_); - // Use of a switch case is intentional to cause compiler warnings - // if a new field size is introduced without updating the test. - switch (field_size) { - case kRsa2048Bit: { - if (!rsa_2048_key_data_.empty()) { - key_ = RsaPrivateKey::Load(rsa_2048_key_data_); - } - if (!key_) { - key_ = RsaPrivateKey::New(kRsa2048Bit); - } - if (rsa_2048_key_data_.empty() && key_) { - rsa_2048_key_data_ = key_->Serialize(); - } - } break; - case kRsa3072Bit: { - if (!rsa_3072_key_data_.empty()) { - key_ = RsaPrivateKey::Load(rsa_3072_key_data_); - } - if (!key_) { - key_ = RsaPrivateKey::New(kRsa3072Bit); - } - if (rsa_3072_key_data_.empty() && key_) { - rsa_3072_key_data_ = key_->Serialize(); - } - } break; - case kRsaFieldUnknown: // Suppress compiler warnings - LOGE("RSA test was incorrectly instantiation"); - exit(EXIT_FAILURE); - break; - } - } - - void TearDown() override { key_.reset(); } - - protected: - std::unique_ptr key_; - static std::mutex rsa_key_mutex_; - static std::vector rsa_2048_key_data_; - static std::vector rsa_3072_key_data_; -}; - -std::mutex OEMCryptoRsaKeyTest::rsa_key_mutex_; -std::vector OEMCryptoRsaKeyTest::rsa_2048_key_data_; -std::vector OEMCryptoRsaKeyTest::rsa_3072_key_data_; - -// Basic verification of RSA private key generation. -TEST_P(OEMCryptoRsaKeyTest, KeyProperties) { - ASSERT_TRUE(key_); - const RsaFieldSize expected_field_size = GetParam(); - - EXPECT_EQ(key_->field_size(), expected_field_size); - EXPECT_NE(nullptr, key_->GetRsaKey()); -} - -// Checks that the private key serialization APIs are compatible -// and performing in a manner that is similar to other OEMCrypto methods -// that retrieve data. -TEST_P(OEMCryptoRsaKeyTest, SerializePrivateKey) { - ASSERT_TRUE(key_); - - constexpr size_t kInitialBufferSize = 10; // Definitely too small. - size_t buffer_size = kInitialBufferSize; - std::vector buffer(buffer_size); - - EXPECT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, - key_->Serialize(buffer.data(), &buffer_size)); - EXPECT_GT(buffer_size, kInitialBufferSize); - - buffer.resize(buffer_size); - EXPECT_EQ(OEMCrypto_SUCCESS, key_->Serialize(buffer.data(), &buffer_size)); - buffer.resize(buffer_size); - - const std::vector direct_key_data = key_->Serialize(); - EXPECT_FALSE(direct_key_data.empty()); - ASSERT_EQ(buffer.size(), direct_key_data.size()); - for (size_t i = 0; i < buffer.size(); i++) { - ASSERT_EQ(buffer[i], direct_key_data[i]) << "i = " << std::to_string(i); - } -} - -// Checks that a private key that is serialized can be deserialized and -// reload. Also checks that the serialization of a key produces the -// same data to ensure consistency. -TEST_P(OEMCryptoRsaKeyTest, SerializeAndReloadPrivateKey) { - ASSERT_TRUE(key_); - - const std::vector key_data = key_->Serialize(); - std::unique_ptr loaded_key = RsaPrivateKey::Load(key_data); - ASSERT_TRUE(loaded_key); - - EXPECT_EQ(key_->field_size(), loaded_key->field_size()); - - const std::vector loaded_key_data = loaded_key->Serialize(); - ASSERT_EQ(key_data.size(), loaded_key_data.size()); - for (size_t i = 0; i < key_data.size(); i++) { - ASSERT_EQ(key_data[i], loaded_key_data[i]) << "i = " << std::to_string(i); - } -} - -// Checks that a private key with explicitly indicated schemes include -// the scheme fields in the reserialized key. -TEST_P(OEMCryptoRsaKeyTest, SerializeAndReloadPrivateKeyWithAllowedSchemes) { - ASSERT_TRUE(key_); - - const std::vector raw_key_data = key_->Serialize(); - std::vector key_data = {'S', 'I', 'G', 'N', 0x00, 0x00, 0x00, 0x03}; - key_data.insert(key_data.end(), raw_key_data.begin(), raw_key_data.end()); - - std::unique_ptr explicit_key = RsaPrivateKey::Load(key_data); - ASSERT_TRUE(explicit_key); - EXPECT_EQ(key_->field_size(), explicit_key->field_size()); - EXPECT_EQ(explicit_key->allowed_schemes(), 0x03); - - const std::vector explicit_key_data = explicit_key->Serialize(); - ASSERT_EQ(key_data.size(), explicit_key_data.size()); - ASSERT_EQ(key_data, explicit_key_data); -} - -// Checks that a public key can be created from the private key. -TEST_P(OEMCryptoRsaKeyTest, DerivePublicKey) { - ASSERT_TRUE(key_); - - std::unique_ptr pub_key = key_->MakePublicKey(); - ASSERT_TRUE(pub_key); - - EXPECT_TRUE(key_->IsMatchingPublicKey(*pub_key)); -} - -// Checks that the public key serialization APIs are compatible -// and performing in a manner that is similar to other OEMCrypto methods -// that retrieve data. -TEST_P(OEMCryptoRsaKeyTest, SerializePublicKey) { - ASSERT_TRUE(key_); - - std::unique_ptr pub_key = key_->MakePublicKey(); - ASSERT_TRUE(pub_key); - - constexpr size_t kInitialBufferSize = 10; // Definitely too small. - size_t buffer_size = kInitialBufferSize; - std::vector buffer(buffer_size); - - EXPECT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, - pub_key->Serialize(buffer.data(), &buffer_size)); - EXPECT_GT(buffer_size, kInitialBufferSize); - - buffer.resize(buffer_size); - EXPECT_EQ(OEMCrypto_SUCCESS, pub_key->Serialize(buffer.data(), &buffer_size)); - buffer.resize(buffer_size); - - const std::vector direct_key_data = pub_key->Serialize(); - EXPECT_FALSE(direct_key_data.empty()); - ASSERT_EQ(buffer.size(), direct_key_data.size()); - for (size_t i = 0; i < buffer.size(); i++) { - ASSERT_EQ(buffer[i], direct_key_data[i]) << "i = " << std::to_string(i); - } -} - -// Checks that a public key that is serialized can be deserialized and -// reload. Also checks that the serialization of a key produces the -// same data to ensure consistency. -TEST_P(OEMCryptoRsaKeyTest, SerializeAndReloadPublicKey) { - ASSERT_TRUE(key_); - - std::unique_ptr pub_key = key_->MakePublicKey(); - ASSERT_TRUE(pub_key); - - const std::vector key_data = pub_key->Serialize(); - - std::unique_ptr loaded_key = RsaPublicKey::Load(key_data); - ASSERT_TRUE(loaded_key); - - EXPECT_EQ(pub_key->field_size(), loaded_key->field_size()); - EXPECT_EQ(pub_key->allowed_schemes(), loaded_key->allowed_schemes()); - - const std::vector loaded_key_data = loaded_key->Serialize(); - ASSERT_EQ(key_data.size(), loaded_key_data.size()); - for (size_t i = 0; i < key_data.size(); i++) { - ASSERT_EQ(key_data[i], loaded_key_data[i]) << "i = " << std::to_string(i); - } -} - -// Checks that the RSA signature generating API operates similar to -// existing signature generation functions. -TEST_P(OEMCryptoRsaKeyTest, GenerateSignature) { - ASSERT_TRUE(key_); - - const std::vector message = RandomData(kMessageSize); - ASSERT_FALSE(message.empty()) << "CdmRandom failed"; - - constexpr size_t kInitialBufferSize = 10; // Definitely too small. - size_t signature_size = kInitialBufferSize; - std::vector signature(signature_size); - EXPECT_EQ( - OEMCrypto_ERROR_SHORT_BUFFER, - key_->GenerateSignature(message.data(), message.size(), kRsaPssDefault, - signature.data(), &signature_size)); - EXPECT_GT(signature_size, kInitialBufferSize); - - signature.resize(signature_size); - EXPECT_EQ( - OEMCrypto_SUCCESS, - key_->GenerateSignature(message.data(), message.size(), kRsaPssDefault, - signature.data(), &signature_size)); - signature.resize(signature_size); - - EXPECT_LE(signature_size, key_->SignatureSize()); -} - -// Checks that RSA signatures can be verified by an RSA public key. -TEST_P(OEMCryptoRsaKeyTest, VerifySignature) { - ASSERT_TRUE(key_); - const std::vector message = RandomData(kMessageSize); - ASSERT_FALSE(message.empty()) << "CdmRandom failed"; - - const std::vector signature = key_->GenerateSignature(message); - - std::unique_ptr pub_key = key_->MakePublicKey(); - ASSERT_TRUE(pub_key); - - EXPECT_EQ(OEMCrypto_SUCCESS, pub_key->VerifySignature(message, signature)); - - // Check with different message. - const std::vector message_two = RandomData(kMessageSize); - EXPECT_EQ(OEMCrypto_ERROR_SIGNATURE_FAILURE, - pub_key->VerifySignature(message_two, signature)); - - // Check with bad signature. - const std::vector bad_signature = RandomData(signature.size()); - EXPECT_EQ(OEMCrypto_ERROR_SIGNATURE_FAILURE, - pub_key->VerifySignature(message, bad_signature)); -} - -// Checks that the special CAST receiver signature scheme works -// to the degree that it is possible to test. -TEST_P(OEMCryptoRsaKeyTest, GenerateAndVerifyRsaSignature) { - ASSERT_TRUE(key_); - // Key must be enabled for PKCS1 Block 1 padding scheme. - // To do so, the key is serialized and the padding scheme is - // added to the key data. - const std::vector key_data = key_->Serialize(); - ASSERT_FALSE(key_data.empty()); - std::vector pkcs_enabled_key_data = { - 'S', 'I', 'G', 'N', 0x00, 0x00, 0x00, kSign_PKCS1_Block1}; - pkcs_enabled_key_data.insert(pkcs_enabled_key_data.end(), key_data.begin(), - key_data.end()); - std::unique_ptr pkcs_enabled_key = - RsaPrivateKey::Load(pkcs_enabled_key_data); - ASSERT_TRUE(pkcs_enabled_key); - - // The actual cast message is a domain specific hash of the message, - // however, random data works for testing purposes. - const std::vector message = RandomData(kCastMessageSize); - - // Generate signature. - constexpr size_t kInitialBufferSize = 10; // Definitely too small. - size_t signature_size = kInitialBufferSize; - std::vector signature(signature_size); - EXPECT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, - pkcs_enabled_key->GenerateSignature(message.data(), message.size(), - kRsaPkcs1Cast, signature.data(), - &signature_size)); - EXPECT_GT(signature_size, kInitialBufferSize); - signature.resize(signature_size); - EXPECT_EQ(OEMCrypto_SUCCESS, - pkcs_enabled_key->GenerateSignature(message.data(), message.size(), - kRsaPkcs1Cast, signature.data(), - &signature_size)); - signature.resize(signature_size); - - EXPECT_LE(signature_size, pkcs_enabled_key->SignatureSize()); - - // Verify signature. - std::unique_ptr pub_key = pkcs_enabled_key->MakePublicKey(); - ASSERT_TRUE(pub_key); - - EXPECT_EQ(OEMCrypto_SUCCESS, - pub_key->VerifySignature(message, signature, kRsaPkcs1Cast)); -} - -// Verifies the session key exchange protocol used by the licensing -// server. -TEST_P(OEMCryptoRsaKeyTest, ShareSessionKey) { - constexpr size_t kSessionKeySize = 16; - ASSERT_TRUE(key_); - std::unique_ptr public_key = key_->MakePublicKey(); - ASSERT_TRUE(public_key); - - // Generate session key. - const std::vector session_key = RandomData(kSessionKeySize); - ASSERT_FALSE(session_key.empty()); - - // Server's perspective. - constexpr size_t kInitialBufferSize = 10; // Definitely too small. - size_t enc_session_key_size = kInitialBufferSize; - std::vector enc_session_key(enc_session_key_size); - OEMCryptoResult result = public_key->EncryptSessionKey( - session_key.data(), session_key.size(), enc_session_key.data(), - &enc_session_key_size); - ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, result); - enc_session_key.resize(enc_session_key_size); - result = public_key->EncryptSessionKey(session_key.data(), session_key.size(), - enc_session_key.data(), - &enc_session_key_size); - ASSERT_EQ(OEMCrypto_SUCCESS, result); - enc_session_key.resize(enc_session_key_size); - - // Client's perspective. - size_t received_session_key_size = kInitialBufferSize; - std::vector received_session_key(received_session_key_size); - result = key_->DecryptSessionKey( - enc_session_key.data(), enc_session_key.size(), - received_session_key.data(), &received_session_key_size); - ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, result); - received_session_key.resize(received_session_key_size); - result = key_->DecryptSessionKey( - enc_session_key.data(), enc_session_key.size(), - received_session_key.data(), &received_session_key_size); - ASSERT_EQ(OEMCrypto_SUCCESS, result); - received_session_key.resize(received_session_key_size); - - // Compare keys. - ASSERT_EQ(session_key.size(), received_session_key.size()); - ASSERT_EQ(session_key, received_session_key); -} - -// Verifies the encryption key exchange protocol used by the licensing -// server. -TEST_P(OEMCryptoRsaKeyTest, ShareEncryptionKey) { - constexpr size_t kEncryptionKeySize = 16; - ASSERT_TRUE(key_); - std::unique_ptr public_key = key_->MakePublicKey(); - ASSERT_TRUE(public_key); - - // Generate session key. - const std::vector encryption_key = RandomData(kEncryptionKeySize); - ASSERT_FALSE(encryption_key.empty()); - - // Server's perspective. - constexpr size_t kInitialBufferSize = 10; // Definitely too small. - size_t enc_encryption_key_size = kInitialBufferSize; - std::vector enc_encryption_key(enc_encryption_key_size); - OEMCryptoResult result = public_key->EncryptEncryptionKey( - encryption_key.data(), encryption_key.size(), enc_encryption_key.data(), - &enc_encryption_key_size); - ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, result); - enc_encryption_key.resize(enc_encryption_key_size); - result = public_key->EncryptEncryptionKey( - encryption_key.data(), encryption_key.size(), enc_encryption_key.data(), - &enc_encryption_key_size); - ASSERT_EQ(OEMCrypto_SUCCESS, result); - enc_encryption_key.resize(enc_encryption_key_size); - - // Client's perspective. - size_t received_encryption_key_size = kInitialBufferSize; - std::vector received_encryption_key(received_encryption_key_size); - result = key_->DecryptEncryptionKey( - enc_encryption_key.data(), enc_encryption_key.size(), - received_encryption_key.data(), &received_encryption_key_size); - ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, result); - received_encryption_key.resize(received_encryption_key_size); - result = key_->DecryptEncryptionKey( - enc_encryption_key.data(), enc_encryption_key.size(), - received_encryption_key.data(), &received_encryption_key_size); - ASSERT_EQ(OEMCrypto_SUCCESS, result); - received_encryption_key.resize(received_encryption_key_size); - - // Compare keys. - ASSERT_EQ(encryption_key.size(), received_encryption_key.size()); - ASSERT_EQ(encryption_key, received_encryption_key); -} - -INSTANTIATE_TEST_CASE_P(AllFieldSizes, OEMCryptoRsaKeyTest, - ::testing::Values(kRsa2048Bit, kRsa3072Bit)); - -} // namespace wvoec_ref diff --git a/libwvdrmengine/oemcrypto/ref/test/oemcrypto_wvcrc32_unittest.cpp b/libwvdrmengine/oemcrypto/ref/test/oemcrypto_wvcrc32_unittest.cpp deleted file mode 100644 index baabaa14..00000000 --- a/libwvdrmengine/oemcrypto/ref/test/oemcrypto_wvcrc32_unittest.cpp +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine License -// Agreement. -// -// Reference implementation of OEMCrypto APIs -// -#include - -#include "wvcrc32.h" - -namespace wvoec_ref { - -uint32_t ComputeCrc32(const std::string& s) { - return wvcrc32(reinterpret_cast(s.data()), s.size()); -} - -uint32_t ComputeCrc32Cont(const std::string& s, uint32_t prev_crc) { - return wvcrc32Cont(reinterpret_cast(s.data()), s.size(), - prev_crc); -} - -TEST(OEMCryptoWvCrc32Test, BasicTest) { - EXPECT_EQ(0xF88AC628, ComputeCrc32("abcdefg")); - EXPECT_EQ(0xDF520F72, ComputeCrc32("Widevine")); - EXPECT_EQ(0x0376E6E7, ComputeCrc32("123456789")); - EXPECT_EQ(0xBA62119E, - ComputeCrc32("The quick brown fox jumps over the lazy dog")); -} - -TEST(OEMCryptoWvCrc32Test, StreamTest) { - const std::vector parts = {"The ", "quick", " brown ", - "fox", " jumps ", "over", - " the ", "lazy", " dog"}; - uint32_t crc = wvcrc32Init(); - for (const auto& part : parts) { - crc = ComputeCrc32Cont(part, crc); - } - EXPECT_EQ(0xBA62119E, crc); -} - -TEST(OEMCryptoWvCrc32Test, Keybox) { - // clang-format off - const uint8_t kKeyboxData[128] = { - // deviceID = WidevineCRCTestKeyBox - 0x57, 0x69, 0x64, 0x65, 0x76, 0x69, 0x6e, 0x65, - 0x43, 0x52, 0x43, 0x54, 0x65, 0x73, 0x74, 0x4b, - 0x65, 0x79, 0x62, 0x6f, 0x78, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // key = random - 0x8a, 0x7c, 0xda, 0x3e, 0x09, 0xd9, 0x8e, 0xd5, - 0x47, 0x47, 0x00, 0x84, 0x5a, 0x1f, 0x52, 0xd4, - // data = random - 0x98, 0xa5, 0x00, 0x19, 0x8b, 0xfe, 0x54, 0xfd, - 0xca, 0x4d, 0x26, 0xa3, 0xfa, 0xaa, 0x3b, 0x6c, - 0x35, 0xfe, 0x03, 0x7c, 0xbf, 0x35, 0xba, 0xce, - 0x31, 0xb5, 0x1e, 0x3c, 0x49, 0xd6, 0x3f, 0x9c, - 0x3a, 0xde, 0x9b, 0x58, 0xcc, 0x54, 0x8d, 0xc0, - 0x4b, 0x04, 0xcc, 0xee, 0xae, 0x4d, 0x9f, 0x90, - 0xd3, 0xf3, 0xfe, 0x23, 0x26, 0x13, 0x56, 0x80, - 0xe4, 0x3b, 0x79, 0x22, 0x69, 0x5d, 0xd6, 0xb7, - 0xa0, 0x0e, 0x7e, 0x07, 0xcd, 0x1a, 0x15, 0xca, - // magic - 'k', 'b', 'o', 'x', - // crc - 0x09, 0x7b, 0x7e, 0xcc - }; - // clang-format on - const uint32_t crc_computed = wvcrc32n(kKeyboxData, 124); - uint32_t crc_current; - memcpy(&crc_current, &kKeyboxData[124], 4); - EXPECT_EQ(crc_computed, crc_current); -} - -} // namespace wvoec_ref