Update Simulcrypt ECMg
This commit is contained in:
@@ -13,7 +13,7 @@
|
||||
//
|
||||
// RSA signature details:
|
||||
// Algorithm: RSASSA-PSS
|
||||
// Hash algorithm: SHA1
|
||||
// Hash algorithm: |hash_algorithm|
|
||||
// Mask generation function: mgf1SHA1
|
||||
// Salt length: 20 bytes
|
||||
// Trailer field: 0xbc
|
||||
@@ -21,7 +21,7 @@
|
||||
// RSA encryption details:
|
||||
// Algorithm: RSA-OAEP
|
||||
// Mask generation function: mgf1SHA1
|
||||
// Label (encoding paramter): empty std::string
|
||||
// Label (encoding parameter): empty std::string
|
||||
|
||||
#include "common/rsa_key.h"
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "openssl/evp.h"
|
||||
#include "openssl/rsa.h"
|
||||
#include "openssl/sha.h"
|
||||
#include "common/hash_algorithm.h"
|
||||
#include "common/rsa_util.h"
|
||||
#include "common/sha_util.h"
|
||||
|
||||
@@ -51,6 +52,21 @@ std::string OpenSSLErrorString(uint32_t error) {
|
||||
return buf;
|
||||
}
|
||||
|
||||
std::string GetMessageDigest(const std::string& message,
|
||||
widevine::HashAlgorithm hash_algorithm) {
|
||||
switch (hash_algorithm) {
|
||||
// The default hash algorithm of RSA signature is SHA1.
|
||||
case widevine::HashAlgorithm::kUnspecified:
|
||||
case widevine::HashAlgorithm::kSha1:
|
||||
return widevine::Sha1_Hash(message);
|
||||
case widevine::HashAlgorithm::kSha256:
|
||||
return widevine::Sha256_Hash(message);
|
||||
}
|
||||
LOG(FATAL) << "Unexpected hash algorithm: "
|
||||
<< static_cast<int>(hash_algorithm);
|
||||
return "";
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace widevine {
|
||||
@@ -137,6 +153,47 @@ bool RsaPrivateKey::GenerateSignature(const std::string& message,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RsaPrivateKey::GenerateSignature(const std::string& message,
|
||||
HashAlgorithm hash_algorithm,
|
||||
std::string* signature) const {
|
||||
DCHECK(signature);
|
||||
|
||||
if (message.empty()) {
|
||||
LOG(ERROR) << "Message to be signed is empty";
|
||||
return false;
|
||||
}
|
||||
// Hash the message using corresponding hash algorithm.
|
||||
std::string message_digest = GetMessageDigest(message, hash_algorithm);
|
||||
if (message_digest.empty()) {
|
||||
LOG(ERROR) << "Empty message digest";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add PSS padding.
|
||||
size_t rsa_size = RSA_size(key_);
|
||||
std::string padded_digest(rsa_size, 0);
|
||||
if (!RSA_padding_add_PKCS1_PSS_mgf1(
|
||||
key_, reinterpret_cast<unsigned char*>(&padded_digest[0]),
|
||||
reinterpret_cast<unsigned char*>(&message_digest[0]), EVP_sha1(),
|
||||
EVP_sha1(), kPssSaltLength)) {
|
||||
LOG(ERROR) << "RSA padding failure: "
|
||||
<< OpenSSLErrorString(ERR_get_error());
|
||||
return false;
|
||||
}
|
||||
// Encrypt PSS padded digest.
|
||||
signature->assign(rsa_size, 0);
|
||||
if (RSA_private_encrypt(padded_digest.size(),
|
||||
reinterpret_cast<unsigned char*>(&padded_digest[0]),
|
||||
reinterpret_cast<unsigned char*>(&(*signature)[0]),
|
||||
key_, RSA_NO_PADDING) !=
|
||||
static_cast<int>(signature->size())) {
|
||||
LOG(ERROR) << "RSA private encrypt failure: "
|
||||
<< OpenSSLErrorString(ERR_get_error());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RsaPrivateKey::GenerateSignatureSha256Pkcs7(const std::string& message,
|
||||
std::string* signature) const {
|
||||
DCHECK(signature);
|
||||
@@ -253,6 +310,52 @@ bool RsaPublicKey::VerifySignature(const std::string& message,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RsaPublicKey::VerifySignature(const std::string& message,
|
||||
HashAlgorithm hash_algorithm,
|
||||
const std::string& signature) const {
|
||||
if (message.empty()) {
|
||||
LOG(ERROR) << "Signed message is empty";
|
||||
return false;
|
||||
}
|
||||
size_t rsa_size = RSA_size(key_);
|
||||
if (signature.size() != rsa_size) {
|
||||
LOG(ERROR) << "Message signature is of the wrong size (expected "
|
||||
<< rsa_size << ", actual " << signature.size() << ")";
|
||||
return false;
|
||||
}
|
||||
// Decrypt the signature.
|
||||
std::string padded_digest(signature.size(), 0);
|
||||
if (RSA_public_decrypt(
|
||||
signature.size(),
|
||||
const_cast<unsigned char*>(
|
||||
reinterpret_cast<const unsigned char*>(signature.data())),
|
||||
reinterpret_cast<unsigned char*>(&padded_digest[0]), key_,
|
||||
RSA_NO_PADDING) != static_cast<int>(rsa_size)) {
|
||||
LOG(ERROR) << "RSA public decrypt failure: "
|
||||
<< OpenSSLErrorString(ERR_get_error());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Hash the message using SHA1 using corresponding hash algorithm.
|
||||
std::string message_digest = GetMessageDigest(message, hash_algorithm);
|
||||
if (message_digest.empty()) {
|
||||
LOG(ERROR) << "Empty message digest";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verify PSS padding.
|
||||
if (RSA_verify_PKCS1_PSS_mgf1(
|
||||
key_, reinterpret_cast<unsigned char*>(&message_digest[0]),
|
||||
EVP_sha1(), EVP_sha1(),
|
||||
reinterpret_cast<unsigned char*>(&padded_digest[0]),
|
||||
kPssSaltLength) == 0) {
|
||||
LOG(ERROR) << "RSA Verify PSS padding failure: "
|
||||
<< OpenSSLErrorString(ERR_get_error());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RsaPublicKey::VerifySignatureSha256Pkcs7(
|
||||
const std::string& message, const std::string& signature) const {
|
||||
if (message.empty()) {
|
||||
|
||||
Reference in New Issue
Block a user