Add alternate RSA signing

From the Widevine CDM repository:
https://widevine-internal-review.googlesource.com/#/c/9183/

This adds unit tests for RSA signing with  PKCS1 block type 1. It also
adds a reference implementation.  This is part of OEMCrypto v9.

Change-Id: I2a40dbff65f6e09d75f16ae048499512f60c168d
This commit is contained in:
Fred Gylys-Colwell
2014-03-14 16:40:17 -07:00
parent 71e9cacfe2
commit 80e9ea9cb0
4 changed files with 1376 additions and 115 deletions

View File

@@ -8,6 +8,7 @@
#include "oemcrypto_engine_mock.h"
#include <arpa/inet.h>
#include <iostream>
#include <vector>
#include <string.h>
@@ -253,7 +254,8 @@ size_t SessionContext::RSASignatureSize() {
bool SessionContext::GenerateRSASignature(const uint8_t* message,
size_t message_length,
uint8_t* signature,
size_t* signature_length) {
size_t* signature_length,
RSA_Padding_Scheme padding_scheme) {
if (message == NULL || message_length == 0 ||
signature == NULL || signature_length == 0) {
LOGE("[GenerateRSASignature(): OEMCrypto_ERROR_INVALID_CONTEXT]");
@@ -267,33 +269,55 @@ bool SessionContext::GenerateRSASignature(const uint8_t* message,
*signature_length = RSA_size(rsa_key_);
return false;
}
// Hash the message using SHA1.
uint8_t hash[SHA_DIGEST_LENGTH];
if (!SHA1(message, message_length, hash)) {
LOGE("[GeneratRSASignature(): error creating signature hash.]");
dump_openssl_error();
if ((padding_scheme & allowed_schemes_) != padding_scheme) {
LOGE("[GenerateRSASignature(): padding_scheme not allowed]");
return false;
}
// Add PSS padding.
std::vector<uint8_t> padded_digest(*signature_length);
int status = RSA_padding_add_PKCS1_PSS(rsa_key_, &padded_digest[0], hash,
EVP_sha1(), kPssSaltLength);
if (status == -1) {
LOGE("[GeneratRSASignature(): error padding hash.]");
dump_openssl_error();
if (padding_scheme == kSign_RSASSA_PSS) {
// Hash the message using SHA1.
uint8_t hash[SHA_DIGEST_LENGTH];
if (!SHA1(message, message_length, hash)) {
LOGE("[GeneratRSASignature(): error creating signature hash.]");
dump_openssl_error();
return false;
}
// Add PSS padding.
std::vector<uint8_t> padded_digest(*signature_length);
int status = RSA_padding_add_PKCS1_PSS(rsa_key_, &padded_digest[0], hash,
EVP_sha1(), kPssSaltLength);
if (status == -1) {
LOGE("[GeneratRSASignature(): error padding hash.]");
dump_openssl_error();
return false;
}
// Encrypt PSS padded digest.
status = RSA_private_encrypt(*signature_length, &padded_digest[0], signature,
rsa_key_, RSA_NO_PADDING);
if (status == -1) {
LOGE("[GeneratRSASignature(): error in private encrypt.]");
dump_openssl_error();
return false;
}
} else if (padding_scheme == kSign_PKCS1_Block1) {
if (message_length > 83) {
LOGE("[GeneratRSASignature(): RSA digest too large.]");
return false;
}
// Pad the message with PKCS1 padding, and then encrypt.
int status = RSA_private_encrypt(message_length, message, signature,
rsa_key_, RSA_PKCS1_PADDING);
if (status != *signature_length) {
LOGE("[GeneratRSASignature(): error in RSA private encrypt. status=%d]", status);
dump_openssl_error();
return false;
}
} else { // Bad RSA_Padding_Scheme
return false;
}
// Encrypt PSS padded digest.
status = RSA_private_encrypt(*signature_length, &padded_digest[0], signature,
rsa_key_, RSA_NO_PADDING);
if (status == -1) {
LOGE("[GeneratRSASignature(): error in private encrypt.]");
dump_openssl_error();
return false;
}
return true;
}
@@ -486,6 +510,16 @@ bool SessionContext::LoadRSAKey(uint8_t* pkcs8_rsa_key,
RSA_free(rsa_key_);
rsa_key_ = NULL;
}
if (rsa_key_length < 8) {
LOGE("[LoadRSAKey(): Very Short Buffer]");
return false;
}
if( (memcmp(pkcs8_rsa_key, "SIGN", 4) == 0) ) {
uint32_t *schemes_n = (uint32_t *)(pkcs8_rsa_key + 4);
allowed_schemes_ = htonl(*schemes_n);
pkcs8_rsa_key += 8;
rsa_key_length -= 8;
}
BIO *bio = BIO_new_mem_buf(pkcs8_rsa_key, rsa_key_length);
if( bio == NULL ) {
LOGE("[LoadRSAKey(): Could not allocate bio buffer]");

View File

@@ -88,7 +88,7 @@ class SessionContext {
public:
explicit SessionContext(CryptoEngine* ce, SessionId sid)
: valid_(true), ce_(ce), id_(sid), current_content_key_(NULL),
rsa_key_(NULL) {}
rsa_key_(NULL), allowed_schemes_(kSign_RSASSA_PSS) {}
~SessionContext() {}
void Open();
@@ -110,7 +110,8 @@ class SessionContext {
bool GenerateRSASignature(const uint8_t* message,
size_t message_length,
uint8_t* signature,
size_t* signature_length);
size_t* signature_length,
RSA_Padding_Scheme padding_scheme);
bool ValidateMessage(const uint8_t* message,
size_t message_length,
const uint8_t* signature,
@@ -177,6 +178,7 @@ class SessionContext {
encryption_key_ = enc_key;
}
const std::vector<uint8_t>& encryption_key() { return encryption_key_; }
const uint32_t allowed_schemes() { return allowed_schemes_; }
void AddNonce(uint32_t nonce);
bool CheckNonce(uint32_t nonce);
@@ -198,6 +200,7 @@ class SessionContext {
SessionKeyTable session_keys_;
NonceTable nonce_table_;
RSA* rsa_key_;
uint32_t allowed_schemes_; // for RSA signatures.
time_t timer_start_;
CORE_DISALLOW_COPY_AND_ASSIGN(SessionContext);

View File

@@ -928,15 +928,11 @@ OEMCryptoResult OEMCrypto_GenerateRSASignature(OEMCrypto_SESSION session,
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
if (padding_scheme != kSign_RSASSA_PSS) {
LOGE("[OEMCrypto_GenerateRSASignature(): OEMCrypto_ERROR_NOT_IMPLEMENTED]");
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
}
if (session_ctx->GenerateRSASignature(message,
message_length,
signature,
signature_length)) {
signature_length,
padding_scheme)) {
if (trace_all_calls) {
dump_hex("signature", signature, *signature_length);
}
@@ -971,6 +967,11 @@ OEMCryptoResult OEMCrypto_DeriveKeysFromSessionKey(
return OEMCrypto_ERROR_INVALID_SESSION;
}
if (session_ctx->allowed_schemes() != kSign_RSASSA_PSS) {
LOGE("[OEMCrypto_GenerateDerivedKeys(): x509 key used to derive keys]");
return OEMCrypto_ERROR_INVALID_RSA_KEY;
}
const std::vector<uint8_t> ssn_key_str(enc_session_key,
enc_session_key + enc_session_key_length);
const std::vector<uint8_t> mac_ctx_str(mac_key_context,

File diff suppressed because it is too large Load Diff