Support CAST V2 authentication - OEMCrypto Interface - DO NOT MERGE

Squashed commit of these CLs from the widevine cdm repo:

Allow Version 8 OEMCrypto to be linked with CDM (KLP Modular Branch)
https://widevine-internal-review.googlesource.com/#/c/9434/

Allow OEMCrypto v8 or v9 (KLP Modular Branch)
https://widevine-internal-review.googlesource.com/#/c/9172/

Add alternate RSA signing (KLP Modular Branch)
https://widevine-internal-review.googlesource.com/#/c/9171/

bug: 12702350
Change-Id: Ifd0c88c566bb10efe2411af49bc83265ed56cb23
This commit is contained in:
Fred Gylys-Colwell
2014-03-24 13:46:38 -07:00
parent f1e87b1b04
commit a59b935928
14 changed files with 1930 additions and 322 deletions

View File

@@ -8,6 +8,7 @@
#include "oemcrypto_engine_mock.h"
#include <arpa/inet.h>
#include <iostream>
#include <vector>
#include <string.h>
@@ -31,8 +32,9 @@
static const int kPssSaltLength = 20;
namespace {
// Increment counter for AES-CTR
void ctr128_inc(uint8_t* counter) {
// 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;
@@ -252,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]");
@@ -266,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;
}
@@ -485,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]");
@@ -899,11 +934,11 @@ bool CryptoEngine::DecryptCTR(SessionContext* session,
const uint8_t* cipher_data,
size_t cipher_data_length,
bool is_encrypted,
void* clear_data,
uint8_t* clear_data,
BufferType buffer_type) {
// If the data is clear, we do not need a current key selected.
if (!is_encrypted) {
if (!is_encrypted && buffer_type != kBufferTypeDirect) {
memcpy(reinterpret_cast<uint8_t*>(clear_data),
cipher_data, cipher_data_length);
return true;
@@ -961,20 +996,20 @@ bool CryptoEngine::DecryptCTR(SessionContext* session,
// Encrypt the IV.
uint8_t ecount_buf[AES_BLOCK_SIZE];
if (block_offset != 0) {
// The context is needed only when not starting a new block.
AES_encrypt(aes_iv, ecount_buf, &aes_key);
ctr128_inc(aes_iv);
}
// Decryption.
unsigned int block_offset_cur = block_offset;
AES_ctr128_encrypt(
cipher_data, reinterpret_cast<uint8_t*>(clear_data), cipher_data_length,
&aes_key, aes_iv, ecount_buf, &block_offset_cur);
if (block_offset_cur != ((block_offset + cipher_data_length) % AES_BLOCK_SIZE)) {
LOGE("[DecryptCTR(): FAILURE: byte offset wrong.]");
return false;
// 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;
while (l < cipher_data_length) {
AES_encrypt(aes_iv, 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);
block_offset = 0;
}
return true;
}