Snap for 7188367 from 7a46bc3c87 to sc-release
Change-Id: I4e5d1a405ebbaa185373bfe70a8b24bc4906b83e
This commit is contained in:
@@ -4,6 +4,8 @@
|
||||
//
|
||||
// Reference implementation of OEMCrypto APIs
|
||||
//
|
||||
#include "oemcrypto_ecc_key.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -18,7 +20,6 @@
|
||||
#include <openssl/x509.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "oemcrypto_ecc_key.h"
|
||||
#include "scoped_object.h"
|
||||
|
||||
namespace wvoec_ref {
|
||||
|
||||
@@ -70,10 +70,10 @@ class EccPublicKey {
|
||||
|
||||
// Serializes the public key into an ASN.1 DER encoded SubjectPublicKey
|
||||
// representation.
|
||||
// On success, |*buffer_size| is populated with the number of bytes
|
||||
// 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.
|
||||
// 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.
|
||||
@@ -167,10 +167,10 @@ class EccPrivateKey {
|
||||
|
||||
// Serializes the private key into an ASN.1 DER encoded ECPrivateKey
|
||||
// representation.
|
||||
// On success, |*buffer_size| is populated with the number of bytes
|
||||
// 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
|
||||
// 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.
|
||||
@@ -184,10 +184,10 @@ class EccPrivateKey {
|
||||
// - SHA-256 / secp256r1
|
||||
// - SHA-384 / secp384r1 (optional support)
|
||||
// - SHA-512 / secp521r1 (optional support)
|
||||
// On success, |*signature_length| is populated with the number of
|
||||
// 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|
|
||||
// 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,
|
||||
@@ -203,10 +203,10 @@ class EccPrivateKey {
|
||||
|
||||
// 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
|
||||
// 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|
|
||||
// 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,
|
||||
|
||||
1169
libwvdrmengine/oemcrypto/ref/src/oemcrypto_rsa_key.cpp
Normal file
1169
libwvdrmengine/oemcrypto/ref/src/oemcrypto_rsa_key.cpp
Normal file
File diff suppressed because it is too large
Load Diff
359
libwvdrmengine/oemcrypto/ref/src/oemcrypto_rsa_key.h
Normal file
359
libwvdrmengine/oemcrypto/ref/src/oemcrypto_rsa_key.h
Normal file
@@ -0,0 +1,359 @@
|
||||
// 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 <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
#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<RsaPublicKey> 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<RsaPublicKey> Load(const uint8_t* buffer,
|
||||
size_t length);
|
||||
static std::unique_ptr<RsaPublicKey> Load(const std::string& buffer);
|
||||
static std::unique_ptr<RsaPublicKey> Load(const std::vector<uint8_t>& 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<uint8_t> 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<uint8_t>& message,
|
||||
const std::vector<uint8_t>& 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<uint8_t> EncryptSessionKey(
|
||||
const std::vector<uint8_t>& session_key) const;
|
||||
std::vector<uint8_t> 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<uint8_t> EncryptEncryptionKey(
|
||||
const std::vector<uint8_t>& encryption_key) const;
|
||||
std::vector<uint8_t> 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<RsaPrivateKey> 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<RsaPrivateKey> Load(const uint8_t* buffer,
|
||||
size_t length);
|
||||
static std::unique_ptr<RsaPrivateKey> Load(const std::string& buffer);
|
||||
static std::unique_ptr<RsaPrivateKey> Load(
|
||||
const std::vector<uint8_t>& buffer);
|
||||
|
||||
// Creates a new RSA public key of this private key.
|
||||
// Equivalent to calling RsaPublicKey::New with this private
|
||||
// key.
|
||||
std::unique_ptr<RsaPublicKey> 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<uint8_t> 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<uint8_t> GenerateSignature(
|
||||
const std::vector<uint8_t>& message,
|
||||
RsaSignatureAlgorithm algorithm = kRsaPssDefault) const;
|
||||
std::vector<uint8_t> 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<uint8_t> DecryptSessionKey(
|
||||
const std::vector<uint8_t>& enc_session_key) const;
|
||||
std::vector<uint8_t> 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<uint8_t> DecryptEncryptionKey(
|
||||
const std::vector<uint8_t>& enc_encryption_key) const;
|
||||
std::vector<uint8_t> 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_
|
||||
232
libwvdrmengine/oemcrypto/ref/test/oemcrypto_ecc_key_unittest.cpp
Normal file
232
libwvdrmengine/oemcrypto/ref/test/oemcrypto_ecc_key_unittest.cpp
Normal file
@@ -0,0 +1,232 @@
|
||||
// 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 <gtest/gtest.h>
|
||||
|
||||
#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<EccCurve> {
|
||||
public:
|
||||
void SetUp() override { key_ = EccPrivateKey::New(GetParam()); }
|
||||
|
||||
void TearDown() override { key_.reset(); }
|
||||
|
||||
protected:
|
||||
std::unique_ptr<EccPrivateKey> 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<uint8_t> 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<uint8_t> 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<uint8_t> key_data = key_->Serialize();
|
||||
std::unique_ptr<EccPrivateKey> loaded_key = EccPrivateKey::Load(key_data);
|
||||
ASSERT_TRUE(loaded_key);
|
||||
|
||||
EXPECT_EQ(key_->curve(), loaded_key->curve());
|
||||
|
||||
const std::vector<uint8_t> 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<EccPublicKey> 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<EccPublicKey> pub_key = key_->MakePublicKey();
|
||||
ASSERT_TRUE(pub_key);
|
||||
|
||||
constexpr size_t kInitialBufferSize = 10; // Definitely too small.
|
||||
size_t buffer_size = kInitialBufferSize;
|
||||
std::vector<uint8_t> 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<uint8_t> 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<EccPublicKey> pub_key = key_->MakePublicKey();
|
||||
ASSERT_TRUE(pub_key);
|
||||
|
||||
const std::vector<uint8_t> key_data = pub_key->Serialize();
|
||||
|
||||
std::unique_ptr<EccPublicKey> loaded_key = EccPublicKey::Load(key_data);
|
||||
ASSERT_TRUE(loaded_key);
|
||||
|
||||
EXPECT_EQ(pub_key->curve(), loaded_key->curve());
|
||||
|
||||
const std::vector<uint8_t> 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<uint8_t> message = RandomData(kMessageSize);
|
||||
ASSERT_FALSE(message.empty()) << "CdmRandom failed";
|
||||
|
||||
constexpr size_t kInitialBufferSize = 10; // Definitely too small.
|
||||
size_t signature_size = kInitialBufferSize;
|
||||
std::vector<uint8_t> 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<uint8_t> message = RandomData(kMessageSize);
|
||||
ASSERT_FALSE(message.empty()) << "CdmRandom failed";
|
||||
|
||||
const std::vector<uint8_t> signature = key_->GenerateSignature(message);
|
||||
|
||||
std::unique_ptr<EccPublicKey> pub_key = key_->MakePublicKey();
|
||||
ASSERT_TRUE(pub_key);
|
||||
|
||||
EXPECT_EQ(OEMCrypto_SUCCESS, pub_key->VerifySignature(message, signature));
|
||||
|
||||
// Check with different message.
|
||||
const std::vector<uint8_t> message_two = RandomData(kMessageSize);
|
||||
EXPECT_EQ(OEMCrypto_ERROR_SIGNATURE_FAILURE,
|
||||
pub_key->VerifySignature(message_two, signature));
|
||||
|
||||
// Check with bad signature.
|
||||
const std::vector<uint8_t> 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<EccPublicKey> alice_public_key =
|
||||
alice_private_key->MakePublicKey();
|
||||
ASSERT_TRUE(alice_public_key);
|
||||
// Set up Bob.
|
||||
std::unique_ptr<EccPrivateKey> bob_private_key =
|
||||
EccPrivateKey::New(alice_private_key->curve());
|
||||
ASSERT_TRUE(bob_private_key);
|
||||
std::unique_ptr<EccPublicKey> 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<uint8_t> alice_session_key =
|
||||
alice_private_key->DeriveSessionKey(*bob_public_key);
|
||||
|
||||
// From Bob's perspective.
|
||||
const std::vector<uint8_t> 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
|
||||
@@ -0,0 +1,20 @@
|
||||
// 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 <string>
|
||||
|
||||
#include "cdm_random.h"
|
||||
|
||||
namespace wvoec_ref {
|
||||
|
||||
std::vector<uint8_t> RandomData(size_t length) {
|
||||
const std::string data = wvcdm::CdmRandom::RandomData(length);
|
||||
return std::vector<uint8_t>(data.begin(), data.end());
|
||||
}
|
||||
|
||||
} // namespace wvoec_ref
|
||||
21
libwvdrmengine/oemcrypto/ref/test/oemcrypto_ref_test_utils.h
Normal file
21
libwvdrmengine/oemcrypto/ref/test/oemcrypto_ref_test_utils.h
Normal file
@@ -0,0 +1,21 @@
|
||||
// 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 <stdint.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace wvoec_ref {
|
||||
|
||||
// Returns a vector of random bytes.
|
||||
std::vector<uint8_t> RandomData(size_t length);
|
||||
|
||||
} // namespace wvoec_ref
|
||||
|
||||
#endif // OEMCRYPTO_REF_TEST_UTILS_H_
|
||||
Reference in New Issue
Block a user